Add 8 layers to collisions
This commit is contained in:
@@ -24,6 +24,7 @@ add_executable(PixelDefense
|
||||
game/buildings.h
|
||||
game/components.c
|
||||
game/components.h
|
||||
game/constants.h
|
||||
game/entity_factory.c
|
||||
game/entity_factory.h
|
||||
game/entrypoint.c
|
||||
|
||||
@@ -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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
void bzTileMapUpdateCollisions(BzTileMap *map, i32 x, i32 y, i32 sizeX, i32 sizeY) {
|
||||
if (!map->collisionMap) return;
|
||||
updateCollisionMap(map, x, y, x + sizeX, y + sizeY);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ ecs_entity_t placeBuilding(Game *game, BuildingType type,
|
||||
region.rec.height *= sizeY;
|
||||
ecs_set_ptr(ECS, building, TextureRegion, ®ion);
|
||||
|
||||
bzTileMapSetCollisions(&game->map, true, posX, posY, sizeX, sizeY);
|
||||
bzTileMapSetCollisions(&game->map, true, COLL_LAYER_BUILDINGS, posX, posY, sizeX, sizeY);
|
||||
|
||||
switch (type) {
|
||||
case BUILDING_KEEP:
|
||||
|
||||
9
game/constants.h
Normal file
9
game/constants.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef PIXELDEFENSE_CONSTANTS_H
|
||||
#define PIXELDEFENSE_CONSTANTS_H
|
||||
|
||||
enum {
|
||||
COLL_LAYER_TERRAIN = 0,
|
||||
COLL_LAYER_BUILDINGS = 1,
|
||||
};
|
||||
|
||||
#endif //PIXELDEFENSE_CONSTANTS_H
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <breeze.h>
|
||||
#include <flecs.h>
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
typedef enum GameScreen {
|
||||
SCREEN_GAME,
|
||||
SCREEN_PAUSE_MENU,
|
||||
|
||||
@@ -95,7 +95,7 @@ void unloadMap(Game *game) {
|
||||
void loadMap(Game *game, const char *path) {
|
||||
game->map = bzTileMapCreate(&(BzTileMapDesc) {
|
||||
.path=path,
|
||||
.generateCollisionMap=true,
|
||||
.collisionMap=true,
|
||||
.tilesets[0]=game->tileset,
|
||||
|
||||
.layers[LAYER_TERRAIN]=(BzTileLayerDesc) {"terrain", .renderer=terrainRender, .applyColliders=true},
|
||||
@@ -123,6 +123,8 @@ void loadMap(Game *game, const char *path) {
|
||||
game->camera.rotation = 0.0f;
|
||||
game->camera.zoom = 3.0f;
|
||||
|
||||
bzTileMapAddLayerCollisions(&game->map, LAYER_TERRAIN, COLL_LAYER_TERRAIN);
|
||||
|
||||
bzTileMapOverrideLayer(&game->map, LAYER_TREES, initTreesLayer);
|
||||
bzTileMapOverrideLayer(&game->map, LAYER_TREES2, initTreesLayer);
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ bool pathfindAStar(const PathfindingDesc *desc) {
|
||||
x < 0 || x >= map->width)
|
||||
continue;
|
||||
// not walkable
|
||||
if (bzTileMapHasCollision(map, x, y))
|
||||
if (bzTileMapHasAnyCollision(map, x, y))
|
||||
continue;
|
||||
PathNodeRecord *curRecord = &closedSet[y * map->width + x];
|
||||
if (curRecord->visited)
|
||||
|
||||
@@ -412,7 +412,7 @@ void addEntityToInspected(ecs_entity_t entity, Game *game) {
|
||||
}
|
||||
|
||||
static bool isUnitObstructed(f32 x, f32 y, BzTileMap *map) {
|
||||
return bzTileMapHasCollision(map, x / map->tileWidth, y / map->tileHeight);
|
||||
return bzTileMapHasAnyCollision(map, x / map->tileWidth, y / map->tileHeight);
|
||||
}
|
||||
|
||||
static bool canPlaceUnit(Vector2 pos, f32 space, BzTileMap *map) {
|
||||
|
||||
@@ -81,7 +81,7 @@ ECS_DTOR(Building, building, {
|
||||
Vec2i pos = building->pos;
|
||||
Vec2i size = building->size;
|
||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||
bzTileMapSetCollisions(&game->map, false, pos.x, pos.y, size.x, size.y);
|
||||
bzTileMapSetCollisions(&game->map, false, COLL_LAYER_BUILDINGS, pos.x, pos.y, size.x, size.y);
|
||||
})
|
||||
ECS_MOVE(Building, dst, src, {
|
||||
*dst = *src;
|
||||
|
||||
Reference in New Issue
Block a user