GitHub - trollworks/sdk-core: Core SDK of Trollworks engine (original) (raw)

Trollworks SDK Core

tests license version

Trollworks is an (unfinished) game engine in C++ I've been working on for a while.

This repository contains the basis of the SDK, as a header-only C++23 library. It is built around EnTT, an ECS library.

This library provides:

List of backends:

Name 2D/3D URL
SDL2 2D https://github.com/trollworks/sdk-backend-sdl
raylib 2D https://github.com/trollworks/sdk-backend-raylib (TODO)
glfw 3D https://github.com/trollworks/sdk-backend-glfw (TODO)

Installation

Clone the repository in your project (don't forget to pull the submodules) and add the include/ folder to your include paths.

Or, if you are using Shipp, add to your dependencies:

{ "dependencies": [ { "name": "trollworks-sdk-core", "url": "https://github.com/trollworks/sdk-core.git", "version": "v0.3.0" } ] }

Usage

Game loop

#include <trollworks.hpp>

struct game_state { // ... };

struct listener { game_state& gs;

void on_setup(tw::controlflow& cf) { // create window and opengl context, load resources }

void on_teardown() { // free resources, opengl context and window }

void on_frame_begin(tw::controlflow& cf) { // process window events and inputs }

void on_fixed_update(float delta_time, tw::controlflow& cf) { // physics updates }

void on_update(float delta_time, tw::controlflow& cf) { // game logic }

void on_late_update(float delta_time, tw::controlflow& cf) { // more game logic }

void on_render() { // render graphics }

void on_frame_end(tw::controlflow& cf) { // ... } };

int main() { auto gs = game_state{}; auto l = listener{.gs = gs}; auto loop = tw::game_loop{};

loop .with_fps(60) .with_ups(50) .on_setup<&listener::on_setup>(l) .on_teardown<&listener::on_teardown>(l) .on_frame_begin<&listener::on_frame_begin>(l) .on_frame_end<&listener::on_frame_end>(l) .on_update<&listener::on_update>(l) .on_fixed_update<&listener::on_fixed_update>(l) .on_late_update<&listener::on_late_update>(l) .on_render<&listener::on_render>(l) .run();

return 0; }

NB: A concept backend_trait is also provided to facilitate pluging in a specific window/event/render system (SDL, raylib, glfw, ...):

struct sdl_backend { SDL_Window *window; SDL_Renderer *renderer;

void setup(tw::controlflow& cf) { // create window, opengl context, ... }

void teardown() { // free opengl context and window }

void poll_events(tw::controlflow& cf) { // process event, for example with SDL: SDL_Event evt;

while (SDL_PollEvents(&evt)) {
  switch (evt.type) {
    case SDL_QUIT:
      cf = tw::controlflow::exit;
      break;

    default:
      // ...
      break;
  }
}

}

void render() { // get current scene's entity registry auto& registry = tw::scene_manager::main().registry();

SDL_RenderClear(renderer);

// iterate over your entities to draw them

// render UI with imgui, or nuklear, or other

SDL_RenderPresent(renderer);

} };

int main() { auto back = sdl_backend{}; auto loop = tw::game_loop{};

loop .with_fps(60) .with_ups(50) .with_backend(back) .run();

return 0; }

Coroutines

First, create your coroutine function:

tw::coroutine count(int n) { for (auto i = 0; i < n; i++) { co_yield tw::coroutine::none{}; } }

Then, in your game loop:

tw::coroutine_manager::main().start_coroutine(count(5));

Coroutines are run after the update hook and before the late update hook.

Coroutines can also be chained, like in Unity:

tw::coroutine count2(int a, int b) { co_yield count(a); co_yield count(b); }

Scene management

A scene is a class providing 2 methods (load and unload):

class my_scene final : public tw::scene { public: virtual void load(entt::registry& registry) override { // create entities and components }

virtual void unload(entt::registry& registry) override {
  // destroy entities and components
}

};

Then:

tw::scene_manager::main().load(my_scene{});

Assets

The asset manager provides a singleton per asset type. The singleton is simply a resource cache from EnTT, for more information consultthis page.

struct my_asset { // ...

using resource_type = my_asset;

struct loader_type { using result_type = std::shared_ptr;

result_type operator()(/* ... */) const {
  // ...
}

}; };

auto& cache = tw::asset_manager::cache();

NB: The resource_type type name may seem redundant, but it is there for assets that loads the same type of resources, consider the following example:

struct spritesheet { // ... };

struct aseprite_sheet { using resource_type = spritesheet;

struct loader_type { using result_type = std::shared_ptr;

result_type operator()(/* ... */) const {
  // ...
}

}; };

struct texturepacker_sheet { using resource_type = spritesheet;

struct loader_type { using result_type = std::shared_ptr;

result_type operator()(/* ... */) const {
  // ...
}

}; };

Both aseprite_sheet and texturepacker_sheet assets will return aspritesheet resource:

auto [it, loaded] = tw::asset_manager::cache().load(/* ... */); auto [id, sheet] = *it; // sheet is entt::resource

auto [it, loaded] = tw::asset_manager::cache().load(/* ... */); auto [id, sheet] = *it; // sheet is entt::resource

Messaging

The message bus is simply a singleton returning an entt::dispatcher. For more information, please consultthis page.

auto& dispatcher = tw::message_bus::main();

Queued messages are dispatched after the late update hook an before rendering.

Jobs

The job manager is simply a singleton returing an entt::basic_scheduler<float>. For more information, please consultthis page.

UI framework

using namespace entt::literals;

struct foo { void operator()(tw::ui::hooks& h) { auto& local_state = h.use_state(0);

// gui code

} };

struct bar { void operator()(tw::ui::hooks& h) { auto& local_state = h.use_state(0.0f);

// gui code

} };

struct root { bool condition;

void operator()(tw::ui::hooks& h) { h.render("a"_hs);

if (condition) {
  h.render<foo>("b"_hs);
}

h.render<bar>("c"_hs);

} };

Then in your render hook:

tw::ui::h("root"_hs, root{.condition = true});

The ids given to the UI hooks must be unique within the component, not globally.

License

This project is released under the terms of the MIT License.