550 lines
18 KiB
C
550 lines
18 KiB
C
#include "map.h"
|
|
|
|
#include "../core/logger.h"
|
|
#include "../memory/memory.h"
|
|
#include "../math/vec2i.h"
|
|
|
|
#include <cute_tiled.h>
|
|
#include <raymath.h>
|
|
#include <string.h>
|
|
|
|
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;
|
|
}
|
|
|
|
BzTileLayerFunc BZ_TILE_LAYER_CLEAR = bzTileLayerClear;
|
|
BzTileObjectsFunc BZ_TILE_OBJECTS_CLEAR = bzTileObjectsClear;
|
|
|
|
BzTile bzTileLayerGetTile(BzTileLayer *layer, i32 x, i32 y) {
|
|
return layer->data[layer->width * y + x];
|
|
}
|
|
void bzTileLayerSetTile(BzTileLayer *layer, BzTile tile, i32 x, i32 y, i32 w, i32 h) {
|
|
for (i32 yIdx = y; yIdx < y + h; yIdx++) {
|
|
for (i32 xIdx = x; xIdx < x + w; xIdx++) {
|
|
layer->data[yIdx * layer->width + xIdx] = tile;
|
|
}
|
|
}
|
|
}
|
|
BzTileset *bzTileLayerGetTileset(BzTileMap *map, BzTileLayer *layer) {
|
|
i32 idx = layer->tilesetIdx;
|
|
if (idx < 0 || idx >= map->tilesetCount)
|
|
return NULL;
|
|
return &map->tilesets[idx];
|
|
}
|
|
BzTileset *bzTileObjectGroupGetTileset(BzTileMap *map, BzTileObjectGroup *objectGroup) {
|
|
i32 idx = objectGroup->tilesetIdx;
|
|
if (idx < 0 || idx >= map->tilesetCount)
|
|
return NULL;
|
|
return &map->tilesets[idx];
|
|
}
|
|
|
|
static void handleTileLayer(BzTileLayer *layer, cute_tiled_layer_t *cuteLayer) {
|
|
layer->id = cuteLayer->id;
|
|
layer->dataCount = cuteLayer->data_count;
|
|
layer->data = NULL;
|
|
if (layer->dataCount > 0) {
|
|
layer->data = bzAlloc(layer->dataCount * sizeof(*layer->data));
|
|
layer->minData = layer->maxData = (BzTile) cuteLayer->data[0];
|
|
for (i32 i = 0; i < layer->dataCount; i++) {
|
|
layer->data[i] = (BzTile) cuteLayer->data[i];
|
|
if (layer->data[i] < layer->minData)
|
|
layer->minData = layer->data[i];
|
|
else if (layer->data[i] > layer->maxData)
|
|
layer->maxData = layer->data[i];
|
|
}
|
|
}
|
|
|
|
layer->width = cuteLayer->width;
|
|
layer->height = cuteLayer->height;
|
|
|
|
layer->offsetX = cuteLayer->offsetx;
|
|
layer->offsetY = cuteLayer->offsety;
|
|
layer->opacity = cuteLayer->opacity;
|
|
|
|
}
|
|
|
|
// tileset.c
|
|
BzTileShape bzCuteObjectToTileShape(cute_tiled_object_t *object);
|
|
|
|
static void handleTileObjectLayer(BzTileObjectGroup *layer, cute_tiled_layer_t *cuteLayer,
|
|
BzStringHashFunc hashFunc) {
|
|
// Count objects
|
|
layer->objectCount = 0;
|
|
cute_tiled_object_t *object = cuteLayer->objects;
|
|
while (object) {
|
|
layer->objectCount++;
|
|
object = object->next;
|
|
}
|
|
|
|
layer->objects = bzAlloc(layer->objectCount * sizeof(*layer->objects));
|
|
object = cuteLayer->objects;
|
|
for (i32 i = 0; i < layer->objectCount; i++) {
|
|
layer->objects[i].id = hashFunc(object->name.ptr);
|
|
|
|
layer->objects[i].gid = object->gid;
|
|
if (layer->minGID > object->gid) layer->minGID = object->gid;
|
|
else if (layer->maxGID < object->gid) layer->maxGID = object->gid;
|
|
|
|
layer->objects[i].shape = bzCuteObjectToTileShape(object);
|
|
object = object->next;
|
|
}
|
|
|
|
}
|
|
|
|
BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
|
|
BzTileMap map = {.backgroundColor=BLACK};
|
|
// Auto detect tileset count.
|
|
for (i32 i = 0; i < BZ_MAP_MAX_TILESETS; i++) {
|
|
if (!desc->tilesets[i].isValid)
|
|
break;
|
|
map.tilesetCount++;
|
|
}
|
|
for (i32 i = 0; i < map.tilesetCount; i++) {
|
|
map.tilesets[i] = desc->tilesets[i];
|
|
}
|
|
|
|
cute_tiled_map_t *cuteMap = cute_tiled_load_map_from_file(desc->path, NULL);
|
|
|
|
map.backgroundColor = GetColor(cuteMap->backgroundcolor);
|
|
|
|
map.width = cuteMap->width;
|
|
map.height = cuteMap->height;
|
|
map.tileWidth = cuteMap->tilewidth;
|
|
map.tileHeight = cuteMap->tileheight;
|
|
|
|
cute_tiled_layer_t *cuteLayer = cuteMap->layers;
|
|
while (cuteLayer) {
|
|
BZ_ASSERT(map.layerCount < BZ_MAP_MAX_LAYERS);
|
|
BZ_ASSERT(map.objectGroupCount < BZ_MAP_MAX_LAYERS);
|
|
|
|
// Find slot
|
|
i32 slot = -1;
|
|
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)) {
|
|
slot = i;
|
|
break;
|
|
} else if (!layerDesc->name && !objectsDesc->name) {
|
|
break;
|
|
}
|
|
}
|
|
if (slot == -1) {
|
|
bzLogWarning("Dangling layer: %s", cuteLayer->name.ptr);
|
|
cuteLayer = cuteLayer->next;
|
|
continue;
|
|
}
|
|
|
|
if (cuteLayer->data) {
|
|
BzTileLayer *layer = map.layers + slot;
|
|
layer->desc = desc->layers[slot];
|
|
handleTileLayer(layer, cuteLayer);
|
|
layer->hasOwnership = true;
|
|
map.layerCount++;
|
|
} else {
|
|
BzTileObjectGroup *objectGroup = map.objectGroups + slot;
|
|
objectGroup->desc = desc->objectGroups[slot];
|
|
if (!objectGroup->desc.hashFunc)
|
|
objectGroup->desc.hashFunc = bzStringDefaultHash;
|
|
handleTileObjectLayer(objectGroup, cuteLayer, objectGroup->desc.hashFunc);
|
|
|
|
map.objectGroupCount++;
|
|
}
|
|
|
|
cuteLayer = cuteLayer->next;
|
|
}
|
|
|
|
cute_tiled_tileset_t *cuteTileset = cuteMap->tilesets;
|
|
int tilesetCount = 0;
|
|
for (; cuteTileset; cuteTileset = cuteTileset->next) tilesetCount++;
|
|
BZ_ASSERT(tilesetCount == map.tilesetCount);
|
|
|
|
cuteTileset = cuteMap->tilesets;
|
|
for (i32 i = 0; i < map.tilesetCount; i++) {
|
|
BzTileset *tileset = map.tilesets + i;
|
|
tileset->startID = cuteTileset->firstgid;
|
|
cuteTileset = cuteTileset->next;
|
|
}
|
|
|
|
// Assign tilesets to layers
|
|
for (i32 i = 0; i < BZ_MAP_MAX_LAYERS; i++) {
|
|
BzTileLayer *layer = map.layers + i;
|
|
layer->tilesetIdx = -1;
|
|
BzTileObjectGroup *objects = map.objectGroups + i;
|
|
objects->tilesetIdx = -1;
|
|
|
|
bool hasLayer = i < map.layerCount;
|
|
bool hasObjects = i < map.objectGroupCount;
|
|
|
|
for (i32 j = map.tilesetCount - 1; j >= 0; j--) {
|
|
BzTileset *tileset = map.tilesets + j;
|
|
|
|
if (hasLayer && tileset->startID >= layer->minData &&
|
|
tileset->startID <= layer->maxData) {
|
|
layer->tilesetIdx = j;
|
|
hasLayer = false;
|
|
}
|
|
if (hasObjects && tileset->startID >= objects->minGID &&
|
|
tileset->startID <= objects->maxGID) {
|
|
objects->tilesetIdx = j;
|
|
hasObjects = false;
|
|
}
|
|
if (!hasLayer && !hasObjects) break;
|
|
}
|
|
}
|
|
cute_tiled_free_map(cuteMap);
|
|
|
|
if (desc->collisionMap) {
|
|
i32 numBytes = map.width * map.height;
|
|
map.collisionMap = bzAlloc(numBytes);
|
|
bzMemSet(map.collisionMap, 0, numBytes);
|
|
}
|
|
|
|
map.isValid = true;
|
|
return map;
|
|
}
|
|
|
|
void bzTileMapDestroy(BzTileMap *map) {
|
|
for (i32 i = 0; i < map->layerCount; i++) {
|
|
BzTileLayer *layer = map->layers + i;
|
|
if (layer->hasOwnership && layer->data) {
|
|
bzFree(layer->data);
|
|
layer->data = NULL;
|
|
layer->dataCount = 0;
|
|
}
|
|
}
|
|
for (i32 i = 0; i < map->objectGroupCount; i++) {
|
|
BzTileObjectGroup *objectLayer = map->objectGroups + i;
|
|
if (objectLayer->hasOwnership && objectLayer->objects) {
|
|
bzFree(objectLayer->objects);
|
|
objectLayer->objects = NULL;
|
|
objectLayer->objectCount = 0;
|
|
}
|
|
}
|
|
|
|
bzFree(map->collisionMap);
|
|
|
|
*map = BZ_TILEMAP_INVALID;
|
|
}
|
|
|
|
|
|
Vec2i bzTileMapPosToTile(BzTileMap *map, Vector2 pos) {
|
|
return (Vec2i) {
|
|
.x = (i32) (pos.x / (f32) map->tileWidth),
|
|
.y = (i32) (pos.y / (f32) map->tileHeight)
|
|
};
|
|
}
|
|
|
|
void bzTileMapOverrideLayer(BzTileMap *map, i32 slotID, BzTileLayerFunc func) {
|
|
BZ_ASSERT(slotID >= 0 && slotID < map->layerCount);
|
|
BzTileLayer *layer = map->layers + slotID;
|
|
i32 dataCount = layer->dataCount;
|
|
BzTile *data = layer->data;
|
|
if (func(map, layer)) {
|
|
if (!layer->hasOwnership) return;
|
|
bzFree(layer->data);
|
|
if (layer->data == data) {
|
|
layer->data = NULL;
|
|
layer->dataCount = 0;
|
|
}
|
|
layer->hasOwnership = false;
|
|
} else {
|
|
BZ_ASSERT(data == layer->data && dataCount == layer->dataCount);
|
|
}
|
|
}
|
|
void bzTileMapOverrideObjectGroup(BzTileMap *map, i32 slotID, BzTileObjectsFunc func) {
|
|
BZ_ASSERT(slotID >= 0 && slotID < map->objectGroupCount);
|
|
BzTileObjectGroup *objectGroup = map->objectGroups + slotID;
|
|
BzTileObject *objects = objectGroup->objects;
|
|
i32 objectCount = objectGroup->objectCount;
|
|
if (func(map, objectGroup)) {
|
|
bzFree(objectGroup->objects);
|
|
if (objectGroup->objects == objects) {
|
|
objectGroup->objects = NULL;
|
|
objectGroup->objectCount = 0;
|
|
}
|
|
objectGroup->hasOwnership = false;
|
|
} else {
|
|
BZ_ASSERT(objects == objectGroup->objects && objectCount == objectGroup->objectCount);
|
|
}
|
|
}
|
|
|
|
|
|
static void drawLayer(BzTileLayer *layer, BzTileset *tileset) {
|
|
if (!tileset) return;
|
|
if (layer->minData == layer->maxData) return;
|
|
Vector2 drawPos = {layer->offsetX, layer->offsetY};
|
|
|
|
for (i32 y = 0; y < layer->height; y++) {
|
|
for (i32 x = 0; x < layer->width; x++) {
|
|
BzTile tile = bzTileLayerGetTile(layer, x, y);
|
|
BzTileID tileID = bzTilesetGetTileID(tileset, tile);
|
|
if (tileID != -1) {
|
|
Rectangle rec = bzTilesetGetTileRegion(tileset, tileID);
|
|
DrawTextureRec(tileset->tiles, rec, drawPos, WHITE);
|
|
}
|
|
drawPos.x += (float) tileset->tileWidth;
|
|
}
|
|
drawPos.x = layer->offsetX;
|
|
drawPos.y += (float) tileset->tileHeight;
|
|
}
|
|
|
|
}
|
|
|
|
static void drawObjectLayer(BzTileObjectGroup *objectLayer, BzTileset *tileset) {
|
|
Color color = ORANGE;
|
|
for (int i = 0; i < objectLayer->objectCount; i++) {
|
|
BzTileObject object = objectLayer->objects[i];
|
|
BzTileShape shape = object.shape;
|
|
switch (shape.type) {
|
|
case BZ_TILE_SHAPE_NONE:
|
|
break;
|
|
case BZ_TILE_SHAPE_POINT:
|
|
DrawCircle(shape.x, shape.y, 2.0f, color);
|
|
break;
|
|
case BZ_TILE_SHAPE_RECT:
|
|
if (object.gid) {
|
|
Rectangle rec = bzTilesetGetTileRegion(tileset, object.gid);
|
|
Rectangle dest = {shape.x, shape.y - shape.sizeY, shape.sizeX, shape.sizeY};
|
|
DrawTexturePro(tileset->tiles, rec, dest, (Vector2) {0.0f, 0.0f}, 0.0f, WHITE);
|
|
} else {
|
|
DrawRectangle(shape.x, shape.y, shape.sizeX, shape.sizeY, color);
|
|
}
|
|
break;
|
|
case BZ_TILE_SHAPE_ELLIPSE:
|
|
DrawEllipse(shape.x, shape.y, shape.sizeX, shape.sizeY, color);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
BzTileLayer *bzTileMapGetLayer(BzTileMap *map, i32 slotID) {
|
|
BZ_ASSERT(slotID >= 0 && slotID < map->layerCount);
|
|
return &map->layers[slotID];
|
|
}
|
|
BzTileObjectGroup *bzTileMapGetObjects(BzTileMap *map, i32 slotID) {
|
|
BZ_ASSERT(slotID >= 0 && slotID < map->objectGroupCount);
|
|
return &map->objectGroups[slotID];
|
|
}
|
|
static f32 absf32(f32 x) {
|
|
return x > 0 ? x : -x;
|
|
}
|
|
|
|
f32 bzTileMapRayCast(BzTileMap *map, Vector2 from, Vector2 to, f32 maxDst, Vector2 *outIntersection) {
|
|
// Digital Differential Analyzer (DDA)
|
|
Vector2 scale = {1.0f / map->tileWidth, 1.0f / map->tileHeight};
|
|
from = Vector2Multiply(from, scale);
|
|
to = Vector2Multiply(to, scale);
|
|
|
|
Vector2 dir = Vector2Subtract(to, from);
|
|
dir = Vector2Normalize(dir);
|
|
|
|
//Vector2 stepSize = {
|
|
// sqrtf(1 + (dir.y / dir.x) * (dir.y / dir.x)),
|
|
// sqrtf(1 + (dir.x / dir.y) * (dir.x / dir.y))
|
|
//};
|
|
Vector2 stepSize = {absf32(1.0f / dir.x), absf32(1.0f / dir.y)};
|
|
|
|
i32 cellX = (i32) from.x;
|
|
i32 cellY = (i32) from.y;
|
|
if (bzTileMapHasAnyCollision(map, cellX, cellY)) {
|
|
return 0.0f;
|
|
}
|
|
Vector2 rayLength = Vector2Zero();
|
|
i32 stepX, stepY;
|
|
|
|
if (dir.x < 0) {
|
|
stepX = -1;
|
|
rayLength.x = (from.x - (f32) (cellX)) * stepSize.x;
|
|
} else {
|
|
stepX = 1;
|
|
rayLength.x = ((f32) cellX + 1.0f - from.x) * stepSize.x;
|
|
}
|
|
|
|
if (dir.y < 0) {
|
|
stepY = -1;
|
|
rayLength.y = (from.y - (f32) cellY) * stepSize.y;
|
|
} else {
|
|
stepY = 1;
|
|
rayLength.y = ((f32) cellY + 1 - from.y) * stepSize.y;
|
|
}
|
|
f32 distance = 0.0f;
|
|
while (distance < maxDst) {
|
|
if (rayLength.x < rayLength.y) {
|
|
cellX += stepX;
|
|
distance = rayLength.x * map->tileWidth;
|
|
rayLength.x += stepSize.x;
|
|
} else {
|
|
cellY += stepY;
|
|
distance = rayLength.y * map->tileHeight;
|
|
rayLength.y += stepSize.y;
|
|
}
|
|
if (cellX >= 0 && cellX < map->width && cellY >= 0 && cellY < map->height &&
|
|
map->collisionMap[cellY * map->width + cellX]) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (outIntersection) {
|
|
Vector2 intersection = from;
|
|
intersection.x *= map->tileWidth;
|
|
intersection.y *= map->tileHeight;
|
|
intersection = Vector2Add(intersection, Vector2Scale(dir, distance));
|
|
*outIntersection = intersection;
|
|
}
|
|
|
|
return distance;
|
|
}
|
|
bool bzTileMapCanRayCastLine(BzTileMap *map, Vector2 from, Vector2 to) {
|
|
f32 dst = Vector2Distance(from, to);
|
|
f32 rayDst = bzTileMapRayCast(map, from, to, dst, NULL);
|
|
return rayDst >= dst;
|
|
}
|
|
|
|
void bzTileMapDraw(BzTileMap *map) {
|
|
for (i32 i = 0; i < map->layerCount; i++) {
|
|
BzTileLayer *layer = map->layers + i;
|
|
if (!layer->data) continue;
|
|
BzTileset *tileset = NULL;
|
|
if (layer->tilesetIdx != -1) {
|
|
tileset = map->tilesets + layer->tilesetIdx;
|
|
}
|
|
if (layer->desc.renderer)
|
|
layer->desc.renderer(map, layer);
|
|
else
|
|
drawLayer(map->layers + i, tileset);
|
|
}
|
|
|
|
for (i32 i = 0; i < map->objectGroupCount; i++) {
|
|
BzTileObjectGroup *objectLayer = map->objectGroups + i;
|
|
BzTileset *tileset = NULL;
|
|
if (objectLayer->tilesetIdx != -1) {
|
|
tileset = map->tilesets + objectLayer->tilesetIdx;
|
|
}
|
|
if (!objectLayer->objects) continue;
|
|
drawObjectLayer(objectLayer, tileset);
|
|
}
|
|
}
|
|
|
|
void bzTileMapDrawCollisions(BzTileMap *map) {
|
|
if (!map->collisionMap) return;
|
|
Color color = RED;
|
|
color.a = 150;
|
|
i32 sizeX = map->tileWidth;
|
|
i32 sizeY = map->tileHeight;
|
|
for (i32 y = 0; y < map->height; y++) {
|
|
for (i32 x = 0; x < map->width; x++) {
|
|
i32 idx = y * map->width + x;
|
|
i32 posX = x * sizeX;
|
|
i32 posY = y * sizeY;
|
|
if (map->collisionMap[idx])
|
|
DrawRectangleLines(posX, posY, sizeX, sizeY, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
void bzTileMapClearCollisions(BzTileMap *map) {
|
|
BZ_ASSERT(map->collisionMap);
|
|
for (i32 y = 0; y < map->height; y++) {
|
|
for (i32 x = 0; x < map->width; x++) {
|
|
i32 idxOffset = y * map->width + x;
|
|
u8 *cell = map->collisionMap + idxOffset;
|
|
*cell = 0;
|
|
}
|
|
}
|
|
}
|
|
void bzTileMapClearCollisionLayer(BzTileMap *map, i32 layer) {
|
|
BZ_ASSERT(map->collisionMap);
|
|
BZ_ASSERT(layer >= 0 && layer < 8);
|
|
for (i32 y = 0; y < map->height; y++) {
|
|
for (i32 x = 0; x < map->width; x++) {
|
|
i32 idxOffset = y * map->width + x;
|
|
u8 *cell = map->collisionMap + idxOffset;
|
|
*cell &= ~(1 << layer);
|
|
}
|
|
}
|
|
}
|
|
bool bzTileMapHasAnyCollision(BzTileMap *map, i32 x, i32 y) {
|
|
if (!map->collisionMap) return false;
|
|
if (x < 0 || x >= map->width || y < 0 || y >= map->height)
|
|
return false;
|
|
i32 idx = y * map->width + x;
|
|
return map->collisionMap[idx] != 0;
|
|
}
|
|
bool bzTileMapHasCollision(BzTileMap *map, i32 layer, i32 x, i32 y) {
|
|
BZ_ASSERT(layer >= 0 && layer < 8);
|
|
if (x < 0 || x >= map->width || y < 0 || y >= map->height)
|
|
return false;
|
|
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);
|
|
if (startX < 0 || endX >= map->width || startY < 0 || endY >= map->height)
|
|
return;
|
|
for (i32 y = startY; y < endY; y++) {
|
|
for (i32 x = startX; x < endX; x++) {
|
|
i32 idxOffset = y * map->width + x;
|
|
u8 *cell = map->collisionMap + idxOffset;
|
|
if (collision)
|
|
*cell |= (1 << layer);
|
|
else
|
|
*cell &= ~(1 << layer);
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|