Hibiki Overview

Vector2D

Vector2D is a utility template struct for manipulating 2-dimensional vectors.
Vector2D is a simple struct that defines a mathematical vector with two coordinates (x and y) It can be used to represent anything that has two dimensions: a size, a point, a velocity, etc. The template parameter T is the type of the coordinates, It can be any numeric type for example int or float.
Vector2D supports arithmetic operations (+, -, /, /*,), compound assignment (+=, -=, /=, /*=), and comparisons (==, !=) To use you can include this header file somewhere in your code (Hibiki/Vector2D.hpp) and then use like:
class Player {
        Hibiki::Vector2D<int> position;

        Player(Hibiki::Vector2D<int> position) {
            this->position = position;
        }

        void Length() {
            vector2D.Length();
        }

        void Normalize() {
            position.Normalize();
        }

        void Compare() {
            Hibiki::Vector2D<int> temporary = {0, 0};
            if (position == temporary) {
                HIBIKI_CORE_TRACE("Position == {0,0}");
            }
        }

        void Add() {
            position = position + Hibiki::Vector2D<int>(1, 1);
        }
}

Note

Currently Hibiki Game Engine is based in OOP.

GameObject

GameObject are Objects that have states, behaviors, position, width and height.
GameObject is the most important class in the game engine as all objects in the game should inherit from this class.
GameObject is a virtual base class.
GameObject Code Definition
namespace Hibiki {
    class GameObject {
        protected:
            int32_t width = 0;
            int32_t height = 0;
            Vector2D<int32_t> position;
        public:
            GameObject() { }
            virtual ~GameObject() { }
            virtual void Load(const LoaderParams* params) = 0;
            virtual void Update() = 0;
            virtual void Draw() = 0;
            virtual void Clear() = 0;
            virtual int32_t GetWidth() { return width; }
            virtual int32_t GetHeight() { return height; }
            virtual Vector2D<int32_t>& GetPosition() { return position; }
    };
}
Hibiki has two important abstract base game objects StaticGameObject and DynamicGameObject.

StaticGameObject

Any game objects that has no movement. StaticGameObject have only one variable: type.

DynamicGameObject

Any game objects that has movement. DynamicGameObject has the following variables: velocity and acceleration.

Creating a Player inheriting from DynamicGameObject

class Player : public Hibiki::DynamicGameObject {
    private:
        uint8_t currentRow = 0; // Current row in the spritesheet
        uint8_t currentFrame = 0; // Current frame in the spritesheet
        uint8_t numFrames = 0; // Max number of frames in the spritesheet
        uint8_t direction = 0; // Player is looking towards wich direction

        std::string textureID = ""; // ID of the spritesheet texture
    public:
        Player();
        ~Player() override { HIBIKI_CORE_TRACE("~Enemy()"); } // Destructor

        void Load(const LoaderParams* params) override; // Load Function
        void Update() override; // Here we update variables and process the movement
        void Draw() override; // Here we draw the player
        void Clear() override; // Clear Function

        /* Get and Set Methods */
        uint8_t GetCurrentRow() { return this->currentRow; }
        void SetCurrentRow(uint8_t currentRow) { this->currentRow = currentRow; }
        uint8_t GetDirection() { return this->direction; }
        void SetDirection(uint8_t direction) { this->direction = direction; }
        void SetPosition(Hibiki::Vector2D<int32_t> position) { this->position = position; }
};

/* Player Creator so Player class can be created automatically by the Factory */
class PlayerCreator : public Hibiki::BaseCreator {
    Hibiki::GameObject* CreateGameObject() const {
        return new Player();
    }
};

Before using the factory you need to register the created class, you can type the following code in GameController:

GameObjectFactory::GetInstance().RegisterType("Player", new PlayerCreator());
This code should be inserted before the line:
this->gameStateMachine = new GameStateMachine();

Note

Currently Hibiki Game Engine is based in OOP.

UIObject

UIObjects are GameObjects that have states, behaviors, position, base position, anchor, width and height.
UIObject is the base for all UI in the Game Engine and is a virtual base class that inherit from GameObject.
Anchor is a pre-defined point in the screen independent of resolution, when setting a anchor we can be sure the UIObjects will have the same position in diferent resolutions.
Base Position is the position values based on the anchor defined.
Position is the real screen position that is the result calculated from the current resolution, anchor and base position.
UIObject Code Definition
namespace Hibiki::UI {
    enum Anchor : uint16_t {
        NONE = 1,
        TOP_LEFT = 2,
        TOP_CENTER = 3,
        TOP_RIGHT = 4,
        MIDDLE_LEFT = 5,
        MIDDLE_CENTER = 6,
        MIDDLE_RIGHT = 7,
        BOTTOM_LEFT = 8,
        BOTTOM_CENTER = 9,
        BOTTOM_RIGHT = 10,
        BETWEEN_TOP_LEFT_MIDDLE_CENTER = 11,
        BETWEEN_TOP_RIGHT_MIDDLE_CENTER = 12,
        BETWEEN_BOTTOM_LEFT_MIDDLE_CENTER = 13,
        BETWEEN_BOTTOM_RIGHT_MIDDLE_CENTER = 14,
    };

    class UIObject : public GameObject {
        protected:
            Vector2D<int32_t> basePosition;
            Anchor anchor = Anchor::NONE;
        public:
            UIObject() {}
            virtual ~UIObject(){ HIBIKI_CORE_TRACE("~UIObject()"); }
            virtual void Load(const LoaderParams* params) = 0;
            virtual void Update() = 0;
            virtual void UpdateOnWindowResize() = 0;
            virtual void Draw() = 0;
            virtual void Clear() = 0;
            virtual int32_t GetWidth() = 0;
            virtual int32_t GetHeight() = 0;
            virtual Vector2D<int32_t> GetRealPosition() = 0;
    };
}

Text

The Text is a UI Object used to display a text in the screen.

Example

#include "Hibiki/UIObjects/Text.hpp"

text = new Text(fontID, x, y, width, height, anchor, text, callbackID);

text.Update();
text.Draw();

Image

The Image is a UI Object used to display an image in the screen.

Example

#include "Hibiki/UIObjects/Image.hpp"

image = new Image(textureID, x, y, width, height, anchor, fullscreen, animation);

image.Update();
image.Draw();

BasicIntro

The BasicIntro is a UI Object used to show a simple intro before the game starts.

Example

#include "Hibiki/UIObjects/BasicIntro.hpp"

basicIntro = new BasicIntro(textureID, x, y, width, height, anchor, animSpeed, fullscreen, animation, soundID);

basicIntro.Update();
basicIntro.Draw();

ImageButton

The ImageButton is a UI Object that display an image and text with a button funcionality and have only one callback that is called when the button is pressed.

Example

#include "Hibiki/UIObjects/ImageButton.hpp"

imageButton = new ImageButton(textureID, fontID, x, y, width, height, anchor, text, callbackID);

imageButton.Update();
imageButton.Draw();

ActionButton

The ActionButton is a UI Object that display an image and text with a button funcionality and have button up and button down callbacks.

Example

#include "Hibiki/UIObjects/ActionButton.hpp"

actionButton = new ActionButton(textureID, x, y, width, height, anchor, text, buttonDownCallback, buttonUpCallback, fontID);

actionButton.Update();
actionButton.Draw();

GameState

A game can have different sections like menu, level, pause, in Hibiki these sections are called game state, a game state can have all types of objects and the state will be responsible to update and draw these objects.

StateParser

StateParser is a class used to parse a state from a XML file.
To load a state we can do the following:
#include "Hibiki/States/StateParser.hpp"

Hibiki::StateParser stateParser;
stateParser.ParseState(xmlStatePath, stateID, &gameObjects, &uiObjects, &textureIDList, &fontIDList, &soundIDs);

Creating a State with XML

We can create a state with XML using a simple sintax:

Note

All elements in the XML state should be capitalized like <STATES>.

<?xml version="1.0"?> <!-- Here we declare the xml version -->
<STATES> <!-- The state root element should always be the "STATES" element with no attribute.  -->
    <PLAY> <!-- This element should have the same name of the state, here we are defining the PlayState -->
        <TEXTURES>
            <!-- Inside the TEXTURES we define the textures that will be used in the game. -->
        </TEXTURES>
        <FONTS>
            <!-- Inside the FONTS we define the fonts that will be used in the game. -->
        </FONTS>
        <SOUNDS>
            <!-- Inside the SOUNDS we define the sonds that will be used in the game. -->
        </SOUNDS>
        <MUSICS>
            <!-- Inside the MUSICS we define the musics that will be used in the game. -->
        </MUSICS>
        <OBJECTS>
            <!-- Inside the OBJECTS we can create players, enemies and any other game object to be created when loading a state. -->
        </OBJECTS>
    </PLAY>
</STATES>

Creating a State inheriting from GameState

class PlayState : public GameState {
        std::vector<Hibiki::GameObject*> players = std::vector<Hibiki::GameObject*>();
        std::vector<Hibiki::GameObject*> enemies = std::vector<Hibiki::GameObject*>();
        std::vector<Hibiki::GameObject*> staticGameObjects = std::vector<Hibiki::GameObject*>();
        std::vector<Hibiki::UI::UIObject*> uiObjects = std::vector<Hibiki::UI::UIObject*>();

        std::map<std::string, std::function<void()>> functionCallbacks = std::map<std::string, std::function<void()>>();

        static const std::string stateID;

        void PlayersUpdate();
        void EnemiesUpdate();
        void StaticGameObjectsUpdate();
        void UIGameObjectsUpdate();

        void SetCallbacks();
    public:
        PlayState();
        ~PlayState() override;

        void Update() override;
        void UpdateOnWindowResize() override;
        void Draw() override;
        std::string GetStateID() const override { return stateID; }

        std::vector<Hibiki::GameObject*>* GetPlayers() {
            return &players;
        }
        std::vector<Hibiki::GameObject*>* GetEnemies() {
            return &enemies;
        }
        std::vector<Hibiki::GameObject*>* GetStaticGameObjects() {
            return &staticGameObjects;
        }
        std::vector<Hibiki::GameObject*>* GetUIGameObjects() {
            return &uiObjects;
        }
};

Map

We can load maps created in the Tiled Map Editor, to used Tiled maps in Hibiki we need maps with the following groups: MapAttributes, GameObjects, Textures, Map.

Note

The Map property Tile Layer Format should be Base64 (zlib compression).

MapAttributes is a group layer that can contain multiple object layers and each object layer can have multiple objects, all objects inside a object layer will have the same behaivour that should be specified in the State that will load the map.
GameObjects is the group layer that should contain different types of game objects, the game objects will be created at map load time and will have the same position speficied in the editor.
Textures is a group layer that has one object layer that should contain textures that will be used in the game.
Map is a group layer that contains all layers of tiles to be draw in the screen.
../_images/tiledMap.png

MapParser

MapParser is a class used to parse maps from a TMX file.

Note

TMX is a format used by the Tiled Map Editor.

To load a map we can do the following:
#include "Hibiki/Map/MapParser.hpp"

Hibiki::MapParser mapParser;
mapParser.ParseMap(tmxMapPath, &layers, &tilesets, &players, &enemies, &staticGameObjects, &mapAttributes, &tileSize);

Collisions

Grid

This is a simple Grid implementation that uses a divisor to make the cells in the map, so we can query gameObjects in the same cell and neighbors cells.
Usage:
#include "Hibiki/GameController.hpp"
#include "Hibiki/Collision/BroadPhase/Grid.hpp"

Hibiki::Collision::Grid<int32_t> grid;

void ExampleState::Init() {
    int tileSize = 32;
    int divisor = 32;
    int width = (Hibiki::GameController::GetInstance().GetMapSize().x/tileSize)/divisor;
    int height = (Hibiki::GameController::GetInstance().GetMapSize().y/tileSize)/divisor;
    this->grid = Hibiki::Collision::Grid<int>(width, height, divisor, tileSize);
    //...
}

void PlayState::Update() {
    for (auto& it : this->staticGameObjects) {
        this->grid.Update(it);
    }
    for (auto& it : this->players) {
        this->grid.Update(it);
    }
    for (auto& it : this->enemies) {
        this->grid.Update(it);
    }
    //...
}
To Query a vector of GameObjects we can use the following code:
std::vector<Hibiki::GameObject*> gameObjectsFound = std::vector<Hibiki::GameObject*>();
this->grid.Query(someGameObject*, &gameObjectsFound);
After querying we can loop the gameObjectsFound vector and only check for collisions against the GameObjects found in the query instead of checking all GameObjects in the game or in the current state.

QuadTree

Attention

QuadTree is recommend only for StaticGameObjects, so we don’t need to update the QuadTree but if we want to update we need to delete everything in the QuadTree and Insert all gameobjects again and when updating the QuadTree make sure to not destroy any gameObject pointer.

QuadTree is a tree data structure in which each internal quad has exactly four children. Quadtrees are most often used to partition a two-dimensional space by recursively subdividing it intofour quadrants or regions.
This QuadTree implementation uses a Rectangle stored as a x, y, width and height to represent the boundaries of this quadtree.
Usage:
#include "Hibiki/GameController.hpp"
#include "Hibiki/Collision/Shapes/Rectangle.hpp"
#include "Hibiki/Collision/BroadPhase/QuadTree.hpp"

Hibiki::Collision::Rectangle<int> rectangleBoundary;
Hibiki::Collision::QuadTree<int> quadTree;

void ExampleState::Init() {
    rectangleBoundary = {0, 0, Hibiki::GameController::GetInstance().GetMapSize().x, Hibiki::GameController::GetInstance().GetMapSize().y};
    int maxNodeCapacity = 4;
    int tileSize = 32;
    quadTree = {rectangleBoundary, maxNodeCapacity, tileSize};

    for (auto& it : staticGameObjects) {
        quadTree.Insert(it);
    }
    //...
}
To Query a vector of GameObjects we can use the following code:
std::vector<Hibiki::GameObject*> gameObjectsFound = std::vector<Hibiki::GameObject*>();
Hibiki::Collision::Rectangle<int32_t> someRectanglePosition = {x, y, width, height};
this->quadTree.Query(someRectanglePosition, &gameObjectsFound);
After querying we can loop the gameObjectsFound vector and only check for collisions against the GameObjects found in the query instead of checking all GameObjects in the game or in the current state.

AABBQuadTree

An AABBQuadTree has the same funcinality and usage of the QuadTree but is implemented using AABB insted of a Rectangle.
AABB is a axis-aligned bounding box stored as a center with half-dimensions.

Camera

Class used for games with maps greater than the screen size, with this class we can set a target that the camera will follow and draw the Map and GameObjects based on the screen size and current camera position.
We can set a target with:
#include "Hibiki/Camera.hpp"

Hibiki::Camera::GetInstance().SetTarget(&vector2DPosition);
And a draw a GameObject based on camera position with:
void ExampleGameObject::Draw() {
    int tileSize = 32;
    Hibiki::Vector2D<int> camera = Hibiki::Camera::GetInstance().GetPosition();
    Hibiki::Vector2D<int> positionBasedOnCamera = {(this->position.x*tileSize)-camera.x, (this->position.y*tileSize)-camera.y};
    Hibiki::TextureManager::GetInstance().DrawFrame(this->textureID, positionBasedOnCamera.x, positionBasedOnCamera.y, this->width, this->height, this->currentRow, this->currentFrame);
}