Add 8 layers to collisions

This commit is contained in:
2024-01-13 08:09:34 +01:00
parent 0118e574de
commit 8692d89479
10 changed files with 76 additions and 61 deletions

View File

@@ -112,47 +112,6 @@ static void handleTileObjectLayer(BzTileObjectGroup *layer, cute_tiled_layer_t *
}
static void updateCollisionMap(BzTileMap *map, i32 startX, i32 startY, i32 endX, i32 endY) {
BZ_ASSERT(map->collisionMap);
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->collisionMap[y * map->width + x] = false;
}
}
// 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;
for (i32 y = startY; y < endY; y++) {
for (i32 x = startX; x < endX; x++) {
i32 idx = y * map->width + x;
if (map->collisionMap[idx]) continue;
BzTile tile = bzTileLayerGetTile(layer, x, y);
BzTileID tileID = bzTilesetGetTileID(tileset, tile);
BzTileShape tilesetShape = bzTilesetGetTileCollider(tileset, tileID);
if (tilesetShape.type == BZ_TILE_SHAPE_NONE ||
tilesetShape.type == BZ_TILE_SHAPE_POINT)
continue;
map->collisionMap[idx] = true;
}
}
}
}
static void createColliders(BzTileMap *map) {
map->collisionMap = bzAlloc(map->width * map->height * sizeof(*map->collisionMap));
updateCollisionMap(map, 0, 0, map->width, map->height);
}
BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
BzTileMap map = {.backgroundColor=BLACK};
// Auto detect tileset count.
@@ -257,8 +216,11 @@ BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
}
cute_tiled_free_map(cuteMap);
if (desc->generateCollisionMap)
createColliders(&map);
if (desc->collisionMap) {
i32 numBytes = map.width * map.height;
map.collisionMap = bzAlloc(numBytes);
bzMemSet(map.collisionMap, 0, numBytes);
}
map.isValid = true;
return map;
@@ -407,7 +369,7 @@ f32 bzTileMapRayCast(BzTileMap *map, Vector2 from, Vector2 to, f32 maxDst, Vecto
i32 cellX = (i32) from.x;
i32 cellY = (i32) from.y;
if (bzTileMapHasCollision(map, cellX, cellY)) {
if (bzTileMapHasAnyCollision(map, cellX, cellY)) {
return 0.0f;
}
Vector2 rayLength = Vector2Zero();
@@ -503,25 +465,61 @@ void bzTileMapDrawCollisions(BzTileMap *map) {
}
}
bool bzTileMapHasCollision(BzTileMap *map, i32 x, i32 y) {
bool bzTileMapHasAnyCollision(BzTileMap *map, i32 x, i32 y) {
if (!map->collisionMap) return false;
i32 idx = y * map->width + x;
return map->collisionMap[idx];
return map->collisionMap[idx] != 0;
}
void bzTileMapSetCollisions(BzTileMap *map, bool collision, i32 startX, i32 startY, i32 sizeX, i32 sizeY) {
bool bzTileMapHasCollision(BzTileMap *map, i32 layer, i32 x, i32 y) {
BZ_ASSERT(layer >= 0 && layer < 8);
if (!map->collisionMap) return false;
i32 idx = y * map->width + x;
return (map->collisionMap[idx] & (1 << layer)) != 0;
}
void bzTileMapSetCollisions(BzTileMap *map, bool collision, i32 layer, i32 startX, i32 startY, i32 sizeX, i32 sizeY) {
i32 endX = startX + sizeX;
i32 endY = startY + sizeY;
BZ_ASSERT(layer >= 0 && layer < 8);
BZ_ASSERT(map->collisionMap);
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->collisionMap[y * map->width + x] = collision;
i32 idxOffset = y * map->width + x;
u8 *cell = map->collisionMap + idxOffset;
if (collision)
*cell |= (1 << layer);
else
*cell &= ~(1 << layer);
}
}
}
void bzTileMapUpdateCollisions(BzTileMap *map, i32 x, i32 y, i32 sizeX, i32 sizeY) {
if (!map->collisionMap) return;
updateCollisionMap(map, x, y, x + sizeX, y + sizeY);
void bzTileMapAddLayerCollisions(BzTileMap *map, i32 mapLayer, i32 collLayer) {
BZ_ASSERT(map);
BZ_ASSERT(mapLayer >= 0 && mapLayer < map->layerCount);
BZ_ASSERT(collLayer >= 0 && collLayer < 8);
const i32 layerBit = (1 << collLayer);
BzTileLayer *layer = map->layers + mapLayer;
BzTileset *tileset = map->tilesets + layer->tilesetIdx;
for (i32 y = 0; y < map->height; y++) {
for (i32 x = 0; x < map->width; x++) {
i32 idx = y * map->width + x;
if (map->collisionMap[idx]) continue;
BzTile tile = bzTileLayerGetTile(layer, x, y);
BzTileID tileID = bzTilesetGetTileID(tileset, tile);
BzTileShape tilesetShape = bzTilesetGetTileCollider(tileset, tileID);
u8 *cell = map->collisionMap + idx;
if (tilesetShape.type == BZ_TILE_SHAPE_NONE ||
tilesetShape.type == BZ_TILE_SHAPE_POINT) {
// Reset
*cell &= ~layerBit;
} else {
*cell |= layerBit;
}
}
}
}

View File

@@ -32,7 +32,7 @@ typedef struct BzTileObjectsDesc {
typedef struct BzTileMapDesc {
const char *path;
bool generateCollisionMap;
bool collisionMap;
BzTileset tilesets[BZ_MAP_MAX_TILESETS];
BzTileLayerDesc layers[BZ_MAP_MAX_LAYERS];
@@ -86,7 +86,8 @@ typedef struct BzTileMap {
i32 tileWidth;
i32 tileHeight;
bool *collisionMap;
u8 *collisionMap;
i32 resolution;
BzTileLayer layers[BZ_MAP_MAX_LAYERS];
i32 layerCount;
@@ -129,10 +130,12 @@ f32 bzTileMapRayCast(BzTileMap *map, Vector2 from, Vector2 to, f32 maxDst, Vecto
bool bzTileMapCanRayCastLine(BzTileMap *map, Vector2 from, Vector2 to);
void bzTileMapDraw(BzTileMap *map);
void bzTileMapDrawCollisions(BzTileMap *map);
bool bzTileMapHasCollision(BzTileMap *map, i32 x, i32 y);
void bzTileMapSetCollisions(BzTileMap *map, bool collision, i32 startX, i32 startY, i32 sizeX, i32 sizeY);
void bzTileMapUpdateCollisions(BzTileMap *map, i32 x, i32 y, i32 sizeX, i32 sizeY);
bool bzTileMapHasAnyCollision(BzTileMap *map, i32 x, i32 y);
bool bzTileMapHasCollision(BzTileMap *map, i32 layer, i32 x, i32 y);
void bzTileMapSetCollisions(BzTileMap *map, bool collision, i32 layer, i32 startX, i32 startY, i32 sizeX, i32 sizeY);
void bzTileMapAddLayerCollisions(BzTileMap *map, i32 mapLayer, i32 layer);