Best approach for Asteroids-style movement/physics?

Started by
3 comments, last by Nypyren 9 years, 1 month ago

I'm trying to create a 2D space shooter with controls similar to the classic arcade game Asteroids. The controls involve a thrust button which propels the player in whatever direction they are facing, and left/right rotation controls which changes the player's angle. I plan to build on of this basic scheme and perhaps include mouse control for direction, multiple thrust directions, etc. But first I want to have the core mechanic down in a way that will be easy to build on.

My thoughts are storing the data for position and movement as follows:

Position - X,Y co-ordinates

Speed - simple scaler variable from 0 to some MaxSpeed value

Angle - float variable in radians

Direction vector - X,Y movement vector between -1 and 1

For the movement algorithm, when the player presses the thrust button, the speed value will increase and the direction vectors will be calculated based on the player angle. During the player update phase, the players position will be incremented along the X and Y axis by multiplying the direction vectors by the speed value.

What I'm not sure how to incorporate is momentum. Ideally, I want the player to keep moving after the thrust button is released. I also don't want the player to immediately change direction when they initiate a thrust in a different angle.

Any thoughts on how to approach this?

edited to add: Thinking about this a bit, I wonder if having two direction vectors would work. Have one for the existing movement direction, and then if the player changes direction, create a new "target" direction vector. Then simply increment/decrement the direction vector over time until it matches the "target" vector.

Advertisement

I think "Force" is a better value to use for Asteroids instead of speed, that's what's rally happening, the engine's is applying force in a specific direction.

You could also just use a 2d physics library (chipmunk-physics or box2d) for this; it's what I would do, unless you specifically want to handle the physics yourself, which is fine too.

Good luck.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

For this simple problem you don't need a physics engine, but you will end up with a approach that is closer to a real body position evaluation given parameters such speed and acceleration (which is implemented in Box2D for instance using a more sofisticated and better approximate approach). These libraries supplies rotational motion in the case you want it; hard-coding them correctly can be a little bit painful.

I think BeerNutts is right - you should be thinking in terms of force rather than speed. If you are familiar with classical physics, then you can imagine making a free-body diagram of your ship. You will need to maintain a position and a velocity for the ship. Let's assume both start out at (0,0). Then to create some movement, you apply Newton's second law: F=ma, which just indicates that when you apply a force to your ship, then you have an acceleration that is inversely proportional to the mass of the object. To keep it really simple, let's assume the mass is 1.

That means your force is proportional to the acceleration for each simulation step. Then you can update the velocity with Vnew = Vold + a*t where t is the amount of time since the last step. Similarly, you can then update the position with Pnew = Pold + Vnew*t. That gets you a physically based update mechanism, which will also respect the momentum of the system. Once you apply a force to the object, it will start moving and keep going until an opposite force is applied.

What you will probably want to do is apply a 'drag' force which is applied in the opposite direction of the velocity, which will let you drift to a stop over a long period of time.

Any thoughts on how to approach this?



Persistent variables reused every frame
{
  Vector2D position;
  Vector2D velocity;
  Vector2D acceleration;
  float shipHeadingRadians;
  const float shipThrust = whatever.0f;
}

Each frame, only if the player is applying thrust
{
  acceleration.x += shipThrust * cos(shipHeadingRadians);
  acceleration.y += shipThrust * sin(shipHeadingRadians);
}

Each frame, regardless of whether player presses anything
{
  position += velocity * timestep;
  velocity += acceleration * timestep;
  acceleration.x = 0;
  acceleration.y = 0;
}
If you want friction, the simplest way is to multiply velocity by a constant value slightly less than 1 every frame.

This topic is closed to new replies.

Advertisement