]> 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 }