A C++20 game project featuring 3D procedural world generation and 2D tile-based gameplay.
- 3D spherical world generation
- 2D top-down tile-based gameplay sampled from the 3D world
- Infinite pannable world via chunk-based loading
- Vector-based assets (SVG) with procedural variation and seamless blending
- Testable UI framework with inspection capabilities
- Custom Entity Component System (ECS)
- C++20 compiler (Clang, GCC, or MSVC)
- CMake 3.25+
- Ninja + ccache (build toolchain, setup below)
- vcpkg (for dependency management)
- VSCode (recommended) with extensions:
- C/C++ (ms-vscode.cpptools)
- CMake Tools (ms-vscode.cmake-tools)
- clangd (llvm-vs-code-extensions.vscode-clangd)
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh # or bootstrap-vcpkg.bat on Windows
export VCPKG_ROOT=/path/to/vcpkg # Add to your shell profileOn Windows (PowerShell), set it with an assignment, and persist it for future sessions:
$env:VCPKG_ROOT = "C:\vcpkg" # current session
[Environment]::SetEnvironmentVariable("VCPKG_ROOT", "C:\vcpkg", "User") # persistedKeep vcpkg current. Dependencies are pinned in
vcpkg.jsonviabuiltin-baseline(a vcpkg commit). If your local vcpkg checkout is older than that commit, configure fails withno version database entry for <pkg> at <version>. Fix it by updating vcpkg:git -C $VCPKG_ROOT fetch && git -C $VCPKG_ROOT checkout <builtin-baseline> && $VCPKG_ROOT/bootstrap-vcpkg.{sh,bat}, or just pull the latest master (the version database only grows).
Local builds use Ninja with a ccache compiler cache (the presets wire both in). ccache is what makes clean rebuilds, branch switches, and fresh git worktrees cheap: identical compilations replay from the cache instead of re-running the compiler.
macOS / Linux:
brew install ccache ninja # or apt-get install ccache ninja-buildWindows (needs VS 2022 or VS Build Tools with the C++ x64 workload):
winget install Ccache.Ccache
./scripts/setup-msvc-env.ps1 # persists cl/ninja/rc paths + VCPKG_ROOT to the User envThe script makes cl.exe and the VS-bundled Ninja available in any plain shell, no VS
developer prompt needed. Re-run it after a Visual Studio update (the symptom of a stale
environment is cannot open include file: 'corecrt.h').
Then configure the cache (any OS). base_dir makes ccache normalize absolute paths under
it so identical sources hit the same cache entries from any checkout beneath it: point it
at your checkout dir — git worktrees live inside it under .claude/worktrees/, so one
cache serves them all.
ccache --set-config max_size=30G
ccache --set-config base_dir=C:/Users/you/Code/worldsim # your checkout dir
ccache --set-config hash_dir=false
ccache --set-config sloppiness=pch_defines,time_macros
ccache --set-config depend_mode=true
ccache --set-config namespace=worldsim-1 # retires pre-depend-mode manifests on upgrading machinesdepend_mode=true is required for correctness with worktrees, not a tune-up; see
build-performance.md for why. On Windows
setup-msvc-env.ps1 applies this block for you.
macOS / Linux (Ninja, single-config):
cmake --preset default
# Build
cmake --build build
# Run
./build/apps/world-sim/world-simWindows (Ninja Multi-Config + MSVC), from any shell:
cmake --preset windows
# Build (pick a config)
cmake --build build --config Debug
# Run (note the per-config subdirectory)
./build/apps/world-sim/Debug/world-sim.exeThe build generates the SDF font atlas (fonts/Roboto-SDF.png) automatically, so a fresh
checkout needs no manual asset steps. On the multi-config Windows generator binaries land in
a per-config subdirectory (Debug/, RelWithDebInfo/); on single-config (macOS/Linux)
they're in the target directory directly.
Check cache effectiveness anytime with ccache -s (a warm rebuild should be >90% hits).
Open the project in VSCode. CMake should configure automatically.
Build: Cmd+Shift+B (or Ctrl+Shift+B)
Format code: Shift+Alt+F (manual - not on save)
Debug: Use the debug configurations in Run & Debug panel
Enable automatic code formatting on commit:
cd .git/hooks
ln -s ../../scripts/git-hooks/pre-commit pre-commitThis hook automatically formats staged C++ files before each commit.
world-sim/
├── libs/ # Modular libraries (dependency layers)
│ ├── ui/ # UI framework with inspector/testability
│ ├── world/ # World generation (pluggable generators)
│ ├── game-systems/ # Chunks, tiles, camera (game-specific)
│ └── engine/ # App lifecycle, scenes, ECS, config
├── apps/
│ ├── world-sim/ # Main game application
│ │ ├── scenes/ # Splash, menu, world creator, game
│ │ └── assets/ # SVG files, configs
│ └── ui-sandbox/ # UI testing/demo app
│ └── demos/ # Component demos
└── docs/ # Documentation
├── status.md # Current development status
├── workflows.md # Common development tasks
├── technical/ # Technical design docs
└── specs/ # Product specifications
Dependency Rules:
- Each layer depends only on layers below it
- No circular dependencies
engine→game-systems/ui/world→renderer→foundationfoundationandrendererlive in salal and arrive via CMake FetchContent, pinned byGIT_TAGin the rootCMakeLists.txt(seeCLAUDE.mdfor building against a local checkout)
For full details, see docs/technical/monorepo-structure.md.
- CLAUDE.md - AI assistant guidance (start here for AI agents)
- Development Status - Current tasks and progress
- Workflows - Common development tasks and how-tos
- Technical Docs - Architecture and design decisions
- C++ Coding Standards - Style guide and best practices
- Game Design Documents - Feature requirements and game design
- Check docs/status.md for current work
- Read relevant technical documentation
- Write code following coding standards
- Format manually with
Shift+Alt+F - Fix clang-tidy warnings
- Test in
ui-sandboxbefore integrating into main game - Update
docs/status.mdafter significant work
For detailed workflows (adding libraries, creating scenes, etc.), see docs/workflows.md.
# Run all tests
ctest --test-dir build --output-on-failure
# Run UI sandbox
./build/apps/ui-sandbox/ui-sandbox --help
./build/apps/ui-sandbox/ui-sandbox --component button --http-port 8080- clang-format: Code formatting (
.clang-format) - clang-tidy: Static analysis and linting (
.clang-tidy) - Run formatter manually to learn the style
- Address warnings as you code
Copyright (c) 2025 Kevin Jonson. All rights reserved.
This project is licensed under the PolyForm Noncommercial License 1.0.0. You may use, modify, and distribute this software for non-commercial purposes only. Attribution is required.
For commercial licensing inquiries, please contact the maintainer.