From f8c6953803e32b866ff6139fb82876a5d16e633a Mon Sep 17 00:00:00 2001 From: KikooDX Date: Mon, 4 Jan 2021 18:02:11 +0100 Subject: [PATCH] Tile and bitmask system base --- include/collide.h | 6 ++++-- include/level.h | 4 +++- include/tiles.h | 21 +++++++++++++++++++++ include/vec.h | 6 +++--- levels/generate_c.lua | 5 +++-- src/collide.c | 41 +++++++++++++++++++++++++---------------- src/level.c | 5 +++-- src/player.c | 11 ++++++----- src/tiles.c | 9 +++++++++ 9 files changed, 77 insertions(+), 31 deletions(-) create mode 100644 include/tiles.h create mode 100644 src/tiles.c diff --git a/include/collide.h b/include/collide.h index ba3fed1..48099df 100644 --- a/include/collide.h +++ b/include/collide.h @@ -6,10 +6,12 @@ #include "conf.h" #include "level.h" +#include "tiles.h" /* Return tile at the given position. * 0 is out of bound or empty. */ -uint8_t collide_point(Vec point, const Level *level, uint layer); -bool player_collide(Player *player, Vec position, const Level *level, uint layer_id); +Tile collide_point(Vec point, const Level *level, uint layer); +Tile_flags player_collide_or(Player *player, Vec position, const Level *level, uint layer_id); +Tile_flags player_collide_and(Player *player, Vec position, const Level *level, uint layer_id); #endif /* _DEF_PLAYER_COLLIDE */ diff --git a/include/level.h b/include/level.h index baaa51b..bc725ed 100644 --- a/include/level.h +++ b/include/level.h @@ -3,10 +3,12 @@ #include +#include "tiles.h" + typedef struct Level { uint width; /* in tiles */ uint height; /* in tiles */ - const uint8_t **layers; /* points toward the level content */ + const Tile **layers; /* points toward the level content */ uint8_t layers_count; uint8_t solid_layer; /* id of the solid layer */ } Level; diff --git a/include/tiles.h b/include/tiles.h new file mode 100644 index 0000000..f3270c9 --- /dev/null +++ b/include/tiles.h @@ -0,0 +1,21 @@ +#ifndef _DEF_TILES +#define _DEF_TILES +typedef unsigned char Tile; /* the tile ID */ +typedef unsigned char Tile_flags; /* the tile properties (bitmask) */ + +/* define flags */ +#define F_VISIBLE 0b1 +#define F_SOLID 0b10 + +/* define properties */ +#define P_AIR (0) +#define P_BASE (F_VISIBLE | F_SOLID) +#define P_UNKNOWN (F_VISIBLE) + +enum { + ID_AIR, + ID_BASE, +}; + +Tile_flags tile_get_flags(Tile tile); +#endif /* _DEF_TILES */ diff --git a/include/vec.h b/include/vec.h index 2567587..206a2e0 100644 --- a/include/vec.h +++ b/include/vec.h @@ -1,5 +1,5 @@ -#ifndef _DEF_VEC -#define _DEF_VEC +#ifndef _DEF_TILE_PROPS +#define _DEF_TILE_PROPS typedef struct { int x; @@ -33,4 +33,4 @@ void vec_clamp(Vec *to_limit, Vec min, Vec max); /* Draw a rectangle using two Vec as coordinates */ void vec_drect(Vec top_left, Vec bottom_right, int color); -#endif /* _DEF_VEC */ +#endif /* _DEF_TILE_PROPS */ diff --git a/levels/generate_c.lua b/levels/generate_c.lua index 9e73e04..1835c6b 100755 --- a/levels/generate_c.lua +++ b/levels/generate_c.lua @@ -2,6 +2,7 @@ local function create_includes_c() io.write[[#include "level.h" +#include "tiles.h" ]] end @@ -40,7 +41,7 @@ local function create_structure_c(id) if content then -- layers for i, layer in ipairs(content.layers) do - io.write("const uint8_t tiles_", id, "_", i, "[] = {\n\t") + io.write("const Tile tiles_", id, "_", i, "[] = {\n\t") for i, v in ipairs(layer) do io.write(v, ", ") if i % 14 == 0 and i ~= #layer then @@ -50,7 +51,7 @@ local function create_structure_c(id) io.write("\n};\n"); end -- array - io.write("const uint8_t *layers_", id, "[] = {") + io.write("const Tile *layers_", id, "[] = {") for i = 1, #content.layers, 1 do io.write("tiles_", id, "_", i, ", ") end diff --git a/src/collide.c b/src/collide.c index 89cd459..bd212f6 100644 --- a/src/collide.c +++ b/src/collide.c @@ -4,8 +4,9 @@ #include "collide.h" #include "conf.h" #include "level.h" +#include "tiles.h" -uint8_t collide_point(Vec point, const Level *level, uint layer_id) { +Tile_flags collide_point(Vec point, const Level *level, uint layer_id) { Vec cursor; /* the final position to test */ vec_cpy(&cursor, point); vec_div(&cursor, TILE_SIZE); /* get the expected tile ID */ @@ -14,27 +15,35 @@ uint8_t collide_point(Vec point, const Level *level, uint layer_id) { return 0; /* the point is out of bounds */ } else { - return level->layers[layer_id][cursor.x + cursor.y * level->width]; + const Tile tile_id = level->layers[layer_id][cursor.x + cursor.y * level->width]; + return tile_get_flags(tile_id); } } -bool player_collide(Player *player, Vec position, const Level *level, uint layer_id) { +Tile_flags player_collide_or(Player *player, Vec position, const Level *level, uint layer_id) { Vec pos; vec_cpy(&pos, position); - if (collide_point(pos, level, layer_id)) { - return true; - } + Tile_flags flags = 0; + flags |= collide_point(pos, level, layer_id); pos.x += player->hbox.x; - if (collide_point(pos, level, layer_id)) { - return true; - } + flags |= collide_point(pos, level, layer_id); pos.y += player->hbox.y; - if (collide_point(pos, level, layer_id)) { - return true; - } + flags |= collide_point(pos, level, layer_id); pos.x -= player->hbox.x; - if (collide_point(pos, level, layer_id)) { - return true; - } - return false; + flags |= collide_point(pos, level, layer_id); + return flags; +} + +Tile_flags player_collide_and(Player *player, Vec position, const Level *level, uint layer_id) { + Vec pos; + vec_cpy(&pos, position); + Tile_flags flags = -1; + flags &= collide_point(pos, level, layer_id); + pos.x += player->hbox.x; + flags &= collide_point(pos, level, layer_id); + pos.y += player->hbox.y; + flags &= collide_point(pos, level, layer_id); + pos.x -= player->hbox.x; + flags &= collide_point(pos, level, layer_id); + return flags; } diff --git a/src/level.c b/src/level.c index 9b90b76..7d111ff 100644 --- a/src/level.c +++ b/src/level.c @@ -3,6 +3,7 @@ #include "conf.h" #include "level.h" #include "camera.h" +#include "tiles.h" #define VEC_PRECISE_HALF_DISP (Vec){DWIDTH * VEC_PRECISION / (2 * SCALE), DHEIGHT * VEC_PRECISION / (2 * SCALE)} @@ -16,7 +17,7 @@ void level_draw(const Level *level, Camera *camera) { } void layer_draw(const Level *level, Camera *camera, uint layer_id) { - const uint8_t *layer = level->layers[layer_id]; + const Tile *layer = level->layers[layer_id]; Vec display_tl, display_br; vec_cpy(&display_tl, camera->pos); vec_cpy(&display_br, display_tl); @@ -30,7 +31,7 @@ void layer_draw(const Level *level, Camera *camera, uint layer_id) { int end_y = (display_br.y < level->height) ? display_br.y + 1 : level->height; for (int y = start_y; y < end_y; ++y) { for (int x = start_x; x < end_x; ++x) { - const uint8_t cell = layer[x + y * level->width]; + const Tile cell = layer[x + y * level->width]; #ifdef FX9860G const int color = C_LIGHT; #endif /* FX9860G */ diff --git a/src/player.c b/src/player.c index cf67e95..bce8299 100644 --- a/src/player.c +++ b/src/player.c @@ -7,6 +7,7 @@ #include "camera.h" #include "input.h" #include "collide.h" +#include "tiles.h" /* TODO: Determine FRICTION and ACCELERATION from UPS. */ #define MAX_SPD (128 * PXS) @@ -17,7 +18,7 @@ #define GRACE_UNITS (int)(UPS / 5) #define EARLY_UNITS (int)(UPS / 5) #define SGN(x) ((x > 0) ? (1) : ((x < 0) ? (-1) : (0))) -#define PLAYER_COLLIDE(pos) player_collide(player, pos, level, level->solid_layer) +#define PLAYER_COLLIDE_SOLID(pos) (player_collide_or(player, pos, level, level->solid_layer) & F_SOLID) void player_move(Player *player, const Level *level) { /* TODO: Take into account player's hitbox */ @@ -27,11 +28,11 @@ void player_move(Player *player, const Level *level) { vec_cpy(&destination, player->pos); /* snap the player to the grid if they hit a wall */ destination.x += player->spd.x; - if (PLAYER_COLLIDE(destination)) { + if (PLAYER_COLLIDE_SOLID(destination)) { destination.x = player->pos.x - player->pos.x % TILE_SIZE; /* Move the player tile per tile until it enters an * occuped tile. */ - while (!PLAYER_COLLIDE(destination)) { + while (!PLAYER_COLLIDE_SOLID(destination)) { destination.x += TILE_SIZE * sgn_spd_x; } /* then, move it back one tile */ @@ -40,9 +41,9 @@ void player_move(Player *player, const Level *level) { } /* do the same for y */ destination.y += player->spd.y; - if (PLAYER_COLLIDE(destination)) { + if (PLAYER_COLLIDE_SOLID(destination)) { destination.y = player->pos.y - player->pos.y % TILE_SIZE; - while (!PLAYER_COLLIDE(destination)) { + while (!PLAYER_COLLIDE_SOLID(destination)) { destination.y += TILE_SIZE * sgn_spd_y; } destination.y -= TILE_SIZE * sgn_spd_y; diff --git a/src/tiles.c b/src/tiles.c new file mode 100644 index 0000000..5a83f28 --- /dev/null +++ b/src/tiles.c @@ -0,0 +1,9 @@ +#include "tiles.h" + +Tile_flags tile_get_flags(Tile tile) { + switch (tile) { + case ID_AIR: return P_AIR; break; + case ID_BASE: return P_BASE; break; + default: return P_UNKNOWN; break; + } +}