SDL3
2D Action Platformer
Stay close to the light and survive for as long as you can. Run and jump between torches, dash through enemies and collect upgrades that reduce your dash cooldown. Enemies spawn faster over time and merge into stronger forms, so you must keep moving and choose when to fight.

Project Overview
This 2D survival platformer was built from scratch with C++ and SDL3. The player must fight enemies while moving through a dark level.
Torchlight creates safe areas. The player loses health while outside the light and gains health while inside it. This makes movement between torches part of both combat and survival.
Gameplay Systems
The player can run, jump, fall, and dash toward the mouse cursor. The dash works as both movement and an attack. Hitting an enemy during a dash deals damage. Touching an enemy without dashing hurts the player.
Enemies spawn outside the camera view and move toward the player. They spawn faster as the game continues. Enemies of the same strength merge when they overlap. The merged enemy becomes larger and stronger.
Power-ups reduce the dash cooldown. The game also includes player health, a kill score, sprite animation, sound effects, a start menu and a game-over screen.
Technical Approach
The game uses C++20, SDL3, SDL3_image, SDL3_ttf, GLM, ImGui, JSON, and CMake.
The level was made in Tiled and loaded from a JSON file. The map data defines tile layers, walls, the player start point, torch positions, power-up points and background images.
The game uses delta time for movement and physics. Custom systems handle gravity, tile collision, animation, audio, camera movement and rendering.
A screen-sized texture creates the darkness effect. The renderer cuts clear areas around each torch before drawing the texture over the game.
Architecture
The code separates engine systems from the main game loop. Engine modules handle the player, enemies, collisions, maps, animation, resources, audio, lighting, menus, health and power-ups.
All active objects use a shared GameObject type. Each object stores data for its role, such as player, enemy, light or power-up data.
GameState stores the active objects, player reference, score and menu state. The main loop handles input, updates the game, checks collisions, spawns objects, moves the camera and draws each frame.