Add 8 layers to collisions
This commit is contained in:
@@ -24,6 +24,7 @@ add_executable(PixelDefense
|
|||||||
game/buildings.h
|
game/buildings.h
|
||||||
game/components.c
|
game/components.c
|
||||||
game/components.h
|
game/components.h
|
||||||
|
game/constants.h
|
||||||
game/entity_factory.c
|
game/entity_factory.c
|
||||||
game/entity_factory.h
|
game/entity_factory.h
|
||||||
game/entrypoint.c
|
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 bzTileMapCreate(const BzTileMapDesc *desc) {
|
||||||
BzTileMap map = {.backgroundColor=BLACK};
|
BzTileMap map = {.backgroundColor=BLACK};
|
||||||
// Auto detect tileset count.
|
// Auto detect tileset count.
|
||||||
@@ -257,8 +216,11 @@ BzTileMap bzTileMapCreate(const BzTileMapDesc *desc) {
|
|||||||
}
|
}
|
||||||
cute_tiled_free_map(cuteMap);
|
cute_tiled_free_map(cuteMap);
|
||||||
|
|
||||||
if (desc->generateCollisionMap)
|
if (desc->collisionMap) {
|
||||||
createColliders(&map);
|
i32 numBytes = map.width * map.height;
|
||||||
|
map.collisionMap = bzAlloc(numBytes);
|
||||||
|
bzMemSet(map.collisionMap, 0, numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
map.isValid = true;
|
map.isValid = true;
|
||||||
return map;
|
return map;
|
||||||
@@ -407,7 +369,7 @@ f32 bzTileMapRayCast(BzTileMap *map, Vector2 from, Vector2 to, f32 maxDst, Vecto
|
|||||||
|
|
||||||
i32 cellX = (i32) from.x;
|
i32 cellX = (i32) from.x;
|
||||||
i32 cellY = (i32) from.y;
|
i32 cellY = (i32) from.y;
|
||||||
if (bzTileMapHasCollision(map, cellX, cellY)) {
|
if (bzTileMapHasAnyCollision(map, cellX, cellY)) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
Vector2 rayLength = Vector2Zero();
|
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;
|
if (!map->collisionMap) return false;
|
||||||
i32 idx = y * map->width + x;
|
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 endX = startX + sizeX;
|
||||||
i32 endY = startY + sizeY;
|
i32 endY = startY + sizeY;
|
||||||
|
BZ_ASSERT(layer >= 0 && layer < 8);
|
||||||
BZ_ASSERT(map->collisionMap);
|
BZ_ASSERT(map->collisionMap);
|
||||||
BZ_ASSERT(startX >= 0 && endX <= map->width &&
|
BZ_ASSERT(startX >= 0 && endX <= map->width &&
|
||||||
startY >= 0 && endY <= map->height);
|
startY >= 0 && endY <= map->height);
|
||||||
|
|
||||||
for (i32 y = startY; y < endY; y++) {
|
for (i32 y = startY; y < endY; y++) {
|
||||||
for (i32 x = startX; x < endX; x++) {
|
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) {
|
void bzTileMapAddLayerCollisions(BzTileMap *map, i32 mapLayer, i32 collLayer) {
|
||||||
if (!map->collisionMap) return;
|
BZ_ASSERT(map);
|
||||||
updateCollisionMap(map, x, y, x + sizeX, y + sizeY);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ typedef struct BzTileObjectsDesc {
|
|||||||
|
|
||||||
typedef struct BzTileMapDesc {
|
typedef struct BzTileMapDesc {
|
||||||
const char *path;
|
const char *path;
|
||||||
bool generateCollisionMap;
|
bool collisionMap;
|
||||||
BzTileset tilesets[BZ_MAP_MAX_TILESETS];
|
BzTileset tilesets[BZ_MAP_MAX_TILESETS];
|
||||||
|
|
||||||
BzTileLayerDesc layers[BZ_MAP_MAX_LAYERS];
|
BzTileLayerDesc layers[BZ_MAP_MAX_LAYERS];
|
||||||
@@ -86,7 +86,8 @@ typedef struct BzTileMap {
|
|||||||
i32 tileWidth;
|
i32 tileWidth;
|
||||||
i32 tileHeight;
|
i32 tileHeight;
|
||||||
|
|
||||||
bool *collisionMap;
|
u8 *collisionMap;
|
||||||
|
i32 resolution;
|
||||||
|
|
||||||
BzTileLayer layers[BZ_MAP_MAX_LAYERS];
|
BzTileLayer layers[BZ_MAP_MAX_LAYERS];
|
||||||
i32 layerCount;
|
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);
|
bool bzTileMapCanRayCastLine(BzTileMap *map, Vector2 from, Vector2 to);
|
||||||
|
|
||||||
void bzTileMapDraw(BzTileMap *map);
|
void bzTileMapDraw(BzTileMap *map);
|
||||||
|
|
||||||
void bzTileMapDrawCollisions(BzTileMap *map);
|
void bzTileMapDrawCollisions(BzTileMap *map);
|
||||||
bool bzTileMapHasCollision(BzTileMap *map, i32 x, i32 y);
|
bool bzTileMapHasAnyCollision(BzTileMap *map, i32 x, i32 y);
|
||||||
void bzTileMapSetCollisions(BzTileMap *map, bool collision, i32 startX, i32 startY, i32 sizeX, i32 sizeY);
|
bool bzTileMapHasCollision(BzTileMap *map, i32 layer, i32 x, i32 y);
|
||||||
void bzTileMapUpdateCollisions(BzTileMap *map, i32 x, i32 y, i32 sizeX, i32 sizeY);
|
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;
|
region.rec.height *= sizeY;
|
||||||
ecs_set_ptr(ECS, building, TextureRegion, ®ion);
|
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) {
|
switch (type) {
|
||||||
case BUILDING_KEEP:
|
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 <breeze.h>
|
||||||
#include <flecs.h>
|
#include <flecs.h>
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
typedef enum GameScreen {
|
typedef enum GameScreen {
|
||||||
SCREEN_GAME,
|
SCREEN_GAME,
|
||||||
SCREEN_PAUSE_MENU,
|
SCREEN_PAUSE_MENU,
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ void unloadMap(Game *game) {
|
|||||||
void loadMap(Game *game, const char *path) {
|
void loadMap(Game *game, const char *path) {
|
||||||
game->map = bzTileMapCreate(&(BzTileMapDesc) {
|
game->map = bzTileMapCreate(&(BzTileMapDesc) {
|
||||||
.path=path,
|
.path=path,
|
||||||
.generateCollisionMap=true,
|
.collisionMap=true,
|
||||||
.tilesets[0]=game->tileset,
|
.tilesets[0]=game->tileset,
|
||||||
|
|
||||||
.layers[LAYER_TERRAIN]=(BzTileLayerDesc) {"terrain", .renderer=terrainRender, .applyColliders=true},
|
.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.rotation = 0.0f;
|
||||||
game->camera.zoom = 3.0f;
|
game->camera.zoom = 3.0f;
|
||||||
|
|
||||||
|
bzTileMapAddLayerCollisions(&game->map, LAYER_TERRAIN, COLL_LAYER_TERRAIN);
|
||||||
|
|
||||||
bzTileMapOverrideLayer(&game->map, LAYER_TREES, initTreesLayer);
|
bzTileMapOverrideLayer(&game->map, LAYER_TREES, initTreesLayer);
|
||||||
bzTileMapOverrideLayer(&game->map, LAYER_TREES2, initTreesLayer);
|
bzTileMapOverrideLayer(&game->map, LAYER_TREES2, initTreesLayer);
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ bool pathfindAStar(const PathfindingDesc *desc) {
|
|||||||
x < 0 || x >= map->width)
|
x < 0 || x >= map->width)
|
||||||
continue;
|
continue;
|
||||||
// not walkable
|
// not walkable
|
||||||
if (bzTileMapHasCollision(map, x, y))
|
if (bzTileMapHasAnyCollision(map, x, y))
|
||||||
continue;
|
continue;
|
||||||
PathNodeRecord *curRecord = &closedSet[y * map->width + x];
|
PathNodeRecord *curRecord = &closedSet[y * map->width + x];
|
||||||
if (curRecord->visited)
|
if (curRecord->visited)
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ void addEntityToInspected(ecs_entity_t entity, Game *game) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool isUnitObstructed(f32 x, f32 y, BzTileMap *map) {
|
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) {
|
static bool canPlaceUnit(Vector2 pos, f32 space, BzTileMap *map) {
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ ECS_DTOR(Building, building, {
|
|||||||
Vec2i pos = building->pos;
|
Vec2i pos = building->pos;
|
||||||
Vec2i size = building->size;
|
Vec2i size = building->size;
|
||||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
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, {
|
ECS_MOVE(Building, dst, src, {
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
|
|||||||
Reference in New Issue
Block a user