This site uses cookies to ensure you get the best experience. More info
Got it!

Embracing SFML



Integrating SFML

After a short break I came back to work on my project. Meanwhile I was reading the SFML’s docs and implementing small examples.

So far I must say I really like it. It’s definitely a bit lower-level than your usual experience with big engines but the API is very straightforward and flexible.

I’ll definitely keep it in mind for some smaller projects in the future, but let’s go back on the tracks.

Integrating it fully into the engine actually bears some consequences.

Primitives

Firstly, SFML introduces it’s own implementation of primitives like Vectors, which would need to slowly replace usage of Bramble.Core.Vector2D structures.

For now, the engine uses both internally and the external API is exposed along with vector implementations from Bramble library.

Events and player input

Another consequence was a change to the events handling for things like mouse and keyboard input or game window’s events.

Firstly, there was a few more events to be handled now and exposing them to game objects had to be done differently.

Previously I have exposed the events by custom handlers placed on the Game class which every instantiated Game Object had access to via it’s property.

Now, hence we are fully going to embrace the SFML’s way of things, the objects that want to create callbacks for SFML window’s events will need to access the SFML window’s instance directly. The handlers of the RenderWindow instance are accessed by Window property of Game instance.

Going further, the obvious next consequence is the difference of event args passed into those callbacks.

Initially, Praedium’s engine implemented it’s own layer of abstractions for keyboard key codes, mouse button codes and custom event handlers with custom event args passed. Because of the change here, quite a bit of code had to be redacted.

Another type of units

Working with the new events brought together with SFML I had to implement a simple API for handling the Window-based units of mouse event positions.

Hence the SFML’s API is directly exposed to the Game Objects, the engine needs to provide some kind of helper method to translate those units into Viewport or World based coordinates.

To refresh things up:

  • World coordinates are the real coordinates of game objects.
  • Viewport coordinates are coordinates of visible tile cells. The top left rendered character on the game’s terminal will always have the position of (0, 0).

And now, SFML introduces the third kind of units - pixel based offset from Window’s left and top edge.

This obviously doesn’t translate at all into the viewport or world based coordinates and needs to be calculated depending on the glyphsheet characters sizes and the scale with which the sprites are rendered on the screen.

Better game loop

A direct and very obvious improvement is the changed game loop.

Previously I had to work with native platform events by calling native functions from managed code, which is not that elegant and may look confusing to other people who had no previous experience with it.

Because SFML is cross platform and wraps this problem with it’s nice API, the game loop is now much more clean.

Also, the framerate is regulated internally by SFML, and can be easily manipulated by calling the SetTargetFrameRate() method on the window.

Take a look on the new, simplified game loop code:

public void Run()
{
    while (Window.IsOpen())
    {
        TimeSpan currentTime = watch.Elapsed;
        TimeSpan elapsedTime = currentTime - lastTime;

        lastTime = currentTime;

        DeltaTime = elapsedTime.TotalSeconds;

        Window.Clear(Color.Black);
        Window.DispatchEvents();

        Update();
        Render();

        Window.Display();
    }
}

The DispatchEvents method handles all native event problems, and the game loop is now very straightforward.

Wrapping up

To be honest, integrating the SFML into the engine produced a few more problems than I expected but I think it is worth it.

This is actually an on-going process as some of the parts will require further refactoring down the line, but for now - I’ve got the old Praedium code working, so moving the camera and giving our player orders to move via mouse works just as fine as before.

Because of the switch to SFML, the performance issue is now resolved (although there is always room for performance upgrades) and I can finally focus on implementing multiple layers for the terminal to implement GUI and other more interesting things.

Another thing is that I’ll have to soon look onto building the code on linux as I have not yet experimented with that.

Also, sorry for my short week-long break. I’m back on the track and I’ll keep on working as usual.

See you next time!