A small top‑down dungeon crawler built with Pygame and TMX maps. Find keys, unlock doors, avoid traps and enemies, and reach the exit ladder to escape. Includes a main menu, level select, and an in‑menu Instructions screen.
- TMX maps via PyTMX with animated tiles and decorations
- Player movement, combat, HP, score, and inventory (silver/golden keys)
- Doors with key requirements, spike traps, collectibles (coins, potions, keys)
- Enemies with simple AI and death animations
- Fog of war effect and a camera with zoom
- Menu system: Main Menu, Level Select, and Instructions
- Sound effects and music with a central Sound Manager (mute toggle in menu)
- Move: W/A/S/D or Arrow Keys
- Attack: Space
- Interact/Use: E (e.g., ladders)
- Pause: Esc (Resume/Retry/Main Menu/Quit)
Menu navigation
- Up/Down or W/S to move the selection
- Enter/Space to select
- Esc to go back
Instructions screen
- From the Main Menu, choose “Instructions” to see an in‑game quick guide with controls and tips.
These are available for testing but hidden from the on‑screen HUD:
- F1: Give silver keys
- F2: Give golden keys
- F3: Restore full HP
- F4: Toggle invincibility
- F5: Kill all enemies
- F6: Teleport near exit
- Python 3.10+ is recommended
- Install dependencies from requirements.txt
- Ensure assets and maps folders remain in place
Quick setup (Windows, cmd):
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txtFrom the project root (Windows, cmd):
.venv\Scripts\activate
python src\main.pyAlternative (if you prefer the launcher):
py src\main.pysrc/– game codemain.py– app entry with menus and state managementgame.py– game loop, entities, HUD, screensmap_loader.py– TMX loading, animated tiles, layersplayer.py,enemy.py,door.py,ladder.py,trap.py,collectible.py– gameplay entitiessound_manager.py– music/SFX loading and playbackcamera.py,fog_of_war.py– rendering helpers
maps/– TMX levels (e.g.,level1.tmx,level2.tmx)assets/– sprites, tilesets, and UI art (plus optionalassets/menu_bg.pngfor menu background)sounds/– audio files
- If you get an audio device error, try updating Pygame and your audio drivers, or set a different SDL audio driver in the environment.
- Window is too large? Change
window_sizeinsrc/main.py. - Performance: running without a debugger and closing other heavy apps can help. Ensure your Python and Pygame versions are up‑to‑date.
The following section is the original mechanics overview for this project. It documents how TMX properties map to runtime behaviors and is useful for level design and implementation reference.
This document summarizes all gameplay mechanics, inferred behaviors, and runtime systems based on the TMX level provided. Everything is grouped by feature, with clear priorities and implementation hints.
TMX Data:
object Player Spawn (id=8)
obj_name: player_spawnx=62.66, y=46.66width=19.33, height=20
Behaviour:
- Player spawns at this position when the level loads.
- Treat
(x, y)as the mid-bottom anchor of the player.
Notes & Hints:
- Since tiles are 16×16, player sprites should be ~16×24 in visual size.
- Normalize the hitbox to tile units so movement feels consistent.
TMX: Collision tile layer containing many solid tile indices (e.g., tile 79).
Behaviour:
- Used for physics/collision checks for players, enemies, objects.
Hints:
- Build a collision grid at runtime from this layer.
- Resolve collisions separately on X and Y.
- Use
pygame.Rectfor tile rects.
TMX Objects: Door (id: 2, 3) and FinalDoor (id: 5)
obj_type: doorrequired_key: silver/goldencount: 4 or 2- Optional:
orientation
Behaviour:
- Doors remain locked until player has enough keys.
- Interacting/overlapping checks if:
inventory[required_key] >= count
Hints:
- When unlocked: remove collision, play animation.
orientationmay determine which sprite animation to play.
TMX Objects: id 11–16
obj_type: collectibleitem: keykey_type: silver/goldenframes: 4
Behaviour:
- Picking up a key increases inventory of that key type.
- Used to unlock doors above.
Hints:
- Remove key object after pickup.
- Update HUD to show counts.
TMX Objects: many (id 19..22, 30..36)
item: coinvalue: 10frames: 4
Behaviour:
- Increases score on pickup.
- Animated coins provide visual feedback.
Hints:
- Play coin SFX.
- Spawn small particle effects if desired.
TMX Objects: id 39, 40
item: potionheal: 25frames: 4
Behaviour:
- Heal player HP by given value.
- Could be auto-use or stored.
Hints:
- If instant-use: flash HP bar.
- If stored: show count on HUD.
TMX: Ladder (id=18)
obj_type: ladderdestination: "level2.tmx"
Behaviour:
- Touching/interacting loads the next level.
- Player respawns at the next level’s spawn point.
Hints:
- Implement fade-out → load → fade-in.
- Ensure camera resets properly.
TMX Objects: ids 45, 46, 47, 59, 61
obj_type: enemyobj_name: skeleton1- Tile size 32×32
Behaviour:
- Spawn enemy at given coordinates.
Hints:
- Suggested simple AI:
- idle → patrol → chase
- chase when player within radius
- Make collision hitbox smaller than sprite for fairness.
TMX Objects: ids 86–110
obj_type: trapobj_name: peaksdamage: 25frames: 4frame_duration: 0.15
Behaviour:
- Animated spike traps.
- Damage player when overlapping during “active” frames.
Hints:
- Give player i-frames so spikes don’t kill instantly.
- Use
AnimatedTrapclass with timing.
Many objects include:
framesframe_duration
Behaviour:
Use these properties to drive animations (coins, keys, potions, traps).
Hints:
- Implement a reusable
AnimatedEntitybase class. - Avoid hardcoded sprite paths; use tileset frame indices.
Common TMX prop: obj_type
Examples:
door, spawn, collectible, ladder, enemy, trap
Behaviour:
- The map loader should create the correct class based on
obj_type.
Example:
if obj.properties['obj_type'] == 'collectible':
spawn Collectible(obj)TMX uses different object sizes:
- Keys / Coins / Potions → 16×16
- Enemies → 32×32
- Player spawn → ~19×20
Hints:
- Standardize hitboxes (e.g., player width 12–14 px) so movement feels fair and consistent.
Use:
rect.inflate(-n, -m)TMX implies the need for a basic heads-up display (HUD) showing:
- Silver key count
- Golden key count
- Score
- HP bar
- Door locked/unlocked messages
- Pickup notifications
Behaviour: The HUD should always reflect:
player.inventoryplayer.hpplayer.score
Map dimensions: 50 × 38 tiles (16 px each).
Behaviour:
- The camera follows the player.
- Camera must clamp to map boundaries so it never shows outside the world.
Formula:
camera_offset = player.center - (screen_w/2, screen_h/2)
camera_offset = clamp(camera_offset, map_bounds)Useful debug features for development:
- Draw object IDs above each object
- Toggle visibility of the collision layer
- Show collision hitboxes
- Highlight object groups (doors, traps, collectibles, etc.) These tools make gameplay tuning and level testing much easier.
Based on map content:
- Silver keys required → 4
- Golden keys required → 2
- Potion heal → 25
- Spike damage → 25
- Ideal player max HP → 100 (multiple of 25) Enemies are sparse, so a simple patrol → chase AI suits the map well.
| Class | Purpose |
|---|---|
| Player | Movement, HP, inventory, i-frames |
| TileMap | Layer rendering, collision grid |
| Door | Key checks, locked/open animations |
| Collectible | Coins, keys, potions pickup logic |
| Enemy | AI, hitbox, movement |
| Trap | Animated spike logic + damage |
| Ladder | Level transition to next map |