Skip to content
This repository has been archived by the owner on Jan 14, 2021. It is now read-only.
/ termlike Public archive

A game engine for CP437 enthusiasts

License

Notifications You must be signed in to change notification settings

jhauberg/termlike

Repository files navigation

Termlike

code style: compliant

A small and specialized library for making high-performance cross-platform games in the aesthetic of traditional text-based applications, but with the benefits of modern graphics technology.

The name Termlike is in reference to the Roguelike genre of games, which historically has roots in text-based terminals.

Termlike is written in C99 and requires OpenGL 3.3 or later.

Usage

Termlike is intended to be used as a static library that you link into your program.

See Building for instructions on building the project from source.

Example

Here's the smallest program that just runs a Termlike window, prints "Hello" and quits once Esc is pressed:

#include <termlike/termlike.h>

int
main(void)
{
    term_open(defaults("Termlike"));

    while (!term_is_closing()) {
        if (term_key_down(TERM_KEY_ESCAPE)) {
            term_set_closing(true);
        }
        
        term_printstr("Hello", positioned(0, 0), colored(255, 255, 255), TERM_BOUNDS_NONE);
        
        term_run(TERM_FREQUENCY_DEFAULT);
    }
    
    term_close();
    
    return 0;
}

Take a look in examples for more usage samples.

Similar projects

Termlike may not suit your tastes or requirements, in that case, there's several other options.

Here's a few good ones:

Dependencies

A few dependencies are required to keep the scope of the project down. Most of these are small and already included as part of the repository (see external).

Included as a submodule:

  • glfw/GLFW3 handles cross-platform window creation

Included:

Building

Termlike is a cross-platform library. However, it is also a project that i'm only working on in my sparetime, and mainly on a single platform. This imposes some difficulties when it comes down to making the project buildable for others.

Enter CMake

Since every platform has its own preferable development environments and compilers, it would not be an insignificant task to maintain a working project for each supported platform by hand (Xcode, Visual Studio...).

To reduce the effort required, Termlike uses CMake.

This nifty tool generates the kind of build files you'd expect on your preferred platform, whether it be macOS, Windows or Linux. It just needs to know which files should be compiled, and how they relate to each other (see CMakeLists.txt)- it will figure out the rest automagically.

Cloning the repository

First of all, however, make sure to clone the repository recursively so that it also pulls in the glfw dependency (which is only included as a git submodule):

$ git clone --recursive https://github.com/jhauberg/termlike.git

This should leave you with all the sources necessary to let CMake generate build files.

Generating build files

To generate build files, make your way to the root of the repository and run CMake:

$ cd termlike
$ cmake .

Debug builds

You can explicitly specify whether CMake build files should define the DEBUG symbol. For example, to make a debug build:

$ cmake -DCMAKE_BUILD_TYPE=Debug .

Note that the build type will default to Release unless you specify otherwise. In release builds, some options may be omitted to produce smaller binaries.

Profiling overlay

Termlike can display a profiling overlay that shows performance metrics, but it has to be enabled using the TERM_BUILD_PROFILER option (found in the CMakeLists.txt). Set it to ON to enable it.

Building the library

Depending on your platform, CMake should now have generated a project, solution or a script that can build the required dependencies, a static Termlike library and all the executable examples.

For example, on macOS and Linux, you're provided with a Makefile:

$ make

On Windows, you typically end up with a Visual Studio solution.

Technicalities

CPU heavy

Termlike is implemented as a typical game engine, which means taking as much advantage of the hardware as possible; all the time, and never stopping.

For example, there is no sleeping or idling between frames to throttle CPU usage. It will run as fast as it can, all the time, to be as responsive as possible- which is a bane for battery-powered laptops with loud fans, but a boon for games with a lot of animation or a focus on action. You can, however, reduce CPU impact significantly by enabling vsync.

Not tile-based

Because Termlike does not operate on a grid of cells, it cannot take advantage of static elements that do not change from frame to frame (for example, the floor of a dungeon).

Instead, Termlike will draw every frame from a blank slate, from the ground up, over and over. It has no concept of only drawing dirty or changed parts of the screen. This obviously comes at the cost of reduced performance when compared to traditional roguelike engines, but in return you get a lot of freedom.

This is important to note, as both of these points may be dealbreakers for many roguelike developers.

Because of this, Termlike is well-suited for games with a lot of action, movement or animation, but less so for more traditional games. Here's some good alternatives for that.

OpenGL

Termlike uses OpenGL to perform all rendering. This has both upsides and downsides. It is great because it really is the only truly widespread cross-platform graphics API available, but also not so great because the quality of driver implementation varies significantly from system to system (and is actually deprecated on macOS).

Sprite batching

Behind the scenes, deep inside the guts of it all, Termlike performs glyph rendering by utilizing what is commonly known as sprite batching. This is a very GPU-efficient technique that lets a program make as few draw calls as possible.

Command buffering

Whenever a program calls any of the term_print functions, Termlike does not immediately render the character glyphs. Instead, the call is buffered as a command that contains all the necessary information to make the glyphs appear as expected.

Termlike will accumulate all these commands for every single frame and trigger them only when appropriate (and in the expected order). This allows a program to not worry about when or where it issues print commands, and is a requirement to guarantee correct layering/ordering when coupled with sprite batching (without it, glyphs on top could be flushed before those below).

Limitations

Termlike specializes in one thing; getting character glyphs on the screen- fast. This makes Termlike differ from typical roguelike engines in a few ways:

256 Glyphs

Termlike only supports the 256 glyphs defined by Codepage 437, and provides a built-in font that resembles the one found on the original IBM PC.

Not a terminal

Termlike is not a terminal, nor is it a terminal emulator.

There is no concept of a grid of cells for glyphs to be put into, or a cursor from which you print. There's just a surface full of pixels. As such, there are no restrictions on where, or how many, glyphs can be put on the display surface.

Not event-based

Termlike does not idle or block between input events.

It renders frames and glyphs continuously, making it less energy efficient, but more encouraging toward visually appealing animations.

License

Termlike is a Free Open-Source Software project released under the MIT License.