Loading
Personal Project
Eurekiel: Galaxy Tetris Destroyer

Eurekiel: Galaxy Tetris Destroyer is a 2D arcade shooter built in C++ on a custom engine. Players pilot a ship against waves of enemies while managing a playfield of falling Tetris blocks. The spaceship tracks the mouse cursor, enemy formations advance in waves, and Tetris blocks can be shot apart or cleared in rows. The project includes entity management, an event bus, particle simulation, and an XML-driven content pipeline.

Starship Banner
The game combines spaceship combat with Tetris block mechanics in a single playfield

The main menu features animated transitions managed by WidgetManager, which controls widget lifecycles, input dispatching, and camera render order across screen and world viewports.

0:00
/0:00
Main menu UI with animated transitions and widget management

Ship orientation and targeting

The player ship aims toward the cursor by converting screen-space mouse coordinates into world coordinates through a dual-camera system (a 1600x800 UI camera and a 200x100 world camera). Ship heading evaluates via atan2 between ship position and the converted world cursor point.

0:00
/0:00
Player spaceship orientation follows the mouse cursor through screen-to-world coordinate conversion

Tetris block mechanics

Breakable blocks and collision

Tetrominoes consist of individual Cube entities arranged on a grid. Cubes track health and take damage from player projectiles. When a cube is destroyed, the grid clears that cell while remaining blocks stay in position.

0:00
/0:00
Shooting individual blocks out of a Tetris piece, leaving remaining cubes on the grid

Tetromino destruction bonus

When all blocks in a piece are destroyed, TetrominoAllChildDieEvent broadcasts over the event bus, awarding bonus points for aggressive play.

0:00
/0:00
Destroying all blocks of a Tetromino grants extra bonus points

Line clear scoring

When a horizontal row fills completely with blocks, the row clears and all blocks above drop down one tile. Scoring multipliers scale with simultaneously cleared lines, broadcasting PointGainEvent to update the HUD and advance wave thresholds.

0:00
/0:00
Line clear mechanic with score multiplier based on the number of lines cleared at once

Vertical piece placement

Players can nudge falling pieces vertically using the mouse wheel. Input events trigger TetrominoRequestOperateEvent, which validates movement boundaries before adjusting piece elevation.

0:00
/0:00
Mouse wheel controls vertical movement of the active Tetris piece

Wave progression

LevelHandler tracks wave progression using score milestones. Each wave specifies active enemy types, spawn timers, and the score needed to unlock subsequent stages. Wave configurations use FLevel data structures that can be adjusted in XML.

0:00
/0:00
Wave progression triggered by reaching score thresholds, unlocking new enemy types

Enemy types

Beetle

Beetles drift toward the player at a steady velocity, providing early target practice for aiming and spacing.

0:00
/0:00
Beetle enemy slowly tracking toward the player ship

Wasp

Wasps accelerate toward the player over time, requiring players to prioritize them before they close distance.

0:00
/0:00
Wasp enemy accelerating toward the player with increasing speed

2D particle simulation

A custom particle system simulates impacts, debris, and thruster plumes. ParticleHandler manages particle memory pools, tracking position, velocity, acceleration, color gradients, and scale curves specified in FParticleProperty.

0:00
/0:00
Custom 2D particle system with physics-based emitters for visual effects

Sprite sheet resources

Visuals are drawn from packed sprite sheets defined in SpriteSheetDefinition XML files, allowing texture coordinates and frame layouts to be updated without code adjustments.

Sprite Sheet Resources
Sprite sheet atlas used for all game entities, UI elements, and particle effects

System architecture

EventManager coordinates gameplay systems, decoupling scoring, grid updates, and enemy waves:

graph TD
    subgraph Core["Core Engine"]
        APP[App] --> GAME[Game Loop]
        GAME --> EM[EventManager]
        GAME --> RM[ResourceManager]
        GAME --> WM[WidgetManager]
    end

    subgraph Entities["Entity System"]
        PS[PlayerShip]
        BUL[Bullet]
        BEE[Beetle]
        WSP[Wasp]
        AST[Asteroid]
        TET[Tetromino]
        CUB[Cube]
    end

    subgraph Grid["Grid System"]
        GR[Grid] --> LC[Line Clear]
        GR --> OCC[Cell Occupancy]
    end

    subgraph Data["Data-Driven Definitions"]
        XML[XML Files] --> SPR[SpriteSheetDefinition]
        XML --> SND[SoundDefinition]
        XML --> TXR[TextureDefinition]
        XML --> TDF[TetrominoDefinition]
    end

    subgraph Systems["Game Systems"]
        LH[LevelHandler / Waves]
        PH[ParticleHandler]
        SC[Score System]
    end

    GAME --> Entities
    GAME --> Grid
    RM --> Data
    PS -->|fires| BUL
    BUL -->|damages| CUB
    CUB -->|occupies| GR
    TET -->|spawns| CUB
    LC -->|PointGainEvent| EM
    EM -->|score update| SC
    SC -->|threshold check| LH
    LH -->|spawn enemies| Entities
    CUB -->|death| PH

Data-driven content pipeline

Game content is declared in XML files under Run/Data/Definitions/:

  • SpriteSheetDefinition maps sprite names to texture coordinates and frame counts.
  • TetrominoDefinition sets piece shapes, colors, and initial block layouts for standard shapes (I, J, L, O, S, T, Z).
  • SoundDefinition maps sound IDs to audio assets with volume and playback parameters.
  • TextureDefinition configures image asset paths and texture filter modes.

Design decisions

Event-driven decoupling

Systems coordinate through EventManager rather than holding direct object references. When blocks break or pieces clear, events broadcast to the scoring system, wave controller, and HUD independently.

Data-driven assets

Visual assets, sound profiles, and piece layouts are defined in XML, allowing designers to add tetromino configurations or adjust animations without recompiling the executable.

Dual-camera coordinate mapping

The engine operates two coordinate viewports: a 200x100 world camera for gameplay and a 1600x800 pixel camera for interface widgets. Cursor input is mapped from screen space to world space for aiming.

Component-style entity design

Game objects derive from a shared Entity base that encapsulates movement, health, and rendering, with specialized aiming or grid logic added in subclasses.

Physics-based particles

Rather than relying on pre-baked sprite animations, particle effects simulate velocity and drag over time from parameters configured in FParticleProperty.