There are four types of moving object in the games. Asteroids in four sizes from 35×35, 70×70, 140×140 and 280×280 pixels, the player’s ship (fits in 64 x 64 pixels), alien ships (also in 64 x 64) and a bullet which is solid 3×3 pixels with the four corners empty.
As these move around the screen at 60 frames per second, they will come into contact and the collision detection has to figure out when they hit or miss.
To make it more complicated, the asteroids and player’s ship come in 24 rotations, each by 15 degrees so detection has to take that into account. The image shows an asteroid just about to hit the player’s ship.. At the bottom you can see where another asteroid has been blown up (the 50 is the score) and there’s a bullet to the right.
The detection occurs in several stages. First each object has a bounding square. This is an invisible square that just fits round each object. For the player’s ship it’s 64 x 64 and it corresponds to the sizes of each asteroid. As the image shows, the two bounding boxes overlap and it’s in this overlap rectangle that we have to check for a possible collision.
First things first. Every frame all objects are moved and we have to detect if there’s a chance of a collision. This is done by dividing the entire playing area (set in the book to 1024 x 768) into 64 x 64 pixels cells. I chose that as a convenient size. Once the object’s new x,y location has been calculated, I determine which cells it overlaps.
The player’s ship can fit completely into one cell but most times it is either overlapping two or four cells. Even a 3 x 3 bullet will occasionally overlap two or four cells but most of the time it will fit completely in one. The largest Asteroid (280 x 280) always overlaps five or six cells in each direction so it gets added into to 25,30 or 36 cells each frame. The image shows the grid of 64 x 64 cells and the asteroid overlaps 25 cells, the player’s ship just overlaps 4 cells. The number is a count of the number of overlapping item in each cell. It’s the bounding box size that determines if it overlaps which is why the top left and bottom right empty cells of the asteroid still show 1.
In each cell, I keep a list of objects that overlap that cell. The first step is scanning all cells with overlapping objects in to see if there are two or more objects overlapping in that cell. The SDL library includes a function SDL_IntersectRect() You pass in the two bounding rectangles of overlapping objects and it returns a rectangle of the intersection, which corresponds to the overlap in the image above. If there are multiple objects in a cell e.g. four then you have to check to see if any of those (1,2), (1,3), (1,4), (2,3), (2,4), (3,4) overlap.
The next bit is what makes it pixel perfect. For every object and its rotations, I have created a mask. It’s a file of bytes with a 1 value corresponding to every coloured pixel in the object and 0 to empty pixels.
I have stretched this image to make it the same aspect ratio and it shows 0s and 1s in the player’s ship mask.
The collision detection algorithm processes the intersection rectangle and calculates where each pixel in that rectangle falls in the corresponding mask (adjusting for rotations) of each object. If either mask pixel is 0 then no collision occurs but if both are 1 then bam!
Although I could have used a mask of bits, it was quicker to use bytes.
During development I wanted to verify that it was pixel perfect, so I disabled explosions and instead when two pixels overlapped, I output a green pixel to highlight it. The image shows the player’s ship passing through an asteroid!