Skip to content

Latest commit

ย 

History

886 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

rift

A modern 2.5D RPG game built with C++23.

๐Ÿ  Mainpage | ๐Ÿงฑ Building | ๐Ÿ›๏ธ Architecture | ๐Ÿค Contributing

Genre Game Windows CMake OpenGL Vulkan License
Quality Gate Status Maintainability Rating Reliability Rating Codacy Badge
build tests
Sponsor

A modern 2.5D RPG game built with C++23, featuring dual OpenGL 4.6 and Vulkan 1.4 rendering backends that can be switched at runtime. It includes dynamic world simulation with a full day/night cycle, weather effects, and NPC interactions, alongside a built-in level editor for rapid content creation. Rift is focused on tile-based RPG gameplay, performance, and visual polish.


Game

Important

Assets Not Included

Rift does not include game assets (sprites, tilesets, fonts, maps). To run it, you will need to provide your own:

  • Source free/open-licensed sprites and tilesets (e.g., from OpenGameArt, itch.io)
  • Place them in the assets/ directory following the structure in Project Structure
  • Wire them into Rift by editing rift.project.json; do not edit Game.cpp just to change asset paths

Rift will not run without valid assets in place.

/* ============================================================================================== *
 *
 *                                                            โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ ณโฃถโกค
 *                                                            โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ ˆโ  โฃพโฃฆโก€
 *                                                            โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โ €โฃˆโฃปโกงโข€
 *           :::::::::  ::::::::::: :::::::::: :::::::::::    โขทโฃฆโฃคโก€โ €โข€โฃ โฃคโก†โขฐโฃถโฃถโฃพโฃฟโฃฟโฃทโฃ•โฃกโก€
 *           :+:    :+:     :+:     :+:            :+:        โ ˜โฃฟโฃฟโ ‡โ €โฃฆโก€โ ‰โ ‰โ ˆโ ‰โ โขธโฃฟโฃฟโฃฟโฃฟโกฟโ ƒ
 *           +:+    +:+     +:+     +:+            +:+        โ €โ €โ €โฃ€โฃดโฃฟโฃฟโฃ„โฃ€โฃ€โฃ€โข€โฃผโฃฟโฃฟโฃฟโ 
 *           +#++:++#:      +#+     :#::+::#       +#+        โ €โ €โ €โ €โ ‰โขฉโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโฃฟโก€
 *           +#+    +#+     +#+     +#+            +#+        โ €โ €โ €โ €โ €โฃธโฃฟโฃฟโกฟโขปโฃฟโฃฟโฃฟโฃฟโกฟโขฟโ ‡
 *           #+#    #+#     #+#     #+#            #+#        โ €โ €โ €โ €โขฐโฃฟโฃฟโฃฟโ ฐโ ™โ โ ˆโฃฟโฃฟโ ฑโ ˜
 *           ###    ### ########### ###            ###        โ €โ €โ €โ €โขธโกโฃพโกฟโ โ €โ €โ €โขฟโฃผโฃทโ 
 *                                                            โ €โ €โ €โ €โ ˜โ ทโขฟโฃงโก€โ €โ €โ €โ ˆโ ›โขฟโฃ†
 *                                                            โ €โ €โ €โ €โ €โ €โ €โ ‰โ ‰โ €โ €โ €โ €โ €โ €โ ˆ
 *                                      << 2 . 5 D   R P G >>
 *
 * ============================================================================================== */
rift/
|-- src/                               # Engine source (flat; grouped by subsystem)
|   |-- main.cpp                       # Program entry point; boots and runs Game
|   |-- Game.*                         # Core loop + state (partials: GameInput/Menus/Dialogue)
|   |-- GameMode.hpp                   # Title / Playing / Paused top-level mode
|   |-- WorldServices.hpp              # Non-owning service pointers in the ECS globals
|   |-- Version.hpp                    # 4-part version string, parsed by CMake
|   |-- DoxygenGroups.hpp              # The only file with @addtogroup; elsewhere use @ingroup
|   |-- IRenderer.*                    # Renderer strategy interface
|   |-- OpenGLRenderer.*               # OpenGL 4.6 backend (batching, bloom, PostFX)
|   |-- VulkanRenderer.*               # Vulkan 1.4 backend (partials: Buffers/Helpers)
|   |-- VulkanShader.*                 # Vulkan shader-module loading
|   |-- VulkanCommon.hpp               # Shared Vulkan types + helpers
|   |-- RendererFactory.*              # Creates the active backend at runtime
|   |-- RendererAPI.hpp                # Backend selector enum (OpenGL / Vulkan)
|   |-- RendererMacros.hpp             # Macros keeping both backends in lockstep
|   |-- RenderDrawable.*               # Y-sorted draw-list build
|   |-- CharacterRender.*              # Shared character sprite draw
|   |-- PlayerRender.*                 # Player sprite draw over components
|   |-- NpcRender.*                    # NPC sprite draw over components
|   |-- PostFXParams.hpp               # Bloom / grading / vignette / grain params
|   |-- DrawTracer.*                   # Per-frame draw-call tracing
|   |-- ViewScaling.hpp                # Resolution / view scaling helpers
|   |-- RenderModes.hpp                # Flat 2.5D vs world-space 3D path selector
|   |-- CameraRig.*                    # Orbit camera rig behind the `world3d` toggle
|   |-- CameraFacing.hpp               # Camera basis the 3D path faces sprites with
|   |-- Billboard.hpp                  # Camera-facing quad build for sprites
|   |-- Frustum.hpp                    # View-frustum planes + cull tests
|   |-- SceneMath.hpp                  # World <-> scene space math for the 3D path
|   |-- Texture.*                      # Texture resource (upload, bind)
|   |-- TextureHandle.hpp              # Lightweight texture handle
|   |-- TextureStore.*                 # Owns textures; re-uploads on backend switch
|   |-- ProceduralTexture.hpp          # CPU-generated texture helpers
|   |-- AuroraTextures.*               # Generated aurora ribbon textures
|   |-- AuroraMath.hpp                 # Aurora curve / noise math
|   |-- Tilemap.*                      # Dynamic layer stack (10 default) + elevation; sparse JSON
|   |-- CollisionMap.hpp               # Player-blocking bit grid
|   |-- NavigationMap.hpp              # NPC-walkability bit grid
|   |-- BoolGrid.hpp                   # Backing bit grid for both maps
|   |-- CollisionGeometry.hpp          # Feet-anchored AABB collision geometry
|   |-- CollisionSystem.*              # Stateless AABB collision over Hitbox
|   |-- TileMath.hpp                   # Shared tile / feet-AABB coord helpers
|   |-- TileStance.hpp                 # Per-tile stance: Flat / Prop / Wall / Structure
|   |-- TileRole.hpp                   # Maps an authored stance to render behavior
|   |-- ElevationRole.hpp              # Per-layer participation in a cell's elevation
|   |-- SupportSurface.hpp             # Support surface (Ground / Elevation) + state
|   |-- SurfaceSystem.*                # Ground vs elevation support resolution
|   |-- DefaultedVector.hpp            # Sparse vector defaulting unset cells
|   |-- ColumnProxy.hpp                # Column view into the tile grid
|   |-- Pathfinding.*                  # A* over the navigation map
|   |-- NavigationRecalc.*             # Rebuilds nav + patrol routes on edits
|   |-- PatrolRoute.*                  # Runtime patrol-route cache (not a component)
|   |-- ProjectManifest.*              # Parses rift.project.json (assets, tile size)
|   |-- AssetRegistry.*                # Asset path lookup by handle
|   |-- Transform.hpp                  # World position component
|   |-- Elevation.hpp                  # Integer elevation (Z plane) component
|   |-- ElevationAxis.hpp              # Which axis a ramp engages
|   |-- Facing.hpp                     # Facing-direction component
|   |-- AnimationState.hpp             # Current animation frame / timer
|   |-- AnimationType.hpp              # Animation kind enum
|   |-- Appearance.hpp                 # Sprite sheet / tint component
|   |-- Motor.hpp                      # Velocity / momentum body component
|   |-- MotorParams.hpp                # Per-entity motor tuning
|   |-- Speed.hpp                      # Movement-speed component
|   |-- Hitbox.hpp                     # Feet-anchored collision AABB component
|   |-- Identity.hpp                   # Stable instance id (survives despawn)
|   |-- PlayerTag.hpp                  # Marks the player entity
|   |-- NpcTag.hpp                     # Marks NPC entities
|   |-- PlayerInputState.hpp           # Buffered player input component
|   |-- PlayerMovementState.hpp        # Slide / lane-snap / stuck hysteresis
|   |-- PlayerModes.hpp                # Player mode flags
|   |-- PlayerSprite.hpp               # Player sprite-sheet layout
|   |-- NpcIdle.hpp                    # NPC idle-wait state component
|   |-- NpcSprite.hpp                  # NPC sprite-sheet layout
|   |-- NpcRecord.hpp                  # Serialized NPC spawn record
|   |-- Patrol.hpp                     # NPC patrol waypoints component
|   |-- CharacterType.hpp              # Character archetype enum
|   |-- CharacterConstants.hpp         # Shared character tuning constants
|   |-- CharacterDirection.hpp         # 8-way direction enum + helpers
|   |-- EntityStore.*                  # Spawn / despawn / query over the registry
|   |-- MotionSystem.*                 # Momentum kinematics over Motor
|   |-- PlayerMovementSystem.*         # Player movement + collision response
|   |-- PlayerSystem.*                 # Per-frame player update (anim, overlap-stop)
|   |-- NpcAiSystem.*                  # Patrol / idle NPC AI (UpdateAll)
|   |-- CharacterKinematics.*          # Shared per-entity step / kinematics
|   |-- TimeManager.*                  # 24h day/night cycle, moon phase
|   |-- SkyRenderer.*                  # Procedural sky, stars, aurora, lightning
|   |-- WeatherDefinitions.*           # Static weather data table
|   |-- WeatherDirector.*              # Weather scheduling + forecast
|   |-- WeatherBlend.*                 # Smooth weather transitions + gusts
|   |-- ParticleSystem.*               # Weather + zone particle spawning
|   |-- AmbienceConfig.hpp             # Centralized ambience / PostFX tuning
|   |-- Dialogue.hpp                   # Dialogue component (holds a handle)
|   |-- DialogueHandle.hpp             # Stable key into the dialogue store
|   |-- DialogueTypes.hpp              # Dialogue condition / consequence types
|   |-- DialogueManager.*              # Branching conversation runtime
|   |-- DialogueStore.*                # Dialogue trees keyed by handle
|   |-- Dialogues.*                    # Authored dialogue-tree data
|   |-- GameStateManager.*             # Flags backing dialogue conditions
|   |-- Editor.*                       # Editor state (partials: EditorInput/Rendering)
|   |-- EditorCommand.hpp              # Undo/redo command base interface
|   |-- EditorCommands.*               # Concrete editor commands
|   |-- UndoRedoStack.hpp              # Command-pattern undo/redo stack
|   |-- EditorBrushTransform.hpp       # Brush flip / rotate transform
|   |-- EditorStrokeAccumulators.hpp   # Batches drag-paint edits per stroke
|   |-- Console.*                      # F12 dev console; authorized state mutator
|   |-- ConsoleCommands.*              # Console command handlers + registry
|   |-- CameraController.*             # Follow camera + look-ahead
|   |-- KeyToggle.hpp                  # Edge-triggered key helper
|   |-- Logger.*                       # Per-subsystem logging
|   |-- EnumTraits.hpp                 # Compile-time enum reflection
|   |-- MenuLogic.hpp                  # Menu navigation helpers
|   |-- MathConstants.hpp              # Shared math constants
|   +-- MathUtils.hpp                  # Shared math helpers
|-- shaders/                           # GLSL 450 (compiled to *.spv at build; gitignored)
|   |-- Geometry.vert/frag             # Forward pass: sprites, tiles, particles
|   |-- Geometry3D.vert/frag           # World-space 3D path: depth-tested geometry
|   |-- FullscreenTriangle.vert        # Fullscreen VS for post-processing
|   |-- BloomPrefilter.frag            # Bloom: bright-pass prefilter
|   |-- BloomDownsample.frag           # Bloom: mip downsample
|   |-- BloomUpsample.frag             # Bloom: mip upsample + combine
|   +-- PostFXComposite.frag           # Composite: bloom, grading, vignette, grain
|-- tests/                             # Google Test suite (unit + system; run via test.bat)
|-- assets/                            # Game assets - NOT included; provide your own
|-- docs/                              # Documentation (Markdown guides + Doxygen output)
|   |-- ARCHITECTURE.md                # Architecture overview
|   |-- RENDERING.md                   # Rendering pipeline guide
|   |-- TIME_SYSTEM.md                 # Day/night + weather guide
|   |-- COLLISION.md                   # Collision + navigation guide
|   |-- EDITOR.md                      # In-game editor guide
|   |-- PROJECT_MANIFEST.md            # rift.project.json reference
|   |-- SETUP.md                       # First-time setup
|   |-- BUILDING.md                    # Build instructions
|   +-- MAINPAGE.md                    # Doxygen landing page
|-- external/                          # Third-party deps (fetched / cloned by setup.ps1)
|-- CMakeLists.txt                     # Build config (game + tests share one build/)
|-- CMakePresets.json                  # Presets: default / ci / compile-db
|-- vcpkg.json                         # vcpkg manifest (glm, glfw3, freetype, gtest)
|-- rift.project.json                  # Project manifest: assets, tile size, defaults
|-- Doxyfile.in                        # Doxygen API-docs template
|-- setup.ps1                          # One-time dependency fetch
|-- build.bat                          # Full pipeline: format -> tidy -> build -> docs
|-- test.bat                           # Configure + build + run tests
+-- run.bat                            # Runs build\Release\rift.exe from the repo root

Features

Dual Rendering Backend

Switch between OpenGL and Vulkan at runtime. Press F12 to open the console, then run renderer.set opengl or renderer.set vulkan. The startup backend comes from startupRenderer in rift.project.json. A switch destroys and recreates the window and the renderer, then re-uploads every texture.

Warning

Vulkan is work-in-progress. Runtime switching can cause missing textures or visual glitches. OpenGL is recommended for now.

Dynamic Day/Night Cycle

A complete time-of-day system drives ambient lighting, sky colors, celestial bodies, and atmospheric effects:

---
config:
  look: handDrawn
  theme: mc
  themeVariables:
    fontSize: 18px
  layout: elk
---
graph LR
    classDef night fill:#1a1a2e,stroke:#9aa4c0,stroke-width:2.5px,color:#ffffff,font-weight:800
    classDef dawn  fill:#614385,stroke:#d7a3ff,stroke-width:2.5px,color:#ffffff,font-weight:800
    classDef day   fill:#f39c12,stroke:#7a3e00,stroke-width:2.5px,color:#ffffff,font-weight:900
    classDef dusk  fill:#c0392b,stroke:#ff9a9a,stroke-width:2.5px,color:#ffffff,font-weight:800

    N["Night ๐ŸŒ™โœจ<br/>22:00-04:00"]:::night --> LN["LateNight ๐ŸŒ‘<br/>04:00-05:00"]:::night
    LN --> D["Dawn ๐ŸŒ…๐Ÿ•Š๏ธ<br/>05:00-07:00"]:::dawn
    D --> M["Morning โ˜€๏ธ๐ŸŒฟ<br/>07:00-10:00"]:::day
    M --> MD["Midday ๐ŸŒž<br/>10:00-16:00"]:::day
    MD --> A["Afternoon ๐ŸŒค๏ธ๐Ÿ•ถ๏ธ<br/>16:00-18:00"]:::day
    A --> DU["Dusk ๐ŸŒ‡๐Ÿ”ฅ<br/>18:00-20:00"]:::dusk
    DU --> E["Evening ๐ŸŒƒ๐ŸŒŸ<br/>20:00-22:00"]:::night
    E --> N
Loading
  • Sun and moon god rays with arc-based positioning
  • Star field with shooting stars and atmospheric glow
  • Smooth color transitions between time periods

Multi-Layer Tilemap System

Efficient tile-based world rendering. The default stack is ten layers - five drawn before the actors, five after - but the count is data-driven: a loaded map may carry any number, and Tilemap::GetLayerCount() is the only authority. In the editor, keys 1-9 and 0 select layers 1-10.

---
config:
  look: handDrawn
  theme: mc
  themeVariables:
    fontSize: 18px
  layout: elk
---
flowchart LR
  classDef ov fill:#2e1f5e,stroke:#8b5cf6,stroke-width:2.5px,color:#e2e8f0,font-weight:800
  classDef fg fill:#134e3a,stroke:#10b981,stroke-width:2.5px,color:#e2e8f0,font-weight:800
  classDef ob fill:#4a3520,stroke:#f59e0b,stroke-width:2.5px,color:#e2e8f0,font-weight:800
  classDef gr fill:#1e3a5f,stroke:#3b82f6,stroke-width:2.5px,color:#e2e8f0,font-weight:800
  classDef act fill:#3a1f2e,stroke:#f43f5e,stroke-width:2.5px,color:#e2e8f0,font-weight:800

  O["9-7 Overlay 1-3 ๐ŸŒฆ๏ธโœจ<br/>Weather - Canopy ๐Ÿงญ<br/>keys 0 9 8"]:::ov
  F["6-5 Foreground 1-2 ๐Ÿงโ€โ™‚๏ธโš”๏ธ<br/>Tree Tops - Eaves ๐Ÿ‘‘<br/>keys 7 6"]:::fg
  P["Player and NPCs ๐Ÿงโ€โ™‚๏ธ<br/>Y-sorted actors"]:::act
  B["4-2 Objects 1-3 ๐Ÿ ๐Ÿชจ๐ŸŒฒ<br/>Buildings - Rocks - Trees ๐Ÿงฑ<br/>keys 5 4 3"]:::ob
  G["1 Ground Detail ๐Ÿƒ๐Ÿ›ค๏ธ๐Ÿชด<br/>Grass - Paths - Deco ๐ŸŽจ<br/>key 2"]:::gr
  T["0 Ground ๐Ÿ—บ๏ธ๐ŸŸซ<br/>Base Terrain ๐ŸŒ<br/>key 1"]:::gr

  O --> F --> P --> B --> G --> T

Loading

Advanced Rendering Features

---
config:
  look: handDrawn
  theme: mc
  themeVariables:
    fontSize: 18px
  layout: elk
---
flowchart LR
  classDef batch fill:#1e3a5f,stroke:#3b82f6,stroke-width:2.5px,color:#e2e8f0,font-weight:800
  classDef sort fill:#134e3a,stroke:#10b981,stroke-width:2.5px,color:#e2e8f0,font-weight:800
  classDef proj fill:#4a3520,stroke:#f59e0b,stroke-width:2.5px,color:#e2e8f0,font-weight:800
  classDef fx fill:#2e1f5e,stroke:#8b5cf6,stroke-width:2.5px,color:#e2e8f0,font-weight:800

  subgraph Pipeline["Rendering Pipeline ๐ŸŽจ"]
    B["Sprite Batching ๐Ÿ“ฆ<br/>Draw Call Optimization ๐Ÿš€"]:::batch
    Y["Y-Sorting ๐Ÿงญ<br/>Depth Ordering ๐Ÿชœ"]:::sort
    N["Upright Tiles ๐Ÿ—๏ธ<br/>Buildings & Signs ๐Ÿงฑ"]:::proj
    FX["Particles โœจ<br/>Zone Spawning ๐ŸŒช๏ธ"]:::fx
  end

  B --> Y
  Y --> N
  N --> FX
Loading
  • Sprite batching groups draw calls for optimal GPU efficiency
  • Y-sorting ensures correct depth ordering of entities and tiles
  • Upright tiles mark buildings and signs so they stand up in the 3D camera path
  • Particle systems spawn effects within defined zones

In-Game Level Editor

Open the console with F12 and run ed to toggle a full-featured editor (the tile picker opens with it). Every edit goes through an undoable command, so Ctrl+Z / Ctrl+Y reverse any mistake:

  • Tile placement with multi-tile selection and rotation
  • Collision and navigation map painting
  • Tile elevation for height variation
  • NPC placement and patrol route configuration
  • Animation definition tools

Entity System

  • Player character with 8-directional movement and animation
  • NPCs with autonomous patrol behavior and pathfinding
  • Dialogue system supporting branching conversations with quests

Architecture

---
config:
  look: handDrawn
  theme: mc
  themeVariables:
    fontSize: 18px
  layout: elk
---
graph LR
    classDef core fill:#1e3a5f,stroke:#3b82f6,color:#e2e8f0
    classDef render fill:#2e1f5e,stroke:#8b5cf6,color:#e2e8f0
    classDef world fill:#134e3a,stroke:#10b981,color:#e2e8f0
    classDef entity fill:#4a3520,stroke:#f59e0b,color:#e2e8f0

    Game(("Game ๐ŸŽฎ")):::core

    subgraph Rendering["Rendering ๐ŸŽจ"]
        IRenderer["IRenderer ๐Ÿ”Œ"]:::render
        OpenGL["OpenGLRenderer ๐ŸŸข"]:::render
        Vulkan["VulkanRenderer ๐Ÿ”บ"]:::render
    end

    subgraph World["World ๐ŸŒ"]
        Tilemap["Tilemap ๐Ÿ—บ๏ธ"]:::world
        Collision["CollisionMap ๐Ÿšง"]:::world
        Navigation["NavigationMap ๐Ÿงญ"]:::world
    end

    subgraph Entities["ECS ๐Ÿงฉ"]
        Registry[("ecs::registry m_World ๐Ÿ—ƒ๏ธ")]:::entity
        Components["Components ๐Ÿ“ฆ<br/>Transform - Motor - Hitbox ๐Ÿ“<br/>Facing - Appearance - Patrol ๐ŸŽญ"]:::entity
        Systems["Stateless systems โš™๏ธ<br/>PlayerSystem - NpcAiSystem ๐Ÿงโ€โ™‚๏ธ<br/>MotionSystem - CollisionSystem ๐Ÿƒโ€โ™‚๏ธ"]:::entity
        Services["WorldServices ๐Ÿ”—<br/>non-owning pointers in globals() ๐ŸŒ"]:::entity
    end

    Game --> Rendering
    Game --> World
    Game --> Registry
    Game -->|calls per frame| Systems
    Registry --> Components
    Registry --> Services
    Systems -->|read / write| Components
    Systems -->|reach shared state| Services
Loading

Game is the composition root: it owns the window, the renderer, the tilemap, and every subsystem by value. There are no PlayerCharacter or NonPlayerCharacter classes - an entity is a set of plain-struct components, and behavior lives in free functions that take the registry.

Technology Stack

Component Technology
Language C++23
Graphics OpenGL 4.6 / Vulkan 1.4
Windowing GLFW 3.3+
Math GLM
Image Loading stb_image
Font Rendering FreeType 2
Build System CMake 3.21+

Quick Start

Prerequisites

  • CMake 3.21+ (required by CMakePresets.json, which build.bat uses; the bare CMakeLists.txt floor is 3.10)
  • C++23 compatible compiler (MSVC 2022+)
  • Vulkan SDK - a hard dependency, both backends are always compiled in
  • OpenGL 4.6 compatible GPU, or any Vulkan 1.0+ device (the Vulkan backend requests instance API version 1.0)

Windows

# 1. Clone the repository
git clone https://github.com/lextpf/rift.git
cd rift

# 2. Run setup script to download dependencies
.\setup.ps1

# 3. Configure your assets in rift.project.json
#    The sample manifest documents tilesets, player sprites, NPC sprites, fonts, and the save file.

# 4. Build the project
.\build.bat

# 5. Run the game
.\build\Release\rift.exe

Controls

Gameplay is WASD plus a handful of modifier keys. Everything else - the editor, renderer switching, debug overlays, time and weather - is a developer-console command.

General Keybinds

Developer Console

F12 opens and closes the console. help lists all ~100 commands; most take on, off or toggle. The everyday ones:

Command Action
help List every registered command and its aliases
ed Toggle the level editor (editor)
renderer.set <opengl|vulkan> Switch backend at runtime (rndr.set, gfx)
debug.overlays Collision / navigation / anchor overlays (dbg)
debug.info FPS and coordinate HUD (fps)
time.set <hours> / time.next Set the clock (ts) / step to the next period (tn)
weather.next [seconds] Blend to the next weather state
world3d Render through the world-space 3D camera path
teleport <tx> <ty> Move the player to a tile coordinate (tp)
noclip Disable player tile/NPC collision (nc)
character.next Cycle the player character (cn)
appearance.copy / appearance.restore Mimic the nearest NPC's look, then undo it

Gameplay

Key Action
W/A/S/D Move player (8-directional)
Shift Run while held (1.75x base speed)
B Toggle bicycle mode (2.25x base speed)
F Talk to NPC when facing
Ctrl+Scroll Zoom camera
Arrow Keys Pan camera
Z Reset zoom to 1.0x
Space Free camera mode
X Toggle corner-cut blocking on the tile under the cursor; needs debug.overlays on

Dialogue

Key Action
W/S or Up/Down Navigate dialogue options
Enter/Space Confirm selection / advance
Escape End dialogue

Movement Modes

The modes are mutually exclusive and resolve bicycle > run > walk. The console player.speed multiplier is applied on top of whichever mode is active.

Mode Multiplier Speed
Walking 1.0x 50 px/s
Running 1.75x 87.5 px/s
Bicycle 2.25x 112.5 px/s

Mode changes speed and sprite sheet only. Collision is identical in every mode: one feet-anchored AABB, and CollisionSystem never reads the mode flags.

Editor

Run ed in the console to open the editor. Only one sub-mode is active at a time; pressing its key again returns to the default place/collision mode.

Key Action
1-9, 0 Select tile layer 1-10
T Toggle tile picker
M Navigation (walkability) editing
N NPC placement
B Stance editing (Flat / Prop / Wall / Structure)
G Structure editing (multi-tile bodies)
H Elevation editing
J Particle zone editing
K Animated tile editing
Y Y-sort-plus editing
O Y-sort-minus editing
R Rotate brush and the tile under the cursor 90 deg
F / Shift+F Flip the brush and reflect the selection on X / Y
S Save the map to the defaultMap path
L Reload the map, discarding undo history
Delete Remove tiles under the cursor (drag)
, / . Cycle the type the active mode paints
Ctrl+Z / Ctrl+Y Undo / redo
Ctrl+drag Select a rectangular tile region
Ctrl+C / Ctrl+V Copy / paste the selected region (all layers, collision, nav)
Esc Cancel the pending selection, anchor, or animation
Left Click Place tile/NPC/zone
Right Click Toggle collision/navigation
Arrows Pan camera, or the tile picker while it is open
Shift+Arrows Pan fast
Scroll Pan tile picker
Ctrl+Scroll Zoom

Debug and Visual

No function key except F12 is bound. Every debug and visual toggle is a console command:

Command Action
renderer.set <opengl|vulkan> Switch renderer at runtime
debug.overlays Collision, navigation and anchor overlays
debug.info FPS and player-coordinate HUD
renderer.trace Per-frame draw-call tracing
particles All particle rendering (weather, zones, ambient)
fps.cap Cap the frame rate at 500, or run uncapped
time.set <hours> / time.next Set the clock, or step to the next time-of-day period
time.freeze Pause and resume the day/night cycle
weather.next [seconds] Blend to the next weather state
world3d, cam.preset World-space 3D camera path and its preset

For detailed editor controls, see the Editor Guide.

Documentation

---
config:
  look: handDrawn
  theme: mc
  themeVariables:
    fontSize: 18px
  layout: elk
---
graph LR
    classDef guide fill:#1e3a5f,stroke:#3b82f6,color:#e2e8f0
    classDef tech fill:#134e3a,stroke:#10b981,color:#e2e8f0

    subgraph Guides
        Setup[Setup]:::guide
        Building[Building]:::guide
        Editor[Editor]:::guide
    end

    subgraph Technical
        Arch[Architecture]:::tech
        Render[Rendering]:::tech
        Time[Time System]:::tech
        Collision[Collision]:::tech
    end

    Setup --> Building --> Editor
    Arch --> Render
    Arch --> Time
    Arch --> Collision
Loading
Document Description
Setup Guide Install dependencies and configure your environment
Building Guide Compile on Windows
Architecture Game architecture, loop, system relationships
Rendering Pipeline Coordinate systems, transformations, batching
Time System Day/night cycle, celestial mechanics, lighting
Collision & Pathfinding AABB collision, navigation, NPC AI
Editor Guide Level editor usage and tools
Project Manifest Configure startup assets and map defaults

Generating API Docs

# Install Doxygen
# Windows: choco install doxygen

# The repository holds only Doxyfile.in; CMake configures it into build\Doxyfile
cmake --preset default
doxygen build\Doxyfile

# Open docs/html/index.html in your browser

build.bat runs this as its final step, so a full build leaves the API docs up to date whenever Doxygen is on PATH.

File Formats

  • .json - Map data (layers, tiles, NPCs)
  • .png - Sprites (32-bit RGBA)
  • .ttf - Fonts (TrueType)
  • .vert/.frag - Shaders (GLSL 450)

Contributing

Contributions are welcome! Please read the Contributing Guidelines before submitting pull requests.

Development Workflow

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run .\test.bat (or ctest --test-dir build -C Release) and ensure the build passes
  5. Commit with descriptive messages
  6. Push to your fork and open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • GLFW - Window and input handling
  • GLM - Mathematics library
  • stb_image - Image loading
  • FreeType - Font rendering
  • Vulkan SDK - Vulkan development tools
  • Claude - AI coding assistant by Anthropic
  • Codex - AI coding assistant by OpenAI
  • DeviantArt - Pixel art for characters and tilesets
  • Sora - Particle effect generation

About

A C++23 2.5D RPG game with runtime-switchable OpenGL 4.6/Vulkan 1.4, tilemap for dynamic world simulation, NPCs, and a built-in level editor.

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages