This is an engine for a 2-d platforming game. It includes:
The other part of the physics system applies forces such as gravity and friction at the end of each time step, and updates their velocities accordingly. One part of this is worth mentioning: to simulate a unit walking, I imagine that the unit's lower surface consists of tank tread which moves at a velocity relative to the ground. Friction with the ground then propels the unit forward. The interesting part is that in order to make units accelerate rapidly when walking yet take high, relatively slow jumps, as in Mario and similar games, the friction has to be a value greater than one (currently 3.8). If the friction was a physically realistic value less than one, units would not be able to accelerate horizontally (when walking) as fast as they accelerate vertically (when jumping/falling).
Lua is a language that could have served a similar purpose.
Due to the incomplete status of this project, I do not recommend that you use it, but if you want to I am releasing it under the GPLv3. Instructions for compiling lie in the README file.
Physics Engine
The core of the physics engine is an impulse-based collision system. Most collision systems (such as Box2D) step every object forward according to its velocity, then check if any pair of objects intersect. This sometimes causes glitches where an object can get "stuck" in another object, especially if one of the objects is moving very fast. Also, it has trouble when many objects are stacked on top of each other--the result is frequently more of a "spring" than a solid stack. My collision system attempts to predict exact collision time and position without waiting for intersection. To evaluate a single time step, I follow this rough plan:- I divide the screen up by a checkerboard pattern, or a board (currently each square on the board is 50 pixels on a side). Each square holds a list of every object that could possibly touch that square in the remainder of the time step, in the absence of collisions. Thus, if two objects are going to collide, there must be a square in which both objects are listed. As units collide and change direction this board must be updated. The board allows me to avoid the O(n^2) overhead of checking collisions between every pair of objects.
- Using the board, I obtain a list of possible collisions and the exact times at which those collisions could happen. Not all of these collisions will actually happen, however. If I have a potential collision between A and B, and another potential collision between B and C, only the collision that occurs earliest in time is going to be valid; since the position and velocity of B will have changed after the first collision, the later collision will be invalid.
- For each object, I maintain a local time, set to 0 initially. While there are still any potential collisions, I:
- find the earliest of those collisions and update the positions and velocities of the two objects in the collision,
- set the local time of both of those objects to the time of the collision,
- invalidate (remove from my list) any collisions on my list that would have involved either of those two objects, and
- recalculate potential future collisions for those two objects and add them back to the list.
- Now that the list is empty, there are no more collisions in this time step, so I move each unit a distance according to its velocity and the remainder of the time it has left (the length of the time step minus the object's local time).
The other part of the physics system applies forces such as gravity and friction at the end of each time step, and updates their velocities accordingly. One part of this is worth mentioning: to simulate a unit walking, I imagine that the unit's lower surface consists of tank tread which moves at a velocity relative to the ground. Friction with the ground then propels the unit forward. The interesting part is that in order to make units accelerate rapidly when walking yet take high, relatively slow jumps, as in Mario and similar games, the friction has to be a value greater than one (currently 3.8). If the friction was a physically realistic value less than one, units would not be able to accelerate horizontally (when walking) as fast as they accelerate vertically (when jumping/falling).
Unit Event Handling
Every unit has a state machine. On every time step, the unit receives signals such as "your lower surface contacts the ground" or "the user is holding the right arrow key." Based on the current state of a unit and on the signals received, the unit may move to a different state and/or perform some action such as applying force to itself or another unit, engaging its walking tread, or changing the size of its bounding box. I associate each state with a frame to be displayed.Scripting Language
I have incorporated my config file parser scripting language, which I wrote for inclusion in this game. This language allows me to concisely specify new units without writing a lot of hard-to-maintain C code (or even recompiling). This is the code to specify the behavior of the robotic-looking character that you control in load_test.c. Specifying a new unit involves loading the bitmaps into frames for the different states of the unit, providing any special actions that a unit takes upon entering a state, and wiring up the transitions of the state machine. Note that even though walking left involves 14 different states, I can use loops and variables to handle them concisely (an advantage over the typical config file).Lua is a language that could have served a similar purpose.
Graphics
The graphics and user input are based around SDL, so the engine should be portable to other systems. Note, however, that I have only tested it on Mac OS X. Some of the bitmaps I use come from http://panelmonkey.org/.Due to the incomplete status of this project, I do not recommend that you use it, but if you want to I am releasing it under the GPLv3. Instructions for compiling lie in the README file.
© Bart Parkis
Last modified:Tue May 19 19:07:53 2009