changed BD engine to use two-step directions with smooth movement
authorHolger Schemel <holger.schemel@virtion.de>
Tue, 24 Sep 2024 00:06:26 +0000 (02:06 +0200)
committerHolger Schemel <holger.schemel@virtion.de>
Tue, 24 Sep 2024 00:07:00 +0000 (02:07 +0200)
src/game_bd/bd_caveengine.c
src/game_bd/bd_graphics.c

index 69c986786b1ef2d25a0a646d180ba93f4982582a..080046e6d403a295181c4f69662400a14d425a00 100644 (file)
@@ -645,30 +645,11 @@ static inline boolean is_like_dirt(const GdCave *cave, const int x, const int y,
 // store from/to directions in special buffers for smooth movement animations
 static inline void store_dir_buffer(GdCave *cave, const int x, const int y, const GdDirection dir)
 {
-  int old_x = x;
-  int old_y = y;
+  int new_x = getx(cave, x + gd_dx[dir], y + gd_dy[dir]);
+  int new_y = gety(cave, x + gd_dx[dir], y + gd_dy[dir]);
 
-  // raw values without range correction
-  int raw_x = x + gd_dx[dir];
-  int raw_y = y + gd_dy[dir];
-
-  // final values with range correction
-  int new_x = getx(cave, raw_x, raw_y);
-  int new_y = gety(cave, raw_x, raw_y);
-  int new_dir = (dir > GD_MV_TWICE ? dir - GD_MV_TWICE : dir);
-
-  // if tile is moving two steps at once, correct old position
-  if (dir > GD_MV_TWICE)
-  {
-    raw_x = x + gd_dx[new_dir];
-    raw_y = y + gd_dy[new_dir];
-
-    old_x = getx(cave, raw_x, raw_y);
-    old_y = gety(cave, raw_x, raw_y);
-  }
-
-  game_bd.game->dir_buffer_from[old_y][old_x] = new_dir;
-  game_bd.game->dir_buffer_to[new_y][new_x] = new_dir;
+  game_bd.game->dir_buffer_from[y][x] = dir;
+  game_bd.game->dir_buffer_to[new_y][new_x] = dir;
 }
 
 // Store an element at a given position; lava absorbs everything.
@@ -1241,6 +1222,8 @@ static boolean do_teleporter(GdCave *cave, int px, int py, GdDirection player_mo
 static boolean do_push(GdCave *cave, int x, int y, GdDirection player_move, boolean player_fire)
 {
   GdElement what = get_dir(cave, x, y, player_move);
+  int what_x = getx(cave, x + gd_dx[player_move], y + gd_dy[player_move]);
+  int what_y = gety(cave, x + gd_dx[player_move], y + gd_dy[player_move]);
 
   // gravity for falling wall, bladder, ...
   GdDirection grav_compat = (cave->gravity_affects_all ? cave->gravity : GD_MV_DOWN);
@@ -1310,9 +1293,9 @@ static boolean do_push(GdCave *cave, int x, int y, GdDirection player_move, bool
 
           // if pushed a stone, it "bounces". all other elements are simply pushed.
           if (what == O_STONE)
-            store_dir(cave, x, y, twice[player_move], cave->stone_bouncing_effect);
+            store_dir(cave, what_x, what_y, player_move, cave->stone_bouncing_effect);
           else
-            store_dir(cave, x, y, twice[player_move], what);
+            store_dir(cave, what_x, what_y, player_move, what);
 
          result = TRUE;
        }
@@ -1437,7 +1420,7 @@ static boolean do_push(GdCave *cave, int x, int y, GdDirection player_move, bool
            if (is_like_space(cave, x, y, twice[player_move]))
            {
              // yes, so push.
-             store_dir(cave, x, y, twice[player_move], O_BOX);
+             store_dir(cave, what_x, what_y, player_move, O_BOX);
              result = TRUE;
              gd_sound_play(cave, GD_S_BOX_PUSHING, what, x, y);
            }
index 52f270db0465680c3875bff7722d3afc8a7942bc..5f1c01d8536a873f7f227bf9af00fa3286c1cef4 100644 (file)
@@ -679,6 +679,7 @@ static void gd_drawcave_tile(Bitmap *dest, GdGame *game, int x, int y, boolean d
   boolean is_moving = (is_moving_from || is_moving_to);
   boolean is_diagonal_movement_from = (dx_from != 0 && dy_from != 0);
   boolean is_diagonal_movement_to = (dx_to != 0 && dy_to != 0);
+  boolean is_double_movement = (dir_from > GD_MV_TWICE);
   boolean use_smooth_movements = use_bd_smooth_movements();
 
   // if element is moving away from this tile, determine element that is moving
@@ -691,6 +692,13 @@ static void gd_drawcave_tile(Bitmap *dest, GdGame *game, int x, int y, boolean d
     tile_from = game->element_buffer[new_y][new_x];
     draw_from = game->drawing_buffer[new_y][new_x];
 
+    if (is_double_movement)
+    {
+      // for magic wall or slime, use source tile instead of target tile
+      tile_from = tile_last;
+      draw_from = draw_last;
+    }
+
     // handle special case of player running into enemy/explosion from top or left side
     if (el_player(tile_last) && !el_player(tile) && el_destroying(tile_from))
       tile_from = tile_last;