Chapter 1: Introduction

Welcome to Terreate Wiki

Welcome to the Terreate documentation. This documentation is intended to provide a comprehensive guide to the Terreate platform, including its features, capabilities, and how to use it.

What is Terreate

Terreate is a 3D game library for C++. This repository is designed for creating 3D games with SDL and OpenGL.

If you want to know about the licensing, see licensing section.

Let's start!

Now, let's dive into the journey of Terreate!

Library dependency

Here's the packages that are used in this library.

  • SDL

    Simple DirectMedia Layer is a cross-platform development library designed to provide low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D. It is used by video playback software, emulators, and popular games including Valve's award winning catalog and many Humble Bundle games. SDL officially supports Windows, macOS, Linux, iOS, and Android. Support for other platforms may be found in the source code. SDL is written in C, works natively with C++, and there are bindings available for several other languages, including C# and Python. SDL is distributed under the zlib license. This license allows you to use SDL freely in any software.
    from SDL website

  • glad

    Multi-Language GL/GLES/EGL/GLX/WGL Loader-Generator based on the official specs.
    from glad website

  • glm

    OpenGL Mathematics (GLM) is a header only C++ mathematics library for graphics software based on the OpenGL Shading Language (GLSL) specifications.
    from GLM README.md

  • freetype

    FreeType is a freely available software library to render fonts. It is written in C, designed to be small, efficient, highly customizable, and portable while capable of producing high-quality output (glyph images) of most vector and bitmap font formats.
    from FreeType website

Build Dependency

This library uses cmake to build the projects so make sure to install cmake before building this library.

on Windows

There is no additional dependence to build this library on Windows.

on Linux

If you are using linux environment, these packages are needed to build and execute.
(Package names might be different in package managers. The names listed below are example in nix)

  • alsa-lib
  • hidapi
  • ibus
  • dbus
  • jack2
  • libdecor
  • libGL
  • libpulseaudio
  • libusb1
  • libsysprof-capture
  • libdrm
  • xorg.libX11
  • xorg.libXcursor
  • xorg.libXinerama
  • xorg.libXrandr
  • xorg.libXi
  • xorg.libXext
  • xorg.libXrender
  • xorg.libXtst
  • libxkbcommon
  • mesa
  • pipewire
  • sndio
  • wayland
  • wayland-protocols
If you are using `nix` package manager and `direnv`, dependence installing is automatically executed.

Building project

Make sure you installed cmake before building.

Build outputs

In this example, build outputs are stored in <REPOSITRY ROOT DIR>/build/ folder.

Cmake options

TERREATE_BUILD_TEST

Default: ON

Specifies whether to build test code.

TERREATE_DEBUG_BUILD

Default: OFF

Specifies whether to build in debug mode. In debug mode, TERREATE_DEBUG_MODE is defined.

Windows & Linux

Make sure you installed dependencies before building.

cmake -S . -B build
cmake --build build

nix installed env

nix develop // or `direnv allow` if you have direnv.
cmake -S . -B build
cmake --build build

Licensing

This repository is provided under the BSD-3-CLAUSE license. So you can use this library whatever you want.
You don't have to contact me to use.

Contact

If you want to contact me, please send an e-mail to upiscium@gmail.com.

Chapter2: The basics

Create a window

Section overview

  • Window representation
  • Simple game loop

In this section, we will create our first simplest application. It is only a blank black window.

Create Context

First, we need to create a manager of Terreate, called Context. Context is a manager for all resources or resource handlers that are used in the program. The first thing we need to do is create a Context class instance:

#include "Terreate/Terreate.hpp"

int main() {
  Terreate::Context context;
  return 0;
}

Once you execute the program above, you will see that the program immediately terminates and returns code 0.

Create Window

Next, we need to create a Window to represent our awesome app. Windows are created by the createWindow() function, which is a method of the Context class:

#include "Terreate/Terreate.hpp"

int main() {
  Terreate::Context context;

  auto window = context.createWindow(700, 500, "My first window");
  // or
  // Terreate::shared<Terreate::Window> window = context.createWindow(700, 500, "My first window");

  return 0;
}

If you execute this code, you may see a black window for a moment.

Define Mainloop

In the current code, we cannot see our awesome app due to the life time of the window. Now, we will add Mainloop that keeps the window and other objects in our app alive until the app terminates.

#include "Terreate/Terreate.hpp"

int main() {
  ...

  while (context.valid()) {
    window->fill(0.85, 0, 0);
    window->clear();

    window->update();
    context.tick(120);
  }

  return 0;
}

Now, we can see the black blank window in front of us!

Handle events

Section overview

  • Use event handler of Context
  • Retrieve window associated events via Event.
  • Use pub-sub event system

Review the last section

In the last section, "Create a Window", we created a simple base app that shows only a black blank window. The code that we created is shown below.

#include "Terreate/Terreate.hpp"

int main() {
  Terreate::Context context;

  auto window = context.createWindow(700, 500, "My first window");

  while (context.valid()) {
    window->fill(0.85, 0, 0);
    window->clear();

    window->update();
    context.tick(120);
  }

  return 0;
}

In this section, we will handle some events that is associated to window.

Get event handler

The first thing we need to do is to get an event handler from the Context:

...

int main() {
  ...

  auto window = context.createWindow(700, 500, "My first window");
  auto event = context.getEventHandler();

  ...
}

EventHandler has various events that is essential to create applications like mouse, clipboard, keyboard, text input(including IME), and more! If you want to know more about the events, see Event type documentation for more information.

Subscribe to an event

Earlier we got the event handler from the context, but this is not enough to get the event itself - in order to get the event, we need to register a callback to the event:

#include <Terreate/Terreate.hpp>
#include <iostream>

int main() {
  ...

  auto event = context.getEventHandler();

  auto mousePosCallback = [](u64 timestamp, shared<Window> window, shared<Mouse> mouse, vec2 const &pos, vec2 const &rel) {
    std::cout << "Mouse moved to: (" << pos.x << ", " << pos.y << ")" << std::endl;
  };
  event->onMouseMotion.subscribe(mousePosCallback);

  ...
}

This code outputs the mouse position when the mouse cursor is moved. Let's take a look at this step by step. First, we get a handler from context. Next, we define the callback for retrieving the event. The arguments of function is defined for each event type. This is shown in the Event callback type documentation. Finally, we called subscribe to register the callback to event.

If you want to retrieve one of the event instances and not interested in other instances that comes after the retrieved event, you should use `trigger` instead of `subscribe`.

Event documentation

Event types

Event callbacks