First application

This guide takes you through writing a small application using RæptorCogs. By the end of this tutorial, you will have a basic understanding of how to create a window and render simple graphics using the framework.

Step by step

Including RæptorCogs headers

To start using RæptorCogs in your application, you need to include the necessary header.

#include <RaeptorCogs/RaeptorCogs.hpp>

This header includes all the core functionalities of RæptorCogs. It allow you to manipulate the state of the framework, create windows, render graphics, and handle input events.

When using components like Sprite or Text, you may need to include their specific headers as well:

#include <RaeptorCogs/Graphics/Sprite.hpp>
#include <RaeptorCogs/Graphics/Text.hpp>

Which will give you access to the classes and functions needed to work with these graphics elements.

Initializing and terminating RæptorCogs

Before using any RæptorCogs functionality, you must initialize the framework. This is done by calling the RaeptorCogs::Initialize() function. It is important to call this function at the beginning of your application, before creating any windows or rendering graphics.

RaeptorCogs::Initialize();

At the end of your application, you should call RaeptorCogs::Destroy() to clean up resources and properly terminate the framework.

RaeptorCogs::Destroy();

This ensures that all allocated resources are released and that the application exits cleanly.

Initializing the Renderer

The Renderer is responsible for all rendering operations in RæptorCogs. Before you can render anything, you need to initialize the Renderer with the desired graphics backend (e.g., OpenGL).

RaeptorCogs::Renderer().Initialize(RaeptorCogs::GraphicsBackend::GL);
// Initialize OpenGL backend

This initializes the Renderer to use the OpenGL graphics backend. You can choose other backends if supported by your system. This step is crucial as it sets up the necessary graphics context for rendering.

Creating a window

To create a window where your graphics will be displayed, use the Platform::createWindow() method of the Renderer. You can specify the width, height, and title of the window.

RaeptorCogs::Window* window = RaeptorCogs::Renderer().CreateWindow(
    800,
    600,
    "My First RæptorCogs Application"
    );

This creates a window with a width of 800 pixels, a height of 600 pixels, and the title “My First RæptorCogs Application”.

Entering the main loop

After creating the window, you need to enter the main loop of your application. This loop will keep your application running, handle events, and render graphics until the window is closed. To do this, use the RaeptorCogs::Renderer::StartLoop() method. This method takes a function that will be called each frame to perform rendering and a pointer to the window you created earlier.

RaeptorCogs::Renderer().StartLoop(
    [](RaeptorCogs::Window* win) {
        // Rendering code goes here
    },
    window
);

Checking inputs

Inside the main loop function, you can check for input events such as keyboard and mouse actions. RæptorCogs provides methods to check the state of keys and mouse buttons. For example, to check if the Escape key is pressed, you can use the following code:

if (RaeptorCogs::Input().isKeyPressed(RaeptorCogs::Key::Escape)) {
    // Close the window if Escape is pressed
}

Rendering with RæptorCogs

Inside the main loop function, you can add your rendering code. This is where you will clear the screen, draw sprites, text, and other graphics elements. Here is a simple example of clearing the screen and rendering a sprite:

RaeptorCogs::Renderer().StartLoop(
    [](RaeptorCogs::Window* win) {
        // Create and render a sprite
        RaeptorCogs::Sprite2D sprite;
        sprite.setPosition({400.0f, 300.0f}); // Center of the window
        sprite.setSize({100.0f, 100.0f}); // Size of the sprite
        sprite.setColor({1.0f, 0.0f, 0.0f}); // Red color

        RaeptorCogs::Renderer().add(sprite); // Add sprite to the renderer
        RaeptorCogs::Renderer().render(*win); // Render all added elements
    },
    window
);

Reading the timer

During each iteration of the main loop, you may want to read the time elapsed since the last frame. This is useful for animations and time-based updates. You can use the RaeptorCogs::Time::getDeltaTime() method to get the time in seconds since the last frame.

float deltaTime = RaeptorCogs::Time().getDeltaTime();

You can also get the total time since the application started using RaeptorCogs::Time::getTime().

float totalTime = RaeptorCogs::Time().getTime();

Putting it together

Now that you have the basic components, you can put them together in a simple application. Below is a complete example that initializes RæptorCogs, creates a window, and enters the main rendering loop.

  1#include <RaeptorCogs/RaeptorCogs.hpp>
  2#include <RaeptorCogs/Sprite.hpp>
  3#include <RaeptorCogs/Window.hpp>
  4#include <RaeptorCogs/IO/Texture.hpp>
  5#include <RaeptorCogs/Text.hpp>
  6#include <RaeptorCogs/Camera.hpp>
  7
  8constexpr int WINDOW_WIDTH = 800;
  9constexpr int WINDOW_HEIGHT = 600;
 10
 11RaeptorCogs::Camera2D camera;
 12
 13RaeptorCogs::Sprite2D raeptorLogoSprite;
 14
 15struct RaeptorParticle {
 16    RaeptorCogs::Sprite2D sprite;
 17    float speed;
 18};
 19
 20std::array<RaeptorParticle, 10000> raeptorParticles;
 21
 22RaeptorCogs::Text2D raeptorText;
 23RaeptorCogs::Text2D creditsText;
 24
 25float lastTime = 0.0f;
 26
 27std::string GetFpsString() {
 28    std::ostringstream fps;
 29    fps << std::fixed << std::setprecision(2) << 1.0f / RaeptorCogs::Time().getDeltaTime();
 30    return fps.str();
 31}
 32
 33void UpdateText() {
 34    std::ostringstream fps;
 35    fps << std::fixed << std::setprecision(2) << 1.0f / RaeptorCogs::Time().getDeltaTime();
 36    raeptorText.setContent("Welcome to RæptorCogs!\nC++ Graphics/Game Engine Framework (" + GetFpsString() + " fps)");
 37}
 38
 39void Initialize() {
 40    RaeptorCogs::Renderer().add(camera);
 41
 42    RaeptorCogs::Font &defaultFont = RaeptorCogs::ResourceManager<RaeptorCogs::Font>().get_or_create("assets/fonts/Alef-Bold.ttf");
 43    defaultFont.onLoad = [&]() {
 44        std::cout << "Default font loaded!" << std::endl;
 45        raeptorText = RaeptorCogs::Text2D(defaultFont);
 46        raeptorText.setZIndex(10.0f);
 47        raeptorText.setTextSize(48.0f);
 48        raeptorText.setPosition({0.0f, -200.0f});
 49        raeptorText.setAnchor({0.5f, 0.5f});
 50        raeptorText.setAlignment(RaeptorCogs::TextAlignment::CENTER);
 51        RaeptorCogs::Renderer().add(raeptorText);
 52        creditsText = RaeptorCogs::Text2D(defaultFont, "RæptorCogs Demo - © RÆPTOR\nDeveloped by Estorc\n2025 © MIT License");
 53        creditsText.setZIndex(10.0f);
 54        creditsText.setTextSize(24.0f);
 55        creditsText.setPosition({0.0f, 250.0f});
 56        creditsText.setAnchor({0.5f, 0.5f});
 57        creditsText.setAlignment(RaeptorCogs::TextAlignment::CENTER);
 58        RaeptorCogs::Renderer().add(creditsText);
 59    };
 60
 61    RaeptorCogs::Texture& logoTexture = RaeptorCogs::ResourceManager<RaeptorCogs::Texture>().create("assets/textures/raeptor-cogs-logo.png");
 62    logoTexture.onLoad = [&]() {
 63        std::cout << "RaeptorCogs logo texture loaded!" << std::endl;
 64        raeptorLogoSprite.setTexture(logoTexture);
 65        raeptorLogoSprite.setPosition({0.0f, 0.0f});
 66        raeptorLogoSprite.setAnchor({0.5f, 0.5f});
 67        raeptorLogoSprite.setSize({200.0f, 200.0f});
 68        raeptorLogoSprite.setZIndex(5.0f);
 69        RaeptorCogs::Renderer().add(raeptorLogoSprite);
 70        for (size_t i = 0; i < raeptorParticles.size(); ++i) {
 71            raeptorParticles[i].sprite.setTexture(logoTexture);
 72            float scale = RaeptorCogs::Random().getFloat(0.1f, 1.0f);
 73            raeptorParticles[i].sprite.setScale({scale, scale});
 74            raeptorParticles[i].sprite.setSize({20.0f, 20.0f});
 75            raeptorParticles[i].sprite.setPosition({0.0f, INFINITY});
 76            raeptorParticles[i].sprite.setAnchor({0.5f, 0.5f});
 77            raeptorParticles[i].sprite.setColor({RaeptorCogs::Random().getFloat(0.0f, 1.0f), RaeptorCogs::Random().getFloat(0.0f, 1.0f), RaeptorCogs::Random().getFloat(0.0f, 1.0f)});
 78            RaeptorCogs::Renderer().add(raeptorParticles[i].sprite);
 79            raeptorParticles[i].speed = 50.0f + RaeptorCogs::Random().getFloat(0.0f, 150.0f);
 80        }
 81    };
 82}
 83
 84void Update(RaeptorCogs::Window& mainWindow) {
 85
 86    raeptorText.setRotation(sinf(RaeptorCogs::Time().getTime()) * 0.1f);
 87    if (lastTime + 1.0f < RaeptorCogs::Time().getTime() && raeptorText.isVisible()) {
 88        lastTime = RaeptorCogs::Time().getTime();
 89        UpdateText();
 90        mainWindow.setTitle("RæptorCogs Demo - " + GetFpsString() + " FPS");
 91    }
 92
 93    glm::vec2 frameSize = glm::vec2(mainWindow.getSize()) * 1.8f;
 94    camera.setZoom(sinf(RaeptorCogs::Time().getTime() * 3.0f) * 0.2f + 1.5f);
 95    raeptorLogoSprite.setRotation(sinf(RaeptorCogs::Time().getTime()) * 0.5f);
 96    raeptorLogoSprite.setScale({1.0f + 0.1f * sinf(RaeptorCogs::Time().getTime() * 2.0f),
 97                                 1.0f + 0.1f * sinf(RaeptorCogs::Time().getTime() * 2.0f)});
 98    for (size_t i = 0; i < raeptorParticles.size(); ++i) {
 99        glm::vec2 pos = raeptorParticles[i].sprite.getPosition();
100        pos.y += raeptorParticles[i].speed * RaeptorCogs::Time().getDeltaTime();
101        if (pos.y > frameSize.y / 2.0f) {
102            pos.y = -frameSize.y / 2.0f;
103            pos.x = RaeptorCogs::Random().getFloat(0.0f, frameSize.x) - frameSize.x / 2.0f;
104        }
105        raeptorParticles[i].sprite.setPosition(pos);
106        raeptorParticles[i].sprite.setRotation(raeptorParticles[i].sprite.getRotation() + raeptorParticles[i].speed / 30.0f * RaeptorCogs::Time().getDeltaTime());
107    }
108    RaeptorCogs::Renderer().render(mainWindow);
109}
110
111int main() {
112    RaeptorCogs::Initialize();
113    RaeptorCogs::Renderer().initialize();
114    Initialize();
115    RaeptorCogs::Window& mainWindow = *RaeptorCogs::Platform().createWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "RaeptorCogs Demo");
116    mainWindow.setIcon({
117                        "assets/icons/raeptor-cogs-icon-16.png",
118                        "assets/icons/raeptor-cogs-icon-32.png",
119                        "assets/icons/raeptor-cogs-icon-48.png",
120                        "assets/icons/raeptor-cogs-icon-128.png"
121                        });
122    RaeptorCogs::StartLoop(Update, mainWindow);
123    RaeptorCogs::Destroy();
124    return 0;
125}

The program above can be found in the repository as examples/demo/src/main.cpp. This example demonstrates the basic structure of a RæptorCogs application, including initialization, window creation, and the main rendering loop.