Cardcaptor Sakura
A 2D platformer game built from the ground up using C/C++ and Simple DirectMedia Layer, as a way to learn C/C++ in depth while making a game and an engine.
Published onUpdated on
2.35
Project Summary
A passion project revolving around my childhood character Kimonoto Sakura from the series Cardcaptor Sakura, traverses a 2D platforming world sticking to the original story.
Technologies used:
- C++ 23: using concepts and techniques in C++ over pure C, such as smart pointers, Rules of Zero, as well as operator overloading and template programming.
- SDL3: a low-level framework for windowing and rendering cross-platform, including consoles.
- SDL_image, SDL_ttf: Sister helper utilities for SDL3.
- CMake & GitHub Actions: For automating builds across three major platforms natively Ubuntu (GCC), MacOS (Apple Clang) and Windows (MSVC).
- VCPKG: Caching registry and package manager for C/C++ projects.
Main Concept: Provides a baseline for learning modern C++, as well as low-level memory management (0bytes leaks in all releases), plus an additional library for drawing at a low-level (instead of Pygame or Raylib).
Technical Highlights
Originally planned to be a 3D game with 2D view most of the time, where sometimes it may use 3D objects for learning to model with Blender (but time does not allow), so it was cut down to be a fully 2D game, inspired by: Hollow Knight, Dead Cells, Super Mario Bros.
- 2D-based Primitive Collision system: Built a collision system using primitive shapes in 2D space like axis-aligned boxes, oriented boxes, circles, and capsules.
- Safe SDL wrappers: Built a set of wrapper methods and classes around SDL raw pointers to apply proper ownership semantics and the Rule of Zero in C++. As well as providing methods and ease in building up long function calls.
- Fixed & Variable Tick System: Physics always run at a fixed tick, capped at 60 times per second, but variable ticks can run as fast as the machine allows. My work Macbook may only run at 400FPS but my NVIDIA GPU PC can run it at 20000 FPS with a barebone runner.
- Proper Doxygen documentation: Module documentation is done in Doxygen style and automatically exported and deployed on github pages.
- Scene-Based System (implemented in C but not transferred over to C++ yet): each scene renders on a separate texture, layered together by the scene manager. This provides a much better management set for building transitions and layering in the z axis.
- Global Sprites System (similar to the Flyweight pattern): all objects refer to global living sprites, and they are only loaded if at least one object refers to it.
- Dependency Injection: Applying this pattern allows a lot of components to be mocked for testing instead of relying on unreliable SDL functions in CI pipelines.
I transitioned from pure C to C++23 to leverage concepts, smart pointers, operator overloading, and template programming for generic, high-level code while retaining low-level memory control and zero-overhead performance which I loved from the simplicity of C.
I transferred the project to C++ with smart pointers, standard template library, with super modern features from C++ standard level 23 to get high-level language features in addition to low level memory control.