Writing a simple cpp game with Sfml

Setting up environment on mac

We going to build simple snake game by using sfml library on mac os environment. I prefer creating projects with Makefile rather than using build-in tools so We will not use Xcode.First We need to download sfml library

1
sudo brew install libsfml-dev

then We will add easy c++ project extension in VSCode and after pressing Ctrl+Shift+P, search easy cpp create new project and finally We will create with clang++. Before executing makefile We need add dependencies in libraries in makefile.

1
LIBRARIES	:= -lsfml-graphics -lsfml-window -lsfml-system

In the SFML page, We will borrow the main.cpp sample. As it works, We can start devoloping real project.Every executable starts from main function since kernel is interrupted for looking for another main(). return 0 indicates there is no error in the executable.

We need draw a window first. In game.cpp ,we create Game constructor,destructor and Run methods from game.hpp. We define m_context pointer

1
std::shared_ptr<Context> m_context;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#pragma once   
#include <SFML/System/Time.hpp>

namespace Engine
{
    class State
    {
    public:
        State(){};      // constructor
        virtual ~State(){};     //destructor

        virtual void Init() = 0;   //pure function or interface
        virtual void ProcessInput() = 0;
        virtual void Update(sf::Time deltaTime) = 0;
        virtual void Draw() = 0;

        virtual void Pause(){};
        virtual void Start(){};
    };
    
} 

First of all pragma once is a preprocessor letting compiler know the headers are supposed to be included no more than once. Virtual class can have implementation and it derived classes can override it but if virtual class is pure function via =0, it doesnt have have any defination and must be written defination by derived classes(it is interface).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#pragma once
#include <stack>
#include <memory>
#include <State.hpp>

namespace Engine
{
 class StateMan
 {
  private:
    std::stack<std::unique_ptr<State>> m_stateStack; // m_stateStack[][]
    std::unique_ptr<State> m_newState;

    bool m_add;
    bool m_replace;
    bool m_remove;

  public:
    StateMan();
    ~StateMan();

    void Add(std::unique_ptr<State> toAdd, bool replace = false);
    void PopCurrent();
    void ProcessStateChange();
    std::unique_ptr<State>& GetCurrent();
 };

} 
1
2
3
4
5
6
7
8
#include "Game.hpp"

int main()
{
    Game game;
    game.Run();
    return 0;
}

Game object created and Run() method called.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#pragma once
#include <memory>
#include <SFML/Graphics/RenderWindow.hpp>
#include "AssetMan.hpp"
#include "StateMan.hpp"

enum AssetID
{
    MAIN_FONT = 0,GRASS,FOOD,WALL,SNAKE
};

struct Context
{
    std::unique_ptr<Engine::AssetMan> m_assets;
    std::unique_ptr<Engine::StateMan> m_states;
    std::unique_ptr<sf::RenderWindow> m_window;

    Context()
    {
        m_assets = std::make_unique<Engine::AssetMan>();
        m_states = std::make_unique<Engine::StateMan>();
        m_window = std::make_unique<sf::RenderWindow>();
    }
};

class Game
{
private:
    std::shared_ptr<Context> m_context;
    const sf::Time TIME_PER_FRAME = sf::seconds(1.f/60.f);

public:
    Game();
    ~Game();
    void Run();
};

Memory is standart cpp library in order to manage memory, we will use unique_ptr(which is a smart pointer that indicates only single refernce can point to pointers, smart pointers doesnt need to be cared external memory management, once the program counter out of scope, the array will be deleted). We create 3 array with unique_ptr of std library, their types are written in “< >".we need to add