Y*A*R*T*S (or Yet Another Real Time Strategy game)


Physics (Just in from John, in deepest Australia..)

Using some basic physics in a game can prove useful. It allows an increased level of flexibility and can help add a certain level of realism and consistency.

In YARTS the physics is fairly simple. Rotational effects are basically ignored. When a unit gets pushed around, the unit will not turn. Units can never be made to turn through external means, they turn when they want to turn. This leaves the units position, velocity and acceleration for us to deal with.

The overall integration goes roughly as follows:

Now here is some pseudo java code for the integrate method of the units:


public class Unit {
	private double x, y; // position
	private double vx, vy;  // velocity
	private double mass; // make use this ain't zero
	private double fx, fy; // accumulated forces

	/** Apply a force to the unit. **/
	public void applyForce( double fx, double fy ) {
		this.fx += fx;
		this.fy += fy;
	}

	/** Integrate using basic euler method. **/
	public void integrate( double dt ) {
		// update position given current velocity
		// using euler
		x = x + dt*vx;
		y = y + dt*vy; // calculate acceleration caused by forces
		// uses newtons second law f = ma
		double ax = fx/mass;
		double ay = fy/mass;

		// update the velocities given accelerations
		// again using euler
		vx = vx + dt*ax;
		vy = vy + dt*ay;

		// then best to deal with friction (see "jitters")
		// ...
		//////////////// // then cancel out the accumulated forces
		// as they have been used up for this timestep
		fx = 0;
		fy = 0;
	}
}



Stability

Now what has been described above will give you some basic physics, but it is not very stable. If the forces and/or velocities get too large things will start to mess up. Also if forces suddenly change (during a collision say) then the results might not always be the desired one.

There are several ways to help increase the stability of a sim.

The first two techniques will help and are easy to implement, but they won't solve the stability problems. Weird things may still happen, but they won't be too weird. Also if friction is not correctly implemented it can lead to stability problems itself (see "jitters").

Capping the speed can be done thus:


// vx, vy are velocities in x and y directions
double MAX_SPEED;
double MAX_SPEED_SQUARED = MAX_SPEED*MAX_SPEED;
double speedSquared = vx*vx + vy*vy;
if ( speedSquared > MAX_SPEED_SQUARED ) {
	// calculate the direction vector of the velocity
	double speed = sqrt( speedSquared );
	double dx = vx/speed;
	double dy = vy/speed;
	// then adjust velocity so it has same direction
	// but is moving at max speed
	vx = dx*MAX_SPEED;
	vy = dy*MAX_SPEED;
}

Variable timesteps does some too work quite well, but requires a bit of extra work. It probably needs to be implemented from the outset.

Using a better integration method can help a lot, but a lot of the literature explaining them is often obtuse. The next most complex method after euler (what we've been using) is the mid-point method. The mid-point method basically works out what the average speed during the timestep should be and uses that value, rather than the speed at the beginning of the timestep. This has the effect of smoothing out things, reducing sudden spikes in velocity etc.



The Jitters

This is a problem I have seen many times when doing basic simulations. Object sit and "jitter", i.e. they move rapidly around one point. This is quite unnerving behaviour, particularly when the object in question is meant to be a several ton heavy tank!

In YARTS every now and then we would notice tanks wobbling when they were supposedly not moving. This did not happen all the time so initially we blamed it on the AI (sorry Matt), thinking that it was never reaching it intended target and correcting. Then it happened more often, and even when the tanks had not been moved initially at all. This was for two reasons:

The naive approach, my initial approach, was to believe that the system was underdamped. That the motion was never settling down to nothing. That friction was not high enough. However the floating units, which always had a low and constant friction, never jittered. In fact raising friction did not help at all, if anything it made things worse.

At this point it occurred to me that I was thinking too continuously. I believed that friction, as it depended solely on velocity, could not alter the direction of the velocity, only its magnitude. In a continuous world (the real world) this is true. However as YARTS uses discrete timesteps, this could not be guaranteed.

Here is a brief example:


let vx (speed)    be 10,
     f (friction) be 10,
     m (mass)     be 1.

by euler integration over time dt:

    a = -(f*vx)/m   (acceleration is friction times speed over mass)
      = -100
   vx = vx + dt*a
      = vx - 100*dt

if dt is too large (over 0.1) this will result in the velocity changing from being positive to being negative. This is obviously not correct. This is because although the acceleration caused by friction is was correct for that moment in time, it is not correct through out the rest of the timestep, leading to a potentially large error.

There are a couple of ways to deal with this.

The jitters can lead to major problems in sims. If the maximum speed of objects are not capped they can lead to positive feedback, with the net effect that an object will disappear at a million miles an hour after being lightly pushed. Not very stable or reassuring!



Further reading

http://www.d6.com/hecker/ Chris Heckers articles cover most of what you'll need to write a basic sim. The first 3 articles cover 2D, including collision response and rotational effects. The 4th article covers 3D.

http://www.nr.com/ Numerical Recipes in C. Loads of articles about lots of numerical things. Covers some different integration methods, but not directly talking in terms os position, velocity etc, so you'll need to understand what derivatives and such like are.

http://www.google.com/ Just do a search, I'm sure you will find plenty of other articles out there.