Back in the beginning of 2019, when I officially started working on this project, I really had no clue what I would end up with, whether I would be successful or not, or even if I would enjoy what I was doing. Reflecting back on what I’ve accomplished, I’m proud of how far I’ve come. I have learned so much about the process of game development, a field that has interested me for a long time. As an engineer and a rather avid gamer myself, I can’t help but wonder about what is under the hood of the games I’ve found so entertaining. This experience has allowed me to build a new perspective from the developer’s point of view, and I am grateful to have such an opportunity. I found the project stimulating and intriguing; perhaps most importantly, I enjoyed my time working on it. I won’t be surprised if I find myself working on small hobby projects similar to this in my spare time, using the new skills I have learned these past few months. Overall, I am happy with the experience that I gained, and I am confident that I will use my newfound knowledge in the future.
Month: June 2020
Update 2 – Playin’ Games
Over the past few months, particularly since school ended for the semester, I’ve been working diligently to smash this project out of the park. If the COVID-19 pandemic has been good for anything, it’s widespread quarantining rules have made me unnaturally free to spend my time on projects like this one. If you need a short recap: I decided to use my capstone as an opportunity to endeavor on a learning experience in the growing field of game development. I’m happy to say that I’ve learned a lot about the process of game development; whether it concerns the game art, sound effects, music, coding, or just overall gameplay, I’m thoroughly entertained and satisfied with the work I’ve been able to produce. Of course, I’m no professional game developer, and the game I managed to create is far from flawless, but I am content with my progress and it is something I will certainly pursue as a hobby (or even potentially a career) in the future. With that being said, I would like to unveil my project in it’s final stages.
Setting Up:
The last update, frankly, was a while ago. Unsurprisingly, I’m leaps and bounds ahead of where I was at when I posted that, but I wanted to use what I had created to move forward. Eventually I decided to try to implement an Asteroids style arcade game, which exclusively used Movement Style 2 from the first update. Implementing this was easy, as I had already written the code for it before. After getting movement working, I experimented with screen wrapping, which is the famous visual effect used by Asteroids such that when an asteroid or ship moves off one side of the screen, it appears on the opposite side, as if the world was ‘wrapped’ around a cylinder. Interestingly, the Godot engine provides a nifty little function that takes care of this effect, should you want to add it to your game, which made implementing it nice and simple.
Asteroids:
Of course, one can’t create an Asteroids style game without asteroids. At this point, with the movement and screen wrapping working, it was time to add asteroids. With little knowledge on how to do this, I inquired the help of the internet and stumbled upon a nice set of tutorials to walk through building a game of the same style I was attempting to implement. From this point on, I used the online tutorial created by Youtuber KidsCanCode to guide my journey through the creation process of this game. Unfortunately, the tutorials were quite old, leading to a not insignificant portion of instructions to be out-of-date or in conflict with newer builds of the game engine. This issue, as well as some stylistic and creative decisions made by myself that differed from the tutorials ensured I derived my own end result.
Nonetheless, I learned how to implement asteroids in the game, creating my own sprites for different sizes (Large, Medium, Small). I programmed the asteroids to each spawn in one of eight locations around the screen, shown here (spawn locations are the red and green crosses forming the rectangle around the player):
Several bugs revealed themselves quickly, and while most of them were to the fault of a minor code error, one bug required more attention to fix. The asteroid spawning algorithm originally just spawned several asteroids randomly at any one of those eight locations. But what if one or more asteroids tried to spawn at the same location at the same time? This issue became apparent when I added collision detection to the asteroids, so that asteroids would ricochet off of one another if they collided. In the case where two or more asteroids spawned in the same location, the areas known as ‘Collision Shapes’ would detect overlapping asteroids and cause unpredictable behavior. I eventually created a function to generate a list of numbers that corresponded to unique and random spawn locations for each asteroid to be spawned. The code was ugly, probably really inefficient, and I’m sure there is a better way to solve the issue, but with limited familiarity of the GDScript language, this is what I came up with:
If I was more concerned with efficiency than I was about getting it working, then I probably would have spent significantly more time on this algorithm; but I wasn’t, and it worked, so it was good enough for me.
Lastly, I set up functions to allow the asteroids to split into smaller and smaller asteroids should they be hit, as well as more screen wrapping. The code here was rather interesting, but for the sake of space and time, I will spare all of the technicalities of this process.
The Player:
The player, of course, had already been set up for the most part; it had the ability to move in a ‘space-like’ fashion and the user could control the ship using the keyboard. As I was getting more familiar with the use of collisions, setting up the player collision box was relatively easy and allowed for me to set up for player death. A player would die in any of three scenarios: the player collides with an asteroid, the player collides with an enemy ship, or the player gets hit by an enemy ship bullet. After creating functions to handle these specific events, I wanted a break from coding, so I added an animation that played when the player ship ‘dies’. The primary tool I used to create sprites and sprite sheets (game developer terms for pictures and animation frames) is a free internet browser pixel editor called Piskel. Here is the ship explosion sprite that I created using Piskel‘s toolkit:
After dealing with player death, I came to the realization that I needed to track several variables important to the game, such as: number of player lives left, the score, the level number, whether or not the game was over, how many points each asteroid was worth when destroyed, etc. I figured it would be a good time to add a global script. This is useful to track variables that are crucial to the whole of the game. In this file I created variables that defined each of the criteria I mentioned above. I also, at the advice of the tutorial, added a ‘New Game’ function, that I could call whenever I would need to in order to reset the game variables and restart the game. A part of the global file is shown below:
Finally, the player is completely helpless without the ability to shoot. This was rather challenging, as each bullet was spawned as its own instance, moving in the direction away from the front of the ship. Each bullet also had its own collision box so that colliding with an asteroid or enemy could be detected. In the case of a bullet collision, the entity that it collided with (i.e asteroid or enemy ship) explodes and the bullet itself is removed from the game. To do this involved using a component of Godot called signals, which is essentially a virtual alarm that rings when certain events occur. In this case, I constructed a signal (that fires when a bullet collides with another body) to ‘signal’ the body (i.e asteroid or enemy ship) that it needs to explode. Confusing? Potentially. But, nonetheless, this method worked beautifully and at this point, the game had a user controlled player with asteroids that can be shot and collided with. The more I use these techniques, the less confusing they become.
The Enemy:
Next, I wanted to add an enemy so that the asteroids were not the only obstacle for the player. To implement the enemy, I created 4 different paths for the ship to follow. Shown below is what the paths looked like:
After successfully getting the enemy to spawn and fly on one of those paths, I worked on the enemy’s ability to fire at the player. This required some vector math, which obligated me to relearn some old physics material, but overall it wasn’t too complicated.
Power-ups:
At this point, the tutorial lessons I was using as a guide differed from where I wanted to go with my game. I felt that having some sort of power-up mechanic would add something unique. Since the tutorials did not address anything similar to power-ups, what I created with this idea is entirely my own and effectively utilized the new skills and techniques I had learned over the course of making the project. As of now, I have implemented three separate power-ups: Invincibility, Rapid Fire, and Extra Life, each of which are exactly what they sound like. Here is the code that was used to spawn a power-up:
When a power-up is spawned, it is given a ‘kind’, which signifies which of the three power-ups it will become; this determines which sprite to use. It is also randomly positioned at one of four spawn locations and relies on a series of timers to measure how long it can be collected, as well as how long it’s effects last after it has been collected. Here are the animated sprites that I created for each of the power-ups:
Game Art and Polish:
Nearing the end of the development of the actual game play, I still desired that my game look and feel pleasant. The game was still visually rough, and while I’m not a professional graphic designer, nor maestro music composer, I figured I’d give it my best shot to sand down some of those rough edges; after all, it’s all about learning and having fun. I quickly learned how to make a HUD (heads-up-display), which shows the level, score, number of lives, and a power-up timer on the screen for the player to see at all times. I also added a pause menu, and main menu, both of which have functional buttons to start and quit a game. The background used for the game and the main menu was fashioned using Procreate.
Afterward, I designed several animations and particle effects that were added to make the game more visually stimulating and pleasing. The following are multiple examples of these cosmetic improvements:
Finally, all of the sounds and music in the game are unique and were produced by me. I used a free, online, 8-bit sound making tool called BFXR for all sound effects present, and I composed the music for the game in iOS’s Garageband.
Thus, I officially finished my work on this game. There are still plenty of bugs that could be fixed, rough edges that could be buffed out, and extra content that could eventually be put into the game, but I’m satisfied with where I’m at. I believe now is a good time to take a break and focus on the rest of the capstone. With that being said, here is a video of myself playing the finished product:
Resources and Helpful Links:
Game Art:
- Procreate: https://procreate.art/
- Piskel: https://www.piskelapp.com/
Game Music and Sound Effects:
- Garageband iOS: https://www.apple.com/ios/garageband/
- BFXR: https://www.bfxr.net/
- SFXR: http://sfxr.me/ (I didn’t use this one, because the download links have issues, but still produces nice effects)
Game Engine:
- Godot Engine Main Page: https://godotengine.org/ (Can also be downloaded through Steam)
- Documentation: https://docs.godotengine.org/en/stable/index.html
Tutorials:
- Tutorial Playlist for “Space Rocks” by KidsCanCode: https://www.youtube.com/watch?v=8NNgZpABmLE&list=PLsk-HSGFjnaGcjiD8y9-U_C0rB5kpDX5s
- Tutorial Playlist for Godot 3 by Gamesfromscratch: https://www.youtube.com/watch?v=iDEcP8Mc-7s&list=PLS9MbmO_ssyDk79j9ewONxV88fD5e_o5d