XaiJu
Kevin Cole
Kevin Cole

patreon


How SuperTry Does Game Physics

Hey everybody,

We’re talking about game physics today! For the purpose of this blog, “physics” just refers to how objects move and smack into each other. This hopefully won’t be too complicated.

One of the things that stumped me when I first started making games was physics. GameMaker 1’s default physics engine in the early 2010s was pretty quirky and I could never get things to work quite how I wanted. Characters would get stuck in walls a lot and I wouldn’t know why.

The most annoying thing about it was that I had no idea how GameMaker's physics engine worked. I couldn’t look at GameMaker’s internal code to figure out how to debug it. Instead I went around looking at tutorials and other folks’ code and I gradually figured out my preferred way of doing things.

So I’m going to walk you through the basics of my physics code that I use in nearly every SuperTry game. This isn’t the best, most efficient, most genius system ever devised, it’s just a system that is relatively easy for a person to understand and it rarely breaks in a catastrophic way.

Pixel by Pixel

What we want out of our physics engine is for it to move an object if its path is unobstructed and for it stop moving the object if the path is obstructed. If the path is obstructed we want the object to end its movement right next to the obstruction.

Here’s a really bad physics engine: Check for a collision with obj_wall at x+xspeed and y+yspeed. If there’s no collision, move there!

This bad physics engine technically does what we want, it moves something without colliding it with a wall, but there are a lot of scenarios where it messes up.

Say we’re making a platformer and our player-character is falling down toward a wall. If their speed is 4 pixels per frame and the wall is 3 pixels below them, then they’ll stop and hover 3 pixels above the wall. Not what we want!

We need a more precise method so we’re going to move one pixel at a time. For each pixel step we’ll check for an oncoming collision with obj_wall. If there is a collision, we’ll stop moving and set our speed to 0. If there isn’t an oncoming collision we’ll keep moving ahead until we find one or we move our full speed.

Sparing you the gory details of the code, that’s basically it. Just do a bunch of checks.

Slow Movement

I said before that we only move one pixel at a time in this system. What happens to slow objects that are moving at like 0.5 pixels per frame? We want those to move too!

Each time I run the physics code I grab the decimal value for each speed variable and throw it in a bucket. When the accumulated decimals in our bucket are greater than or equal to 1 or less than or equal to -1, that object gets to move an extra pixel.

So in our first frame our slow object has a speed of 0.5 pixels per frame, so we put .5 pixels in our bucket and the object moves 0 pixels.

In the next frame our slow object still has a speed of 0.5 pixels but that combines with the other 0.5 pixels in our bucket to make 1! Our slow object gets to move 1 pixel and we have an empty bucket.

You can also add this bucketed variable to your object’s x and y coordinates when you draw the object so its movement looks smoother.

Performance

One issue with this system is that it ends up checking collisions a lot which can impact performance and make your game run slow if you aren’t careful. Fast moving objects require more collision checks every step which can eat your framerate if you aren't careful.

However, the impact is lessened the smaller your game resolution is and the chunkier your pixels are. With a chunky style, moving two whole pixels every frame at 60 frames per second feels pretty fast! I find making games in low resolution to be much easier anyway so this works well for pretty much any SuperTry game.

You also don’t need to run that full physics code on every object. Remember that “bad” physics engine? If you check for a collision at the final destination for your object and there is none, you can *probably* just move there, skipping that pixel-by-pixel check. And if there is a collision, you just run the pixel-by-pixel check as normal. That can save a lot of time!

Culling objects that aren’t currently visible on camera is another way to save your performance too!

So that’s basically the SuperTry physics engine. I’d be down to release the GameMaker 1.4 source code if there’s interest and anyone wants to take a closer look!

Again, this isn’t advanced, optimized stuff. It’s simple basic stuff so when a bug does pop up, it’s easier to run through the code in your head and figure out what’s going wrong.

Hope this helped you out or was at least a little interesting!

Thanks for reading.

KC

Comments

I need more KevTalks in my life <3

Greg and his Gregorian Chanting Army of Metal Monks Pledge Their Shred to Kevin

*takes notes*

Medusa Ann Mizikow


More Creators