Voidblade - a N64 postmortem
After more than 25 years of the release of the console, there is still a great Nintendo 64 homebrew community called N64brew (discord server here). Last year they organized the second game jam targeting the system, N64Brew Jam 2021 (source codes available here). Being hooked to the development for the system for more than 3 years now, I decided to give it a go this time. In this post I am sharing my experience with the system, my thought process for game design and my regrets.
A few days before the theme announcement I was already getting hyped about the jam and started thinking about a few conceptual ideas. I could incorporate 2d vector-style graphics with some transparency effects to simulate 2d lighting. Like a lightsource casting light in every direction, which is occluded by other polygons. Maybe I could even add some 2d physics. I was dreaming of something more like a cinematic platformer with potential puzzle elements. I even started working on some polygon rendering stuff based on Rasky’s display list engine (pushed a few fixes/improvements later on). Then the theme was announced; Control by a short YouTube clip. Those puppeteer control bars immediately reminded me doing some rope simulation.
The next weeks I just wondered what can I build to fit the theme. Having a two month game jam is both a blessing and a curse. It forces you to get really crazy on ideas but most of the people on the community including me have dayjobs so at the same time you need to be realistic. I dreamed about a game where you control a rocket ship in a vector environment with transparent water physics and such. Like the rocket games from the flash game-era, where you try to carry a cargo and land the ship somewhere avoiding enemies etc. It would somewhat fit the theme, would use physics and maybe even ropes. At the same time I wanted it to have some story/ambience with nice shadow-casting lights. I soon realized that I was flying a little too high on that ship. It was almost impossible for me to build that many handcrafted levels or story to make it meaningful to my taste. Generating the levels was a possiblity but still too much for the time I could allocate. I also thought of a platformer but it didn’t fit with the theme without having a good storyline, which again I didn’t have the time for. In the end I decided to go with the simplest approach. Building it bit by bit by trial and error, starting from a simple idea and making it potentially an infinite runner for simplicity.
The starting point was making a physics engine work. N64 is a difficult platform to work on. In addition to that I decided to go the route of using the open source library called libdragon, which I try to contribute to for some time as well. (Nintendo is notoriously strict on IP and licencing so in general I try to keep my hands away from the official SDK). When working on such a system, almost everything is unknown to me. I am no embedded developer and I’m not sure about the system’s performance limitations either. Basically there is a main MIPS CPU which generally runs the general logic of the game and orchestrates the other processors, namely the RSP (reality signal processor - a SIMD style vector processing unit) and RDP (reality display processor - a command based hardware rasterizer). I knew from past experience that box2d was performing well on older mobile devices so I first give it a go to. After fiddling around linking C++ objects and libdragon properly, I built a simple scene with a few falling boxes jumping around. It worked pretty much the first time!
Next experiment: make some ropes. I played around with the box2d’s rope class to understand how it is used and implemented a few simple physics ropes to see how they work and look. I fell in love immediately ❤️. Then I had a few exceptions caused by unitialized floats with the ropes, which N64 does not forgive (those were then fixed in box2d - another OSS win!). To render the individual elements, I have used very thin rectangles consisting of two triangles. Then I have attached the ropes to a box and bound its linear speed to a controller’s analog input to see how it goes. At that moment it strike me, I could hang something from the box to “control”. Even better: what if there were two boxes, like the hands of a puppeteer just like in the theme video! I have implemented a prototype by connecting a rope between two boxes controlled by two analog sticks. This means using the both controllers on the N64, which was more awesome as you can feel like you are the puppeteer controlling something.
Now I have the basic idea to work on but I still needed some gameplay. Considering I am building an infinite runner-like game, I have added the falling boxes such that they keep falling forever and started experimenting with what I can do with it. Boxes colliding with the two cursors felt good because of the nice physics but on the other hand there should be a main conflict to force the player to to do something. Either I could make them harmful and the player would avoid them or I could make them some collectible items. Either way I had to ditch the nice physics collisions unless I also incorporate a moving “background” that the boxes can also collide with. But soon I quit that idea to keep things as simple as possible. Instead, if I concentrate making the core mechanics better, I could always re-iterate and add new mechanics. Thus the falling boxes became the enemy. They are based on a pool of limited number of boxes which teleport to the top of the playfield. Making them feel like it is a continous random stream took some time to master and looking back, I think I have spent way too much time for this simple thing. Maybe I could concentrate on something more useful overall. Regardless, this is the postmortem…
Having enemies necessitated a form of health concept and being an infinite runner, I needed a sense of progression. I have implemented a simple UI and the health mechanics such that touching an enemy will cause loosing a life. For the scoring, I first implemented a simple system that the player gains points as the enemies touch the bottom of the playfield. Even though it worked OK and would made the player happy as s/he stays alive, I absolutely needed something that the player was in much more “control”. At the same time I was still not there with regard to the theme interpretation in my mind. Yes it feels like a puppeteer but there is no puppet!
Next I attached a third box in the middle of the two cursors hanging from the rope. Technically it is not the box being hanged. Instead I am increasing the mass of the center link of the rope to a higher value in reality (maximum stable simulation is reported to be an order of magnitude so I went for the maximum, making it 10 times heavier than the other links) and setting the position of another rigid body to match that position at every update. My initial idea was making the center item like a bowl that the player would collect the enemies. While experimenting with that idea I tried giving it angular velocity in the hopes of making the physics simulation more fun. In practice it turned out to be a cacaphony of physics objects flying around. Though at the same time I realized it looked just like a saw blade on the CRT screen without any additional rendering cost 😅 It also fulfilled the gap: I want the player to feel like fighting back the enemies! I then scrapped the idea of enemies constantly scoring points having a new scoring condition.
Tutorial (or the lack thereof)
I admit that at first there is a sharp learning curve until you learn the basics. This was an intentional design decision by me albeit it really made a jury member really upset from what I can understand from the score card 😎. Being probably the most controversial decision in the process, I think this was the most under appreciated part of the design, and probably I am to blame. Let me try to explain my justification.
In general I believe a good game should be able to teach its mechanics without the need for an explicit tutorial. This is true unless it has a form of micro management where things may not be immediately intuitive. Even then, the designer should seek out for ways to make it more intuitive. In my opinion tutorials break the immersion of the game if it is too obvious and take too much attention. So I wanted the game to express its gameplay with the least amount of explicit information while working on the core gameplay loop.
Assuming the game only supports the two controller mode (I then implemented a single controller fallback but it is like 1/10 of the experience), the obvious way of holding the controllers is one at each hand. Thinking back the theme in my mind - the puppeteer as the player - I thought it would be nice to give the player a mechanism to actually hold the cursors with their hands thus I incorporated the triggers as a way to actually hold them. Once you let them go, they start falling down just like the enemies. To transfer this information to the user the game only provides a text saying ”Hold both triggers to START”. On the other hand there are a few very important clues that the game provides to back it up. When you hold a trigger, the color of the cursor changes. So initially the player has a chance of realizing that pressing a trigger does something to the one of the cursors and once both are pressed the game starts, probably an enemy hits you in the face at the same time. At that point I expected the player to realize they needed to do something and the obvious thing is grabbing the control sticks. This is the whole tutorial sequence that I planned. It is likely that you relate controllers to individual cursors because they change color when you press triggers and once you understand you can control them individually and enemies are harmful you now know all the basics. It is then a matter of minutes to see you can kill enemies to score points.
I intentionally didn’t go for more information for a few reasons. The first one is I had limited time - not for improving the tutorial but for adding more content - so I planned this introduction sequence as a way of introducing more content to the game. At the beginning your whole objective is understanding what is going on and on my account the provided information was fair. If I also explained what each controller did and you can move with the sticks etc., it felt like I was holding the player back from that initial experience. Some might not find it fun but the reverse is also true. (watching someone going through that tutorial sequence is absolutely fun though) Also it is important to say that as the development continued, the game started to feel more like a coin-hogging arcade game so this fact intensified the concept. The second reason is providing the player something to keep playing, considering how simple the game actually is. If they had a quick failure I thought they would try it over and over until they grasp it, increasing the play time. And once they start investing more and more, they would get into the loop better. If all was explained, they might even say “meh” and stop playing a few minutes into the first few sessions. Finally, remember my thoughts on tutorials in general, I didn’t want to distract the player. The simple title screen with a blinking START served the arcade feel and the lack of information served the mysterious theme of the game. I would be even happier if I could get rid of the text and I think it would be possible with an autoplaying title screen (again serving the arcade feel well) where it visually hints at using two controller triggers and cursors getting enabled/disabled on their own. I planned such a feature but didn’t have time for.
To give a sense of increasing difficulty, I implemented an increase in gravity and the starting speed at which the boxes are falling. In addition, the number of boxes would also increase up to the maximum pool amount, which I chose based an my intuition. About 16 seemed like it was giving enough space in the playfield to be able to escape the enemies in a reproducible manner. At first the difficulty increments were bound to the total score. Even though the initial scoring system, where each missed enemy was adding a small amount of score, was resulting in a constant difficulty increase, it felt too out of my control. I moved on to a system where the level increases with time. This way I could fine-tune which event occurs when. For example I could adjust it such that in about a minute the playfield will become much more interesting w.r.t the starting condition providing the player with a quick lure to continue playing. Again I spent way too much time adjusting these parameters: starting enemy count, when to start increasing the count/gravity/speed and how much to increase them. It turned out to be a way of procrastinated other work. Still I don’t regret the time I put on that work because I think it turned out to be a nice difficulty curve. During a session it feels like it is constantly pushing your limits and make you want another round and at the same time the next time around you level up to a nice difficulty point quick enough that you would want to play one more round to break your high score. The new time based difficulty system also enabled the score multipliers such that as you play more, you would collect higher and higher rewards giving a feeling of better rewards.
There are also other factors making up the difficulty of the game though and it is primarily the unnatural amount of two hand coordination required. This was one of the things that the game was thought to be too difficult by the players. Still I think it was something that can be learned in a relatively short period of time. That was something I thought would make the game a little bit interesting while still keeping the core mechanics very simple. Because if you invest some time in it you get better at it and want to play more and game will throw more boxes at you as long a you try to keep alive. Still not something for everyone though and I could not change anymore as it was my interpretation of the theme 🤷♂️. I believe it was the right thing to do without introducing more complexity. As a final note, I think the game is not difficult because it is hard to understand what to do initially but rather because it is hard to actually play it, especially after a few minutes. It is easy to learn but hard to play master. That was what I intended to create at least.
Further Considerations and Polish
After the core gameplay and progression system was complete I figured there were a few rough corners. First of all there wasn’t a reason why a player would let go of the triggers. There must be something to encourage it. Simply you don’t take damage until they fall to the ground. At the same time you cannot collect points in that state. This can be used to dodge hard enemies if you ever got in a situation which you cannot escape. At the same time the game does not allow the player to just let go of the triggers and still progress.
Together with a strong sound cue, cursors blinking in red and screen shaking and flashing, it strengthened the initial “enemies are dangerous” thought. After trying a full screen transparent quad for the flash I decided to go for a background change as the performance was really bad with such a big read/modify/write. Sometimes the boxes jumped just right to hit you twice and it really felt unfair so I introduced the damage grace period. Because you can take damage and die after 3 hits, I decided that it would feel much fair if I give an opportunity to collect health. The new reinforcement mechanic acted like a two edged sword where the player can try getting a reinforcement thus going into a potentially more dangerous situation. I thought that would make things more interesting and make some near miss situations to increase interest in the game. Also note that health can only be collected via the cursors and not the blade, which is consistent with the mechanics.
Then I have added one final thing to the mechanics; restriction on how far the cursors can get away from each other. If you get too carried away with keeping the cursors safe and killing enemies the game shakes you by an unexpected death when the string between the cursors snap in a loud hiss. It is hinted with a white noise and color change when you get too close to this situation, again being its own tutorial. This was also designed as something the player will learn relatively later and I hoped it would increase interest in the simple premise of the game.
I started making the UI using the libdragon’s default font, which is not the greatest but in the end I kept it because it fit the arcade-vector look so well. Then I decided on the color scheme, which is primarily purple and a trace amount of red and green for health. This intensified the mysterious feel especially when combined with not so perfect pentagons of enemies. The player cursors on the other hand are perfect triangles which increase the feeling of having control in a chaotic and unpredictable world. The ground at the bottom being deadly made me add some visual noise to it to signify that it is dangerous but then it turned out to look like a portal and I went for the final name of the game, Voidblade. Among those things you can discover later, if you don’t let go the triggers after you are dead, the portal closes and physics simulation continues as long as you keep them pressed. Finally, after testing out a few chiptune music that I think might fit the game, I decided the best experience would be with an ambient soundscape. It uses two slowed down samples that are played at random rates over each other making a never-repeating track.
I know this has been a rather long post but apparently I had too many things in my mind regarding this simple game. Before I started development, I mainly worked on understanding RDP better but once I started building the actual game, I stopped worrying about technical stuff and primarily concentrated on core mechanics. I think it turned out pretty good considering how simple it is. It was enough to award the 3rd place beside two great games like Wizard of the Board and Mission Lost Control. Maybe if I could perfected the tutorial, I would win the heart of that last jury member 😀 This was a great experience to hone my game design skills without abondoning simplicity. I have spent about 80 hours into developing the game and most of it went into the actual design (especially balancing) rather than programming. I can say for sure that the code is a rather big mess as it was almost never refactored or planned.
One of the major things I could do better at was doing more user testing to pinpoint further problems in the tutorial sequence and overall gameplay. I had already improved it a lot thanks to a few sessions captured by the community but it was not enough. It is probably the major regret of mine at this point. Still I have learned a lot from this both on the system and game design in general. A game that looks very simple on the surface has many design decisions leading to that final product. I always appreciate how much work goes into a finished game and respect game developers and designers a lot. Hope you have read this quite long post.
Please let me know in the comments how could I improve my development process and/or your general thoughts. I will be posting a follow up on my high level understanding of the RDP next, so keep an eye!