LibGDX: как да умножа вектор със скалар, без да модифицирам оригиналния вектор? (проста гравитационна система в Java игра)

В момента внедрявам проста гравитационна система в моята игра, използвайки LibGDX. Открих обаче, че начинът, по който умножавате вектори с вектори и вектори със скалари, е малко по-различен.

В Unity бих приложил гравитацията по следния начин:

    public Vector3 velocity;
    public Vector3 acceleration;

    private void FixedUpdate()
    {
        transform.position += velocity*Time.fixedDeltaTime;

        Vector3 force = Physics.gravity*GetComponent<Rigidbody>().mass;
        acceleration = force/GetComponent<Rigidbody>().mass;

        velocity = velocity + acceleration*Time.fixedDeltaTime;
    }
}

Векторното умножение е много просто.

В LibGDX опитвам следното:

    import com.badlogic.gdx.math.Vector2;

    final protected Vector2 _gravity = new Vector2(0f, -9.82f);
    final protected float _mass = 1f;
    protected Vector2 _velocity;
    protected Vector2 _acceleration;

    public void Update(float deltaTime)
    {
        // Transform is a class containing a Vector2 called Position
        Transform.Position.add(_velocity.scl(deltaTime));

        Vector2 force = _gravity.scl(_mass);
        _acceleration = force.scl(1f/_mass);    
        _velocity = _velocity.add(_acceleration.scl(deltaTime));

        System.out.println(_velocity);
        // _velocity gets smaller and smaller and finally hits 0.
    }

Това не работи, тъй като методът scl() на Vector2 директно променя самия вектор, както може да се види в класа Vector2 на LibGDX:

public Vector2 scl (float scalar) {
        x *= scalar;
        y *= scalar;
        return this;
    }

Предполагам, че искам да върне нов Vector2, вместо да променя директно самия вектор.

Как мога да направя това? Или напълно греша? Има ли по-лесен начин в LibGDX за умножаване на вектори със скалари с помощта на оператора "*"?


person Wikzo    schedule 17.11.2015    source източник
comment
Причината да не можете да го направите по начина на Unity е, че Java няма структури. :(   -  person Tenfour04    schedule 17.11.2015


Отговори (3)


Причината методът (и други) да не създават нов вектор е да се избегне създаването на боклук. Създаването на боклук ще накара събирача на боклук да изчисти, което може (и ще) причини проблеми. За игри честите прекъсвания са нещо, което обикновено искате да избегнете.

Така че, ако това е нещо, което трябва да направите само веднъж, тогава е добре да използвате метода cpy() или ключовата дума new. Но за често извиквани методи (като вашия метод за актуализиране), наистина искате да избегнете това. Вместо това можете да използвате член вектор.

final Vector2 force = new Vector2();
public void update(float delta) {
    ...
    force.set(_gravity).scl(mass);
    ...
}

Имайте предвид, че за операции като position += velocity * time можете да използвате метода mulAdd.

position.mulAdd(velocity, deltaTime);
person Xoppa    schedule 17.11.2015

Vector2 force = _gravity.cpy().scl(_mass);

Методът cpy() връща копие на вектора, така че в крайна сметка умножавате копието с _mass, а не с оригиналния вектор.

Малкото предимство на това решение в сравнение с използването на new Vector2() за създаване на копие е, че то работи за всяко векторно измерение без модификация.

person biziclop    schedule 17.11.2015

Можете да опитате да дублирате вектора, преди да го мащабирате, така:

new Vector2(_gravity).scl(_mass);
person Anuken    schedule 17.11.2015