SuperWangKai / kengine

The Koala engine is a type-safe and self-documenting implementation of an Entity-Component-System (ECS), with a focus on runtime extensibility and compile-time type safety and clarity.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Kengine

The Koala engine is a type-safe and self-documenting implementation of an Entity-Component-System (ECS), with a focus on runtime extensibility and compile-time type safety and clarity.

This new version features a greatly optimized memory architecture, better cache-efficiency, and a more advanced API.

It has however (temporarily) lost a couple of features:

  • Entities no longer have names. If you really need to associate strings to your Entities you can create a NameComponent or something similar
  • Entities can no longer be serialized to ostream. I am currently working to re-implement this feature. * Because of the previous point, it is no longer possible to save and load the game state. I am currently working to re-implement this feature, in a manner that will be better optimized than the original (binary saving instead of JSON serialization)
  • Saves now work (in binary format, using a separate save file for each component pool and another file for the list of entities and their masks) but have not been merged into the master branch yet. If you desperately need them ASAP, either use the develop branch or open an issue and I'll merge it.

koala

Installation

The project uses git submodules extensively, and must therefore be cloned recursively.

git clone --recursive git@github.com:phiste/kengine

Alternatively, if using this resository as a submodule of your own project, make sure to init, sync and update your submodules in order to make sure the "putils" folder isn't empty.

The engine requires a C++17 compiler.

Classes

  • Entity: represents an in-game entity. Is simply a container of Components
  • System: holds game logic. A PhysicsSystem might control the movement of Entities, for instance.
  • EntityManager: manages Entities, Components and Systems

Note that there is no Component class. Any type can be used as a Component, and dynamically attached/detached to Entities.

Reflection

Many parts of the engine (such as the scripting systems or the OpenGL system) make use of putils' reflection API. Most of the components in the following samples are thus defined as reflectible.

Samples

These are pre-built, extensible and pluggable elements that can be used in any project, or to bootstrap a project.

Components

General purpose gamedev:

Behaviors:

  • BehaviorComponent: defines a function to be called each frame for a Entity
  • LuaComponent: defines the lua scripts to be run by the LuaSystem for a Entity
  • PyComponent: defines the Python scripts to be run by the PySystem for a Entity
  • CollisionComponent: defines a function to be called when a Entity collides with another

Debug tools:

Graphics and gamedev:

  • GraphicsComponent: provides graphical information about a Entity, such as its appearance, used by the SfSystem
  • CameraComponent: lets Entities be used as in-game cameras, to define a frustrum and position. Follows the same conventions as TransformComponent
  • InputComponent: lets Entities receive keyboard and mouse events
  • GUIComponent: lets Entities be used as GUI elements such as buttons, lists...)
Systems
DataPackets
  • Log: received by the LogSystem, used to log a message
  • Collision: sent by the PhysicsSystem, indicates a collision between two Entities
  • RegisterAppearance: received by the SfSystem, maps an abstract appearance to a concrete texture file.

These are datapackets sent from one System to another to communicate.

Example

Here is a list of simple, half-a-day implementation of games:

Old API, deprecated:

Below is a commented main function that creates an entity and attaches some components to it, as well as a lua script. This should let you get an idea of what is possible using the kengine's support for reflection and runtime extensibility, as well as the compile-time clarity and type-safety that were the two motivations behind the project.

main.cpp
#include <iostream>

#include "go_to_bin_dir.hpp"

#include "EntityManager.hpp"
#include "Entity.hpp"

#include "systems/LuaSystem.hpp"
#include "components/GraphicsComponent.hpp"
#include "components/TransformComponent.hpp"

// Simple system that outputs the transform and lua components of each entity that has them
class DebugSystem : public kengine::System<DebugSystem> {
public:
    DebugSystem(kengine::EntityManager & em) : System<DebugSystem>(em), _em(em) {}

    void execute() final {
        for (const auto & [e, transform, lua] : _em.getEntities<kengine::TransformComponent3f, kengine::LuaComponent>()) {
            std::cout << "Entity " << e.id << '\n';

            std::cout << "\tTransform: " << transform.boundingBox << '\n';

            std::cout << "\tScripts:" << '\n';
            for (const auto & script : lua.getScripts())
                std::cout << "\t\t[" << script << "]\n";

            std::cout << '\n';
        }
    }

private:
	kengine::EntityManager & _em;
};

int main(int, char **av) {
    // Go to the executable's directory to be next to resources and scripts
    putils::goToBinDir(av[0]);

    // Create an EntityManager
    kengine::EntityManager em; // Optionally, pass a number of threads as parameter (kengine::EntityManager em(4);)

    // Load the specified systems, and any plugin placed in the executable's directory
    //      If you specify 'KENGINE_SFML' as TRUE in your CMakeLists.txt, this will load the SfSystem
    em.loadSystems<DebugSystem, kengine::LuaSystem>(".");

    // To add a new system, simply add a DLL with a
    //      `ISystem *getSystem(kengine::EntityManager &em)`
    // To add a new system, simply add a DLL with a

    // Create an Entity and attach Components to it
    em += [](kengine::Entity e) {
        e += kengine::TransformComponent3f({ 42.f, 0.f, 42.f }); // Parameter is a Point3f for position
        e += kengine::LuaComponent({ "scripts/unit.lua" }); // Parameter is a vector of scripts
    };

	// Register types to be used in lua
    try {
        auto &lua = em.getSystem<kengine::LuaSystem>();
        lua.registerTypes<
            kengine::TransformComponent3f, putils::Point<float, 3>, putils::Rect<float, 3>,
            kengine::LuaComponent
        >();
    }
    catch (const std::out_of_range &) {} // If the LuaSystem wasn't found, ignore

    // Start game
    while (em.running)
        em.execute();

    return (EXIT_SUCCESS);
}
scripts/unit.lua
-- Simply modify component

local transform = self:getTransformComponent()
local pos = transform.boundingBox.topLeft
pos.x = pos.x + 1

About

The Koala engine is a type-safe and self-documenting implementation of an Entity-Component-System (ECS), with a focus on runtime extensibility and compile-time type safety and clarity.

License:MIT License


Languages

Language:C++ 98.1%Language:CMake 1.7%Language:Lua 0.2%