eieio.games

by nolen royalty

Game 3: Don't Send Me a Puddle (Ludum Dare 53)

A physics puzzle about taking ice down a mountain

May 5, 2023

Basics

1

Alright I did a two-hour game jam and made a relaxing drive but that doesn’t really count.

Gameplay video

If I showed any more you'd get spoiled!

High level thoughts

Doing my first game jam was a blast! I’m proud of my game and its music and I was pleasantly surprised at how fun the feedback period for Ludum is. It’s great to give and receive feedback in a context where we’re all celebrating having built something. The vibes are good. If you’re on the fence about participating in a future jam I’d strongly encourage you to jump in.

I’m going to go into some more detail about my development process and then I’ll write about the lessons that I’m taking away.

Building “Don’t Send me a Puddle”

Picking an idea

I discarded ideas around mail and pizza delivery for being too obvious 2, considered a few alternate definitions - “set free” was tempting - and pretty quickly settled on the idea of “physics puzzle about getting something down a mountain” 3. I pictured the player manuevering a package down a mountain by raising and lowering a zipline. The game would focus on quick and precise mouse movements where you might make a big slope on one side of the screen, get some momentum, and then snap your mouse to the other side of the screen to catch the package before it hit an obstacle.

2

I don’t think this was a mistake, but I did see plenty of games that used these themes in creative ways - like juggle mail, which is a delight.

3

I was on the way to a 100 gecs when the theme was announced so I got to do this thinking during downtime at the show - which was honestly pretty great.

I wasn’t sure whether I could make challenges that were that difficult with this system and so I thought it’d be useful to add some time pressure - the goal wouldn’t be to complete the challenges but to complete them quickly. That’s where the “ice bucket” mechanic came from - it was the first way I could think to justify time pressure.

Prototype 1: hacking till 5:00 AM

When I got home I started prototyping a “moveable zipline with a thing on top of it.” I’ve built very little physics-type stuff in Godot 4 so I googled around and found this ShaggyDev video about creating rigid and static bodies from a collection of points.

4

This was part of the appeal of building this game during the jam for me!

I got to something that almost worked pretty quickly by adding a point to my “zipline” that tracked the mouse’s position (with some ‘maximum stretch factor’) and plopping a kinematic body that moved straight down at a fixed rate on it. Originally I figured you should be able to ‘release’ the zipline, causing it to snap back to its original orientation and flinging the bucket. That…didn’t work as well.

this went from exciting to dispiriting fast

The problems I ran into are familiar from platris - the only way I could think to snap my zipline back to its original shape was by moving the mouse-dragged point back to its original position. But that movement wasn’t driven by Godot’s physics engine (because I didn’t know how) - so the zipline could easily clip through the object on top of it. To deal with that I added an additional point on the zipline that passed through the object on top of it. This…worked, but ends up making something that looks awkward and plays poorly 5.

5

I realize now that the right way to approach this is likely via joints - Godot has a built in node for “a joint that can stretch out but tries to snap back to its original orientation!” But I had no idea that joints existed at the time.

At around 5 AM, discouraged, I realized I could get rid of this idea of “snapping” and just have the zipline always track the mouse. I figured I’d start on that in the morning.

Prototype 2: “well, it’s a videogame”

Removing zipline ‘snapping’ made it much easier to come up with something reasonable-looking: I hacked together a system where the zipline would always stick to some fixed ‘towers’ across the screen, always stick to the mouse, and always pass through the bucket. To simulate the bucket having some weight, it’d pull the zipline down some - exactly how much depending on how close nearby towers and the mouse were.

prototype 2 was playable but felt...bad.

I committed this code with the message “well, it’s a videogame” and that sums it up pretty well - this technically worked - the game was playable - but it felt bad and awkward and it wasn’t clear to me how to make it better.

The awkwardness came from how I handled tracking the zipline with the mouse and so, after wavering for an hour or so, I made the hard decision to bail and started brainstorming ways to get rid of the mouse. I quickly hit on the idea of attaching the zipline to fixed points, and around two hours later I had a prototype.

this instantly felt better than what I had before.

This was obviously still awkward! But that awkwardness felt tractable and I could feel myself getting excited again - there was a game here. I went to bed confident that I had an idea worth pursuing.

Prototype 3: Joint Resolution

At this point my prototype had two problems:

  1. The hand-rolled in an hour physics felt and looked bad.
  2. The bottom of the bucket could collide with the zipline and block all progress.

The left bucket stops because it collides with the zipline. The right one...does not look like an object experiencing 'gravity.'

I kept experiencing (2) while playtesting and it felt so bad that I knew I needed to resolve it. I wanted to change the collision of just the bottom of the bucket while keeping it attached to the top of the bucket (which needs to collide with the zipline so that it slides down it). After an hour of frantically googling “Godot 3 kinematic body two different collision masks” I saw someone mention “joints” - a way of connecting two different physics bodies. I immediately realized that joints were probably what I needed and, after a short break for a class, sat down to hack joints into the game.

Using a joint ended up indirectly solving both of my problems - it gave me a method of connecting two different physics bodies so that I didn’t need to make a single body with multiple properties. And it forced me to use “rigid bodies” (bodies controlled by Godot’s physics engine) instead of the “kinematic bodies” (bodies controlled by your code) - which immediately looked more natural.

the first point at which the game felt good.

It’s crazy to me how the game felt nothing like the final product for the first 36 or so hours and then suddenly snapped into place with the introduction of joints. But I guess that’s how these things go.

Making an actual game

The final 24 hours involved a whole lot less change. Learning from platris, I sat down and planned out the functionality I thought I should and could add before the end of the jam and then got to work adding it.

this counts as organized for me

Most of this was pretty straightforward wiring up of the game - adding buttons and transitions and fixing boring bugs. A few things stand out:

  1. I had a bizarre bug where the bucket would clip through the zipline
  2. I had to design a bunch of levels
  3. I wrote background music

??????

I have given up on understanding the bug. The internet tells me that there are different systems for collision detection in Godot but none of them appear to fix the issue. Instead of trying to do the ‘right’ thing I just detect when the bucket has started to clip through the string and push it back up until it isn’t clipping anymore. Whatever.

I found it difficult to sit down and design levels on command - partially because the tools I had were relatively limited and partially because it’s hard to be creative on command! The process I settled on was to step away from my desk and try to think of things that the player would be excited to do - like “jump over some flame” or “launch yourself into a crevice” and then try to backfill a level from that.

As for music: if you have any interest in making music for your games I implore you to give it a try. It’s super fun and a great break from coding - and modern tools make it surprisingly simple. On the off chance you are a piano player who has not made electronic music before (like I was until last week), here was my entire process: open garage band, pick a chord progression I like (6-5-4), record myself arpeggiating that chord, record myself noodling over the chord until I found something I liked, add bass my playing the roots of the chords, and click “add drummer track.” That’s it! You can do it too!

Takeaways

The story of the first half of this game jam for me was “learning about built-in physics stuff” - I slowly migrated from a totally hand-rolled shitty physics system to something that mostly just relied on what was built into Godot. Ironically, with the knowledge that I have now I might have been able to make my earlier prototypes work - which could have resulted in a worse game!

Learning new moderately complicated things during a jam is hard - with limited time it feels super expensive to spend 30 minutes just reading. But I typically found skimming things and sprinting back to my code to ultimately take more time since I’d make so many mistakes.

It was also hard to jam in a world that was pretty unfamiliar to me. I bet a more experienced game programmer would have come up with “using joints” pretty quickly even if they weren’t familiar with Godot specifically. There’s a problem of unknown unknowns here; I didn’t even know what vocabulary I needed to use in order to solve my problem.

It’s tempting, based on that, to say something like “only do game jams in areas that you’re already famliliar with.” And that might be ok advice if your goal is to win. But I think it’s definitely the wrong advice if you’re looking to improve as a game developer! Throwing out several prototypes was frustrating but it taught me so much - and having a deadline encouraged me to get up to speed on physics quickly.

Doing Ludum Dare #53 was great - I’m looking forward to my next jam already, and I’m excited to see where “Don’t Send Me a Puddle” ends up getting ranked!

Thanks for reading!

Keep up with me on my socials 👆

Or sub to my newsletter here! 👇