How to Calculate 2D Collisions
December 27, 2021
Collision detection is one of the most important requirements for an interactive video game. There is nothing more infuriating that losing a high record to a bad wall glitch (which happens regularly in many games I’ve developed).
Back in 2016, I probably spent over 500 hours trying to figure out how to make Boxel Rebound’s collision detection feel extra smooth and polished. I tested almost every case scenario know to mankind, and yet it still had bugs. The more bugs that appeared, the more “if” statements I wrote to handle unwanted physics. Eventually, the game felt nearly perfect, but I was still not satisfied with occasional glitches.
After millions of downloads, and positive feedback, I decided to make a new game called Boxel 3D. At the time, I was really excited to forget about 2D collisions, and rely on physics libraries to calculate complex collisions. I used a library called matter.js, and immediately fell in love with it. With matter.js, everything has physical properties, which unleashed a sandbox of gameplay options for me to pick from. I was able to easily add gravity switchers, web slingers, shape-shifters etc. Everything worked perfectly… on my gaming PC. After watching a bunch of Boxel 3D videos online, I quickly realized this library is incredibly expensive on CPU, so low-end computers suffered to render in real-time.
I recently decided to revisit collision detection from scratch since Boxel Rebound had complicated collisions, and Boxel 3D ran poorly on most computers. I took an entire week off from work to dedicate time towards this new pet project, and finally derived a solution that fits my needs perfectly. My code is comprehensive and minimal, and includes nearly no “if” conditions, and I’d like to show you how I did it below.
This small guide won’t cover the code details, but it should help spark solutions for your own problems. The first step is simple: map everything to a single grid (or 2D matrix).
I learned this trick when I first started working on Boxel Rebound. Before I learned how to map indexable data, I would loop through each point, and make assumptions based on relative data. Properly mapping data will save processing time and logic.
After setting up your world, it’s time to calculate collisions between multiple objects. Rather than comparing multiple collision points, it is easier (and produces better results) to just average their coordinates for a single calculation.
The last trick is to perform calculations for more precise results. This is interpolation; the process of inserting “checks” between 2 points. This is very important for calculating fast velocity, or for compensating lag for slow computers. For instance, if your character was flying at a wall at 100mph, you would expect to splat against it violently. Without interpolation, you would likely pass through the wall without ever noticing it. Interpolation allows us to check collisions between points, and respond with meaningful information.
Thank you for reading about my latest obsession. I had a lot of fun writing this code over the last week, and I look forward to testing it out on my new game (I’ll share more about it soon). If you have questions or need help on your own project, please message me on Twitter, and I’ll see if I can help.