]> git.bts.cx Git - benzene.git/blob - src/bz/game/tilemap.c
Sprites
[benzene.git] / src / bz / game / tilemap.c
1 #include <bz/game/tilemap_internal.h>
2
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>
7 #include <parson.h>
8
9 static uint32_t tilemapAddTileTagFlag(BZTilemapID tilemap, BZIdentifierHash tag) {
10 for (size_t i = 0; i < 32; ++i) {
11 if (tag == tilemap->tags[i]) {
12 return 1 << i;
13 }
14
15 if (tilemap->tags[i] == 0) {
16 tilemap->tags[i] = tag;
17 return 1 << i;
18 }
19 }
20
21 bzAssertMessage(false, "Out of flags");
22
23 return 0;
24 }
25
26 BZTilemapID bzGameLoadTilemap(BZMemoryArenaID arena, const char *identifierFmt, ...) {
27 bzMakeIdentifier(identifier, identifierFmt);
28
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);
34
35 //json_set_allocation_functions
36 JSON_Value *tilemapJson = json_parse_string(data);
37 JSON_Object *tilemapJsonObject = json_object(tilemapJson);
38
39 size_t tilemapWidth = json_object_get_number(tilemapJsonObject, "width");
40 size_t tilemapHeight = json_object_get_number(tilemapJsonObject, "height");
41
42 BZTilemap *tilemap = (BZTilemap *)bzMemoryAlloc(arena, sizeof(BZTilemap) + tilemapWidth * tilemapHeight * sizeof(BZTilemapTile));
43 tilemap->width = tilemapWidth;
44 tilemap->height = tilemapHeight;
45
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;
54
55 bzAssert(t < 256); // fixme, define
56 tilemap->tileDefinitions[t].spriteIdx = t;
57 tilemap->tileDefinitions[t].height = 1;
58 tilemap->tileDefinitions[t].tagsFlag = 0;
59 } else {
60 tilemap->tiles[i].tileDefinitionIdx = 0;
61 tilemap->tiles[i].spriteIdx = 0;
62 }
63 }
64 }
65
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"));
71
72 uint32_t tagsFlag = tilemapAddTileTagFlag(tilemap, tag);
73
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;
80 }
81 }
82
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
89
90 if (json_object_has_value(tileDefinitionObject, "height")) {
91 tilemap->tileDefinitions[tileIndex].height = json_object_get_number(tileDefinitionObject, "height");
92 }
93
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));
99
100 uint32_t tagsFlag = tilemapAddTileTagFlag(tilemap, tag);
101
102 tilemap->tileDefinitions[tileIndex].tagsFlag |= tagsFlag;
103 }
104 }
105
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));
113 }
114 }
115 }
116 }
117 }
118
119 json_value_free(tilemapJson);
120
121 return tilemap;
122 }
123
124 uint8_t bzGameGetTilemapTile(BZTilemapID tilemap, uint8_t mx, uint8_t my) {
125 size_t tileIdx = my * tilemap->width + mx;
126
127 //uint8_t spriteIdx = 0;
128
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;
134 }
135 }*/
136
137 return tileDefinitionIdx;
138 }
139
140 uint8_t bzGameGetTilemapSprite(BZTilemapID tilemap, uint8_t mx, uint8_t my) {
141 size_t tileIdx = my * tilemap->width + mx;
142
143 uint8_t spriteIdx = 0;
144
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;
150 }
151 }
152
153 return spriteIdx;
154 }
155
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);
160 }
161
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;
166 }
167
168 uint32_t bzGameCalculateTilemapFlagsMask(BZTilemapID tilemap, size_t tagCount, BZIdentifierHash tags[]) {
169 uint32_t flagMask = 0;
170
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]) {
174 flagMask |= 1 << j;
175 break;
176 }
177 }
178 }
179
180 return flagMask;
181 }