Skip to content

Latest commit

History

70 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

raytmx

Header-only raylib library for loading and drawing Tiled's TMX tilemap documents.

examples/basic/basic.gif

examples/collisions/collisions.gif

examples/smooth_camera/smooth_camera.gif

Features

  • Portable C99, tested with GCC (Windows and Linux), Clang (macOS), and MSVC
  • Supports external tilesets and object templates
  • Supports animations
  • Supports ZLIB and GZIP compression for tile layer data
  • Supports collision checks with Tile Collision Editor objects
  • Supports collision checks with object groups
  • Supports parallaxed scrolling of layers when a Camera2D is used
  • Supports unencoded tile layer data and Base64- and CSV-encoded data
  • Supports tile flipping flags and applies correct transforms
  • Supports single-image and collection of images tilesets
  • Supports drawing of all object types: ellipse, point, polygon, polyline, text, and tile objects
  • Supports word wrapping and all alignment options, including horizontal justification, of text objects
  • Supports loading from disk and memory

Limitations

  • Only the orthogonal orientation is supported; isometric, staggered, and hexagonal are not
  • JSON, which can optionally be used by Tiled, is not currently implemented
  • ZStandard-compressed layer data decompression is not implemented
  • Ellipses are currently treated as rectangles when doing collision checks
  • Wangsets are not implemented
  • Infinite maps are not supported and are treated as fixed-size
  • Object rotations are parsed but currently ignored when drawing
  • Tile object alignment (i.e. placement of tiles when used as objects) is parsed but currently ignored when drawing
  • Text drawing is limited to raylib's default font although the desired font is available as a string
  • Text drawing does not support bold, italics, underline, or strikeout styling
  • Polygon objects currently may fail to draw if their vertices are not defined in counter-clockwise order
  • Concave polygon objects may not be drawn correctly due to drawing with fan triangulation from the centroid
  • Image transparency colors are parsed but their use is not implemented
  • Nested <properties> are not supported; they are merged into a single list of properties

Usage

Define the implementation before including raytmx.

#defineRAYTMX_IMPLEMENTATION#include"raytmx.h"

Only do this in one file. In other source files, include the header without defining the implemntation.

Loading and unloading follows raylib's patterns.

TmxMap*LoadTMX(constchar*fileName);
TmxMap*LoadTMXFromMemory(constchar*content, constchar*workingDirectory);
voidUnloadTMX(TmxMap*map);

Drawing also follows raylib's patterns.

voidDrawTMX(constTmxMap*map, constCamera2D*camera, constRectangle*viewport, intposX, intposY, Colortint);
voidDrawTMXLayers(constTmxMap*map, constCamera2D*camera, constRectangle*viewport, constTmxLayer*layers,
uint32_tlayersLength, intposX, intposY, Colortint);

Animating a TMX is done by calling a specific function once per frame.

voidAnimateTMX(TmxMap*map);

Collision checks also follow raylib's patterns.

boolCheckCollisionTMXObjects(TmxObjectobject1, TmxObjectobject2);
boolCheckCollisionTMXTileLayersRec(constTmxMap*map, constTmxLayer*layers, uint32_tlayersLength, Rectanglerec,
TmxObject*outputObject);
boolCheckCollisionTMXTileLayersCircle(constTmxMap*map, constTmxLayer*layers, uint32_tlayersLength, Vector2center,
floatradius, TmxObject*outputObject);
boolCheckCollisionTMXTileLayersPoint(constTmxMap*map, constTmxLayer*layers, uint32_tlayersLength, Vector2point,
TmxObject*outputObject);
boolCheckCollisionTMXTileLayersPolyPoly(constTmxMap*map, constTmxLayer*layers, uint32_tlayersLength,
Vector2*points, intpointCount, TmxObject*outputObject);
boolCheckCollisionTMXTileLayersPolyPolyEx(constTmxMap*map, constTmxLayer*layers, uint32_tlayersLength,
Vector2*points, intpointCount, Rectangleaabb, TmxObject*outputObject);
boolCheckCollisionTMXObjectGroupRec(TmxObjectGroupgroup, Rectanglerec, TmxObject*outputObject);
boolCheckCollisionTMXObjectGroupCircle(TmxObjectGroupgroup, Vector2center, floatradius, TmxObject*outputObject);
boolCheckCollisionTMXObjectGroupPoint(TmxObjectGroupgroup, Vector2point, TmxObject*outputObject);
boolCheckCollisionTMXObjectGroupPoly(TmxObjectGroupgroup, Vector2*points, intpointCount, TmxObject*outputObject);
boolCheckCollisionTMXObjectGroupPolyEx(TmxObjectGroupgroup, Vector2*points, intpointCount, Rectangleaabb,
TmxObject*outputObject);

Although raytmx doesn't do anything that would be considered collision response, the objects collided with are provided as optional output variables, outputObject, to allow for it.

Example programs that use all of the above features are included.

A more minimal example program would look like:

#include<stddef.h>// Required for: NULL.#include<stdlib.h>// Required for: EXIT_FAILURE, EXIT_SUCCESS.#include"raylib.h"#defineRAYTMX_IMPLEMENTATION#include"raytmx.h"intmain(void)
{
// Configure the window with a resolution and title. This example will also target 60 frames per second.constintscreenWidth=1024;
constintscreenHeight=768;
constfloatpanSpeed=150.0f; // Pixels per second.InitWindow(screenWidth, screenHeight, "raytmx example");
SetTargetFPS(60);
// Load the map from disk. If loading fails, NULL will be returned and details will be TraceLog()'d.TmxMap*map=LoadTMX("example.tmx");
if (map==NULL)
{
TraceLog(LOG_ERROR, "Failed to load TMX \"example.tmx\"");
CloseWindow();
returnEXIT_FAILURE;
}
// Create a camera that initially looks at the center of the map.Camera2Dcamera= { 0 };
camera.target= (Vector2){ (float)(map->width*map->tileWidth)/2.0f, (float)(map->height*map->tileHeight)/2.0f };
camera.offset= (Vector2){ (float)screenWidth/2.0f, (float)screenHeight/2.0f };
camera.rotation=0.0f;
camera.zoom=6.0f;
while (!WindowShouldClose())
{
// Pan the camera based on which arrow key, if any, is pressed.if (IsKeyDown(KEY_RIGHT)) camera.target.x+=panSpeed*GetFrameTime();
if (IsKeyDown(KEY_LEFT)) camera.target.x-=panSpeed*GetFrameTime();
if (IsKeyDown(KEY_DOWN)) camera.target.y+=panSpeed*GetFrameTime();
if (IsKeyDown(KEY_UP)) camera.target.y-=panSpeed*GetFrameTime();
BeginDrawing();
{
ClearBackground(BLACK);
BeginMode2D(camera);
{
AnimateTMX(map);
DrawTMX(map, &camera, NULL, 0, 0, WHITE);
}
EndMode2D();
}
EndDrawing();
}
UnloadTMX(map);
CloseWindow();
returnEXIT_SUCCESS;
}

Dependency

raytmx depends on hoxml for XML parsing and raylib for its graphical, file system, and time utilities.

About

Header-only TMX loader for raylib written in portable C99

Topics

Resources

Stars

64 stars

Watchers

4 watching

Forks

Used by

Contributors

Languages