Dungeon Crawler on Raspberry Pi

A 3D dungeon crawler game, inspired by “Gauntlet”, on a Raspberry Pi

About this project

For this project, we were tasked to create a 3D dungeon crawler game, inspired by the classic arcade game “Gauntlet”, running on a Raspberry Pi 4. This project uses 3D graphics using OpenGL, support for diffuse and specular textures, Phong-based lighting from multiple sources and .obj model loading. It also uses the Bullet library for physics, as well as ImGui for the UI. For the gameplay, it contains a procedural dungeon generator, two different player classes and three unique enemies.

This is a solo student project made during my 1st year at Breda University of Applied Sciences.

My contributions to the project

Since this is a solo project, everything was done by me. A list of my biggest contributions can be seen below:
3D rendering using OpenGL ES: During this project, I used OpenGL to implement a 3D renderer, as well as a bunch of neat graphical features. These will be listed below. 
3D model loading and rendering: I used the Assimp library to add support for loading .obj files. All meshes and textures are read and loaded into the engine. To reduce memory usage, unique models are loaded once and are stored in a resource manager. After they're loaded, they can rendered.  
Lighting using the Phong lighting model:   All 3D objects that exist in the level are lit using the Phong lighting model. This means that they have ambient, diffuse and specular lighting. When rendering an object, the three closest lights are used to light the model. In order to only apply specular highlights to areas of a model where it makes sense, support for loading specular maps (on top of diffuse maps) has been added.
Line drawing: In order to make the debugging process for physics objects a lot easier, line drawing was added. 
Physics using the Bullet Physics SDK: I implemented Bullet, which was a requirement for the project. I use Bullet for adding collision to the level.
Whenever a new game object is added, a physics object is added. This object contains all information that Bullet requires for creating physics objects, like its shape (box or sphere), what it's mass is and what it's group and mask are.
When running in debug mode, the physics collision shape is drawn using the line drawing system mentioned above. This makes it easy to debug whether the collision shapes look correct and whether everything is working as expected.
Procedural dungeon generation: In order to make the game more interesting, I implemented a procedural dungeon generator. The dungeon generator guarantees that there'll always be an exit, a key to the exit and a valid player spawn.
The way it works is that it creates a large room in the center of the map. Next, the generation system picks a random reachable wall tile and checks if it's possible to create a new room + hallway.This process repeats itself, and the dungeon will continue to branch out. After a while, a maximum number of "branches" are generated. When this is the case, the dungeon generator goes back to the center room and picks the next wall tile to branch out from. This process repeats until either a maximum number of rooms are generated, until there is no more space left in the level or until all wall tiles in the center room have been checked.
This generation system has proven to be very reliable, and has resulted in the generation of interesting and maze-like dungeons. 
Three different types of enemies: In order to make the gameplay a bit more interesting, I decided to implement three enemy types. These three enemies all have different attacks and health points. The three enemies will be listed below:
Melee enemy: The melee enemy does what it says on the tin: it attacks the player using a melee attack. When the player collides with the melee enemy, the player will take damage. This enemy deals relatively minor damage and spawns in Easy levels.
Shooting enemy: This enemy shoots slow-moving bullets at the player. When the player is hit by the bullets, they receive significant damage. The player is also damaged when colliding with the enemy, making this enemy a bit more dangerous. This enemy spawns on Intermediate levels. 
Throwing enemy: This enemy throws projectiles at the player if they are within a certain range. Projectiles move along a cubic Bezier curve, resulting in smooth movement of the projectile. The throwing enemy can only throw projectiles every second or so. The projectile deals a significant amount of damage when it hits the player. The enemy also inflicts damage when colliding with the player, making the enemy even more dangerous. This enemy spawns on Hard levels. 
UI using ImGui:  I added ImGui to the project, which I used for easily creating and rendering UI. This includes a main menu, a pause menu and in-game UI like a score counter and the player health. To make it look a bit better, I changed the ImGui window properties to show nothing but the text, and changed the default ImGui font with Comic Sans.

Quick overview

Project Type:  Custom Game Engine
Platform:  Linux
Tools:  C++
Role in Team:  Programmer
Project Duration:  8 weeks
Release Date:  April 14 2022
Team size:  1
Role in Team:  Engine programmer and Lead