Remove multiple colliders, add spatial index component

This commit is contained in:
2023-11-17 15:13:30 +01:00
parent 208cdc6b6f
commit 021df6d77a
11 changed files with 122 additions and 95 deletions

View File

@@ -24,7 +24,7 @@ typedef double f64;
#define DEBUG_MODE
#ifndef DEBUG_MODE
#undef BZ_ASSERT
#define BZ_ASSERT(e) BZ_UNUSDE(x)
#define BZ_ASSERT(e) BZ_UNUSED(x)
#endif
#define BZ_UNUSED(x) (void)(x)

View File

@@ -10,19 +10,25 @@
BzTileMap BZ_TILEMAP_INVALID = {.isValid = false};
void bzTileLayerSkipRender(BzTileMap *map, BzTileLayer *layer) {
BZ_UNUSED(map);
BZ_UNUSED(layer);
}
void bzTileObjectGroupSkipRender(BzTileMap *map, BzTileObjectGroup *objectGroup) {
BZ_UNUSED(map);
BZ_UNUSED(objectGroup);
}
BzTileLayerRenderFunc BZ_TILE_LAYER_SKIP_RENDER = bzTileLayerSkipRender;
BzTileObjectGroupRenderFunc BZ_TILE_OBJECTS_SKIP_RENDER = bzTileObjectGroupSkipRender;
bool bzTileLayerClear(BzTileMap *map, BzTileLayer *layer) {
BZ_UNUSED(map);
BZ_UNUSED(layer);
return true;
}
bool bzTileObjectsClear(BzTileMap *map, BzTileObjectGroup *objectGroup) {
BZ_UNUSED(map);
BZ_UNUSED(objectGroup);
return true;
}
@@ -106,12 +112,20 @@ static void handleTileObjectLayer(BzTileObjectGroup *layer, cute_tiled_layer_t *
}
static void updateColliders(BzTileMap *map, i32 startX, i32 startY, i32 endX, i32 endY) {
BZ_ASSERT(map->colliderMap);
BZ_ASSERT(startX >= 0 && endX <= map->width &&
startY >= 0 && endY <= map->height);
for (i32 y = startY; y < endY; y++) {
for (i32 x = startX; x < endX; x++) {
map->colliderMap[y * map->width + x] = (BzTileShape){.type=BZ_TILE_SHAPE_NONE};
}
}
// Top-most layer takes priority
for (i32 i = map->layerCount - 1; i >= 0; i--) {
BzTileLayer *layer = map->layers + i;
if (!layer->desc.applyColliders) continue;
if (!layer->data) continue;
if (layer->tilesetIdx == -1) continue;
BzTileset *tileset = map->tilesets + layer->tilesetIdx;
@@ -125,15 +139,9 @@ static void updateColliders(BzTileMap *map, i32 startX, i32 startY, i32 endX, i3
tilesetShape.x += layer->offsetX;
tilesetShape.y += layer->offsetY;
i32 colliderIdx = y * map->width + x;
BzTileCollider *collider = map->colliderMap + colliderIdx;
for (i32 sIdx = 0; sIdx < BZ_MAP_COLLIDER_DEPTH; sIdx++) {
BzTileShape *shape = collider->shapes + sIdx;
if (shape->type == BZ_TILE_SHAPE_NONE) {
*shape = tilesetShape;
break;
}
BzTileShape *shape = &map->colliderMap[y * map->width + x];
if (shape->type == BZ_TILE_SHAPE_NONE) {
*shape = tilesetShape;
}
}
}
@@ -141,17 +149,12 @@ static void updateColliders(BzTileMap *map, i32 startX, i32 startY, i32 endX, i3
}
static void createColliders(BzTileMap *map) {
map->collidersCount = map->width * map->height;
map->colliderMap = bzAlloc(map->collidersCount * sizeof(*map->colliderMap));
for (i32 i = 0; i < map->collidersCount; i++) {
map->colliderMap[i] = (BzTileCollider) {{BZ_TILE_SHAPE_NONE}};
}
map->colliderMap = bzAlloc(map->width * map->height * sizeof(*map->colliderMap));
updateColliders(map, 0, 0, map->width, map->height);
}
BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
BzTileMap map = {};
BzTileMap map = {.backgroundColor=BLACK};
// Auto detect tileset count.
for (i32 i = 0; i < BZ_MAP_MAX_TILESETS; i++) {
if (!desc->tilesets[i].isValid)
@@ -181,8 +184,8 @@ BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
for (i32 i = 0; i < BZ_MAP_MAX_LAYERS; i++) {
const BzTileLayerDesc *layerDesc = desc->layers + i;
const BzTileObjectsDesc *objectsDesc = desc->objectGroups + i;
if (layerDesc->name && strcmp(layerDesc->name, cuteLayer->name.ptr) == 0 ||
objectsDesc->name && strcmp(objectsDesc->name, cuteLayer->name.ptr) == 0) {
if ((layerDesc->name && strcmp(layerDesc->name, cuteLayer->name.ptr) == 0) ||
(objectsDesc->name && strcmp(objectsDesc->name, cuteLayer->name.ptr) == 0)) {
slot = i;
break;
} else if (!layerDesc->name && !objectsDesc->name) {
@@ -254,7 +257,8 @@ BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
}
cute_tiled_free_map(cuteMap);
createColliders(&map);
if (desc->generateColliderMap)
createColliders(&map);
map.isValid = true;
return map;
@@ -279,7 +283,6 @@ void bzTileMapDestroy(BzTileMap *map) {
}
bzFree(map->colliderMap);
map->collidersCount = 0;
*map = BZ_TILEMAP_INVALID;
}
@@ -403,28 +406,25 @@ void bzTileMapDrawColliders(BzTileMap *map) {
for (i32 y = 0; y < map->height; y++) {
for (i32 x = 0; x < map->width; x++) {
i32 idx = y * map->width + x;
BzTileCollider collider = map->colliderMap[idx];
for (i32 i = 0; i < BZ_MAP_COLLIDER_DEPTH; i++) {
BzTileShape shape = collider.shapes[i];
if (shape.type == BZ_TILE_SHAPE_NONE)
BzTileShape shape = map->colliderMap[idx];
if (shape.type == BZ_TILE_SHAPE_NONE)
continue;
i32 posX = x * map->tileWidth + shape.x;
i32 posY = y * map->tileHeight + shape.y;
f32 sizeX = shape.sizeX;
f32 sizeY = shape.sizeY;
switch (shape.type) {
case BZ_TILE_SHAPE_NONE:
default:
break;
case BZ_TILE_SHAPE_RECT:
DrawRectangleLines(posX, posY, sizeX, sizeY, color);
break;
case BZ_TILE_SHAPE_ELLIPSE:
DrawEllipseLines(posX, posY, sizeX, sizeY, color);
break;
i32 posX = x * map->tileWidth + shape.x;
i32 posY = y * map->tileHeight + shape.y;
f32 sizeX = shape.sizeX;
f32 sizeY = shape.sizeY;
switch (shape.type) {
case BZ_TILE_SHAPE_NONE:
default:
break;
case BZ_TILE_SHAPE_RECT:
DrawRectangleLines(posX, posY, sizeX, sizeY, color);
break;
case BZ_TILE_SHAPE_ELLIPSE:
DrawEllipseLines(posX, posY, sizeX, sizeY, color);
break;
}
}
@@ -432,17 +432,18 @@ void bzTileMapDrawColliders(BzTileMap *map) {
}
}
void bzTileMapUpdateCollider(BzTileMap *map, i32 x, i32 y) {
BzTileShape bzTileMapGetCollider(BzTileMap *map, i32 x, i32 y) {
BzTileShape invalid = {.type = BZ_TILE_SHAPE_NONE};
if (map->colliderMap == 0) return invalid;
i32 idx = y * map->width + x;
BZ_ASSERT(idx >= 0 && idx < map->collidersCount);
map->colliderMap[idx] = (BzTileCollider){};
updateColliders(map, x, y, x + 1, y + 1);
}
BzTileCollider bzTileMapGetCollider(BzTileMap *map, i32 x, i32 y) {
i32 idx = y * map->width + x;
if (idx < 0 || idx >= map->collidersCount) {
return (BzTileCollider) {{BZ_TILE_SHAPE_NONE}};
if (idx < 0 || idx >= map->width * map->height) {
return invalid;
}
return map->colliderMap[idx];
}
void bzTileMapUpdateColliders(BzTileMap *map, i32 x, i32 y, i32 sizeX, i32 sizeY) {
if (!map->colliderMap) return;
updateColliders(map, x, y, x + sizeX, y + sizeY);
}

View File

@@ -6,7 +6,6 @@
#define BZ_MAP_MAX_LAYERS 8
#define BZ_MAP_MAX_TILESETS 8
#define BZ_MAP_COLLIDER_DEPTH 2
typedef struct BzTileLayer BzTileLayer;
typedef struct BzTileObject BzTileObject;
@@ -22,6 +21,7 @@ extern BzTileObjectGroupRenderFunc BZ_TILE_OBJECTS_SKIP_RENDER;
typedef struct BzTileLayerDesc {
const char *name; // Matches map layer names
BzTileLayerRenderFunc renderer;
bool applyColliders;
} BzTileLayerDesc;
typedef struct BzTileObjectsDesc {
const char *name; // Matches map layer names
@@ -31,6 +31,7 @@ typedef struct BzTileObjectsDesc {
typedef struct BzTileMapDesc {
const char *path;
bool generateColliderMap;
BzTileset tilesets[BZ_MAP_MAX_TILESETS];
BzTileLayerDesc layers[BZ_MAP_MAX_LAYERS];
@@ -76,10 +77,6 @@ typedef struct BzTileObjectGroup {
} BzTileObjectGroup;
typedef struct BzTileCollider {
BzTileShape shapes[BZ_MAP_COLLIDER_DEPTH];
} BzTileCollider;
typedef struct BzTileMap {
Color backgroundColor;
@@ -88,8 +85,7 @@ typedef struct BzTileMap {
i32 tileWidth;
i32 tileHeight;
BzTileCollider *colliderMap;
i32 collidersCount;
BzTileShape *colliderMap;
BzTileLayer layers[BZ_MAP_MAX_LAYERS];
i32 layerCount;
@@ -128,8 +124,8 @@ BzTileObjectGroup *bzTileMapGetObjects(BzTileMap *map, i32 slotID);
void bzTileMapDraw(BzTileMap *map);
void bzTileMapDrawColliders(BzTileMap *map);
BzTileCollider bzTileMapGetCollider(BzTileMap *map, i32 x, i32 y);
void bzTileMapUpdateCollider(BzTileMap *map, i32 x, i32 y);
BzTileShape bzTileMapGetCollider(BzTileMap *map, i32 x, i32 y);
void bzTileMapUpdateColliders(BzTileMap *map, i32 x, i32 y, i32 sizeX, i32 sizeY);