0
votes

I am currently implementing a simple gravity system in my game using LibGDX. However, I found that the way you multiply vectors with vectors and vectors with scalars is a bit different.

In Unity, I would implement gravity like this:

    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;
    }
}

Vector multiplication is very straight forward.

In LibGDX, I am trying the following:

    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.
    }

This does not work, since the scl() method of Vector2 directly changes the vector itself, as can be seen in the Vector2 class of LibGDX:

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

I assume I want it to return a new Vector2, instead of changing the vector itself directly.

How can I do that? Or am I completely wrong? Is there an easier way in LibGDX to multiply vectors with scalars using the "*" operator?

3
The reason you can't do it the Unity way is that Java doesn't have structs. :(Tenfour04

3 Answers

3
votes

The reason that method (and others) don't create a new vector is to avoid creating garbage. Creating garbage will cause the garbage collector to clean up, which can (and will) cause hick ups. For games, frequent hick-ups is something you typically want to avoid.

So, if it is something you only need to once, then it is okay to use the cpy() method or new keyword. But for frequently called methods (like your update method), you really want to avoid that. Instead you can use a member vector.

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

Note that for operations like position += velocity * time you can use the mulAdd method.

position.mulAdd(velocity, deltaTime);
3
votes

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

The cpy() method returns a copy of the vector, thus you end up multiplying the copy with _mass rather than the original vector.

The slight advantage of this solution, compared to using new Vector2() to create the copy is that it works for any vector dimension without modification.

0
votes

You could try duplicating the vector before scaling it, like so:

new Vector2(_gravity).scl(_mass);