The built-in window in tilengine provides a basic, easy to setup environment for quick test and evaluation. It's a very simple environment to ease prototyping but is not intended to be used in production environment.


  • Runs windowed or full-screen
  • User input with keyboard or gamepad
  • CRT post-processing emulation filter
  • Single thread or multi-threaded

Single threaded window

The single threaded window runs inside the main thread and must be handled inside the game loop for each frame. The window is created with TLN_CreateWindow. With default parameters it creates a window with an integer scaling as large as possible for the desktop resolution, and with CRT emulation effect enabled:

TLN_CreateWindow (NULL, 0);

Supported creation flags are as follows:

Flag value Effect
CWF_FULLSCREEN create a full-screen window
CWF_VSYNC sync frame updates with vertical retrace
CWF_Sn force integer upscale factor (n is 1-5)
CWF_NEAREST start with CRT/RF effect disabled

The following key combinations are used to control the window:

Key Effect
Alt + Enter Toggle windowed/full-screen mode
Backspace Toggle CRT/RF effect or on off
Escape Close the window

Once the window is created, it must be processed calling TLN_ProcessWindow for each frame. This function returns true while the window is alive, or false when the user has requested to terminate it. Draw the frames with TLN_DrawFrame. This function takes an optional integer value, that represents a frame counter used by the animation engine.

This basic sample show how to initialize the engine, create the window and do the window loop until the user requests to exit:

TLN_Init (400,240, 2,8,0); /* init the engine */
TLN_CreateWindow (NULL, 0); /* create the window */
while (TLN_ProcessWindow()) /* the window loop */
TLN_DrawFrame (0); /* draw next frame */
TLN_Deinit (); /* release resources */

Multi-threaded window

The multi-threaded window spans its own thread and runs in parallel, without a window loop. It's mainly used for interactive use within an editor as in python. The multi-threaded window is created with TLN_CreateWindowThread and doesn't require continuous calls to TLN_ProcessWindow or TLN_DrawFrame. Instead you query its active state with TLN_IsWindowActive, and optionally you can sync to it with TLN_WaitRedraw.

This is the same sample with the multi-threaded window:

TLN_Init (400,240, 2,8,0); /* init the engine */
TLN_CreateWindowThread (NULL, 0); /* create the window */
while (TLN_IsWindowActive()) /* check window state */
TLN_WaitRedraw (); /* optionally sync to window drawing for fps control */
TLN_Deinit (); /* release resources */

User input

User input in tilengine simulates a basic arcade setup, with 4-way directions, 6 action buttons and a Start button, and up to 4 simultaneous players. It can be controlled with keyboard or joystick/gamepad. By default, only the first 4 buttons of player 1 are assigned as follows:

Player 1 Input Assigned to...
4-way direction keyboard cursors or gamepad D-Pad
Buttons 1-4 Z,X,C,V or gamepad buttons 1-4.
Start button Enter or gamepad button 5.

To check the state of an input, call TLN_GetInput with one of the possible TLN_Input values:

Input name Meaning
INPUT_UP up direction
INPUT_DOWN down direction
INPUT_LEFT left direction
INPUT_RIGHT right direction
INPUT_BUTTONn action button (n is 1-6)
INPUT_START Start button

For example, to check if player 1 left arrow is pushed do this:

/* do your treatment */

Redefining inputs

To define new key and joystick bindings to inputs, use the functions TLN_AssignInputJoystick, TLN_DefineInputKey and TLN_DefineInputButton. The code identifiers for key bindings are the same used inside the SDL2 library, so you'll need to include SDL.h header. For example, to assign the Space key to player 2 start button:

#include <SDL2/SDL.h>

Local multiplayer

By default only player 1 input is enabled. To enable or disable input processing for a given player, call TLN_EnableInput with the desired player PLAYER1 to PLAYER4. For example to enable player 2 input:

To request input for a specific player, combine the name of the input with the modifier INPUT_Pn, where n is the player number (1 to 4). For example, to check if player 2 has pushed start:

/* do your treatment */

Enhanced input with SDL2

If the built-in input layout of tilengine is not enough, because your game needs mouse input, analog sticks, more keys, etc. Tilengine can catch the events delivered by the underlying SDL2 library and pass them to your own input handling. This is done by a user callback, that can be registered with TLN_SetSDLCallback function. The user callback must have the format void sdl_callback(SDL_Event*);. For example, to check mouse click:

#include <SDL2/SDL.h>
/* user callback: check mouse click event and put sprite 0 at clicked coordinates */
void my_mouse_callback(SDL_Event* sdl_event)
if (sdl_event->type == SDL_MOUSEBUTTONDOWN)
SDL_MouseButtonEvent* mouse = (SDL_MouseButtonEvent*)sdl_event;
TLN_SetSpritePosition (0, mosue->x, mouse->y);
/* register the callback */
TLN_SetSDLCallback (my_mouse_callback);

For extended info about SDL input handling, please check this link: https://wiki.libsdl.org/SDL_Event

Time & delay

Tilengine window provides some basic timing functions. TLN_GetTicks returns the number of milliseconds elapsed since system started, and TLN_Delay pauses execution for the given amount of milliseconds.

The CRT effect

All low resolution, pixel art games were played on CRT displays that provided its unique texture and feel. Trying to watch this type of games in crystal-clear, big square pixels, is just wrong. The CRT effect simulates more or less faithfully the characteristics of a CRT display: visible RGB strips, horizontal blur, bright pixel bloom...

Plain output without CRT:
CRT disabled

The same output but with default CRT enabled:
CRT enabled

By default the CRT effect is enabled when the window is created, but it can be disabled with the TLN_DisableCRTEffect function. It can be toggled pressing the Escape key, too.

There are some variations of the effect. There's a choice between three types of rgb subpixels, and optional RF blur. To configure or enable the effect, use the function TLN_ConfigCRTEffect.

This function takes two parameters:

  • type of RGB emulation
  • optional RF (horizontal) blur

Possible types of RGB emulation are the following constants of TLN_CRT enum:

Value Effect
TLN_CRT_SLOT Slot mask without scanlines, similar to legacy (pre 2.10) effect
TLN_CRT_APERTURE Aperture grille with scanlines, matrix-like dot arrangement. Similar to arcade monitors
TLN_CRT_SHADOW Shadow mask with scanlines, diagonal subpixel arrangement. Similar to TV sets

The optional blur parameter applies an horizontal blur that blends adjacent pixels. This blur on actual systems was extensively exploited by Sega megadrive/genesis developers, that interleaved vertical strips of different color to simulate more colors and/or transparency blending, knowing that the discrete colors would be mixed on the RF signal.


This is a quick reference of related functions in this chapter:

Function Quick description
TLN_CreateWindow Creates a SDL2 window for rendering
TLN_CreateWindowThread Creates a multi-threaded SDL2 window for rendering
TLN_SetWindowTitle Sets the window title
TLN_ProcessWindow Process user input events
TLN_IsWindowActive Checks if the window is still active
TLN_GetInput Checks the state of a given input
TLN_EnableInput Enables input for given player
TLN_AssignInputJoystick Binds a joystick to a given player
TLN_DefineInputKey Binds a key to a given player input
TLN_DefineInputButton Binds a joystick button to a given player input
TLN_DrawFrame Renders a new frame to the window
TLN_WaitRedraw Syncs to redraw in multi-threaded window
TLN_DeleteWindow Destroys the window
TLN_ConfigCRTEffect Configures the CRT/RF video effect
TLN_DisableCRTEffect Disables the CRT/RF video effect
TLN_SetSDLCallback Sets function to call when SDL input events happen
TLN_Delay Waits for the specified amount of milliseconds
TLN_GetTicks Returns the number of milliseconds since window creation
bool TLN_CreateWindow(const char *overlay, int flags)
Creates a window for rendering.
Definition: Window.c:312
void TLN_EnableInput(TLN_Player player, bool enable)
Enables or disables input for specified player.
Definition: Window.c:762
Definition: Tilengine.h:299
bool TLN_IsWindowActive(void)
Checks window state.
Definition: Window.c:623
void TLN_Deinit(void)
Deinitialises current engine context and frees used resources.
Definition: Tilengine.c:206
bool TLN_SetSpritePosition(int nsprite, int x, int y)
Sets the sprite position in screen space.
Definition: Sprite.c:171
void TLN_WaitRedraw(void)
Thread synchronization for multithreaded window. Waits until the current frame has ended rendering.
Definition: Window.c:636
TLN_Engine TLN_Init(int hres, int vres, int numlayers, int numsprites, int numanimations)
Initializes the graphic engine.
Definition: Tilengine.c:56
void TLN_DrawFrame(int frame)
Draws a frame to the window.
Definition: Window.c:878
Definition: Tilengine.h:287
void TLN_SetSDLCallback(TLN_SDLCallback)
Registers a user-defined callback to capture internal SDL2 events.
Definition: Window.c:927
bool TLN_GetInput(TLN_Input id)
Returns the state of a given input.
Definition: Window.c:743
bool TLN_CreateWindowThread(const char *overlay, int flags)
Creates a multithreaded window for rendering.
Definition: Window.c:363
Definition: Tilengine.h:307
Definition: Tilengine.h:314
bool TLN_ProcessWindow(void)
Does basic window housekeeping in signgle-threaded window.
Definition: Window.c:521