2D side-scroller platformer game using 2D raytraced portals to create confusing, non-eucledian worlds
  • C++ 94.6%
  • CMake 3.4%
  • Nix 2%
Find a file
2026-05-13 15:33:34 +02:00
assets update readme 2026-05-13 15:19:35 +02:00
assets-src minor map edit 2026-05-12 19:35:01 +02:00
src fix uncompressed map loading codepath 2026-05-13 15:11:27 +02:00
vendor add vs build support to master 2026-05-13 15:05:15 +02:00
.envrc init project 2026-04-19 21:55:45 +02:00
.gitattributes Update .gitattributes 2026-05-11 12:53:29 +02:00
.gitignore Update .gitignore 2026-05-13 15:06:30 +02:00
.gitmodules add imgui debug ui 2026-05-06 18:14:26 +02:00
.markdownlintignore Create .markdownlintignore 2026-05-06 18:22:37 +02:00
CMakeLists.txt fix relative path loading 2026-05-11 21:14:18 +02:00
CMakeSettings.json Update CMakeSettings.json 2026-05-11 20:13:55 +02:00
CREDITS.md cleanup docs 2026-05-13 14:52:49 +02:00
flake.lock Update flake.lock 2026-05-02 15:33:19 +02:00
flake.nix add zed debug.json 2026-05-03 13:11:51 +02:00
klein.slnx add vs build support to master 2026-05-13 15:05:15 +02:00
klein.vcxproj add vs build support to master 2026-05-13 15:05:15 +02:00
klein.vcxproj.filters add vs build support to master 2026-05-13 15:05:15 +02:00
LICENSE.md init {LICENSE,README}.md 2026-05-04 01:49:36 +02:00
README.md Update README.md 2026-05-13 15:33:34 +02:00

project klein

logo

2D side-scroller platformer game prototype using 2D ray-traced portals to create confusing, non-eucledian worlds

This project has been inspired significantly by AAAAXY (by divVerent)

Made as an intake assignment for BUas.

Cloning and building

Important (only applies if cloned with git):
If you obtained this source repository by manually cloning it with git, make sure to initialize the git submodules first:

git submodule update --init --recursive

Windows build instructions

On Windows, both Visual Studio and CMake are supported:

Windows build instructions (Visual Studio)

Open and build the klein.slnx solution in Visual Studio.
The build has been verified on latest version of VS2026 Enterprise.

Windows build instructions (CMake)

Use CMakeLists.txt/CMakeSettings.json provided with the project with VS2026.

  • Make sure to select klein.exe as the build target.
  • Make sure you have git installed in your PATH (system-wide) on your host machine,
    it is required to configure the project (and is not a core part of VS2026)
    (to quickly install it, run winget install Git.Git)

Linux/macOS build instructions (CMake)

On Linux (and macOS, although untested), this project can be built using Nix and CMake:

nix develop # or, use direnv: direnv allow
cmake -B build -G Ninja
ninja -C build

All of the required dependencies and tools (including cmake and compiler) are provided as a part of the Nix flake.nix; there's no need to instal them manually.
You only need nix CLI installed on your system.

(Default configuration is Debug; to build in release mode pass -DCMAKE_BUILD_TYPE=RelWithDebInfo to the cmake command)

Gameplay and controls

Only keyboard input is supported, the controls are fairly basic:

  • Movement: either WASD/Arrow keys to move.
  • Jump: Either Space or Up on movement keys.

This game uses ray-casting-based portals to mess with your perception of the world.

Explore the confusing non-eucledian world and try to find the exit.

Debug menu

Debug menu can be used to visualize rendering internals. (It is only available if the game is built in debug mode/profile.)

Map editing/authoring

To view/edit the tilemap file, use the SpriteFusion Editor

  • Make sure to load the assets-src/klein.json file, NOT the final map.json/.json.gz that can be found in assets/
  • Export the map as JSON (Ctrl-Shift-S), and extract it into assets/ replacing exisitng files.
  • To make the map loadable in-game, it needs to be compressed with gzip first:\
    gzip -f assets/map.json
    

(Save the updated klein.json (Ctrl-S) into assets-src/ before committing the new binary map into the repository)

Technical description

The main unique point of the game is it's rendering pipeline:

  1. First, it casts rays in all directions from the player's position. Rays are allowed to cross portals.
  2. Each time ray crosses a portal, its segmented off into a separate segment;
  3. These segments are used to construct and draw to a stencil buffer (which is used to determine which parts of the map are rendered at each part of the screen)
  4. Then, game renders each unique portal view separately (each view is actually cached, so it only needs to be done once; unless the player moves and reveals new part of the map by doing so)
  5. Finally, the views generated on Step 4 are composed together using the buffer from Step 3.

License

Required Notice: Luna Prasol (https://git.lunya.cc/luna/klein)

All code under src/ is licensed under the terms of the PolyForm Non-Commercial License,
Go to LICENSE.md for more details.

Some assets might be licensed under different terms.

Third-party Asset Licenses/Attribution

NOTE: This is also available in CREDITS.md in this repository and release builds.

Note

No AI/LLM agents, generated code or documentation have been directly used for the development this project (and no such contributions will be made/accepted in the future)

(I have used Copilot auto-complete, and LLM(s) to assist in debugging during development though.)