1 #include <bz/game/tilemap_internal.h>
3 #include <bz/math/random.h>
4 #include <bz/memory/allocator.h>
5 #include <bz/resources/resource.h>
6 #include <bz/types/identifier_internal.h>
9 static uint32_t tilemapAddTileTagFlag(BZTilemapID tilemap, BZIdentifierHash tag) {
10 for (size_t i = 0; i < 32; ++i) {
11 if (tag == tilemap->tags[i]) {
15 if (tilemap->tags[i] == 0) {
16 tilemap->tags[i] = tag;
21 bzAssertMessage(false, "Out of flags");
26 BZTilemapID bzGameLoadTilemap(BZMemoryArenaID arena, const char *identifierFmt, ...) {
27 bzMakeIdentifier(identifier, identifierFmt);
29 BZResourceID handle = bzResourcesOpenResource("tilemap", "assets/tilemaps/%s.tilemap.json", identifier);
30 size_t length = bzResourcesFileLength(handle);
31 char *data = (char *)alloca(length); // FIXME, need working space off the stack
32 bzResourcesReadBytes(handle, data, length);
33 bzResourcesCloseResource(handle);
35 //json_set_allocation_functions
36 JSON_Value *tilemapJson = json_parse_string(data);
37 JSON_Object *tilemapJsonObject = json_object(tilemapJson);
39 size_t tilemapWidth = json_object_get_number(tilemapJsonObject, "width");
40 size_t tilemapHeight = json_object_get_number(tilemapJsonObject, "height");
42 BZTilemap *tilemap = (BZTilemap *)bzMemoryAlloc(arena, sizeof(BZTilemap) + tilemapWidth * tilemapHeight * sizeof(BZTilemapTile));
43 tilemap->width = tilemapWidth;
44 tilemap->height = tilemapHeight;
46 JSON_Array *tilesArray = json_object_get_array(tilemapJsonObject, "tiles");
47 size_t tilesArraySize = json_array_get_count(tilesArray);
48 for (size_t y = 0, i = 0; y < tilemap->height; ++y) {
49 for (size_t x = 0; x < tilemap->width; ++x, ++i) {
50 if (i < tilesArraySize) {
51 uint8_t t = (uint8_t)json_array_get_number(tilesArray, i);
52 tilemap->tiles[i].tileDefinitionIdx = t;
53 tilemap->tiles[i].spriteIdx = 0;
55 bzAssert(t < 256); // fixme, define
56 tilemap->tileDefinitions[t].spriteIdx = t;
57 tilemap->tileDefinitions[t].height = 1;
58 tilemap->tileDefinitions[t].tagsFlag = 0;
60 tilemap->tiles[i].tileDefinitionIdx = 0;
61 tilemap->tiles[i].spriteIdx = 0;
66 JSON_Array *tileTagArray = json_object_get_array(tilemapJsonObject, "tags");
67 size_t tileTagArraySize = json_array_get_count(tileTagArray);
68 for (size_t i = 0; i < tileTagArraySize; ++i) {
69 JSON_Object *tileTagObject = json_array_get_object(tileTagArray, i);
70 BZIdentifierHash tag = bzIdentifierHashFromIdentifier(json_object_get_string(tileTagObject, "tag"));
72 uint32_t tagsFlag = tilemapAddTileTagFlag(tilemap, tag);
74 JSON_Array *tileArray = json_object_get_array(tileTagObject, "tiles");
75 size_t tileArraySize = json_array_get_count(tileArray);
76 for (size_t j = 0; j < tileArraySize; ++j) {
77 size_t t = (size_t)json_array_get_number(tileArray, j);
78 bzAssert(t < 256); // fixme, define
79 tilemap->tileDefinitions[t].tagsFlag |= tagsFlag;
83 JSON_Array *tileDefinitionArray = json_object_get_array(tilemapJsonObject, "definitions");
84 size_t tileDefinitionArraySize = json_array_get_count(tileDefinitionArray);
85 for (size_t i = 0; i < tileDefinitionArraySize; ++i) {
86 JSON_Object *tileDefinitionObject = json_array_get_object(tileDefinitionArray, i);
87 size_t tileIndex = json_object_get_number(tileDefinitionObject, "tile");
88 bzAssert(tileIndex < 256); // fixme
90 if (json_object_has_value(tileDefinitionObject, "height")) {
91 tilemap->tileDefinitions[tileIndex].height = json_object_get_number(tileDefinitionObject, "height");
94 if (json_object_has_value(tileDefinitionObject, "tags")) {
95 JSON_Array *tileTagArray = json_object_get_array(tileDefinitionObject, "tags");
96 size_t tileTagArraySize = json_array_get_count(tileTagArray);
97 for (size_t j = 0; j < tileTagArraySize; ++j) {
98 BZIdentifierHash tag = bzIdentifierHashFromIdentifier(json_array_get_string(tileTagArray, j));
100 uint32_t tagsFlag = tilemapAddTileTagFlag(tilemap, tag);
102 tilemap->tileDefinitions[tileIndex].tagsFlag |= tagsFlag;
106 if (json_object_has_value(tileDefinitionObject, "sprite")) {
107 JSON_Array *tileSpritesArray = json_object_get_array(tileDefinitionObject, "sprite");
108 size_t tileSpritesArraySize = json_array_get_count(tileSpritesArray);
109 for (size_t y = 0, j = 0; y < tilemap->height; ++y) {
110 for (size_t x = 0; x < tilemap->width; ++x, ++j) {
111 if (tilemap->tiles[j].tileDefinitionIdx == tileIndex) {
112 tilemap->tiles[j].spriteIdx = (uint8_t)json_array_get_number(tileSpritesArray, bzRandomInteger(tileSpritesArraySize));
119 json_value_free(tilemapJson);
124 uint8_t bzGameGetTilemapTile(BZTilemapID tilemap, uint8_t mx, uint8_t my) {
125 size_t tileIdx = my * tilemap->width + mx;
127 //uint8_t spriteIdx = 0;
129 uint8_t tileDefinitionIdx = tilemap->tiles[tileIdx].tileDefinitionIdx;
130 /*if (tileDefinitionIdx > 0) {
131 spriteIdx = tilemap->tiles[tileIdx].spriteIdx;
132 if (spriteIdx == 0) {
133 spriteIdx = tilemap->tileDefinitions[tileDefinitionIdx].spriteIdx;
137 return tileDefinitionIdx;
140 uint8_t bzGameGetTilemapSprite(BZTilemapID tilemap, uint8_t mx, uint8_t my) {
141 size_t tileIdx = my * tilemap->width + mx;
143 uint8_t spriteIdx = 0;
145 uint8_t tileDefinitionIdx = bzGameGetTilemapTile(tilemap, mx, my);
146 if (tileDefinitionIdx > 0) {
147 spriteIdx = tilemap->tiles[tileIdx].spriteIdx;
148 if (spriteIdx == 0) {
149 spriteIdx = tilemap->tileDefinitions[tileDefinitionIdx].spriteIdx;
156 uint8_t bzGameSetTilemapTile(BZTilemapID tilemap, uint8_t mx, uint8_t my, uint8_t idx) {
157 size_t tileIdx = my * tilemap->width + mx;
158 tilemap->tiles[tileIdx].spriteIdx = idx;
159 return bzGameGetTilemapTile(tilemap, mx, my);
162 bool bzGameGetTilemapHasFlag(BZTilemapID tilemap, uint8_t mx, uint8_t my, BZIdentifierHash tag) {
163 uint32_t flagMask = bzGameCalculateTilemapFlagsMask(tilemap, 1, &tag);
164 uint8_t tileDefinitionIdx = bzGameGetTilemapTile(tilemap, mx, my);
165 return (tilemap->tileDefinitions[tileDefinitionIdx].tagsFlag & flagMask) > 0;
168 uint32_t bzGameCalculateTilemapFlagsMask(BZTilemapID tilemap, size_t tagCount, BZIdentifierHash tags[]) {
169 uint32_t flagMask = 0;
171 for (size_t i = 0; i < tagCount; ++i) {
172 for (size_t j = 0; j < 32; ++j) {
173 if (tags[i] == tilemap->tags[j]) {