From 70d64256513a57f375431931c606ae85ed5b9d3f Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Sun, 14 Apr 2024 20:38:44 +0200 Subject: [PATCH] added support for "player is pushing" graphics for BD engine --- src/game_bd/bd_cave.c | 24 +++++++++++++++++++++++- src/game_bd/bd_cave.h | 5 +++-- src/game_bd/bd_cavedb.c | 2 ++ src/game_bd/bd_caveengine.c | 9 ++++++++- src/game_bd/bd_caveengine.h | 2 ++ src/game_bd/bd_elements.h | 2 ++ src/game_bd/bd_gameplay.c | 2 +- src/tools.c | 8 ++++++++ 8 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/game_bd/bd_cave.c b/src/game_bd/bd_cave.c index a115cb00..8cc703a4 100644 --- a/src/game_bd/bd_cave.c +++ b/src/game_bd/bd_cave.c @@ -1316,7 +1316,8 @@ void gd_cave_count_diamonds(GdCave *cave) if a cell is changed, it is flagged with GD_REDRAW; the flag can be cleared by the caller. */ -void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer, +void gd_drawcave_game(const GdCave *cave, + int **element_buffer, int **last_element_buffer, int **gfx_buffer, boolean bonus_life_flash, int animcycle, boolean hate_invisible_outbox) { static int player_blinking = 0; @@ -1539,6 +1540,27 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer else draw = elemdrawing[actual]; + // draw special graphics if player is pushing something + if ((cave->last_direction == GD_MV_LEFT || cave->last_direction == GD_MV_RIGHT) && + is_player(cave, x, y) && can_be_pushed_dir(cave, x, y, cave->last_direction)) + { + // special check needed when smooth game element movements selected in setup menu: + // last element must either be player (before pushing) or pushable element (while pushing) + // (extra check needed to prevent pushing animation when moving towards pushable element) + if (!use_bd_smooth_movements() || last_element_buffer[y][x] != O_SPACE) + { + if (cave->last_direction == GD_MV_LEFT) + map = O_PLAYER_PUSH_LEFT; + else + map = O_PLAYER_PUSH_RIGHT; + + if (cave->last_direction == GD_MV_LEFT) + draw = elemdrawing[O_PLAYER_PUSH_LEFT]; + else + draw = elemdrawing[O_PLAYER_PUSH_RIGHT]; + } + } + // if negative, animated. if (draw < 0) draw = -draw + animcycle; diff --git a/src/game_bd/bd_cave.h b/src/game_bd/bd_cave.h index c76923a9..faa90069 100644 --- a/src/game_bd/bd_cave.h +++ b/src/game_bd/bd_cave.h @@ -82,7 +82,7 @@ void gd_struct_set_defaults_from_array(void *str, const GdStructDescriptor *prop // these define the number of the cells in the png file #define GD_NUM_OF_CELLS_X 8 -#define GD_NUM_OF_CELLS_Y 47 +#define GD_NUM_OF_CELLS_Y 51 // +80: placeholder for cells which are rendered by the game; // for example diamond + arrow = falling diamond @@ -697,7 +697,8 @@ GdScheduling gd_scheduling_from_string(const char *str); // game playing helpers #define GD_REDRAW (1 << 10) -void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer, +void gd_drawcave_game(const GdCave *cave, + int **element_buffer, int **last_element_buffer, int **gfx_buffer, boolean bonus_life_flash, int animcycle, boolean hate_invisible_outbox); // function to copy a GdString diff --git a/src/game_bd/bd_cavedb.c b/src/game_bd/bd_cavedb.c index 88e83d6e..ff9df205 100644 --- a/src/game_bd/bd_cavedb.c +++ b/src/game_bd/bd_cavedb.c @@ -377,6 +377,8 @@ GdElements gd_elements[] = { O_PLAYER_TAP, NULL, P_PLAYER, NULL, 0, 216, -216, -216 }, { O_PLAYER_BLINK, NULL, P_PLAYER, NULL, 0, 208, -208, -208 }, { O_PLAYER_TAP_BLINK, NULL, P_PLAYER, NULL, 0, 224, -224, -224 }, + { O_PLAYER_PUSH_LEFT, N_("Player, pushing left"), P_PLAYER, NULL, 0, 392, -392, -392 }, + { O_PLAYER_PUSH_RIGHT, N_("Player, pushing right"), P_PLAYER, NULL, 0, 400, -400, -400 }, { O_CREATURE_SWITCH_ON, NULL, 0, NULL, 0, 19, 19, 19 }, { O_EXPANDING_WALL_SWITCH_HORIZ, NULL, 0, NULL, 0, 40, 40, 40 }, { O_EXPANDING_WALL_SWITCH_VERT, NULL, 0, NULL, 0, 41, 41, 41 }, diff --git a/src/game_bd/bd_caveengine.c b/src/game_bd/bd_caveengine.c index e221ca77..e174f916 100644 --- a/src/game_bd/bd_caveengine.c +++ b/src/game_bd/bd_caveengine.c @@ -449,7 +449,7 @@ static inline boolean rotates_ccw (const GdCave *cave, const int x, const int y) } // returns true if the element is a player -static inline boolean is_player(const GdCave *cave, const int x, const int y) +boolean is_player(const GdCave *cave, const int x, const int y) { return (gd_elements[get(cave, x, y) & O_MASK].properties & P_PLAYER) != 0; } @@ -467,6 +467,13 @@ static inline boolean can_be_hammered_dir(const GdCave *cave, const int x, const return (gd_elements[get_dir(cave, x, y, dir) & O_MASK].properties & P_CAN_BE_HAMMERED) != 0; } +// returns true if the element can be pushed +boolean can_be_pushed_dir(const GdCave *cave, const int x, const int y, + const GdDirection dir) +{ + return (gd_elements[get_dir(cave, x, y, dir) & O_MASK].properties & P_PUSHABLE) != 0; +} + // returns true if the element is explodable and explodes to space, for example the player static inline boolean is_first_stage_of_explosion(const GdCave *cave, const int x, const int y) { diff --git a/src/game_bd/bd_caveengine.h b/src/game_bd/bd_caveengine.h index 0c1a67cf..b4c44f5b 100644 --- a/src/game_bd/bd_caveengine.h +++ b/src/game_bd/bd_caveengine.h @@ -21,6 +21,8 @@ // the game itself +boolean is_player(const GdCave *cave, const int x, const int y); +boolean can_be_pushed_dir(const GdCave *cave, const int x, const int y, const GdDirection dir); GdDirection gd_direction_from_keypress(boolean up, boolean down, boolean left, boolean right); void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, boolean suicide); void set_initial_cave_speed(GdCave *cave); diff --git a/src/game_bd/bd_elements.h b/src/game_bd/bd_elements.h index de04d23a..34945ec7 100644 --- a/src/game_bd/bd_elements.h +++ b/src/game_bd/bd_elements.h @@ -282,6 +282,8 @@ typedef enum _element O_PLAYER_TAP, O_PLAYER_BLINK, O_PLAYER_TAP_BLINK, + O_PLAYER_PUSH_LEFT, + O_PLAYER_PUSH_RIGHT, O_CREATURE_SWITCH_ON, O_EXPANDING_WALL_SWITCH_HORIZ, O_EXPANDING_WALL_SWITCH_VERT, diff --git a/src/game_bd/bd_gameplay.c b/src/game_bd/bd_gameplay.c index b287f085..a981c81b 100644 --- a/src/game_bd/bd_gameplay.c +++ b/src/game_bd/bd_gameplay.c @@ -571,7 +571,7 @@ static GdGameState gd_game_main_int(GdGame *game, boolean allow_iterate, boolean // always render the cave to the gfx buffer; // however it may do nothing if animcycle was not changed. if (game->element_buffer && game->gfx_buffer) - gd_drawcave_game(game->cave, game->element_buffer, game->gfx_buffer, + gd_drawcave_game(game->cave, game->element_buffer, game->last_element_buffer, game->gfx_buffer, game->bonus_life_flash != 0, game->animcycle, gd_no_invisible_outbox); game->state_counter = counter_next; diff --git a/src/tools.c b/src/tools.c index 1fe6fccc..77342590 100644 --- a/src/tools.c +++ b/src/tools.c @@ -7493,6 +7493,14 @@ bd_object_mapping_list[] = O_PLAYER_TAP_BLINK, FALSE, EL_BD_PLAYER, ACTION_BORING_3, -1 }, + { + O_PLAYER_PUSH_LEFT, FALSE, + EL_BD_PLAYER, ACTION_PUSHING, MV_BIT_LEFT + }, + { + O_PLAYER_PUSH_RIGHT, FALSE, + EL_BD_PLAYER, ACTION_PUSHING, MV_BIT_RIGHT + }, { O_CREATURE_SWITCH_ON, FALSE, EL_BD_CREATURE_SWITCH_ACTIVE, -1, -1 -- 2.34.1