#12 Pressure Buttons & Physics Fun
Welcome to the twelfth devlog!
The main attraction of level 1 is a huge crane, holding a platform hanging from a rope/chain. You can jump into the platform to move to places you otherwise can’t reach. (You do need to ask another player to stand on the button that makes it rotate.) If you’re very skilled, you can even throw packages into the platform as it swings by, or jump off the platform to other zones.
Today I want to talk about how I implemented these things. (Because I think it’s very interesting, and I will re-use many code/mechanics in later levels.)
Many, many games feature pressure buttons: a button that activates when a player is standing on top of it. When the player moves way, the button moves upward again (usually over a short period of time), until it’s deactivated.
I call it a pressure button, because it reacts to the pressure that is put on it (by the player or by placing something else on the button).
NOTE: You also have games where you press the button by standing next to it and literally pressing a button on your controller. Or buttons that you “press” by rotating something. But so far, I haven’t found a good use for those in my game.
For YEARS I’ve searched for a performant, consistent way to create these buttons.
- The button needs to realistically react to physics. Something that’s heavy will push it down faster. Something that hits it from the side should NOT push it down, et cetera.
- But the button can only move in one direction, and should provide enough “inverse pressure” => if nobody is standing on it, or you place something on the button that is too lightweight, the pressure should automatically go up and deactivate.
You don’t want players to accidentally hit the button from the side, causing it to fly all over the level or something.
First, I thought I could just make the button a RigidBody, and make movement fixed to one direction. I could do this with a SlideJoint (which does exactly what you think it does => it allows something to slide only in a certain direction/way), or by checking the option in the editor that limits movement to a single axis.
So I implemented this … and it worked horribly. It was glitchy, the button did NOT move up automatically (or in any desirable way), and ten of these buttons put a strain on the physics engine.
Then a lightbulb went off in my head: what if we simply trick the physics system … by moving a StaticBody?
I made the button a StaticBody, which, as the name implies, is meant for objects that do NOT move. But, for some reason, Godot allows you to move it and the physics (so far) respond realistically.
I placed an Area on top of the button, which checks for other bodies within a certain area. This way, I knew if something was standing on top of the button and I could even get the pressure that object exerts (because I had access to the object’s mass and gravity).
The actual code was simple:
- Is something applying pressure? Move the button down. If the button is as low as it can go, it turns green and activates whatever it should activate.
- Is nothing applying pressure? Move the button up. If the button is as high as it can go, turn red and deactivate.
As I implemented this … I realized I didn’t need very precise pressure calculations. So I threw my other ideas out the window, and decided that anything pressing the button was enough to make it go down.
And so far, that has worked wonders. (The pressure button is in the lower right, player 2 jumps on it after a few seconds.)
NOTE: You might have noticed that the button design changed along the way. During my playtesting, I noticed that it was very hard to stand on the button, which became REALLY frustrating as the level progressed. The button also had a weird size, which made it fade into the background – I want it to grab attention, because it’s important that players try pushing this button! So I made it bigger and brighter in … well … all possible ways.
Connecting button and crane
I know that the game will eventually have a load of “interactive objects” that can activate/deactivate something. So I wrote a small system that allows me to select a Node ( = object within the level) and a specific function on that Node, right from the editor.
(There’s not much else to say about it, really. Whenever something happens on the button, it looks up those variables that I set manually, and calls the right function on the right object.)
What is interesting, is something I learned that I never thought about before: different ways of activation.
- A pressure button is what I call “one-way activation”. It either activates something, or deactivates it. It cannot, for example, set three different states on the crane: off, clockwise rotation, counterclockwise rotation.
- A seesaw is a good fit for “two-way activation”. If the left side of the seesaw is down, an elevator goes down. If the right side is down, the elevator goes up. I’ve found this to be very intuitive and fun to interact with.
- A wheel can do “n-way activation”. Rotating the wheel to a different angle, sets a different state on another object. (Think of a platform that can be at one of four different heights. Rotating the wheel to point upwards sets the first height, pointing right sets the second height, etc.)
It’s no rocket science, I just never considered it. Now that I know this, I can be more creative when designing levels, while at the same time optimizing the “intuitiveness” of the interactive objects.
A platform, hanging from a rope
Creating a platform that hangs from a rope, which hangs from a crane that can rotate, seemed like a daunting task.
Luckily, I had used Godot’s joint system before, albeit in 2D (to create a hanging bridge that swings up/down as you run over it).
I had the following plan, and (spoiler alert) it worked the first time:
- There’s something called a “PinJoint”. It pins two bodies to each other, at the exact location of the PinJoint. You’ll see where this going: the rotating arm of the crane is pinned to the static support, the first part of the rope is pinned to the rotating arm, and this system continues until the last rope bit connects to the platform.
- Because there’s only a single rope keeping up the platform, I knew I needed some stabilization. As such, the platform has a small bit of code that corrects its angular velocity, so that it’s stable enough to walk on (or put packages on without them falling off)
- Then I played a bit with the weight of the platform. Making it heavier was realistic and more stable, but the rope was being stretched thin. As I said before: this part is just parameter tweaking until it works. I made the PinJoints adhere more strictly to their rules (I allowed less of a “margin of error”), while at the same time damping any impulses, to keep the rope from swinging all over the place.
- Lastly I changed the weight of the rotating arm – which should have been the first thing I did. By making it heavier, I could make it start/stop almost immediately after you’ve pressed the button. (When it was still unrealistically light, it took a good second for it to “fade out” the rotation. Why? Because the platform was much heavier, and it dragged the rest of the crane with it.)
As I write this, there’s still some tweaking to do: for example, once the platform starts rotating, it somehow never stops. I can fix this by increasing the damping factor on the angular velocity, either via the engine itself or via custom code. But there’s no priority for this, because the level is already quite playable with the bouncy and rotaty platform :p (It even has a silly effect to it, especially when someone mistimes their jump and misses the platform by a hair.)
In the future, I plan to use a similar system for many mechanics:
- An elevator hanging from a rope.
- A swinging bridge (like the one I already made in 3D)
- A “lasso” you can throw at stuff. (Either to pull them towards you, or to swing from the trees or something. Still need to work that bit out.)
Rope mechanics are just very fun and fit well in this game.
I’ve written most of these devlogs “out of sync” with the game development, which means that I’m writing this conclusion a few weeks after I wrote the rest of this devlog. And I can say that the bounciness/unpredictability of the platform has been fixed!
I had to make a dedicated model for the platform anyway (the one I used before was outdated and the wrong scale), so I decided to make it slightly larger and push it a bit higher. This makes it easier to get on/off the platform, reduces the amount of collisions between the platform and the terrain, and looks better in general.
(What’s interesting, is that I solved all these problems without tweaking the physics parameters. The lesson here: sometimes you just need to re-do something in a different way, instead of fiddling with physics settings!)
Next devlog, I’ll talk about those zones you’ve been seeing in the footage (where you pick up and drop packages).
Get Package Party
Leave a comment
Log in with itch.io to leave a comment.