The core concept behind co.llide is for players to be able to build and then pilot their own customized, physically simulated spaceships. This means that when a player stitches together a bunch of pieces into a ship, the game needs to figure out how that ship should move depending on player input. Ours is certainly not the first game to ever address this problem, but we thought an explanation of our specific solution would make an interesting post. But why just tell when I can show?
Note that the graphics you see in the demo are not the same graphics that we use in the game. Instead you are looking at debug rendering that we use to see what’s going on inside our game’s physics simulation while developing.
What’s in a Ship?
From looking at the demo, you may notice that each ship is comprised of two things: solid collision shapes (rectangles), and thrusters (triangles).
The rectangles define the actual shape of the ship to be used in determining how the ship collides with other objects in the scene. The actual shape is comprised of a bunch of tiny rectangles, which we lump together into larger shapes for optimization. If you crash into the walls at high speed (which I highly recommend because it looks cool), you can see the shape change as some of the tiny rectangles break away.
Thrusters allow the ship to move by creating forces at specific points on the ship. You may notice that there are two different colors of thruster: white and green. The green thrusters are “magic” base thrusters. In addition to being indestructible, these base thrusters have some special properties that I will talk about in a later post.
Flying the Ship
When a thruster fires, we apply a force to the ship at the corresponding position and angle. Using a physics engine, (in our case, Box2DWeb), makes this part easy. Like magic, the simulation applies the correct linear and angular acceleration to the ship’s rigidbody, integrates the velocities and positions, and handles collisions.
The much trickier part of the problem is deciding which thrusters should fire based on the player’s input. What is the player trying to do? What is the player probably not trying to do? How do we maximize the former and minimize the latter, given that certain motions might be completely impossible with a specific ship’s shape and thruster loadout?
Our game is heavily inspired by other physics-driven space shooters, particularly Captain Forever. Therefore, our first attempt in solving the movement problem was to mimic the same control scheme as Captain Forever, allowing the player to move forward or backward, rotate, and strafe using the W, A, S, D, Q, and E keys. I could go into the details of precisely how this is done, or I could just point the reader to this really excellent article on moving 2D ships from thrusters, which explains exactly the process that we used.
Something More to the Point
Overall the Captain Forever scheme works well and is pretty easy to implement. However, we wanted to try something a bit different to make it easier for players to steer and aim at opponents. At the moment we are experimenting with the control scheme shown in the demo. This scheme allows the player to steer the ship by using the mouse pointer to specify the exact direction that the ship should face. Simultaneously, the player must be able to move and strafe relative to the ship’s current facing using the WASD keys.
This becomes an even more complex problem. We are no longer interested in just turning the ship clockwise or counterclockwise as in the previous example, but instead want to reach and stop at a specific orientation, all while doing our best to match the ship’s linear motion with the player’s inputs.
If you’re curious about all the nitty gritty details behind how we do this, as well as those mysterious “Thruster AI Weight” values that you can tweak in the demo, then stay tuned. In part II, I’ll be walking through some of the demo code and explaining the math behind the madness.