jmwhitworth's pygame dungeon game git repository banner

A custom game engine with Pygame

This project was a fun one. It’s a game built using Python 3.10 and Pygame 2. The game itself is a dungeon-crawler where the player must navigate a labyrinth of rooms to find a large gem and win the game. The map and locations of spawns are all fixed, so there is no procedural generation or anything as fancy as that. However, the loot drops are all randomised, player stats, enemy stats, loot drops, and everything else in the game is persistent and, as the player navigates from room to room, room progress is saved.

Goals & Features

  • WASD/Arrow Key movement and full collision detection
  • Player and enemy health stats, allowing combat
  • Loot / Treasure to collect, adding to the user’s score
  • Levels/maps loaded from external files to allow world-building without code
  • Room states save upon exit and reload when loaded back
  • Full character animations
  • Full audio implementation

Tech Stack

Demonstration

As you can see above, the game has a style similar to early Pokemon/Zelda titles. It’s a semi-top-down view where you can move a character around using WASD or arrow keys. The rooms/levels are laid out with tree-stump-esque blocks that the player collides with and cannot pass through. Other sprites with collision include trees and treasure chests. On the screenshot above you’ll also see plenty of foliage/plants around resembling grass. These have no collision so the player can pass through freely.

There are pieces of treasure such as gems and coins that are dropped by enemies and treasure chests when they are destroyed by the player. The treasure can be collided with to collect them and add their value to the player’s score. The enemies in this game are little ghost-orb sprites that I used as I found them to be quite adorable and within the same pack as the majority of the sprites I used elsewhere in this project. All sprite credits are provided in the Github repo, in case you are interested. The enemies will path toward the player if the player goes within their targeting range, and will attack the player upon entering attack range. The player can take multiple hits from the enemies without dying, however, enemies all die in just a single hit, making them simple to defeat.

Now that you understand the core elements of this game, the goal is simple: The player must navigate the rooms of the maze/dungeon and find a special large gem in order to win. This gem can be considered the exit to the whole game and upon collection, the game is reset and the player’s score is displayed in the centre of the screen. The player’s score is determined by the quantity of treasure they have managed to collect before reaching the game. If the player’s health drops to or below 0 before they reach the gem then they are considered dead. When this happens the game resets and the player is invited to try again.

Diving Deeper

I really enjoyed this project and, while it is definitely nothing more than a prototype, I’m proud of the state I’ve left it in. As far as I’m aware there are currently no game-breaking bugs. The core system behind the whole game was built from scratch and this project really allowed my Pygame knowledge to click and I feel I’ve very much levelled up in my own skills, having now done this.

If you’re interested in learning Pygame or Python, the best way to do it is to just get coding. I can guarantee that most people will give you this same advice because it is a simple truth: The best way to learn something is to just start doing it. Don’t worry if you feel like you suck at it at first, just keep pushing forward and, before you know it, you might be surprising yourself with just how much you’ve learned.

While I consider myself to be very familiar with Python, having used it for many years, I’m constantly learning and this project gave me a great deal of valuable experience that I will carry into future projects.