Making a simple Physics Engine: Episode 1
So work has begun on YARTS2 (Yet Another Real Time Strategy) and I am going to write the physics engine for it. Seeing as we are going to go for a more server-centric approach I do not have to worry about network effects (as much). With this is mind here are some of the things I hope to achieve:
I will try and write up what I do as I go. Hopefully it will make sense and hopefully it should help me make sure I am doing things properly. If I cannot explain it simply then it is probably not right!
I am not going to give a complete guide or how to - more of a "how I did it".
So now to start the first part...
3D position, velocity/momentum and acceleration/forces
Everything has to start somewhere, so I started with the defining a few things. In particular:
A vector has an x, y and z component. It is used to represent a point in 3D space. At its simplest I could leave it at that, but in my case I added a bunch of methods to the class I created. These are for all sorts of things, such as adding vectors, multiplying by numbers, calculating dot products etc. I will not bore you wih the details here, check out the source if you are interested.
I defined a Body as having Mass, Position and Momentum. That is it. It is a pretty minimalistic definition, but that helps keep things tidy. It also helps to minimise how much we might need to send over the network. You might be wondering where the velocity is. Well it is there, but only implicitly. It can be calculated from the mass and momentum.
Next comes integration, updating the position and momentum over time based on the forces applied to the object. It goes something like this:
// integrate forward by dt seconds
velocity = momentum/mass
next_position = position + dt*velocity
next_momentum = momentum + dt*forces
That is a simplification, but gives you an idea of how it works. One caveat to note is that completing a timestep is a 2-step process. First the next position and momentum are calculated, then once we are happy (we might want to recalculate things with a smaller timestep size) we update and make the next position and momentum the current ones instead. So a loop for integrating a bunch of objects would look something like:
// integrate all objects forward by dt seconds
for all objects
integrate( dt )
// we would calculate collisions here
for all objects
That covers the basics. At this stage I also added friction, so that things would tend to stop moving after a while. Next comes impulse forces and collisions.