Update: A previous bug in this modified engine file has been resolved. The updated platform.c file is live on our itch page (link at the end of this article).
Back in 1985, Super Mario Bros on the NES jumped into the hands of gamers across the world and changed the platforming genre forever. Above all else, the two designers of the game, Shigeru Miyamoto and Tekashi Tezuka, knew that making Mario feel responsive and fair would be critical to the success of the title. It’s obvious to any player when they first begin 1-1 that Mario’s acceleration and deceleration give a great sense of inertia, something that would be constantly reiterated upon as the series continued, but there were some hidden programming tricks that are not quite as apparent to the casual gamer, but are just as revolutionary. In this article, we will not only explore some ways to improve how a platformer player character feels but also share a modified platformer.c file, for use in your very own GB Studio Platformer games!
MODIFYING THE PLATFORMER ENGINE
Before we get into the details, let’s first cover how to make changes to the platformer engine in GB Studio. For those that aren’t familiar, we can gain access to all the “behind the scenes” source code by ejecting the GB Studio engine within our project. To do this:
- Open your project
- Click on Game > Advanced > Eject Engine
The source files can now be found within your projects directory (under assets/engine) and can be freely edited at this point. Specifically, we will be looking at modifications to platformer.c (found in assets/engine/src/states), the file that handles any platformer scene within your project. While you are free to edit this file as you see fit, you can find a link to a modified platformer.c file with all the changes mentioned within this article below.
First up, let’s go over the easiest modification to the GBS platformer engine. By default, platformer.c tells the player to decelerate when a D-pad button is released only when the player is grounded (walking or running while on a platform). But what about when in mid-air? At this stage, if we were to release the D-pad while in the air, the horizontal velocity of the player would stay constant and only change if we were to either land on a platform or press the opposite direction on the D-pad. It might seem like a small detail, but the effect on how the game feels is quite pronounced and makes precision platforming while jumping quite finicky and chaotic from instant to instant.
Looking at the two variants to mid-air behavior above, you can imagine that the added control in the modified platformer engine would make it easier for the player to carry out more precise maneuvers during game play. With that in mind, let’s make a change to the platfomer.c file.
Line 137 to 153 in platformer.c describes how the player character behaves when the left D-pad button (INPUT_LEFT) or the right D-pad button (INPUT_RIGHT) is pressed. That is, the player starts moving according to the various parameters chosen by you in your project’s platformer settings.
From line 154, the code is describing what the player character should do if the left or right D-pad buttons are not pressed and the player character is still moving and the player is grounded. In other words, if the player character’s velocity (pl_vel_x) is not 0, and the player is currently on a platform, then start applying deceleration (plat_dec). All we need to do then, is delete if (grounded) on line 154. Then this deceleration will be applied regardless of whether the player is grounded or not.
Now we have mid-air movement that feels much more like Mario! By setting acceleration and deceleration relatively high, you can also create a platformer that feels as responsive as Mega Man too.
Imagine this… you’re playing a fun platformer game in front of all of your friends. Before you is an incredibly large pit which, if you fall into it, equals instant death! You psych yourself up, commit to the run up and press jump at the very last moment, just so you can make the distance… but you don’t jump… you just run off the ledge and die an embarrassing death… and everyone starts laughing at you. You could have sworn you pressed jump before you ran off the ledge! There is only one thing left to do… RAGE!
This was a regular occurrence in many platformers before Super Mario Bros. Thankfully, it all changed with something called Coyote Time!
Named after the Looney Tunes character Wile E. Coyote, this little trick of programming allows the player to still jump for a small amount of time after they fall off a ledge. Could be 1 frame, could be 60 frames (just look at Donkey Kong Country’s huge amount of coyote time to see an extreme example). The point is, that infuriating moment when you fall into a massive pit because you happened to press the jump button a 60th of a second too late is finally a thing of the past. Seriously, coyote time is the best thing to happen to platformers since jumping.
There is a lot going on here code wise, so for the sake of keeping this article brief, let’s simply go over how to edit the modified platformer.c file so that you can choose how much coyote time suits your own game.
Head to line 237 and change [ct_val] to a value of your choice. That value is equal to the number frames the player can still jump after the player character has fallen off a ledge. It’s as simple as that.
On the other side of the coin, what happens if you’re sprinting through a platformer level at breakneck pace and you happen to press the jump button a couple of frames before you land on a platform, hoping to immediately jump again? Well, much like the poorly timed jump as described above, nothing will happen. You will land, and then just keep running – maybe off a ledge or perhaps straight into an enemy. Wouldn’t feel any good at all, that’s for sure.
The addition of jump buffering stores that input for a small window of time and then executes it when possible. In this case, the player would accidentally press the jump button a few frames too early, the player character would land on a platform and then execute a jump – even though they weren’t technically grounded when the button was pressed.
Head to line 305 and change [jb_val] to a value of your choice. That value is equal to the number of frames a jump input can be stored before the player character lands on a platform.
Yes, it’s true that these tricks of programming are a way of fixing errors in player judgment, picking up the slack of poorly timed button inputs. It would be all too easy to just tell the player to just “Get Good!” But at the same time, removing instances where a player might have a bad time because they were a few frames off an accurate input means that overall, the player will have a much more enjoyable time when playing games – and we as developers, ultimately want the players to do just that!
Thank you to Rulz for helping me with the Mid-Air Deceleration modification and a massive thank you to Byucknah for not only all their work on the Coyote Time and Jump Buffering modification but also freely sharing it with the community!
You can find the modified platformer.c file here. Simply eject your project’s engine and replace this file with the default platformer.c file.