The Making Of Glitch
Introduction / TL;DR
In this GIGA-post I am going to describe in detail how I developed the game "Glitch" during the 2022 Minetest Game Jam. This includes development up to version 1.0.1. Later updates are ignored (unless mentioned).
This post is for developers and nerds who want to understand my design reasons for Glitch. If you're interested in the nitty-gritty details, read on. If not, then you can skip this. :P Sorry, I don't know of a better way to summarize.
Developing Glitch
Before it began
I didn't do anything, not even think of a game concept. But a few days before, just one word floated in my head: "Eyeballs". Don't ask me why. I wanted to do "something with eyeballs, lots of eyeballs". That was it. :D
Day 1
The Game Jam theme was announced and I immediately looked what it was. I was FLOORED. The theme was "Space | Story | Secrets"? WTF. I hated this theme. I didn't like any of these things, and the only tangible theme was "Space". The obvious interpretation of space is "outer space", but I was certain I didn't want to do anything with that. And "eyeballs in space" sounds meh. I quickly decided to completely discard "eyeballs", as I had no idea how to bring it together. Plus, it was also not clear if I have to use all 3 or just one. And if I use only 1, if that would incur a penalty.
Early game idea (that was later discarded)
I made no real progress for a few days, as I still needed to think of a proper game idea. Which is more difficult than you think! I still did not even have an idea. I wondered how much time I would spend with the idea, but I had to get an idea FAST. I was stuck. Eventually, one idea hit me: "Glitch". Or actually, just "something in cyberspace". The game I actually created doesn't have much to do with the first idea, except the theme.
Basically, my first idea was to make something like a "walking simulator" or adventure-style game in which you are lost in a strange, otherworldly place (cyberspace) in which each node represents a piece of data. What's crucial about that idea is the levels expand "infinitely" and have their own unique logic to them and you have to figure it out on your own, it's part of some puzzle. How exactly, I didn't plan that out. Also, you would play as a human.
I thought this was a good idea, and it matched the "Space" theme (Cyberspace!).
At later days, I made little progress. I coded a few very basic nodes to walk on, but no game logic. My game was still an empty shell with just a few nodes. The biggest problem was, I didn't really have any idea for puzzles.
But very early on, I already had the idea of levels that connect to each other.
The early story I thought of was this: You're a human. You start in your home, came back from work and are frustrated by the numerous bills you find in your mail. You get to do a few household tasks, then you go to sleep. When you wake up, you're still in your house, but when you go outside, you find suddenly in ... the Glitch World. This was the world I initially imagined. The Glitch World was a series of interconnected levels (similar to the actual game). I had no concept of collectible items yet, I was more focused on somehow tell a story and interact with other characters who are equally lost. I wanted to make an adventure/puzzle-like game.
Additionally, the game was supposed to have two level types: Puzzle, and city.
A "puzzle" level is a level in which you have to interact with blocks to solve puzzles, but the twist is you must first understand how everything works, and my idea is to add many mechanics that might not be obvious; the blocks are supposed to behave in strange and unexpected ways. But I just didn't have any concrete ideas to make it work.
The "city" levels are not puzzle levels, they are more like levels that connect other levels. And they roughly look like cities. Those levels are more story driven and supposed to have lots of NPCs, including quest givers that give you quests like retrieving a quest item from one of the puzzle levels.
So the idea was, you would travel from level to level, trying to find clues how everything works, until you eventually find the final level which would be some kind of "digital castle" which would be a place where you can escape the Glitch World and get back home, which would be the end of the game.
This was my rough game concept very early in the development time, but it was still very rough around the edges. Most importantly, I was completely stuck on the puzzle mechanics.
[Note: This original game idea was mostly discarded.]
The first breakthrough
So, in the first days, I was stuck. My initial idea wasn't actually great, I had no ideas how to build on it. I added a few dummy nodes but I realized that coding is pointless when I have no good plan what I'm doing. XD
I made very little progress. Especially the intro scene I planned would require very different graphics (the initial house is supposed to look "realistic" and not abstract like the Glitch World), and this bothered me, esp. since I wanted to create all content myself this time. I thought I could make textures based on some real-world photos, however, this would eat important time and is only for a short intro and outro.
But then I FINALLY had a real breakthrough: I thought to myself, why does the main character have to be human? And why does the intro sequence have to be outside of the "Glitch World" anyway? And then I decided the main character would be a bit. This also has another reason because creating the graphics would be way easier if everything is abstract. :-)
The idea of how bits look is very simple: Bits are to be represented by black or white color. Zero being black, and one being white. This is because color in computer is sometimes defined as a range from 0 to 1 and in all graphics programs ever (that I know of) 0 represents colorlessness / black and 1 is "full color" / white. The reason why the character is One and not Zero is completely arbitrary tho.
I initially also planned to spread other "bit" characters in the world around, but time constraints forced me to limit the number of NPCs in the game.
Early coding
Once I was finally happy with my basic concept, I could finally start with some coding. This was at day 3 out of 21. In the early days, I mostly wasted time with adding a bunch of dummy nodes so get the absolute minimum controls working.
One of the first things I did was to figure out the proper player physics, which includes player movement speed, jump height, acceleration, etc.
I intentionally deviated from the default Minetest physics which are too overused. I learned from other game devs that is important to get this thing working and balanced early on and THEN build the levels around your physics, not the other way round. For example, I initially balanced jumping strength to be strong enough to cross a gap of X blocks easily (I don't remember how many exactly). Yes, jumping was initially enabled. I'm glad I remembered this important advice. :-)
One unique physics aspect in this game that sets Glitch apart from other Minetest game is that you can't easily change direction while you're in air, which is why in-air movement seems a bit sluggish. If you have noticed this by playing, this is not the physics being weird, this is by design. But you can change direction *just* enough so that launchpads are useful. I can't set the air acceleration to 0, otherwise using launchpads would be much, much harder; it would mean you once you have left the ground, you can't change direction at all.
I did this "sluggish air movement" so that when you fall down from a platform, you can't easily (or not at all) move back while falling to reach a platform below. You can see this effect easily in the Void Pipe Sector, below the little "bridge".
I'm more or less happy with how the physics turned out in the end. Note that more advanced physics, like powersliding, were coded (and thus balanced) later, when I added those things.
Level spawning
A very important thing to get working early was generating the levels (i.e. sectors) and placing them in the world. I had to make sure to generate levels reliably and with no errors, and also needed a way for the player to teleport between them (for the gateways).
The way this technically works is simple: I use schematics (these are files or pieces of data which save a section of the world on disk) and place them at a pre-programmed position. Each level is somewhere on the X axis in the world with a distance of ca. 2000 blocks. (OK, it's not that simple, I also need to force Minetest to "emerge" the level area first to make it actually work.) When the level is placed, several other things need to be done: Placing electrons, abilities, NPCs, and even setting the node color (which is not stored in the schematic).
Levels are not just made out of schematics, tho, they also need metadata, like level name, spawn positions, special events when you enter (like a dialog), etc. The level metadata is all written in the source code, there is no fancy file format (which would be overkill anyway). Levels can have multiple spawn positions which are used by the story and gateways.
How the electrons work
This is kind of dirty, actually. The spawn position of electrons is simply added by putting a special node in the level files themselves. If you start the game in the hidden Editor Mode, you can see them, but in the real game, they are invisible.
Detecting when the player touches an electron (to collect it) is also tricky. Basically, I just check every tick (globalstep), which happens around every 0.1 seconds if any electron is near the player. However, after the Game Jam I noticed this does not work if the player is very fast as there are too few globalsteps.
[Note: In version 1.1.0, I fixed this by checking 8 points on a straight line between the current and the previous detected player position on a tick, e.g. about every 0.1 seconds. This is much more reliable.]
There is another problem I needed to solve: The game must always remember *which* electrons the player already has. I solved this by simply giving every electron a name. The name is automatically generated looks something like "void|4,6,-3". Where "void" is the level name and the numbers are the coordinates relative to the level origin. So, now all electrons are uniquely identified. Now all I need to do is to store a long list of collected electron names in the player data. Now whenever a level is loaded, only the electrons the player didn't collect are spawned.
But this is not everything: There are actually two lists: All collected electrons and saved electrons. "All collected electrons" includes electrons that were not saved yet (in a save zone) and you're in risk of losing if you fall out. If you fall out, all the game needs to to is to copy the list of "saved electrons" to "all collected electrons".
You can actually view the list of your electrons yourselves with the "/list_collected" chat command, which is an old debug command I left in (Warning! It might fill your screen with text! :D).
Why save zones?
I realized during play tests that falling down and then getting reset is just annoying but not really a problem, as you don't lose anything. Worse, you could just collect electrons in air and fall out of the sector and still keep them. Which means there is no real reason to avoid falling out, as you constantly progress through the game anyway. It meant that once an electron was collected, it was yours forever.
This is why I introduced the concept of "save zones". Save zones were NOT actually created to save the game, as I could easily save any important changes to disk instantly anyway. Save zones actually exist to force the player to not be too careless and to add a little bit of a challenge. And if you paid a lot of attention, you noticed that a collected ability will be saved instantly (no save zone needed).
The first level
The first real level I built is also the level you start in: Void Pipe. The story in this level including the intro was already quite early in my head, although I coded the intro sequence close to the end.
Initially, jumping was permitted so it was actually possible to reach many electrons of the level border by jumping. However, on playtesting the level for a while, I realized how overpowered jumping actually is and that it might offer an interesting change to not allow it, also for level design reasons. Only the launchpads allow you to "launch" upwards, but not jumping. The launchpads are also really useful for level design as I can control possible player moves in a level more. :)
Small nitpick: I called them "launchpads", not "jumppads" because you "launch" from them, rather than jumping. Jumping implies you propel yourself upwards using your own body. Plus, I think it's just a little bit more original name. :P
The Hub
When about the half time of the Game Jam was over, I managed to complete the most important gameplay features. I was *really* happy then because it meant I had now over 10 days left only for content. This was huge! So I started building level after level and was quite productive. OK, later, it turned out I still had to do some coding (for example, completing the dialog system), so I didn't have the full 10 days for levels and content but I still had lots of time.
Anyway. So I was building level after level, but I was still not really happy. So I had a few levels eventually, but they were without real connections. It was a loose, messy set of levels, which didn't feel great.
So I had an idea to build a special level that connects everything else, just to have an "access room". This eventually became the Hub.
Ooff! I cannot stress enough how IMPORTANT the Hub idea is to this game, especially for my personal motivation. :D Once the Hub stood, I had hopes I could actually put a (semi-)complete game together. My motivation got a major boost once this level was complete.
Designing the Hub was actually based on a very simple idea. First I thought about the basic shape. I wanted the Hub to be special ... First, I could do a cube like the Void Pipe, but I thought that would be too boring. I remembered the classic building advice: Build the ground floor first before going 3D. Because the "block"-shaped buildings are too overused! VERY good advice. So I thought about various basic geometrical shapes, and the octagon won. I tried out different sizes and wall, when I was happy, I just //stacked it with WorldEdit. The rest was just decorating the level. I am very happy I chose an octagon instead of a boring cube, the octagon shape really works great.
Level design in general
I don't know what to write here, except I just tried to be creative? :D
Okay, one technical thing: For each level, I needed about 6 hours to complete it.
Okay, another thing: I designed various levels so that you can't reach all electrons initially, but if you get more abilities, you can return and collect the rest. This is intentional. The first sector has many electrons you need new abilities for to get them all.
The final Day
The final Day way quite hectic. This is when I tried to polish and get the story finally to an end. It was very important to me to have a complete story, with a beginning and an end, even if the story is simple. I wanted to make sure this game isn't just a level collection. On the final day, I finalized the dialog and also wrote the ending on the story. The ending dialog (not the final level tho!) was written entirely in the final day, so it was quite hectic to me, and I was afraid it would not be liked by people, but apparently, it was. :)
I even wanted to create music on this day but then I realized I don't have any skill so I just quickly took something from FreeMusicArchive. This was allowed.
Another feature I did in the final day was level colorization. Before this point, every level was white only. I decided to just use the same color per level, rather than mixing color. This is directly inspired by the old FOSS game Freedroid (not to be confused by FreedroidRPG). I was briefly tempted to also turn "solved" levels (all electrons collected) gray, like in Freedroid but decided against it and instead used gray color as a regular level color. I think this was the right decision. Level colorization is done automatically, the color is NOT stored in the level schematic, but in the metadata. This is nice because I can change the level color with a single line of code, I don't have to open the level editor for that. :)
Time came to an end. And just when I was about to submit the game, I have found a critical bug! :O I noticed in the final level, the teleportation did not work correctly and it would have broken the story. I had to think FAST and only had about 10 minutes left but thankfully, I found the bug and it was a simple bugfix. But imagine my shock when I found it. :D
We developers still got an extra hour anyway, but still!
It was almost a Lazarr! situation all over again. (In Lazarr!, my previous game jam game, level 8 was impossible to win and I noticed it too late.)
Development Tools
I have used numerous tools which saved me time:
- The GIMP (2D graphics, textures)
- Blender (3D models like electrons, abilities and slopes)
- sfxr (sound generator)
- Mod: Schematic Editor (schematics)
- Mod: WorldEdit (makes building levels easier)
- Mod: Get Item (basically a creative inventory)
- Mod: Perlin Explorer (helped making "Far Lands" and the final sector)
- Minetest itself (yes, Minetest was itself a development tool. For me, it was for level building and playtesting)
Glitch is the first time I've actually used Perlin Explorer for something useful, I would have NEVER thought back then I would use this like this. I originally thought I would just use this to find values to put into the mapgen, not to actually generate an entire level template directly! In case you're wondering, sorry, no, I no longer have the noise value settings I used for creating the levels. :( I needed this tool for the "Far Lands" sector and the mysterious final sector. I used it for a basic shape/landscape of these sectors. This has saved me so much time, I could have never built these massive structures by hand. I still needed manual editing for placing all the game-specific stuff, of course, the work was still about as much as for most other levels.
The "Get Item" mod [getitem] saved me a lot of time, because I needed to switch items during level building all the time. For my previous Game Jam project (Lazarr!), I used the Chest of Everything mod from Development Test, but this was always awkward to use as I had to place it somewhere, and the chest was always in the way. Using an item instead to open the "all items" inventory was a big upgrade, it was much faster and more convenient. I published this mod post-jam, this is very useful if you write a new game but don't have a built-in creative inventory.
sfxr is a tool that was specifically made for game jams. I used it often before, although it has a limitation; the sounds are always so retro and usually those sounds are meant more like dummy sounds so you can quickly dump in sound effects quickly into your game. But this time was different. Because for Glitch, this tool was actually PERFECT, the retro style is EXACTLY what I needed. I am very happy with how my sound effects turned out.
Things I wanted to do but couldn't due to time
- Fix the controls. Sometimes, electrons don't get collected. Sometimes, the powerslide ability doesn't fire. I partially blame Minetest here because Aux1 sucks. (note: controls got fixed after the Game Jam)
- More levels. I wanted to do a HUGE number of levels but then I always got carried away of creating polished levels. These levels took LONG. Always around 6 hours. I'm still glad I went for quality over quantity. The levels I was still planning at the end are mostly "transitional" levels that act as a buffer between the Hub and the ability sector because some sectors from the Hub lead directly to an ability, and not with a level between them. I wanted to have at least one "buffer" level for each Hub direction. Also, I wanted to have levels at all eight sides of the Hub octagon
- Have 1024 electrons in the game, because it's a power of 2 :D
- More story and characters / more polished out story: Especially I wanted to introduce a few more helpers for story, but probably they weren't necessary. Especially I wanted to add other bit characters to talk to for some story, but on the other hand I'm not sure it's a good idea if the levels become too crowded with story. Some players complained the dialog is too long so I might cut it down to the relevant parts (without compromising the story)
- Music: I did the graphics, models, story, design, levels, testing, sounds, ... EVERYTHING. Except for the music. But I actuallly planned to even do the music myself, I wanted to make a 100% Wuzzy creation this year. But I postponed music for the last day. Obviously, I failed, I had no experience anyway, silly me. :D I still tried, wasted a few hours, then I caved an grabbed something from FreeMusicArchive. I'm glad I did. Good I postponed music to the end and didn't waste too much time.
I created a few features during developemt that I had to discard:
- "Jump" ability: Early on, I thought the player could learn jumping as an ability. But I realized jumping is just too overpowered for my levels so I removed it completely. I added the launchpads as a replacement.
- "Carry" ability: This ability would allow you to hold one item. A mini-inventory, basically. I thought it would be useful for some fetch quests. But once I added electrons, this became mostly pointless, and I removed it. This feature was even fully functional, with GUI and everything.
- Blocks that move when you punch them: Very early on, I had simple block that move to a certain direction in a straight line until they collide when you punch them. This was meant to be a simple puzzle mechanic, while I was still thinking of the game as a puzzle game. It was a lazy experiment that didn't go anywhere, so I removed them.
- Toggleble lamps: Initially, I wanted the yellow "lamps" (light blocks) to be togglable, meaning a type of lamp that must be "turned on" first. My idea was for levels which start dark and you have to spread the light to make more of the level visible. This was when I still saw the game as a puzzle game.
- The Sneak Glitch: You won't find a commit in the code repository, but I briefly experimented with a "sneak glitch" ability (if you don't know what this is: https://wiki.minetest.net/Sneaking). I thought it would be funny because the game was called Glitch. But I quickly scrapped the idea because the sneak glitch doesn't "work" if the player is only about 1 block tall
- Rainbow noise: This is like the normal white noise block, but with rainbow colors. It's still in the game files, but not used in any level. I wanted to try to have a special event with this, but I had no good idea, so this is unused.
These are some situations in which my tools worked not with me, but against me and I had to work around them …
- I found a Minetest bug in which entities (including the player) that use the "cube" visual (e.g. they look like a cube) become invisible when they are near a light source. This bug was an old known bug actually, but I reported it again (accidentally), they even fixed it during jam-time, but this was useless for me of course since I was stuck with 5.6.1. Thankfully, I found a workaround: Just make a mesh instead in Blender really quick. The light bug does not happen for mesh files. I'm glad I actually went out of my way to do a workaround for this, the helpers would have been invisible otherwise. :O
- My Schematic Editor mod bugged around when I exported the schematic for the Void Pipe sector. Sometimes, the upper portion was not exported. I quickly found the reason: The area wasn't loaded, so the schematic editor exported only half the level. I pointlessly wasted some time with that. I fixed the bug in Schematic Editor after the game jam.
- WorldEdit keeps TRIGGERING me because its border marking keeps z-fighting with nodes. Argh! XD
- IMHO the WorldEdit usability could still use some improvement IMHO. Working with it is not efficient, even if you know what you must do. Typing commands is tedious and WorldEdit GUI is not a great improvement either (in terms of efficiency).
- The climbing ability isn't as simple as it seems. It was not possible to turn climbing on or off for a player in Minetest. A node is either climbable or not, but it cannot be changed per-player. So what I did do instead was adding 2 nodes for each cable, one that is climbable and one that isn't (the player does not see any difference). All cables start non-climbable in a level by default. But if the player collects the Climbing ability or already has it, these nodes will be replaced by their climbable counterpart automatically. A dirty trick, but it works as this game is singleplayer. :-)
Overall, I did have fun making the game and it was a challenge, but I am very happy how it turned out, for obvious reasons. :P
Thanks for reading this GIGA-post, I hoped it gave some insight. :)
There's probably a ton of other things I could have mentioned but I have to stop at some point. If you have questions, just ask.
----
EDIT 25 Jan 2023: Added section about climbing