The Shooting of Isaac: Rebirth
The Shooting Of Isaac was a student holiday project that I did during Christmas 2013. In July 2020, seven years later, I finally found the time to start developping a remake with better mechanics and graphics, using the assets from The Binding of Isaac: Rebirth. Thanks to the Afterbirth+ DLC and its modding capabilities (data extractor and in game console), I had access to every file in the game, allowing me to be as close as possible to the base game. The wiki website of the game also helped me tremendously.
The Shooting of Isaac: Rebirth is a 2D vertical shooter in which you play as one of six characters, each one with their own statistics, going through various levels filled with enemy to kill for score and a boss at the end. From time to time, there will be items spawning coming down the screen to pick up. You can have three items at a time and their effects synergise with each other to change your gameplay or give effects to the tears you shoot. If you already have three items and see one you like on the floor, you can select which one you want to replace in your inventory (tab / RB by default) and the new item will go in its slot. Between each level, there will be a shop where you can heal and buy new items. When the end boss is killed, or when you die, you’ll be able to enter a name and save your score.
I wasn’t really pleased with some aspects of my first game, limited by the time or my skills. The first thing that comes to mind is the Technology (laser instead of normal tears) + Wiggle Worm (sinusoidal tears) synergy, which should have resulted in a sinusoidal laser, instead of a straight one moving left and right. Having this in mind, I wanted to readapt the synergies to have cooler effects. Even if Wiggle Worm is not in the Rebirth version, Technology got some nice reworks, one of them being the combination with Spoon Bender (homing tears) to make a homing laser that goes from its starting point to the enemies on its way.
This is the first big project that I’ve done with FaZoN, my personnal SFML based framework, using C++ and a bit of C# in Visual Studio 2017 and 2019, and I’m quite pleased with the result. Working with my framework made me tweak and upgrade it a lot, since I had a lot of needs throughout the production. I, for example, had to add an entire new animation system that could use the files coming from the base game, instead of converting them to what I already had. This took some time but I’m glad I did it because it was much faster after this, I could just take the .anm2 files of the base game and paste them in my game directory and it worked instantly. It also was a much better system than the rudimentary one I had at the time.
Like I said with the animation system, all the additions to my framework took time to do and surely slowed the production down a bit, but I’m glad I did them because FaZoN is better now than before and future projects will go more smoothly.
One of the big steps I had to go through during development was how to manage my enemies, I had a good number of them planned and didn’t want to go with inheritance as it would have created a lot of class with little amount of code in them. What I did instead was to look what actions and triggers my enemies needed and put them as separate functions to be called by my unique enemy class via an array and action descriptions. For example, two enemies that shoot bullets will both call the shoot function I created, but with different descriptions detailed in an XML file and stored in the enemy class.
On the picture above is displayed an example XML of an enemy, it is one of the first I created. We can see the functions block in red, the animations block in green and the sounds block in blue.
There are three types of functions:
– Movement, describing how the enemy move (random behavior, chasing the player, etc…).
– Action, describing what the enemy can do (shoot, charge, etc…).
– ActionTrigger, describing how and when the enemy will do an action (proximity with the player, timer, etc…).
Movement functions are cumulative, for example, an enemy that have a function that chases the player and an other one that make it move randomly, will make the enemy go towards the player in an eratic and random manner instead of going straight to the player.
Later on, I added behavior trees to the enemies, it also took a bit of time but really smoothed the process with some of them.
I worked on a system allowing me to call enemies action functions from within the behavior tree, which made a lot of things easier as I just had to fill a name of an existing function instead of creating variables and initialise them in a behavior tree task.
We can see the occurences of the action function squared in red in the behavior tree highlighted in green in the image above.
At first, I was editing my XML files by hand, but it quickly became more and more difficult as I had more and more variables to put in and affect and remember which variable goes with which function. To make things easier for me and also work faster, I created an editor which read my files and put everything in a nice ImGUI window for me to tweak. It helped a lot once I started messing around with behavior trees aswell.
It also let me have a window displaying all my enums and masks values clearly so I wouldn’t have to have a file opened on the side displaying which value corresponds to which enum field or mask bit.
Creating this editor was also a way to create and work on my enemies patterns. While the first enemy I created shot a single bullet toward the player, others were far more complicated like Mom’s Heart which had multiple phases and shooting behaviors to look at. This meant that not only did I had to manage a behavior tree, I also had to have a place to handle my patterns and most importantly preview them.
The two videos above show the edition of a pattern (left) and the preview of some of the ones I created for Mom’s Heart. When Isaac is displayed, it means that the patterns adapts to the player’s position:
– The brimstones (red lasers) will rotate towards the player (the player is on the left of the bottom right laser, so the rotation goes to the left).
– The single line of bullets (0:47) simply shoot at the player.
– The five bullet lines one (0:56) rotates the opposite direction of the player.
Since I don’t own the graphic and audio assets, but share my game on my github, I wanted to protect its data. It has always been a goal for me to crypt data since that’s what you’re supposed to do with your productions but since mine have always been little student projects, I never looked into it till now. I won’t go into too much detail here to keep the security up on the assets. What I can say is that it was a bit difficult to wrap my head around it at first and I may change the way I did it in the future but I’m glad I did it and I now have a working encryption system for my projects with a nice Windows Forms application to make it easier.
The application is divided in three parts:
– On the left is the hierarchy of the “raw” files, the ones I’m going to encrypt. I can check a file or folder and build only the checked ones, or build all my assets at once with the buttons just below. By default, the application doesn’t overwrite existing files but I can force it by checking the “Force Build” checkbox, in case I modified a file and want to encrypt it again for example.
– On the right is the hierarchy of the encrypted files so I can see if everything is there. From there, I can also decrypt a chosen file to see if the encryption worked well, it’s more of a debugging feature. I added a “Delete Decrypted Files” button to clean the decrypted files before copying my data folder for a release.
– At the bottom is the progress bar of the encryption with the current count of encrypted files and the console indicating which file is being processed. If the file already exists and I’m not forcing the build, there will be a gray “skipped” text instead of the “encrypting” black we see on the screenshot.
During development, I streamed on Twitch to make myself an archive and show people what I was working on. I started around the time I was working on the editor and stopped (for now) when I started working on the encryption so all the production is not on there but you can check the playlists of my streams on Twitch and also on Youtube.
This project was really challenging and I’m glad that I got people to help me with it from time to time, so I would like to thank Rémi Maigné and Jérôme Benvenuti for their assistance and suggestions, but also Simon Parzer, lead programmer on the base game, who answered some of my questions about the game, and everyone around me for their support during the development.
You can download the alpha version of the game below. It’s not entirely finished yet, but it’s in a showable enough stage for me to share it.