What did I learn?
This project was made in a C++ framework taken from my Programming 2 course which I reworked based on the C++ design patterns that we were taught in our Programming 4 course. I learned how to read in game objects through a text file using a simple format. I learned more about the implementation of the Command pattern which I used to wrap actions into objects. I researched a maze generation algorithm which I used to generate the dungeon world consisting of separate rooms. I also used the Prototype pattern to create spawners which would in turn spawn enemies and randomize their stats such as, damage, speed and so on.
___________________________________________________________________________________
During the summer of 2021 I used a framework we receive in our first year of Game Development which has SDL and OpenGL implemented and I modified that framework to function like a small game engine.
I did this based on the design patterns we had just learned during one of our programming courses.
A component system was the first thing I implemented into the framework to prevent game objects from becoming monolithic classes.
The next general pattern I implemented was the command pattern. I used this to be able to wrap actions into objects. I mainly used this pattern to better manage my general user input.
Once I had the basic set-up ready, I went ahead to brainstorm some game ideas. The main idea I had for a game was a dungeon crawler. I had already used a maze generation algorithm to generate mazes of which the size was just a parameter that could be passed in by the user.
I implemented this maze generating algorithm into my engine and refactored it somewhat for it to work like a dungeon crawler world generator.
After that I started work on the structure of the enemies. I wanted to make everything very flexible by reading in data from text files and using that data to determine in-game events/mechanics. But before I got to using text files to determine in-game stuff, I just wanted to be able to spawn enemies in a smooth way.
For this I used the prototype pattern. I made a Spawner class which holds a pointer to an enemy component. This way I can just create a Spawner instance and pass it a pointer to the type of enemy I'd like to be able to spawn. I turn the enemy component into a prototype class by giving it a factory method called "Clone". The clone method simply creates a new game object and adds all components that the current enemy has, passing them the data of the current enemy to create a perfect clone.
Now i have a working spawner because I can just create a spawn method in which I can call the factory method of the prototype that it holds.
I then made an enemy manager which manages all spawned enemies, updates them, destroys them when necessary and spawns enemies based on an arbitrary number which determines the amount of spawners per room.
The next thing I wanted to make flexible was the item system in the game. I didn't just want to hardcode weapons and make a separate class for each unique item. In order to tackle that, I based the inner workings of all weapons that spawned in the game on bytecode in text files. This text file containes data about the name, damage, attack speed, programmed random occurence, weapon quality and the name of the weapon texture I want for that specific weapon.
I used this same method for ranged weapons and consumables for added flexibility.
The next workpoint was the rooms. I wanted different types of rooms: a normal room, a treasure room and a vendor room. The normal room just spawns an arbitrary amount of enemies, the treasure room is blocked by obstacles which you can break with a melee weapon (but this also breaks your melee weapon in the process so it's a win-lose situation). The treasure room contains a randomized weapon or item which you can pick up if your inventory isn't full. Ultimately, the vendor room contains three randomized items/weapons which all have a price which is based on the item quality. The better the quality of a weapon, the more expensive it is to purchase.
When I implemented this, I didn't have an economy system yet, so I implemented a coin drop with an arbitrary drop chance when you kill enemies.
Ultimately, I wanted to add a roguelike effect when the player died, so I just reset the world generation algorithm when the player dies and reset the player's inventory.
Conclusion
At the end, the game was put together in a flexible way, but the main goal was to practice the implementation of design patterns into an engine and a game AND to make sure that the world was randomly generated at the start of the game.
Sources:
Nystrom, R. (2014). Game Programming Patterns. Genever | Benning.
Nystrom, R. (2014). Game Programming Patterns. Genever | Benning.