In the summer of 2019, I had very recently started learning Rust and was looking for a project to work on in order to improve my Rust programming skills. I ended up deciding on making a game. I started searching for game engines using Rust and came across the arewegameyet website where I discovered the Amethyst game engine. Amethyst uses the entity, component, system (ECS) paradigm to organize data and logic. At the time my only prior game development experience was with Unity, Pygame, and LÖVE2D, so ECS was very new to me. However, despite my unfamiliarity with ECS, I ended up deciding to use the Amethyst game engine to make my game, currently called space_shooter_rs.
One of my favorite games of all time is The Binding of Isaac. To put the game simply, the player progresses through a series of floors each composed of a maze of rooms containing enemies. At the end of the maze there is a boss which the player must defeat before progressing to the next floor. Most of these rooms contain enemies, which the player can defeat by shooting with tears. On each floor there is an item room and a shop room where the player can collect items. When items are collected, the rules of the game are permanently modified for the rest of the run. Some of the items are simple stat upgrades, such as increasing the damage or fire rate of tears. Other items affect different parts of the game such as giving the player vision of each floor’s maze, modifying prices in shops, or allowing the player to see through walls. As I have worked on space_shooter_rs, I have frequently drawn inspiration from The Binding of Isaac.
The first thing that I wanted to implement in space_shooter_rs was a satisfying way to shoot at enemies. This is one of the many things that The Binding of Isaac does really well. In particular, in The Binding of Isaac, the velocity of shot tears are influenced by the velocity of the player who is firing the tear. This makes firing shots a lot more interesting than just pressing a fire button. It also creates a much higher skill capacity for shot accuracy which contributes to making the game more fun and replayable. In this commit to space_shooter_rs, I changed the blast firing to factor in the player’s velocity.
A comparison between the shot velocity in space_shooter_rs and The Binding of Isaac.
Since then the project has also gained a collision system:
Collisions in space_shooter_rs.
“Barrel roll” active ability (with cooldown bar):
Barrel roll ability in space_shooter_rs.
An item store with 12 items:
Purchasing and collecting the 'plasma blasts' item from the store in space_shooter_rs (increases damage and fire rate).
4 consumable drops:
Enemies dropping consumables in space_shooter_rs (currency and blue defense wrench).
A WIP boss:
The work-in-progress 'Repeater' boss.
Also, 3 enemies, an ally, a level phase system, sounds effects, animations, status bars, and 3D background objects.
Pushing the Project Forward
Most of the front facing features in space_shooter_rs listed above were added in 2019. Around 2020 progress made on the project drastically slowed down to making no progress at all. This was in part due to other commitments I had, however, I attribute this more to the disorganization of the project. There were many days when I wanted to spend an evening working on a feature for the game, but soon after I would open the space_shooter_rs code to work on it, I would become overwhelmed and confused. I typically would end up not adding anything. This was very frustrating for me because I had a lot of cool ideas that I really wanted to add to the game. The state of the project was preventing me from adding the features that I wanted, and if I did add a new feature it would only dig a deeper grave for the game because the code for the feature would compound onto the already disorganized code.
Fast-forward to August of 2020 when an all online Rustconf is happening. When the speaker lineup was released, I looked over the topics people were covering and immediately noticed that Micah Tigley @tigleym was going to do a talk on her experience with ECS and the Amethyst Game Engine. After Rustconf, all of the talks were uploaded onto Youtube. This is where I watched Micah’s talk: “My First Rust Project: Creating a Roguelike with Amethyst”.
In the talk, she covers her experience learning ECS and Amethyst, how she implemented animations, and gives a great explanation of what ECS is. After I watched this talk, I was inspired to try working on space_shooter_rs again. I ran into the same frustrating roadblocks as before. This is when I began considering reaching out to Micah. She seemed like someone who enjoys working on games in their free time, had industry experience working at Mozilla, and seemed like someone that I could learn a lot from. I ended up reaching out to her to see if she was interested in teaming up with me to work on space_shooter_rs. She responded saying that she was interested, and since then we have worked on space_shooter_rs together for about a month.
Learning Together and Making Progress
For the past month Micah and I have been making regular contributions to space_shooter_rs mostly focused on refactoring code to conform more to ECS. Most of these refactors consist of dividing a single large component that is very specific to a particular type of entity into many smaller components that can be used in many different entities. For example, previously, I created a single component called “Spaceship” containing data for the entity’s hitbox, health, blaster, motion, etc. In this past month, we have divided this single large Spaceship component into a HealthComponent, Motion2DComponent, Hitbox2DComponent, BlasterComponent, and ManualFireComponent.
Since beginning our work together on space_shooter_rs, we have also added a few enhancements to the game. One of the issues that I worked on was refactoring the hitbox data used across many entities into its own dedicated hitbox component. After I was satisfied with the new Hitbox2DComponet, I implemented collision detection between rotated hitboxes using the separating axis theorem (SAT). In the future, this will allow us to add more interesting enemies such as missiles that rotate to face and home in on the player. I also currently give a rotated hitbox to the arms of the repeater boss, which spawns in the last phase of the game.
The current version of the 'Repeater' boss has rotated hitboxes on top of the arm segments.
Micah added a new item that increases the visual size and hitbox size of blasts. When the item is acquired, it increases the scale of the blasts’ Transform component and increases the width and height dimensions of the blasts’ HitboxComponent.
The new 'Blast Size Enhancer' item.
Learning Collaborative Coding Practices
Besides contributing to the game code itself, Micah has taught me a lot about collaborative coding practices using tools like git and Github. In the past I have done some collaborative projects, but they have always had some level of disorganization due to me not knowing about tools, or not effectively using tools to aid in collaborative programming. One very important thing that Micah brought to the project was a formal method of writing issues, making feature/development branches, making pull requests, and doing code reviews before merging. After just a week of working with Micah, I added her as a maintainer for space_shooter_rs. I could tell that she was serious about working on the project, so I didn’t see any harm in elevating her privileges. This gave her the ability to manage issues and pull requests without having to go through me. Which in turn allowed me to pick up on what she was doing and start doing it myself. The general process is the following:
- Find or create an issue describing a change that should be made in the code. It is nice to make issues detailed, but if you don’t know the details at the moment it is better to submit the issue with the information that you do have. Issues can always be edited and commented on later. Before submitting the issue, add relevant tags so that it can be easily searched and identified.
- Create a new branch from the development branch to work on your changes.
- Address the issue by making changes to the code in your new branch.
- When you are satisfied with the changes in your branch, make a final commit and create a pull request from your new branch into the development branch. Make sure to request reviews from the relevant people involved with the project.
- Wait for your code to be reviewed.
- When your code is reviewed, look through each comment. If you agree with a suggestion and it makes sense to you, make the change and mark the comment as resolved. If you have a counterpoint for the review comment, make your case and leave the comment unresolved.
- Make changes to your branch addressing the review comments. Then commit the changes to your branch.
- Repeat steps 5 to 7 until you and the reviewers come to a consensus. At this point the pull request can be merged into the development branch by any one of the repository’s maintainers.
Keep in mind the general process listed above is currently what we use between us both being maintainers of space_shooter_rs. When making a contribution to a project you are not directly involved with, you cannot have the expectation that your pull request will necessarily be accepted. This is why it is a good idea to let the maintainers of the project know your intentions by submitting an issue before working on a contribution.
Sharing Ideas with Collaborative Documents
Having started working on this game more than a year before Micah joined the project, I have had a lot of time to think about the structure and features that I want to include in the game. Now that there was another person working on the game, it was important that I get these ideas out of my head and into documents, so that we can be on the same page, and so that I can get a second opinion on the ideas. Since Micah joined the project, we have made many documents for logging ideas down. The first document I created was about the current state of the game. This document mainly contained an outline of the entities, components, and systems in the game. This was meant to help Micah navigate the already large and somewhat disorganized project. The next document I created was called the “Ideal State” document. At the time of creating this document, I already knew that large components had to be broken down into smaller ones, but this document was for logging exactly what smaller components I thought we needed at the time. Later as Micah became more familiar with the project, this document turned into a place where we can share ideas about features we think would be cool in space_shooter_rs. I think it has been very healthy for this project to have a place where collaborators can casually throw ideas around without needing to go through a formal issue filing process. The last document that I’ll mention here is our minimum viable product (MVP) specification. In this document we created two MVPs, one for space_shooter_rs as a public showcase game for Amethyst, and the second MVP for a potential release of a full game built off of the foundation of space_shooter_rs. Below is a rough outline of our current MVP for space_shooter_rs as a showcase game.
- 3 stages
- 4 characters
- 50 Items
- Store to buy items
- Health, defense, armor, currency, and power-up consumables
- 9 Enemies
- 3 bosses (1 for each stage)
- Menus (main, options, character selection)
A couple weeks into Micah contributing to the game, I realized that I had a basic idea for the structure and flow of the game in my head that I hadn’t yet shared with her. Even though we are still pretty far from being at a point where we will be working on the game’s progression, I think it is still important to get all collaborators on the same page. This way we can start exchanging feedback and ideas now. I created a game progression flowchart that used basic flow logic to describe how a player would progress through the levels of the game. Here is a section of it as an example.
A section of the progression flowchart for space_shooter_rs.
We also used drawings to share ideas on refactoring code. For example, Micah created a flow diagram to explain how event chaining would be used to manage collisions.
A diagram showing how collision events are chained.
This diagram was very useful for me to reference when reviewing her code so I had an idea of what her intent was when making the contribution. This diagram will also be helpful for future contributors to the space_shooter_rs project when working on collision based features.
space_shooter_rs still has a long way to go before reaching the point that we specified in the showcase game MVP. We still have a lot more refactoring to do and we still have a lot of new features that we want to add after that. This project has made a lot of progress this month after I teamed up with Micah, and I’m excited to see where this game ends up in the future. Micah has also written about her own experience working on space_shooter_rs, you can find it here.