[libgdx] Moving a sprite at a changing angle

I’ve managed to move my sprites from point A to point B thanks to the universal tween engine.
However, I want sprites to move at a constant speed, without a specific end value. This is something the tween engine can’t do (to the best of my knowledge). Moreover, I want to continuously change the angle at which the sprite is travelling. I plan on using the tween engine for angle interpolation because I will have an end value for this property.
So far all I could think of was doing some math and then constantly update my sprites’ X and Y coords. I’m also reading up on Matrix3 class to see if it could be of use.

I’m working with many 2D sprites that I want to move differently in various directions. What’s the best way to go about achieving this?

Any help is welcome.
Thanks!

I was just helping a guy with that, how about this:


class Bullet extends Sprite { // as an example
	
	Vector2 velocity; // initialized elsewhere

	public void update(float delta) {
		/*
		Do any stuff with velocity like Euler integration etc here
		*/

		Vector2 vdt = velocity.cpy().scl(delta);
		translate(vdt.x, vdt.y);

		setOriginCenter();
		setRotation(velocity.angle());
	}

}

In render() you draw it with sprite.draw(batch);
Rotation and everything is handled internally.

Just change the velocity and the sprite will change direction it’s moving.

For instance, to have the “bullet” move at a 45 degree angle upwards at 10 units/sec:

[icode]bullet.velocity.setAngle(45).nor().scl(10);[/icode] should do the trick.

You could easily tween the setAngle().

Very cool! Thanks. I’m gonna be playing around with this. Didn’t think to check the Vector2 class implementation.

I got a little lost. Would’ve been easier to grasp this if I was paying attention in my high school math class, years ago :frowning:

Here’s my train of thought:
Velocity is initialized without any values. It is then continuously assigned an angle by the tween engine (up to 45). This specifies the direction of the vector (right?). I logged the velocity at this point, and its x,y values were growing fast and far. So normalizing should help here. However, after normalizing velocity, the x,y values were just 0s. Assuming it would have worked correctly, all that was left is to multiply by the rate; rate is also assigned by the tween engine (up to 10). The last step didn’t do anything to the velocity x,y fields because obviously they were 0s after normalization.
Finally we copy the velocity vector into some temp(vdt?) vector and multiply it by delta. Then translate the sprite by the temp vector’s coords.

Do I understand everything correctly so far?

Now, the structure of my code is a little different. I don’t have everything stuffed into my update method.
I perform the angle and rate changes in one separate method. In that same method I perform the velocity calculation. This method is used by the tween engine which of course gets updated in the update method.


public void setVelocity(float angle, float rate) {
		this.angle = angle;
		velocity.setAngle(angle).nor().scl(rate);

The translation happens in the update method.

public boolean update(float delta) {
		vdt = velocity.cpy().scl(delta);
		translate(vdt.x, vdt.y);

                //origin is set to the centre elsewhere, and I don't need the sprite to rotate, so I excluded those 2 lines
                tween.update(delta);


It’s not working, but it’s most likely because I don’t understand something. Does what I wrote make sense?

If velocity starts at (or is ever) (0, 0), then yes, scl(rate) will do nothing. So a better setVelocity would be this:


public void setVelocity(float angle, float rate) {
      /*
       * Sets velocity to length <speed> at 0 degrees (flat along x-axis),
       * then sets the angle (preserving the length of <speed>)
       */
      this.angle = angle;
      velocity.set(rate, 0).setAngle(angle);
}

The update is this:

Position<sub>n+1</sub> = Position<sub>n</sub> + Velocity<sub>n</sub> * ΔTime

This is one of the parts of Euler integration and obviously that can be coded a myriad of ways.

My approach with Vector2 is to copy velocity (since we don’t want to change the actual velocity) and scale (multiply) it by the delta, then add it to position (translate).
The temporary vector is not even necessary if you don’t like it: (I’m actually not sure why I didn’t do this originally)


translate(velocity.x * delta, velocity.y * delta);
tween.update(delta);

Also, if you’re not rotating the sprite, then setOriginCenter() is also not needed.

EDIT: a primer on numeric integration such as this: http://gafferongames.com/game-physics/integration-basics/

Wonderful, thank you! Now it works :slight_smile: