Problems I encountered when using a built-in physics engine, and how I fixed them.

Posted by joshyaxley on Jun 13th, 2015

In my last post, I discussed what kind of game I wanted Faerie to be. However, this isn't how I actually started making Faerie, and it actually came a few weeks after I had started the project. I began simply out of curiosity.

I knew that GameMaker: Studio (GM:S) had a physics engine. Though I had never used it, and didn't know how it worked, I wanted to find out. I opened up the documentation, loaded up a few tutorials on YouTube, and set to work. The thing I most remember is being impressed at how 'easy' using the physics system made things. All collisions were handled automatically based on the properties of each object (friction, density, etc), and all you had to do was execute impulses and forces and let the system calculate everything that happens after that. How easy this would make building any game that uses physics!

Oh, how naïve I was.

I'm not saying that the physics system isn't good, because it really is. It's based off of Box2D, an open source C++ engine developed by Erin Catto, and can let you do all sorts of wondrous things involving joints and pulleys and bridges. However, don't think that it is a one-stop solution for your game as, at least in my case, you may need to do quite a bit of work to get things to work just as you want them.

I'll give you a few examples of some things that annoyed me.

Disclaimer: I am not an expert in this system, and my knowledge of it is not complete by a long shot. There may be more elegant solutions to the problems I found, but I was very much doing a learn-as-you-go approach while coding and these are the solutions I found.

Slip-sliding

In real life, when you apply a continous force to an object, it will move faster and faster until it reaches terminal velocity. However, in a lot of games, particularly platformers, you don't want to have to have a run-up every time you want to make a jump that requires maximum speed (for example). You want to be able to pretty much instantly hit max speed when you press the control. Similarly, when you let go, you don't want to keep sliding and sliding until friction eventually brings you to a halt. If there's a pit of spikes in front of you, and you let go of the movement control, you expect not to run into the pit of spikes. This is particularly important in games that require precise movement with little room for error.

The actual solution to this is pretty simple. What I did was apply a huge force to the player character whenever Left/Right was pressed, which would cause them to accelerate very quickly and not need to have a 'run-up'. Then, I hard-coded limitations on the max speed so that the player wouldn't just keep accelerating to a ridiculous velocity:

Then, to solve the issue of sliding once Left/Right was released, I gave the player an unrealistically high amount of friction.





With and without realistic levels of friction.



Can't walk up slopes

Another issue I found was that the player would struggle to climb up a slope - sometimes being unable to climb it at all. This makes sense, as it takes more energy to climb up a slope and therefore more force. However, it doesn't make for fun playing when you slow down to half your speed every time there's a slight hill.

The issue to this was also simple in the end, and just required that an upward force was given to the player whenever they were in contact with a slope. The amount of the upward force needed to be a sweet spot between 'being able to climb the slope easily' and 'not outweighing the force of gravity so that the player flies into the air whenever they try to climb up a slope'.





With and without the helping lift force when climbing a slope.



Falling down ladders

I wanted to include ladder objects in my game that could be climbed up and down. This essentially meant that while the player was on the ladder, they needed to not be affected by gravity (which would cause them to simply fall to the ground). However, in the physics system, you simply set a gravity amount for each room, and this affects every object with physics enabled regardless of whether you want it to or not. This meant that I couldn't just 'turn off' gravity for particular objects whenever I felt like it. There are a few potential fixes for this.

The first fix would be to set the global gravity to zero, and then create my own gravity object that would control it for me. It would go through every physics object, check a boolean of that object to see if that object should be affected by gravity at that point, and, if so, apply the appropriate force. While this would be the most general solution to my problem, and would potentially provide solutions to other problems that may come up if I decide I want different objects affected by gravity in different ways, it seemed quite cumbersome to implement for what should be a small problem.

The second fix that seemed the simplest, was to simply have a boolean that told me when the player was 'attached' to a ladder, and if this was true then simply set phy_speed_x and phy_speed_y to zero. You would think this would work. You really would, but this was the result:





For some reason, despite having a definitive vertical speed of zero being set every step of the game, the player was still inching his way towards the ground pixel by pixel. I'm still not entirely sure why, though I suspect it might have something to do with either rounding errors, or the fact that the physics system does 10 calculations for every 1 step. Either way, I slapped on a band-aid fix by, instead of setting:



phy_speed_y = 0;



setting:



phy_speed_y = -0.2775;



to offset the problem. '-0.2775' is just a number that I found, from experimentation, would give me the required result. Not very professional at all, I suppose, but it gets the job done and its efficient.

A third possible fix would have been to change the player's density to zero while on a ladder. In the physics system, objects with a density of zero are essentially flagged as not being affected by gravity (slightly counter-intuitive, as an object with a density of zero would imply an infinite mass which would imply an infinite gravitational force). This would involve removing the players fixture and binding a new one to them, this time with the modified density. However, this would be less efficient than the fix that I already had in place, so it didn't seem worth the effort.

Getting stuck in walls

And now we arrive at the classic problem of two things colliding and then getting stuck together. It can happen in a number of ways and for a variety of reasons. I tried for a good 10 minutes to replicate getting stuck in a wall for this blog (after removing my fix code obviously), but I just couldn't seem to manage it. This in itself is one of the annoying aspects of this kind of bug - it depends very much on the angle, speed, and shapes of the two things colliding, that it is very difficult to replicate and hence actually know 'for sure' if you have fixed it.

I tried a lot of different solutions to fix my issues, and finally settled on one that simply moves you away from any walls you are touching. It's not completely ideal or realistic, but it prevents a game-breaking bug so unless I can think of a better working solution, I'll keep this in.

*** Sarcasm warning. ***

Besides, plenty of AAA games have bugs where you can get stuck in a wall, so maybe it's a benchmark for great things!





There are plenty more physics-related bugs that I have had to deal with, or issues that have needed to be tweaked, but there is nowhere near enough room for them here!

The main point that I'm trying to get across is that physics engines are really useful, but you might need to work around them at times if you want the physics in your game to function just as you imagine it should. I have ended up with a bit of a mish mash of Box2D physics and hard-coded physics, but I am really happy with my resulting engine, where everything (pretty much... so far) works as it should!

Maybe I would have had more success without using the physics engine at all, but I do doubt it, as it has made a lot of things easier.

Thank you for reading! If you've had any similar problems, or if you think you have better solutions to the ones I mentioned, let me know in the comments!

Feel free to follow me on your favourite social media!





I plan on having a playable demo available by the end of the month, and I'll welcome all the feedback that I can get!

Josh