a peek into the kitchen


This is the most graphically-polished game I’ve made in puzzlescript to date, and I want to write a bit about the process of adding that polish.

(This post won’t have any level solution spoilers.)

01 Prototype

Here’s the initial prototype I sent out to the fine folks who made the guest levels:

Not much flair to it, clearly.

02 Jam Submission

Later, I added a bit of non-default color:

Here’s what the game looked like by the time the jam ended:

Looking decent!

03 Tools

I decided to spend some time making the butter do a little bounce when it hits an obstacle:

Animations like this in puzzlescript are a huge hassle, but after I’d added them, suddenly the game felt way more fun to just noodle around in. I knew things were heading in a good direction.

This is a good time to talk about tools: vanilla puzzlescript doesn’t have mouse support, so I was already using a fork (a custom version / custom extension) called PuzzleScriptPlus that adds mouse support and some other nice features.

At this point, I started to use my aseprite extension that lets you easily extract puzzlescript tiles from an Aseprite file. This was very helpful for managing the many slightly-different butter animation tiles. (I don’t have an in-progress spritesheet saved, but I’ll show off the final spritesheet later.)

04 Polish

The game is finally done! That butter animation code was pretty tricky…

I sent out this build to some gamedev friends and got some great feedback on the difficulty curve. (many more than just the two playtesters credited on the itch page – those two in particular were more intense watch-them-play-the-entire-game-and-think-out-loud type of playtests. to the others who playtested and might be reading this: thank you!!)

I wasn’t quite happy with the bread sprite, but I didn’t know what to do about it and it had sort of faded into familiarity, so it didn’t bother me anymore. When my playtesters brought it up, I said something like “yeah I don’t love it but it’s the best I’ve got. I thought about something like this instead but it really doesn’t work…”

Puzzlescript uses 5x5 sprites, and I didn’t expect to be able to make anything much better than the dark-brown lumps from the jam submission… but then Geegaz whipped up these BEAUTIFUL 5x5 bread loaves (very very similar to the ones you see in the finished game) and I knew I had a LOT more work to do. I spent some time drawing mockups, trying to fit them into the game as it was, but it was clear to me that the rest of the game needed to be slightly 3D as well for it to work:

05 Crisis

But the animation code was already realllly hairy, and trying to make the butter 5x6 instead of 5x5 (for the slight 3D effect) AND animated seemed daunting. The animation code was already exploding combinatorically, and I wasn’t sure how to proceed while still feeling confident that the code would be editable afterward when something was inevitably wrong and needed fixing.

Then I remembered Menderbug’s psuedo-3D puzzlescript fork – it’s an elegant little change, allowing the sprites to be different sizes than the grid cells they’re contained in. This let me make 5x6 butter sprites easily – instead of splitting each sprite into two 5x5 puzzlescript sprites with complicated rules keeping them moving and animating in sync, I simply used 5x6 sprites. Brilliant! The animation code was still gross, and even worse now that the butter had a slight 3D shadow at the bottom, ruining a shortcut I was using previously… but I got it done.

One small issue: I was now using two separate forks of puzzlescript. There’s no easy way to combine them and get the features of both. I knew I wanted a level select screen (not available in the pseduo-3D fork), so I dug into the PuzzleScriptPlus source code and hacked in the code from the pseudo-3D fork. This was its own annoying adventure (puzzlescriptplus has an optimization where every sprite gets rendered into a cell on a spritesheet, which meant I had to make a lot of custom edits to allow for arbitrary-sized sprites). This is the main reason I haven’t released the full source code to this game – it only runs in my custom hacked-together puzzlescript franken-fork.

Looking back, it would be nice if sprites could be arbitrarily wide as well as arbitrarily tall… that probably would have solved the remaining visual bugs without requiring any hard-to-read, combinatorically-explosive puzzlescript code.

06 Final_Final_FeedbackEdits_Final_Real2.docx

Two final screenshots:

See if you can spot the differences! There are four, by my count:

07 A Taste of Code 🥄

The code for the butter is pretty large, but it’s conceptually not too bad:

(although, it does look particularly gnarly with word-wrapping on…)

(butter z0 - unique sprite for each URDL combination. a lot are very very similar)
[butter_z0_a0] -> []
[butter no butter_z0_aany no gluedown no glueup no glueright no glueleft] -> [butter                                                butter_z0_0000]
[butter no butter_z0_aany no gluedown no glueup no glueright    glueleft] -> [butter                                       glueleft butter_z0_000L]
[butter no butter_z0_aany no gluedown no glueup    glueright no glueleft] -> [butter                          glueright             butter_z0_00R0]
[butter no butter_z0_aany no gluedown no glueup    glueright    glueleft] -> [butter                          glueright    glueleft butter_z0_00RL]
[butter no butter_z0_aany no gluedown    glueup no glueright no glueleft] -> [butter                glueup                          butter_z0_0U00]
[butter no butter_z0_aany no gluedown    glueup no glueright    glueleft] -> [butter                glueup                 glueleft butter_z0_0U0L]
[butter no butter_z0_aany no gluedown    glueup    glueright no glueleft] -> [butter                glueup    glueright             butter_z0_0UR0]
[butter no butter_z0_aany no gluedown    glueup    glueright    glueleft] -> [butter                glueup    glueright    glueleft butter_z0_0URL]
[butter no butter_z0_aany    gluedown no glueup no glueright no glueleft] -> [butter    gluedown                                    butter_z0_D000]
[butter no butter_z0_aany    gluedown no glueup no glueright    glueleft] -> [butter    gluedown                           glueleft butter_z0_D00L]
[butter no butter_z0_aany    gluedown no glueup    glueright no glueleft] -> [butter    gluedown              glueright             butter_z0_D0R0]
[butter no butter_z0_aany    gluedown no glueup    glueright    glueleft] -> [butter    gluedown              glueright    glueleft butter_z0_D0RL]
[butter no butter_z0_aany    gluedown    glueup no glueright no glueleft] -> [butter    gluedown    glueup                          butter_z0_DU00]
[butter no butter_z0_aany    gluedown    glueup no glueright    glueleft] -> [butter    gluedown    glueup                 glueleft butter_z0_DU0L]
[butter no butter_z0_aany    gluedown    glueup    glueright no glueleft] -> [butter    gluedown    glueup    glueright             butter_z0_DUR0]
[butter no butter_z0_aany    gluedown    glueup    glueright    glueleft] -> [butter    gluedown    glueup    glueright    glueleft butter_z0_DURL]

Basically, there are 16 different butter sprites - one for each combination of up/down/left/right butter-neighbors. Oh, and also there are 4 additional versions of the above code snippet – 1 for each direction of 1-pixel bounce when hitting a wall

Here’s the pic I promised of my final spritesheet in aseprite – the little blue rectangles are the areas I’ve marked as sprites for exporting:

Most of the space is taken up by butter animations, which seems entirely fair.

08 Final Thoughts

Repetitive but simple code combined with proper drawing tools was the secret sauce that made the animations feasible.

Also, the pseudo-3D puzzlescript fork was an essential ingredient – without it, the spritesheet would have been something like 2~4x as large, and the code might have collapsed into un-editability under its own weight. Plus, who knows how performant the game would be; the final version already chugs along pretty hard on some of the large levels.

I wish the puzzlescript ecosystem had something like a base engine with many individual plugins you could add at will; sort of like what they’ve got going on in the bitsy scene. Many people are extending puzzlescript in cool ways, but getting the various extensions to work together just isn’t feasible. The only reason I felt comfortable hacking together my bespoke version was because the changes in the pseudo-3D fork were very very small and weren’t too difficult to port manually.

Leave a comment

Log in with itch.io to leave a comment.