Support for colliders
This commit is contained in:
@@ -8,6 +8,34 @@
|
|||||||
"tilecount":297,
|
"tilecount":297,
|
||||||
"tiledversion":"1.10.2",
|
"tiledversion":"1.10.2",
|
||||||
"tileheight":16,
|
"tileheight":16,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":185,
|
||||||
|
"objectgroup":
|
||||||
|
{
|
||||||
|
"draworder":"index",
|
||||||
|
"id":2,
|
||||||
|
"name":"",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"ellipse":true,
|
||||||
|
"height":6,
|
||||||
|
"id":1,
|
||||||
|
"name":"collision",
|
||||||
|
"rotation":0,
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":6,
|
||||||
|
"x":5,
|
||||||
|
"y":8
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}
|
||||||
|
}],
|
||||||
"tilewidth":16,
|
"tilewidth":16,
|
||||||
"type":"tileset",
|
"type":"tileset",
|
||||||
"version":"1.10",
|
"version":"1.10",
|
||||||
|
|||||||
59
assets/test.json
Normal file
59
assets/test.json
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
{ "columns":18,
|
||||||
|
"image":"tilemap_packed.png",
|
||||||
|
"imageheight":176,
|
||||||
|
"imagewidth":288,
|
||||||
|
"margin":0,
|
||||||
|
"name":"test",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":198,
|
||||||
|
"tiledversion":"1.10.2",
|
||||||
|
"tileheight":16,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"objectgroup":
|
||||||
|
{
|
||||||
|
"draworder":"index",
|
||||||
|
"id":2,
|
||||||
|
"name":"",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"height":12,
|
||||||
|
"id":1,
|
||||||
|
"name":"test",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"test",
|
||||||
|
"type":"string",
|
||||||
|
"value":"123"
|
||||||
|
}],
|
||||||
|
"rotation":0,
|
||||||
|
"type":"test",
|
||||||
|
"visible":true,
|
||||||
|
"width":12,
|
||||||
|
"x":2,
|
||||||
|
"y":2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":4,
|
||||||
|
"id":2,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":4,
|
||||||
|
"x":6,
|
||||||
|
"y":6
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
"type":"grass"
|
||||||
|
}],
|
||||||
|
"tilewidth":16,
|
||||||
|
"type":"tileset",
|
||||||
|
"version":"1.10"
|
||||||
|
}
|
||||||
@@ -7,6 +7,11 @@
|
|||||||
|
|
||||||
BzTileMap BZ_TILEMAP_INVALID = {.isValid = false};
|
BzTileMap BZ_TILEMAP_INVALID = {.isValid = false};
|
||||||
|
|
||||||
|
|
||||||
|
int16_t bzTileLayerGetTile(BzTileLayer *layer, i32 x, i32 y) {
|
||||||
|
return layer->data[layer->width * y + x];
|
||||||
|
}
|
||||||
|
|
||||||
BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
|
BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
|
||||||
BzTileMap map = {};
|
BzTileMap map = {};
|
||||||
i32 tilesetCount = desc->tilesetCount;
|
i32 tilesetCount = desc->tilesetCount;
|
||||||
@@ -97,6 +102,17 @@ BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bzTileMapDestroy(BzTileMap *tilemap) {
|
||||||
|
for (i32 i = 0; i < tilemap->layerCount; i++) {
|
||||||
|
BzTileLayer *layer = tilemap->layers + i;
|
||||||
|
bzFree(layer->data);
|
||||||
|
layer->data = NULL;
|
||||||
|
layer->dataCount = 0;
|
||||||
|
}
|
||||||
|
*tilemap = BZ_TILEMAP_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void drawLayer(BzTileLayer *layer, BzTileset *tileset) {
|
static void drawLayer(BzTileLayer *layer, BzTileset *tileset) {
|
||||||
if (!tileset) return;
|
if (!tileset) return;
|
||||||
if (layer->minData == layer->maxData) return;
|
if (layer->minData == layer->maxData) return;
|
||||||
@@ -128,17 +144,23 @@ void bzTileMapDraw(BzTileMap *map) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bzTileMapDestroy(BzTileMap *tilemap) {
|
bool bzTileMapCanPlace(BzTileMap *map, i32 tileX, i32 tileY, i32 sizeX, i32 sizeY) {
|
||||||
for (i32 i = 0; i < tilemap->layerCount; i++) {
|
for (i32 y = tileY; y < tileY + sizeY; y++) {
|
||||||
BzTileLayer *layer = tilemap->layers + i;
|
for (i32 x = tileX; x < tileX + sizeX; x++) {
|
||||||
bzFree(layer->data);
|
|
||||||
layer->data = NULL;
|
for (i32 i = 0; i < map->layerCount; i++) {
|
||||||
layer->dataCount = 0;
|
BzTileLayer *layer = map->layers + i;
|
||||||
|
if (layer->tilesetIdx == -1) continue;
|
||||||
|
|
||||||
|
BzTileset *tileset = map->tilesets + layer->tilesetIdx;
|
||||||
|
|
||||||
|
i16 tile = bzTileLayerGetTile(layer, x, y);
|
||||||
|
BzTileCollider collider = bzTilesetGetTileCollider(tileset, tile);
|
||||||
|
if (collider.type != BZ_TILE_COLLIDER_NONE)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*tilemap = BZ_TILEMAP_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return true;
|
||||||
int16_t bzTileLayerGetTile(BzTileLayer *layer, i32 x, i32 y) {
|
|
||||||
return layer->data[layer->width * y + x];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,9 +54,11 @@ extern BzTileMap BZ_TILEMAP_INVALID;
|
|||||||
int16_t bzTileLayerGetTile(BzTileLayer *layer, i32 x, i32 y);
|
int16_t bzTileLayerGetTile(BzTileLayer *layer, i32 x, i32 y);
|
||||||
|
|
||||||
BzTileMap bzTileMapCreate(const BzTileMapDesc *desc);
|
BzTileMap bzTileMapCreate(const BzTileMapDesc *desc);
|
||||||
void bzTileMapDraw(BzTileMap *map);
|
|
||||||
void bzTileMapDestroy(BzTileMap *tilemap);
|
void bzTileMapDestroy(BzTileMap *tilemap);
|
||||||
|
|
||||||
|
void bzTileMapDraw(BzTileMap *map);
|
||||||
|
bool bzTileMapCanPlace(BzTileMap *map, i32 tileX, i32 tileY, i32 sizeX, i32 sizeY);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //BREEZE_MAP_H
|
#endif //BREEZE_MAP_H
|
||||||
|
|||||||
@@ -1,31 +1,57 @@
|
|||||||
#include <assert.h>
|
#include <cute_tiled.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <cute_tiled.h>
|
|
||||||
|
|
||||||
#include "tileset.h"
|
#include "tileset.h"
|
||||||
|
#include "../core/memory.h"
|
||||||
|
|
||||||
BzTileset BZ_TILESET_INVALID = {.isValid = false};
|
BzTileset BZ_TILESET_INVALID = {.isValid = false};
|
||||||
|
|
||||||
BzTileset bzTilesetCreate(const BzTilesetDesc *desc) {
|
BzTileset bzTilesetCreate(const BzTilesetDesc *desc) {
|
||||||
BzTileset tileset = {};
|
BzTileset tileset = {};
|
||||||
cute_tiled_tileset_t *source = cute_tiled_load_external_tileset(desc->path, NULL);
|
cute_tiled_tileset_t *cuteTileset = cute_tiled_load_external_tileset(desc->path, NULL);
|
||||||
|
|
||||||
tileset.tiles = LoadTexture(desc->texturePath);
|
tileset.tiles = LoadTexture(desc->texturePath);
|
||||||
tileset.startID = source->firstgid;
|
tileset.startID = cuteTileset->firstgid;
|
||||||
tileset.tileWidth = source->tilewidth;
|
tileset.tileWidth = cuteTileset->tilewidth;
|
||||||
tileset.tileHeight = source->tileheight;
|
tileset.tileHeight = cuteTileset->tileheight;
|
||||||
|
|
||||||
tileset.offsetX = source->tileoffset_x;
|
tileset.offsetX = cuteTileset->tileoffset_x;
|
||||||
tileset.offsetY = source->tileoffset_y;
|
tileset.offsetY = cuteTileset->tileoffset_y;
|
||||||
|
|
||||||
tileset.width = tileset.tiles.width / tileset.tileWidth;
|
tileset.width = tileset.tiles.width / tileset.tileWidth;
|
||||||
tileset.height = tileset.tiles.height / tileset.tileHeight;
|
tileset.height = tileset.tiles.height / tileset.tileHeight;
|
||||||
|
|
||||||
cute_tiled_free_external_tileset(source);
|
tileset.tileCount = tileset.width * tileset.tileHeight;
|
||||||
|
tileset.tileColliders = bzAlloc(tileset.tileCount * sizeof(*tileset.tileColliders));
|
||||||
|
for (i32 i = 0; i < tileset.tileCount; i++) {
|
||||||
|
tileset.tileColliders[i] = (BzTileCollider) {BZ_TILE_COLLIDER_NONE};
|
||||||
|
}
|
||||||
|
|
||||||
if (tileset.tiles.width != source->imagewidth ||
|
cute_tiled_tile_descriptor_t *cuteTile = cuteTileset->tiles;
|
||||||
tileset.tiles.height != source->imageheight) {
|
while (cuteTile) {
|
||||||
|
if (!cuteTile->objectgroup) break;
|
||||||
|
cute_tiled_object_t *cuteObject = cuteTile->objectgroup->objects;
|
||||||
|
// NOTE: Only supporting single collider (integer values)
|
||||||
|
if (cuteObject) {
|
||||||
|
if (cuteObject->vertices) break;
|
||||||
|
|
||||||
|
BzTileCollider collider = {BZ_TILE_COLLIDER_RECT};
|
||||||
|
if (cuteObject->ellipse)
|
||||||
|
collider.type = BZ_TILE_COLLIDER_ELLIPSE;
|
||||||
|
collider.x = (i8) cuteObject->x;
|
||||||
|
collider.y = (i8) cuteObject->y;
|
||||||
|
collider.sizeX = (i8) cuteObject->width;
|
||||||
|
collider.sizeY = (i8) cuteObject->height;
|
||||||
|
|
||||||
|
tileset.tileColliders[cuteTile->tile_index] = collider;
|
||||||
|
}
|
||||||
|
cuteTile = cuteTile->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
cute_tiled_free_external_tileset(cuteTileset);
|
||||||
|
|
||||||
|
if (tileset.tiles.width != cuteTileset->imagewidth ||
|
||||||
|
tileset.tiles.height != cuteTileset->imageheight) {
|
||||||
bzTilesetDestroy(&tileset);
|
bzTilesetDestroy(&tileset);
|
||||||
return BZ_TILESET_INVALID;
|
return BZ_TILESET_INVALID;
|
||||||
}
|
}
|
||||||
@@ -36,11 +62,23 @@ BzTileset bzTilesetCreate(const BzTilesetDesc *desc) {
|
|||||||
|
|
||||||
Rectangle bzTilesetGetTileRegion(BzTileset *tileset, int tileID) {
|
Rectangle bzTilesetGetTileRegion(BzTileset *tileset, int tileID) {
|
||||||
tileID = tileID - tileset->startID;
|
tileID = tileID - tileset->startID;
|
||||||
|
if (tileID < 0 || tileID >= tileset->tileCount) {
|
||||||
|
return (Rectangle){};
|
||||||
|
}
|
||||||
int posX = tileID % tileset->width;
|
int posX = tileID % tileset->width;
|
||||||
int posY = tileID / tileset->width;
|
int posY = tileID / tileset->width;
|
||||||
return (Rectangle) {posX * tileset->tileWidth, posY * tileset->tileHeight,
|
return (Rectangle) {posX * tileset->tileWidth, posY * tileset->tileHeight,
|
||||||
tileset->tileWidth, tileset->tileHeight};
|
tileset->tileWidth, tileset->tileHeight};
|
||||||
}
|
}
|
||||||
|
BzTileCollider bzTilesetGetTileCollider(BzTileset *tileset, int tileID) {
|
||||||
|
tileID = tileID - tileset->startID;
|
||||||
|
|
||||||
|
if (tileID < 0 || tileID >= tileset->tileCount) {
|
||||||
|
return (BzTileCollider) {.type = BZ_TILE_COLLIDER_NONE};
|
||||||
|
}
|
||||||
|
|
||||||
|
return tileset->tileColliders[tileID];
|
||||||
|
}
|
||||||
|
|
||||||
void bzTilesetDestroy(BzTileset *tileset) {
|
void bzTilesetDestroy(BzTileset *tileset) {
|
||||||
UnloadTexture(tileset->tiles);
|
UnloadTexture(tileset->tiles);
|
||||||
|
|||||||
@@ -10,8 +10,24 @@ typedef struct BzTilesetDesc {
|
|||||||
const char *texturePath;
|
const char *texturePath;
|
||||||
} BzTilesetDesc;
|
} BzTilesetDesc;
|
||||||
|
|
||||||
|
typedef enum BzTileColliderType {
|
||||||
|
BZ_TILE_COLLIDER_NONE,
|
||||||
|
BZ_TILE_COLLIDER_RECT,
|
||||||
|
BZ_TILE_COLLIDER_ELLIPSE
|
||||||
|
} BzTileColliderType;
|
||||||
|
|
||||||
|
typedef struct BzTileCollider {
|
||||||
|
BzTileColliderType type;
|
||||||
|
u8 x;
|
||||||
|
u8 y;
|
||||||
|
u8 sizeX;
|
||||||
|
u8 sizeY;
|
||||||
|
} BzTileCollider;
|
||||||
|
|
||||||
typedef struct BzTileset {
|
typedef struct BzTileset {
|
||||||
Texture2D tiles;
|
Texture2D tiles;
|
||||||
|
i32 tileCount;
|
||||||
|
BzTileCollider *tileColliders;
|
||||||
i32 startID;
|
i32 startID;
|
||||||
i32 tileWidth;
|
i32 tileWidth;
|
||||||
i32 tileHeight;
|
i32 tileHeight;
|
||||||
@@ -27,6 +43,7 @@ extern BzTileset BZ_TILESET_INVALID;
|
|||||||
BzTileset bzTilesetCreate(const BzTilesetDesc *desc);
|
BzTileset bzTilesetCreate(const BzTilesetDesc *desc);
|
||||||
|
|
||||||
Rectangle bzTilesetGetTileRegion(BzTileset *tileset, int tileID);
|
Rectangle bzTilesetGetTileRegion(BzTileset *tileset, int tileID);
|
||||||
|
BzTileCollider bzTilesetGetTileCollider(BzTileset *tileset, int tileID);
|
||||||
|
|
||||||
void bzTilesetDestroy(BzTileset *tileset);
|
void bzTilesetDestroy(BzTileset *tileset);
|
||||||
|
|
||||||
|
|||||||
@@ -5,3 +5,6 @@ target_link_libraries(window_test LINK_PRIVATE Breeze)
|
|||||||
|
|
||||||
add_executable(nuklear_test nuklear_test.c)
|
add_executable(nuklear_test nuklear_test.c)
|
||||||
target_link_libraries(nuklear_test LINK_PRIVATE Breeze)
|
target_link_libraries(nuklear_test LINK_PRIVATE Breeze)
|
||||||
|
|
||||||
|
add_executable(cute_tiled_test cute_tiled_test.c)
|
||||||
|
target_link_libraries(cute_tiled_test LINK_PRIVATE Breeze)
|
||||||
|
|||||||
26
engine/tests/cute_tiled_test.c
Normal file
26
engine/tests/cute_tiled_test.c
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include <cute_tiled.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
cute_tiled_tileset_t *tileset = cute_tiled_load_external_tileset("test.json", NULL);
|
||||||
|
|
||||||
|
cute_tiled_tile_descriptor_t *tile = tileset->tiles;
|
||||||
|
|
||||||
|
printf("Tileset name: %p %s\n", tileset->name.ptr, tileset->name.ptr);
|
||||||
|
while (tile) {
|
||||||
|
cute_tiled_layer_t *layer = tile->objectgroup;
|
||||||
|
cute_tiled_object_t *object = layer->objects;
|
||||||
|
|
||||||
|
while (object) {
|
||||||
|
printf("[%p]: ellipse:%d x:%2.f y:%2.f w:%2.f h:%2.f\n",
|
||||||
|
object->name.ptr, object->ellipse,
|
||||||
|
object->x, object->y, object->width, object->height);
|
||||||
|
|
||||||
|
object = object->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
tile = tile->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
cute_tiled_free_external_tileset(tileset);
|
||||||
|
}
|
||||||
29
game/main.c
29
game/main.c
@@ -47,6 +47,10 @@ void deinit(Game *game) {
|
|||||||
bzTilesetDestroy(&game->buildingsTileset);
|
bzTilesetDestroy(&game->buildingsTileset);
|
||||||
bzTileMapDestroy(&game->map);
|
bzTileMapDestroy(&game->map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sizeX = 1;
|
||||||
|
int sizeY = 1;
|
||||||
|
|
||||||
void render(float dt, Game *game) {
|
void render(float dt, Game *game) {
|
||||||
Camera2D *camera = &game->camera;
|
Camera2D *camera = &game->camera;
|
||||||
if (IsKeyDown(KEY_W)) camera->target.y -= 20;
|
if (IsKeyDown(KEY_W)) camera->target.y -= 20;
|
||||||
@@ -64,15 +68,34 @@ void render(float dt, Game *game) {
|
|||||||
|
|
||||||
bzTileMapDraw(&game->map);
|
bzTileMapDraw(&game->map);
|
||||||
|
|
||||||
|
Vector2 worldPos = GetScreenToWorld2D(GetMousePosition(), game->camera);
|
||||||
|
int tileX = (int) worldPos.x / 16;
|
||||||
|
int tileY = (int) worldPos.y / 16;
|
||||||
|
|
||||||
|
if (tileX != 0 && tileY != 0) {
|
||||||
|
|
||||||
|
bool canPlace = bzTileMapCanPlace(&game->map, tileX, tileY, sizeX, sizeY);
|
||||||
|
Color placeColor = canPlace ?
|
||||||
|
(Color) {0, 255, 0, 200} :
|
||||||
|
(Color) {255, 0, 0, 200};
|
||||||
|
|
||||||
|
DrawRectangleLines(tileX * 16, tileY * 16, sizeX * 16, sizeY * 16, placeColor);
|
||||||
|
}
|
||||||
|
|
||||||
EndMode2D();
|
EndMode2D();
|
||||||
|
|
||||||
if (nk_begin(NK, "Show", nk_rect(50, 50, 220, 220),
|
if (nk_begin(NK, "Show", nk_rect(50, 50, 220, 220),
|
||||||
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
|
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
|
||||||
// fixed widget pixel width
|
// fixed widget pixel width
|
||||||
nk_layout_row_static(NK, 30, 80, 1);
|
nk_layout_row_static(NK, 30, 80, 1);
|
||||||
if (nk_button_label(NK, "button")) {
|
nk_labelf(NK, NK_TEXT_LEFT, "tileX: %d", tileX);
|
||||||
// event handling
|
nk_labelf(NK, NK_TEXT_LEFT, "tileY: %d", tileY);
|
||||||
}
|
|
||||||
|
nk_labelf(NK, NK_TEXT_LEFT, "x: %d", sizeX);
|
||||||
|
nk_labelf(NK, NK_TEXT_LEFT, "y: %d", sizeY);
|
||||||
|
nk_slider_int(NK, 0, &sizeX, 10, 1);
|
||||||
|
nk_slider_int(NK, 0, &sizeY, 10, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
nk_end(NK);
|
nk_end(NK);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<tileset version="1.10" tiledversion="1.10.2" name="terrain" tilewidth="16" tileheight="16" tilecount="297" columns="27">
|
<tileset version="1.10" tiledversion="1.10.2" name="terrain" tilewidth="16" tileheight="16" tilecount="297" columns="27">
|
||||||
|
<editorsettings>
|
||||||
|
<export target="../assets/terrain.tsj" format="json"/>
|
||||||
|
</editorsettings>
|
||||||
<image source="../assets/terrain.png" width="432" height="176"/>
|
<image source="../assets/terrain.png" width="432" height="176"/>
|
||||||
|
<tile id="185">
|
||||||
|
<objectgroup draworder="index" id="2">
|
||||||
|
<object id="1" x="5" y="8" width="6" height="6">
|
||||||
|
<ellipse/>
|
||||||
|
</object>
|
||||||
|
</objectgroup>
|
||||||
|
</tile>
|
||||||
<wangsets>
|
<wangsets>
|
||||||
<wangset name="River" type="edge" tile="-1">
|
<wangset name="River" type="edge" tile="-1">
|
||||||
<wangcolor name="" color="#1c95ff" tile="-1" probability="1"/>
|
<wangcolor name="" color="#1c95ff" tile="-1" probability="1"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user