Ludum Dare 42 was held August 10th – 13th, 2018. The theme was "Running out of Space", and I made a puzzle / adventure game I'm very happy with called "Runnink out of Space".
About Ludum Dare 41
Before I talk about LD 42, let me just briefly mention my LD 41 entry, Advance Cookwares. Yes, I participated and I submitted a game but I was really unhappy about the result towards the end. The game looked fine, but the gameplay suffered a lot from not being properly explained. I never got around to writing much about it.
The game barely ended up in top 100 for two categories but overall it is a disappointing one!
Back to LD 42.
Themes and early start
These were my votes for the themes in the final round:
0Running out of space
+1Night is coming
-1Safe in the dark
-1You are the final boss
-1Light is key
-1Death is useful
+1Two points of view
-1One enemy only
-1You control the environment, not player
I downvoted the duplicate-sounding themes in this and the previous rounds. "Running out of Space" was one of those themes that I just felt neutral about and didn't really think much about it.
In fact, since this time around LD started a couple hours earlier than usual, I discovered the theme at 11 pm local time, and I used the evening to brainstorm. Before the jam, I was thinking of doing a game vaguely inspired by Flashback, but that thought very quickly dissolved and I ended up just making a retro game. Like always!
During that first brainstorming session I thought of an interesting (I hope) mechanic for the inventory system: the world map = the inventory = the player's abilities. Knowing where you are is a trade off for having an item, or being capable of performing an action like jumping. At this point I was thinking of a vaguely metroidvaniac puzzle platformer.
However, having one single container for everything that the player needs (map, inventory, abilities) got me thinking – what if these "things" are all essentially the same? How to unify the abilities and the items? (How to unify program code and data?)
With that line of thought I got to System's Twilight, an amazing puzzle game that I love a lot. In the game, there is an area called the swamps, in which the player solves levels based on manipulating words and answering riddles. The levels increase in difficulty and size, and it is very possible to get into unsolvable states by answering riddles with the wrong word or by manipulating your words in the wrong way. This makes the puzzles quite challenging and a little bit frustrating also. I wasn't sure if I wanted this kind of difficulty in my game at this point.
(As an aside: King Kinplot in the game is a reference to System's Twilight creator, Andrew Plotkin.)
Still during the first brainstorming session, I thought of a story that was centred around literally running out of space in the cosmic sense, and a way to explain why the player was running out of memory, as well as why they should embark on a completely surreal adventure – it's an illusory puzzle labyrinth of course. This story got the girlfriend stamp of approval, though I suspect the pun in the title played a role in that.
And I listened to Out of Space. At around 1 am I called it a night and went to sleep.
On Saturday I continued the brainstorm as we were eating out for breakfast. I was firmly discouraged from having levels where the player would be completely stuck and would have to reset the level. After some thought I agreed, and I realised that if the game was unlosable, I could also get away with having a single large map instead of multiple smaller levels. After all, if the player got stuck towards the end of a large map, they might be too upset to restart and give the game another try!
When we got home, I started drawing the map along with whatever words / riddles would be present in each room. This was to be the core of the gameplay, so the hours I spent on this before doing practically anything else were hours well spent.
If you haven't played the game (I encourage you to do so to avoid more spoilers!), here is what the gameplay is like, so that you understand what I am describing in the following section:
- the player moves around a map split into individual rooms
- in each room, there may be interactions in which
- a word can be "taken" from the map - the player has to manually type out the answer to a riddle and they can then take this answer and keep it in their inventory
- a word can be "given" - the player needs to have the answer to the riddle in their inventory
- a word can be "transformed" - a word from the player's inventory may be given to be transformed, and if the transformation works on the given word, the player may keep the transformed word in their inventory
I am also happy with the approach I took, an approach which made drawing the map a relatively straight-forward task – I started from the end of the game and worked my way backwards until I thought there was enough content. So, I drew the bottom floor of the map first, including the ultimate goal, the Cuttlefiship. Since it was the final room, it needed to be guarded, naturally, so I added the three guardians, who took three very similar answers. And so on, and so forth. I wrote down all the answers, and I thought of some common transformations that could be applied to get TO the answers FROM a different set of words, which then became the words given to the player, or intermediate steps.
The set of word transformations I had come up with:
- reverse word
- swap first and last letters
- increase the first letter by one (a to b, b to c, etc)
- decrease the first letter by three (d to a)
- remove all c letters
- change o's to u's
- remove the first letter
(Notice one transformation that ended up in the game is missing: I had to add it last-minute because I was too tired to realise that "climb" has an "m" while "blind" has an "n"!)
At some point I was considering adding a word transformation to the game which would add a letter to the supplied word. But I realised, when the player has the ability to cut off the first letter, increase or decrease the first letter, AND add a letter, they can actually make any word whatsoever, without having to take the words from the rooms in the map. Such a set of transformations would be too powerful and would be a generating set for all possible words. So of course I made sure not to put this transformation in the game!
As it is, I was worried that I missed a way to "sequence break" the game, i.e. solve certain riddles without taking all the words needed from the map. When I watched my friend playtest the game (a day or two after submission), he got really close to a sequence break ... but he only found a different way to generate a required word.
I had the map and word lists finished and almost finalised quite early in the jam. However, no actual dialogue was written, only the key sentence for one or two riddles. I delayed dialogue writing until the third day.
(What a corny subtitle.)
Just like with many of my previous LD entries, I asked my friend "Eidovolta" (whose real name shall remain hidden!) to make the music for the game. Unfortunately, this did not happen due to some last-minue work assignment. This meant that I was unsure what would become of the audio, or if there would be anything besides the basic beeps and boops I could get from bfxr.
As luck would have it, however, I was hanging out on the #alakajam IRC channel, as one does during gamejams, and wan happened to be there. I also knew he was a solid audio artist from his previous gamejam entries, so I asked him for help. My vision (audiation?) for the soundtrack was simply something retro, Amiga-like, to hopefully fit with the feel of the game overall.
So wan abandoned his not-quite-started LD entry to make music for my / our game. Thanks again, wan!
In the evening on the first day, I had the map ready, so I selected a palette and started drawing the backgrounds for the first floor. I thought I would finally get to use my drawing tablet for this LD, but it never happened. In fact, I think the sort of pixel art that I used in the game is easier to draw for me with the laptop trackpad.
While I was drawing the first floor I realised the final amount of image data would be relatively large, even though individually they were quite low-res. 7 floors, each of which has 5 rooms with one background layer and one foreground layer, perhaps a bit more if there are moving bits. So I tried to think of a way to prevent having a single huge bitmap for all the room imagery.
I drew a grid and tried to align the graphics to it. I wanted to run a script which would check the contents of all the tiles, detect duplicates with some fast hashing, and then only save the unique tiles in addition to a map referencing those tiles by ID.
Cool idea but naturally a waste of time. Instead I had each floor in a separate file (so as to not exceed some engine limitations for bitmap sizes) and saw that the PNGs were pretty tiny in the end.
But in the end I was quite happy I had a grid, since it was very easy to align the interactive bits drawn in the room backgrounds with interactive zones that the player can click to activate.
There is a lesson there: over-engineering, then giving up halfway through can lead to benefits in the long-term.
With the first floor done, I had to think of a way to visually show the transition between the rooms.
The sides of rooms generally lined up with the same kind of door on either side, and I made sure to have ladders line up as well. Still, I didn't think a simple scroll would be good enough. So instead, I scrolled each row of pixels separately (or column of pixels for vertical transitions), with some delay.
In addition to the delay in rows, each row was also moved non-linearly, using a smoothed timing curve.
The pseudo-code for a left-to-right transition would then be:
let TransitionLength := 20 frames let RoomWidth := 318 pixels let RoomHeight := 175 pixels for Frame from 0 to TransitionLength: for Y from 0 (top) to RoomHeight (bottom): let RowProgress := (Frame / TransitionLength) - (Y / RoomHeight) let SmoothProgress := QuartInOut(RowProgress) * RoomWidth copy Yth row of left room to X: SmoothProgress copy Yth row of right room to X: SmoothProgress + RoomWidth
QuartInOut is a quartic ease-in-out function.)
Or look here if you prefer actual code for transitions in all 4 directions. I felt these transitions worked very nicely and added a bit of interesting eye-candy to the game.
It was time to place the player into the world. Maybe because of the smoothness of the room transitions, I thought of ragdoll animations. I modelled all of the characters in the game, including the player, as humanoid ragdolls made out of:
- a head
- a torso
- left and right upper arm
- left and right lower arm
- left and right thigh
- left and right calf
Then I could create a small number of poses and animations and be able to apply them to all the characters without having to animate each. Well, that was the idea. In the end, only the player ragdoll uses the animations:
- falling down
Everything else uses an idle standing animation, except the King and the Queen, who are (very awkwardly) sitting.
My original intention was to create a simple tool in which I could arrange a ragdoll the way I wanted and use that to create the keyframes for animations. This did not end up happening, as it would probably take a long time. The alternative was, unfortunately, to create the keyframes by setting the angle at each limb manually, loosely based on a walk cycle tutorial. Naturally, this made the animation look rather stilted and robotic. But of course, since the player character IS a robot, it looked appropriate!
Second day, more ragdolls
During the second day, I kept working on the ragdoll animations. Making sure the player moved smoothly from tile to tile while walking or climbing was a little bit frustrating, same for making queued actions work properly (e.g. walk THEN climb).
But in the end, after spending maybe 12 to 18 hours of my total LD time, I had the player walking around the map smoothly, transitioning from room to room. It is quite a large chunk of time and with some foresight the process could have been planned somewhat better, but all in all I don't regret the choice.
More than halfway through the jam I realised there was no actual gameplay in the game yet. No way to solve riddles, transform words, etc. I had the general layout for the UI but, well, judge for yourself:
You may notice that there are four sections in the layout. The bottom two ended up the same in the final game, but for a long time I wasn't sure what to put in the top right. The actual rooms were displayed in the top left only. The idea was to have a minimap in the top right, from which the player could drag their current location onto their memory to "remember" it. I eventually abandoned this idea in favour of just centring the room visuals in the top part of the screen, since the map discovery was made automatic. This is why there are vertical bars on the sides of the rooms in the final game.
I made the bottom left window be the dialogue box. Expanding upwards to show more text in a chat-like fashion seemed a natural choice. I was happy I had an automatic text justification ready from my Alakajam! 2 entry, otherwise manually justifying each bit of dialogue like I had to do for LD 40 would be a major pain and a waste of time. The justification worked pretty well for the most part, the one exception being:
I didn't think this was worth fixing.
The bottom right is the memory / map / inventory system. I was considering at some point making the memory of a room more important – e.g. if you remove the room from memory, you will need to answer the riddles in it once again to get back the words. But this would probably be very annoying. As it is, the map overriding the player's words if they are not careful can be sufficiently challenging.
Pixel art morning
With the UI done, the gameplay was basically complete. Except ... I was missing most of the floor graphics and most of the dialogues! I had about 14 hours, but I figured it takes about 1 hour to complete the graphics for 1 floor, reusing common elements like the doors, of course.
So with that in mind I spent the entire morning of the third day drawing. I tried to make each room somewhat unique, but naturally my time was running out. I guess it shows that the last floors are a bit less varied than the first ones.
But hey, by the time players get there, noticing the pixel art is the last thing on their minds!
As I already mentioned above, all of this was drawn using a trackpad. I use my laptop as my primary workstation, and over the last couple of years I haven't been using a mouse very much. It feels very comfortable and easy to draw with the trackpad as a result. In the case of this game, most of the art is rather geometric and technical, rather than organic or natural. If I were creating a game with more of the latter, I would probably give the tablet a go again, since it is easier to draw organic shapes free-hand.
Dialogues, wrapping up
By this point (early afternoon of the third day), it was really time to tie up the loose ends. There was a lot of dialogue still missing from the game, though I knew roughly what all of it should say. I made sure no interaction was missing, placed all the character ragdolls in the correct positions, tried a couple of playtests to spot some obvious problems.
Originally I wanted the dialogue system to support branching paths, where different text could display based on the current game state. As it turns out, the only dialogue that actually used this feature was the King, who would say different lines if the player hasn't helped the Queen yet. With the chat system as it was, this seemed rather complex to implement and I was worried it would confuse the players anyway, so I scrapped the feature and instead made the door leading to the King a bit more intelligent – it checked that both the Guard's and the Queen's puzzles were solved before opening.
By this time I also had all the music and sound effects from wan, so I put them in the game as appropriate. I used the crossfade system I had from LD 40 / LD 41 for transitioning between music tracks.
With about 1 hour to go, I had enough time to put in little markers on the map, display the room titles, i.e. a bit of polish. I put in a title screen as a little wall of text, but did not have the time to put in an end screen, so players get a disappointing "(YOU WIN!)" in the dialogue box, allowing them to explore the world after finishing the game.
The end screen was meant to show space, and when the space was restored by the player, the camera would simply zoom out, thereby showing more space. (Idea courtesy of Danae!) This would have been fun, I admit.
Now it is time to wait for the results. I am extremely happy with how the game turned out, and I am now convinced that a regular sleeping schedule during gamejams actually leads to much better results; the few extra hours are not worth the decrease in productivity. Watching a couple of streamers play the game was very entertaining, see ursagames' playthrough or ArdjenDesign's partial playthrough.
You can play the game here, or on itch.io. I uploaded a timelapse, and wan made a post about the soundtrack. And, if you are stuck, here is a walkthrough.
That is it for now, I hope you enjoyed reading this as much as I enjoyed making the game!