A game engine for top-down 2D RPG games.
rpg game-engine raylib c99

Halve tile struct size from 6 bytes to 3 bytes

Changed files
+47 -41
include
keraforge
src
+17 -12
include/keraforge/world.h
··· 10 10 11 11 #define KF_TILE_SIZE_PX 16 12 12 13 - #define KF_TILEID_MAX UINT16_MAX 13 + #define KF_TILE_IDWIDTH 10 14 + #define KF_TILE_DATAWIDTH 4 15 + 16 + #define KF_TILEID_MAX (1023) /* 2^10-1 */ 17 + 18 + /* Used to store tile IDs. Stored in 10 bits; max value is 1023! */ 14 19 typedef u16 kf_tileid_t; 15 - /* Used to store connectivity variant. */ 16 - typedef u16 kf_tiledatum_t; 20 + /* Used to store connectivity variant. Stored in 4 bits; max value is 15! */ 21 + typedef u8 kf_tiledatum_t; 17 22 18 23 19 24 struct kf_actor; /* Forward declaration */ 20 25 21 26 22 - #define KF_TILEMASK_NORTH (0x0001) 23 - #define KF_TILEMASK_WEST (0x0010) 24 - #define KF_TILEMASK_EAST (0x0100) 25 - #define KF_TILEMASK_SOUTH (0x1000) 27 + #define KF_TILEMASK_NORTH (0b0001) 28 + #define KF_TILEMASK_WEST (0b0010) 29 + #define KF_TILEMASK_EAST (0b0100) 30 + #define KF_TILEMASK_SOUTH (0b1000) 26 31 27 32 28 33 /* Represents a singular tile in the world. */ 29 34 struct kf_tile 30 35 { 31 - kf_tileid_t subid; 32 - kf_tileid_t id; 33 - kf_tiledatum_t data; 34 - }; 36 + kf_tileid_t subid : KF_TILE_IDWIDTH; 37 + kf_tileid_t id : KF_TILE_IDWIDTH; 38 + kf_tiledatum_t data : KF_TILE_DATAWIDTH; 39 + } __attribute__((packed)); 35 40 36 41 /* Represents a world (or a subworld, often called "rooms"). */ 37 42 struct kf_world ··· 93 98 size_t kf_world_getsize(struct kf_world *world); 94 99 95 100 /* Get the sprite offset for a given tile datum. */ 96 - struct kf_vec2(u32) kf_getspritefortilebitmask(kf_tiledatum_t t); 101 + struct kf_vec2(u32) kf_getspritefordatum(kf_tiledatum_t t); 97 102 98 103 /* Update a tile and optionally its neighbours. */ 99 104 void kf_world_updatetile(struct kf_world *world, u32 x, u32 y, bool update_neighbours);
+1 -1
src/input.c
··· 21 21 } 22 22 kf_inputbinds.count++; 23 23 24 - kf_logdbg("add keybind: %d: %s (k=%d a=%d m=%d g=%d x=%d)", i, id, key, alt, mouse, gamepad, axis); 24 + // kf_logdbg("add keybind: %d: %s (k=%d a=%d m=%d g=%d x=%d)", i, id, key, alt, mouse, gamepad, axis); 25 25 kf_inputbinds.id[i] = id; 26 26 kf_inputbinds.key[i] = key; 27 27 kf_inputbinds.alt[i] = alt;
+1 -2
src/main.c
··· 341 341 selected_tile = t->id; 342 342 343 343 DrawRectangleLines(select.x * KF_TILE_SIZE_PX, select.y * KF_TILE_SIZE_PX, KF_TILE_SIZE_PX, KF_TILE_SIZE_PX, WHITE); 344 - struct kf_vec2(u32) s = kf_getspritefortilebitmask(t->data); 345 - DrawText(TextFormat("%d [0x%04x] (%d,%d) {%d,%d}", t->id, t->data, select.x, select.y, s.x, s.y), select.x * KF_TILE_SIZE_PX, select.y * KF_TILE_SIZE_PX - 10, 10, BLACK); 344 + DrawText(TextFormat("%d [%d] (%d,%d)", t->id, t->data, select.x, select.y), select.x * KF_TILE_SIZE_PX, select.y * KF_TILE_SIZE_PX - 10, 10, BLACK); 346 345 } 347 346 player->draw(world, player); 348 347 EndMode2D();
+28 -26
src/world.c
··· 72 72 w = x-1 >= world->width ? 0 : kf_world_gettile(world, x-1, y)->id, 73 73 e = x+1 >= world->width ? 0 : kf_world_gettile(world, x+1, y)->id, 74 74 s = y+1 >= world->height ? 0 : kf_world_gettile(world, x, y+1)->id; 75 - t->data = 0x0000; 75 + t->data = 0b0000; 76 76 if (t->id == n) t->data |= KF_TILEMASK_NORTH; 77 77 if (t->id == w) t->data |= KF_TILEMASK_WEST; 78 78 if (t->id == e) t->data |= KF_TILEMASK_EAST; ··· 92 92 } 93 93 94 94 inline 95 - struct kf_vec2(u32) kf_getspritefortilebitmask(kf_tiledatum_t t) 95 + struct kf_vec2(u32) kf_getspritefordatum(kf_tiledatum_t t) 96 96 { 97 - switch (t) 98 - { 99 - case 0x0000: return (struct kf_vec2(u32)){0, 3}; /* 0x0000: */ 100 - case 0x0001: return (struct kf_vec2(u32)){0, 2}; /* 0x0001: N */ 101 - case 0x0010: return (struct kf_vec2(u32)){3, 3}; /* 0x0010: W */ 102 - case 0x0011: return (struct kf_vec2(u32)){3, 2}; /* 0x0011: NW */ 103 - case 0x0100: return (struct kf_vec2(u32)){1, 3}; /* 0x0100: E */ 104 - case 0x0101: return (struct kf_vec2(u32)){1, 2}; /* 0x0101: EN */ 105 - case 0x0110: return (struct kf_vec2(u32)){2, 3}; /* 0x0110: EW */ 106 - case 0x0111: return (struct kf_vec2(u32)){2, 2}; /* 0x0111: EWN */ 107 - case 0x1000: return (struct kf_vec2(u32)){0, 0}; /* 0x1000: S */ 108 - case 0x1001: return (struct kf_vec2(u32)){0, 1}; /* 0x1001: SN */ 109 - case 0x1010: return (struct kf_vec2(u32)){3, 0}; /* 0x1010: SW */ 110 - case 0x1011: return (struct kf_vec2(u32)){3, 1}; /* 0x1011: SWN */ 111 - case 0x1100: return (struct kf_vec2(u32)){1, 0}; /* 0x1100: SE */ 112 - case 0x1101: return (struct kf_vec2(u32)){1, 1}; /* 0x1101: SEN */ 113 - case 0x1110: return (struct kf_vec2(u32)){2, 0}; /* 0x1110: SEW */ 114 - case 0x1111: return (struct kf_vec2(u32)){2, 1}; /* 0x1111: NESW */ 115 - } 116 - KF_UNREACHABLE("invalid bitmask: 0x%x", t); 117 - return (struct kf_vec2(u32)){-1, -1}; 97 + static const 98 + struct kf_vec2(u32) v[] = { 99 + {0, 3}, /* 0b0000: */ 100 + {0, 2}, /* 0b0001: N */ 101 + {3, 3}, /* 0b0010: W */ 102 + {3, 2}, /* 0b0011: NW */ 103 + {1, 3}, /* 0b0100: E */ 104 + {1, 2}, /* 0b0101: EN */ 105 + {2, 3}, /* 0b0110: EW */ 106 + {2, 2}, /* 0b0111: EWN */ 107 + {0, 0}, /* 0b1000: S */ 108 + {0, 1}, /* 0b1001: SN */ 109 + {3, 0}, /* 0b1010: SW */ 110 + {3, 1}, /* 0b1011: SWN */ 111 + {1, 0}, /* 0b1100: SE */ 112 + {1, 1}, /* 0b1101: SEN */ 113 + {2, 0}, /* 0b1110: SEW */ 114 + {2, 1}, /* 0b1111: NESW */ 115 + }; 116 + return v[t]; 118 117 } 119 118 120 119 struct kf_tile *kf_world_gettile(struct kf_world *world, u32 x, u32 y) ··· 184 183 for (x = sx ; x < ex ; x++) 185 184 { 186 185 KF_SANITY_CHECK(tile->subid <= kf_tiles.count, "erroneous subtile on map at %u,%u: %u (count=%u)", x, y, tile->subid, kf_tiles.count); 187 - /* 0x1111: full tile, no subtile rendering needed */ 188 186 KF_SANITY_CHECK(tile->id <= kf_tiles.count, "erroneous tile on map at %u,%u: %u (count=%u)", x, y, tile->id, kf_tiles.count); 189 - if ((tile->data != 0x1111 || kf_tiles.transparent[tile->id]) && tile->subid && tile->id) 187 + 188 + /* 15: full tile, no subtile rendering needed (unless transparent) */ 189 + if ((tile->data != 15 || kf_tiles.transparent[tile->id]) && tile->subid && tile->id) 190 190 { 191 191 kf_drawsprite_wh( 192 192 kf_tiles.sheet[tile->subid], ··· 198 198 kf_tiles.sprite[tile->subid].y + 1 199 199 ); 200 200 } 201 + 201 202 if (tile->id) 202 203 { 203 - struct kf_vec2(u32) s = kf_getspritefortilebitmask(tile->data); 204 + struct kf_vec2(u32) s = kf_getspritefordatum(tile->data); 204 205 kf_drawsprite_wh( 205 206 kf_tiles.sheet[tile->id], 206 207 x*KF_TILE_SIZE_PX, ··· 211 212 kf_tiles.sprite[tile->id].y + s.y 212 213 ); 213 214 } 215 + 214 216 tile++; /* shift tile pointer to the right */ 215 217 } 216 218 tile += down; /* shift tile pointer down */