-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Genode (Game EngiNe On DEmand) is a game framework that is written in C++17 and built on top of SFML V3.
As the name suggests, this project is on the contrary side of other common engines or frameworks; initially, it is not built for the general use case. It began with the idea that it would only evolve or change to satisfy the demands of my own game development needs, which favor certain conventions, patterns, and even my own personal preferences.
The easiest way to use Genode in the current form is to drop entire src
and include
directly into your SFML game source tree. No particular macros or configuration are required.
Alternatively, you can include the CMake project into your project or build the library statically via CMake command, linking it into your project:
cmake -B ./build -DCMAKE_BUILD_TYPE=Release
cmake --build ./build --config Release
Genode requires sfml-system
, sfml-audio
, sfml-graphics
and sfml-window
. Unlike SFML, each module in Genode is not designed to be compiled or distributed separately. As such, omitting one of those dependencies may result in a compilation error (it is untested)
The following articles introduce the modules and teach you to build your game with Genode. It is strongly recommended to read those articles in the following order, from low- to high-levels of abstraction, so you can decide the right amount of abstraction and become familiar with the layers of implementations that you wish to optimize later:
Genode primarily uses SceneGraph
as its building block. However, you can always omit some of these components and roll out your implementation. This could be useful if you're particular about performance and/or implementation in specific areas. See Only pay for what you use for more details.
Typically, you will need to implement these 2 classes:
Gx::Application
Gx::Scene
This class represents your application class; it provides some simple lifecycle events, such as Boot
and Shutdown
, which will be called when the application is about to start and exit, respectively. Here's how application class would typically look like:
Important
Gx::Application
is designed to work with a single thread for polling inputs and rendering; it also only supports a single render window at a time.
If this does not fit your use case, use Gx::SceneDirector
directly or manage Gx::Scene
objects manually
#include <Genode/System/Application.hpp>
#include "MyAwesomeScene.hpp"
class MyAwesomeGame : public Gx::Application
{
public:
// Application constructor
MyAwesomeGame(std::string title, const sf::VideoMode& mode, const sf::View& view, const bool fullScreen, const sf::ContextSettings& settings) :
Gx::Application(std::move(title), mode, view, fullScreen, settings)
{
}
protected:
void Boot() override
{
// Initialize your game here.
// For example, you can load global resources, load game config, register scene loaders, etc.
// You should also present your initial scene here
GetSceneDirector().Present<MyAwesomeScene>();
}
int Shutdown() override
{
// Called when the game is about to close. Return application exit code here
return 0;
}
}
Scene (also known as State or Page) represents a virtual environment comprising a collection of node objects. A game typically has multiple scenes, such as the Main Menu, Inventory, and Battle scenes.
In Genode, every object in the SceneGraph
is made of a Gx::Node
object, which is a class that represents an object inside the scene. In fact, the Gx::Scene
class itself is made of Gx::Node
. Each of node objects can have other nodes as children. This allows you to build a complex object hierarchy inside the scene.
For this purpose, many SFML drawable entities such as sf::Sprite
, sf::Text
and sf::Shape
are re-implemented to work with Gx::Node
; see Drawable re-implementation for more details.
Here's how a Gx::Scene
implementation is typically written:
#include <Genode/SceneGraph/Scene.hpp>
#include <Genode/Graphics/Sprite.hpp>
class MyAwesomeScene : public Gx::Scene
{
public:
// Avoid performing complex initialization in the constructor.
// This is because many scenes' contexts are not initialized when the object is newly constructed.
MyAwesomeScene() = default;
// Similar advice also applies to the destructor.
~MyAwesomeScene() = default;
protected:
// Instead, you should do initialization and clean-up in `Initialize` and `Finalize` respectively
void Initialize() override
{
// Initialize texture and sprite
m_texture = sf::Texture("./some/path/to/texture.png");
m_sprite = Gx::Sprite(m_texture);
// Add sprite into the scene
// You need to ensure that textures and sprites are alive when they are still a part of the active scene
AddChild(m_sprite);
}
void Finalize() override
{
// Do clean-up here if necessary
}
private:
sf::Texture m_texture;
Gx::Sprite m_sprite;
}
Running your game is straightforward: simply instantiate your application with the required parameters and call Start()
function to start the game.
#include "MyAwesomeGame.hpp"
int main(int argc , char** argv)
{
auto myGame = MyAwesomeGame(
"My Awesome Game", // Title bar string
sf::VideoMode({1920, 1080}), // sf::VideoMode to initialize the window
sf::View({0, 0, 1920, 1080}), // Default view of the application
false // Fullscreen mode
);
// Start is a thread blocking function which returns the exit code of the application, propagated from `Shutdown()`
return myGame.Start();
}
Copyright © 2024 - CXO2
This open-source library is licensed under the zlib/libpng license.