Senpai App Engine

Code
C++
Game
Author

Daniel Schwarzenbach

Published

April 24, 2025


Github Senpai-App-Engine

The Senpai App Engine is very much still in development.

It’s an easy to use C++ library with wich Apps and Games can be made.


Example Project

The Engine comes with an example game: Five Knights against King Fredric

How to use it

Main Function

To run an app, one has to define scene-load-functions and push them into the app.sceneLoaders

#include <Senpai>

extern void load_loading_scene(Senpai::Scene* scenePtr);
extern void load_main_menu_scene(Senpai::Scene* scenePtr);
extern void load_game_scene(Senpai::Scene* scenePtr);

int main() {
   // create an app
   Senpai::App app;
   // set the app settings
   app.settings.fpsTarget = 30;
   // add the scenes to the app
   app.sceneLoaders.push_back(load_loading_scene);
   app.sceneLoaders.push_back(load_main_menu_scene);
   app.sceneLoaders.push_back(load_game_scene);
   // run the app
   app.run();
   // return 0 to the OS
   return 0;
}

Scene Load Function

here is how one has to define such a scene-load-function

#pragma once
#include <Senpai>

namespace base {
  // declare a global click_sound
  extern Assets::Audio* clicksound;
};

// script that animates the loading screen
struct loading_animator final : public Script {
   f32 timetochange = 0.1f;

   void on_update(f32 dt) override {
      if ((timetochange -= dt) > 0) return;
      timetochange = 0.3f;
      auto &b = entityPtr->get_component<Components::ButtonUI>();
      auto &tr = entityPtr->get_component<Components::Transform>();
      f32 shift = b.fontPtr->size / 10.0f;
      if (b.text == "Loading...") {
         b.text = "Loading";
         tr.frame.position.x = 0;
      } else if (b.text == "Loading") {
         b.text = "Loading.";
         tr.frame.position.x = +shift;
      } else if (b.text == "Loading.") {
         b.text = "Loading..";
         tr.frame.position.x = +2 * shift;
      } else if (b.text == "Loading..") {
         b.text = "Loading...";
         tr.frame.position.x = +3 * shift;
      }
   }
};

// define the loading-function for the loading screen
void load_loading_scene(Ptr<Scene> scenePtr) {
   // system that runs the scripts
   scenePtr->add_system<Systems::ScriptRunner>();
   // system that handles the UI elemnts
   scenePtr->add_system<Systems::UIRenderSystem>();
   // load the font asset
   Assets::Font &font = scenePtr->add_asset<Assets::Font>(std::move(
       Assets::Font{"./assets/fonts/The Centurion .ttf", 200, "HeroFont"}));
   // load in the clicksound
   auto& clicksound = scenePtr->add_asset<Assets::Audio>("./assets/audio/Click.mp3");
   base::clicksound = &clicksound;
   // add the text entity
   Entity &loadingText = scenePtr->add_entity();
   // add the transform component to the entity
   auto &tr = loadingText.add_component<Components::Transform>();
   // add a button ui component to the entity
   auto &button = loadingText.add_component<Components::ButtonUI>(
       Components::ButtonUI{&font,
                            "Loading",
                            {255, 255, 255, 255},
                            {0, 0, 0, 0},
                            {0, 0, 0, 0},
                            {0, 0}});
   // add the animation script to the entity
   loadingText.add_script<loading_animator>();
}

Assets

here you can find information about all avaiable Senpai::Assets

Assets are used to load in Pictures, Audio, Animations and other stuff into the App.

Components

here you can find information about all avaiable Senpai::Components

The Engine is based on Entities that can be filled with Components.

Systems

here you can find information about all avaiable Senpai::Systems

Systems update all Scripts and Components and make the scene alive.

How it works

The app loads scenes via load functions.

Every scene consists of assets, entities, and systems. An entity, in turn, consists of multiple components that are updated by the systems.

Senpai Engine

ECRegistry

The Entity Component Registry contains all components and keeps track of which entity has which component.

AssetsRegistry

The Assets Registry makes assets more accessible by id and name.

Reference Safety

All assets, components, entities, and systems are stored in either lists or deques to ensure reference safety. If you take a reference or pointer to one of these objects, it will remain valid for the duration of the object’s lifetime.

Senpai Engine

Input Class

A static class that provides easy access to events and input.

See: Senpai/core/Inputs.h++

EventDispatcher

Contains callback functions and calls them when a specific event occurs.

See: Senpai/core/Event.h++

Inspiration

The game engine I created is based on this book: CROSS-PLATFORM 2D GAME WITH SDL2

The source code of the book is available here: https://github.com/Madsycode/book-fuse-engine

However, Senpai is not just a simple copy!

Features such as multiple scenes, lighting, geometry, and cameras are just a few of the custom features and optimizations.