itch.io is community of indie game creators and players

Devlogs

A Postmortem of RedShift Protoype

RedShift Prototype
A downloadable game for Windows and Linux

First of all, thanks to all who played my game! RedShift Prototype placed 1st Overall in Bullet Hell Jam 2021, and have received 18 insightful comments, thanks to you. Was it fun for you? I’m deeply grateful to you.

During the jam, some have asked me to do a writeup to document the process, and how the rewind mechanic was implemented. In this post, I hope to expose some of that.

Making the game

I have always loved bullet hell shooters, and made numerous attempts at making one in the distant past, but those never came to any fruition. The first “bullet hell” I ever made public is Designated Victim back in Ludum Dare 44, where it placed 18th Overall and 10th in Fun. Satisfied with the results of my first LD, I went on to experiment with other genres in a few more game jams that followed.

Until I saw Bullet Hell Jam in my inbox, I didn’t really have a recent plan to build a bullet hell again. As a result, I had to implement any systems from scratch. This did work to my advantage, however, since I was conversely able to architecture the code freely without the bounds of legacy code. This ended up to be somewhat beneficial to the rewind mechanic, as I will later explain.

When the theme, “10 seconds”, came out, I didn’t have any good ideas for it, and throughout the first day, I considered dropping out. It didn’t help that “X seconds” is one of the most common cliches in Ludum Dare slaughter rounds, one of which I have just finished before the jam. Eventually, however, I thought of something. A series of games that shared the initials with what my game was titled with. That’s what inspired me to make the mechanic of time reversal.

Turns out that even with some experience, the basic systems still took quite some time to code. I only finished all of them on day 3, by which time I still had zero content. I had to crunch quite a bit in the 4 following days, rushing out music, sounds, shaders and sprites, despite cutting a lot of content, even including the final boss that would have justified my game’s namesake (which is why it’s called RedShift Prototype, instead of just RedShift).

In the end, a lot of the game isn’t quite satisfactory, and I regret being unable to fully present to you what I had in mind. I never expected it to place #1, but to my surprise, people seemingly liked it despite its copious failings. Again, before I move on to more technical stuff, I’d like to thank you for reading this far.

Behind the rewind

While it might seem magical if you don’t know what to look for, the rewind mechanic is actually very trivial to implement. In a sense, I didn’t even implement it. Rather, I allowed it to happen.

If that didn’t mean anything to you, then consider an emulator of an arcade machine, or a classic console. Emulators often have this save-state feature, which allowed you to return completely to any early point in time: audio, graphics, game state, everything. Does this sound familiar to you? Yes.

RSP simply makes 60 save-states every second. That’s it.

Now, unlike emulators, modern game engines don’t usually support save-states, for a good reason. In an emulator, a save-state is just a snapshot of the RAM and registers of the virtual hardware. Making and restoring one is as simple as memcpy. That’s easy, fast, and bug-proof. Modern engines have much, much more going on internally, making such instant save-states infeasible to generally implement. That’s why I had to allow it to happen myself.

What I did is:

  • Consolidating the game state into a central SSOT. This makes it much easier to reason about history, than if the data is scattered in individual objects.
  • Programming the old way, being very stingy with dynamic allocation. This allows me to memcpy most of the state, speeding the save-state process up drastically, enough for it to happen in 60fps, even on low-end machines.
  • Writing the game logic in the system programming language Rust, instead of GDScript, for easy control of said low-level aspects.

With the help of high-level features in Rust, the Godot Rust bindings (full disclosure: I maintain it), and a heavily modified version of hecs, it was fairly easy to code the game considering all the constraints. Once the rewind itself is working, the rest of the game is made normally, since the mechanic works outside the game logic. I could easily use the intuitive model of state and mutation in enemy / player behavior, without fear that rewinds might somehow become screwed up.

While time reversal itself is not a new idea, it was a lot of fun implementing it.

What went right

  • Godot is a good engine and Rust is a good language. Those are what made the game possible in the first place.
  • The full-screen rewind meter was a success. I’ve always wondered about how the extra space on a modern wide screen monitor could be used in a traditional vertical scroller, and I’m glad I spent some time to make this one look right.
  • Crabs.

What went wrong

  • Time management. Contents take a long, long time to make. Many things in the game are far from satisfactory in quality:
    • The background animation is just a grid in perspective. This was originally intended for a tutorial, but ended up being using on the main game because I didn’t have time to make a real one.
    • The music isn’t finished. It isn’t arranged properly. It isn’t mixed properly. Some of the placeholder instruments made it to the end. It even has some stock drum loops from the DAW in it. Oh well.
    • Some of the sound effects are just made with sfxr. Bleh.
    • The player doesn’t have an engine trail.
    • There isn’t a focus shot pattern. It’s just the same as the normal one.
    • The mid-boss isn’t animated.
    • There is no boss. What?
    • The game ends very abruptly with no stage end animation and no ending.
    • The title screen is… the title screen. I’ll leave it at that.
    • I didn’t ensure that it’s possible to achieve a full chain. I did design the stage with that (somewhat) in mind, but I didn’t have the time to check.
  • Having worked with hecs for some while, I’m increasingly feeling that it’s being outgrown by my needs. I managed to patch it enough to fit the requirements this time, but eventually I might want do a hard fork of it or even reinvent my own wheels. Who knows?
  • There is no global or local leaderboard.
  • Replays are recorded internally but not saved, nor can they be loaded anyway.
  • The difficulty progression is not ideal. I didn’t have time to fully balance it out.
  • I didn’t have time to add a tutorial, and while the controls and hit-chain mechanics are rather standard, many details went unexplained. This led to a very low “Easy to get into” rank at #74, the lowest of all categories.
  • The theme isn’t that well-integrated into the game, in my opinion, despite the game ranking a decent #13 in the category. In my original idea, there would have also been a 10-second countdown boss at the end, which might have improved the result or not. I’m not sure how this theme can be implemented well, at all. Indeed, I didn’t really see anything that wowed me in this aspect among the games I played this jam.
  • The rewind mechanic is not very useful for survival, compared to a traditional life stock system. While I added the score-keeping effect for scoring, it doesn’t really help players who struggle to complete the stage. I might need to think this over if I’m to take the project further.
  • Many raters have noted that hit-rewinds can result in chain deaths. While I did anticipate this, and have added a release curve that delayed and then slowed updates for a short while after a rewind ends, it seems that the effect alone is not enough to prevent the issue. Hit-rewinds have the strong penalty of rewinding your score and removing your combo, so it might have been useful to add some extra survival benefits to them.
  • Right after the jam, I participated in Ludum Dare 48 that immediately followed, so I didn’t have as much time to play and rate Bullet Hell Jam entries as others had, and it took a long time for me to get back to those who rated and commented on my game. Apparently, this caused me to place higher than I deserved, according to some people in the community. If my placing made you upset, my apologizes to you. Please don’t give up.

Wrapping up

Despite previous experience in game jams short and long, time management is still one of my weakest points. I really need to learn how to plan my time better, not just for jams, but also for longer projects. And while personally I’m not very satisfied with the game, I’m very glad that people likes it nevertheless.

Thank you for reading to the end.

Download RedShift Prototype
Read comments (4)