Building a 2D Game Engine Using SFML I've always loved making games and using SFML, and up until a few days ago, I've had to re-write code over and over again. So I decided to write a game engine so I can reuse my code.

I've never done something like this before. I've read about it, and I watched a few videos. I'd love if you could look around, give me some ideas. Keep in mind I've only worked on this for less than a week.

GitHub

So far, I've just re-skinned SFML functions and classes using my own classes, but I've changed some functions around and made things a bit simpler.

Is it, for example, any good creating my own Sprite class that is basically a re-skin of the SFML sprite class, with perhaps some added functionality, or should my resource manager just return an SFML sprite, which the user of the engine can just use all the in-built functionality for the sf::Sprite?

Here is a very simple program that creates a sprite and a text and draws them on the screen. And we can use WASD to move the sprite.

#include &lt;Tengine2D\ResourceManager.hpp&gt;
#include &lt;Tengine2D\Window.hpp&gt;
#include &lt;Tengine2D\Keyboard.hpp&gt;
#include &lt;Tengine2D\Clock.hpp&gt;
#include &lt;Tengine2D\Text.hpp&gt;
#include &lt;Tengine2D\Vector2.hpp&gt;
#include &lt;Tengine2D\GameState.hpp&gt;
#include &lt;Tengine2D\Camera.hpp&gt;

#include &lt;iostream&gt;

int screenWidth = 1600;
int screenHeight = 640;

t2d::Clock _clock;
t2d::GameState gameState;

int main()
{

    t2d::Window _window;
    _window.create(screenWidth, screenHeight, "BELLO!");

    gameState = t2d::GameState::PLAY;

    // Text
    t2d::ResourceManager::createText("Text", "Fonts/times.ttf");
    t2d::ResourceManager::getText("Text").setCharacterSize(50);
    t2d::ResourceManager::getText("Text").setStyle(t2d::TextStyle::Bold);
    t2d::ResourceManager::getText("Text").setColor(t2d::Color::Magenta);
    t2d::ResourceManager::getText("Text").setPosition(screenWidth / 4.0f, screenHeight / 2.0f);
    t2d::ResourceManager::getText("Text").setString("Hello World");

    // Sprite
    t2d::ResourceManager::createSprite("RedPlayer", "Sprites/RedPlayer.png");
    t2d::ResourceManager::getSprite("RedPlayer").setPosition(screenWidth / 4.0f, screenHeight / 2.0f);

    while (gameState != t2d::GameState::QUIT)
    {
        float delta = _clock.restart().asSeconds();

        while (_window.pollEvent())
        {
            if(t2d::Keyboard::keyPressed(t2d::Keyboard::Escape))
            {
                gameState = t2d::GameState::QUIT;
            }
        }

        if (t2d::Keyboard::isKeyPressed(t2d::Keyboard::D))
        {
            t2d::ResourceManager::getSprite("RedPlayer").translate(400 * delta, 0.0f);
        }
        if (t2d::Keyboard::isKeyPressed(t2d::Keyboard::A))
        {
            t2d::ResourceManager::getSprite("RedPlayer").translate(-400 * delta, 0.0f);
        }
        if (t2d::Keyboard::isKeyPressed(t2d::Keyboard::S))
        {
            t2d::ResourceManager::getSprite("RedPlayer").translate(0.0f, 400 * delta);
        }
        if (t2d::Keyboard::isKeyPressed(t2d::Keyboard::W))
        {
            t2d::ResourceManager::getSprite("RedPlayer").translate(0.0f, -400 * delta);
        }

        _window.clear(t2d::Color(150, 150, 5, 255));
        _window.draw(t2d::ResourceManager::getSprite("RedPlayer"));
        _window.draw(t2d::ResourceManager::getText("Text"));
        _window.display();
    }

    return 0;
}
Personally, I see no gain in abstracting SFML at this stage. In general I only see two situations where abstracting such a fundamental library really makes sense and that would be for:


If you want to fully test your code. In that case you need to be able to decouple from the "system" and thus from SFML.
If your engine has advanced to a stage where it isn't just a cheap tech demo, but actually something real, used for some real games. Only then does it make sense to think about, whether it would make sense to refactor the code base to potentially allow for different "backends".


Additionally, option 2 is rarely possible to do cleanly, since all the frameworks offer a different set of functionalities and switching between them with a single API on top, doesn't really work and limits the set of features to be used of said library.

As for your code and question, there's a reason why SFML splits font and text, texture and sprites, soundbuffer and sound, etc. The point is that you have a heavy resource (font, texture, soundbuffer) and a light "instance" object (text, sprite, sound). That way you can move, copy, manipulate the light instances all you want and not run into any issues performance wise, while the heavy resources need to be loaded once and then kept alive as long as the light instances are using it.

Your resource manager as such shouldn't hold on to text objects or sprites and instead just handle the heavy resources and ensure that they stay alive as long as they're used. I recommend to take a look at Thor's resource management well and Thor in general as it's a nice addition to SFML.

How you want to store text or sprites is up to you and depends on the kind of game. For most simple games, it's enough to save them directly in a game state class and if you need lots, then just use a std::vector but keep in mind the advantages and limitations of used containers.