added support for crumbled sand for native BD graphics engine
authorHolger Schemel <holger.schemel@virtion.de>
Tue, 10 Dec 2024 20:00:50 +0000 (21:00 +0100)
committerHolger Schemel <holger.schemel@virtion.de>
Wed, 11 Dec 2024 08:57:04 +0000 (09:57 +0100)
src/game_bd/bd_cavedb.c
src/game_bd/bd_elements.h
src/game_bd/bd_graphics.c
src/tools.c

index 5798638a2c88be0fbdd9d4fe017dd7a460bd260f..f59408895e4f7fa8843a80ce5ad3e9ec33aa3265 100644 (file)
@@ -129,6 +129,11 @@ GdElementProperty gd_element_properties[] =
     P_AMOEBA_CONSUMES | P_VISUAL_EFFECT | P_DIRT | P_DIGGABLE,
     "DIRT", '.', 2, 2, 2
   },
+  {
+    O_DIRT_CRUMBLED, O_DIRT_CRUMBLED, N_("Dirt (crumbled)"),
+    P_AMOEBA_CONSUMES | P_VISUAL_EFFECT | P_DIRT | P_DIGGABLE,
+    "DIRT_CRUMBLED", 0, 2, 2, 2
+  },
   {
     O_DIRT_SLOPED_UP_RIGHT, O_DIRT_SLOPED_UP_RIGHT, N_("Sloped dirt (up & right)"),
     P_DIRT | P_SLOPED_UP | P_SLOPED_RIGHT | P_AMOEBA_CONSUMES | P_DIGGABLE,
index 85d34602de4893edc5a90b98d51e06c73e094716..e5bb0dfd8420987666491cf7155bd6aa95cbcaf6 100644 (file)
@@ -26,6 +26,7 @@ typedef enum _element
 {
   O_SPACE,
   O_DIRT,
+  O_DIRT_CRUMBLED,
   O_DIRT_SLOPED_UP_RIGHT,
   O_DIRT_SLOPED_UP_LEFT,
   O_DIRT_SLOPED_DOWN_LEFT,
index bf469f80d15d6d55d968d80764a9396ae122bf08..d7f41e2b5e7220c02fb0d5e38bf4d98528f70876 100644 (file)
@@ -542,6 +542,55 @@ static inline boolean el_smooth_movable(const int element)
           el_pushable(element));
 }
 
+static void gd_drawcave_crumbled(Bitmap *dest, GdGame *game, int x, int y, boolean draw_masked)
+{
+  void (*blit_bitmap)(Bitmap *, Bitmap *, int, int, int, int, int, int) =
+    (draw_masked ? BlitBitmapMasked : BlitBitmap);
+  GdCave *cave = game->cave;
+  int sx = x * cell_size - scroll_x;
+  int sy = y * cell_size - scroll_y;
+  int frame = game->animcycle;
+  int border_size = cell_size / 8;
+  struct GraphicInfo_BD *gfx = &graphic_info_bd_object[O_DIRT][frame];
+  struct GraphicInfo_BD *crm = &graphic_info_bd_object[O_DIRT_CRUMBLED][frame];
+  int dirs[] = { GD_MV_UP, GD_MV_LEFT, GD_MV_RIGHT, GD_MV_DOWN };
+  int i;
+
+  // first draw middle part only (because element might be drawn in masked mode)
+  blit_bitmap(gfx->bitmap, dest, gfx->src_x + border_size, gfx->src_y + border_size,
+              cell_size - 2 * border_size, cell_size - 2 * border_size,
+              sx + border_size, sy + border_size);
+
+  // then draw crumbled sand borders if not next to sand, else draw normal sand borders
+  for (i = 0; i < ARRAY_SIZE(dirs); i++)
+  {
+    int dir = dirs[i];
+    int dx = gd_dx[dir];
+    int dy = gd_dy[dir];
+    int xx = (x + dx + cave->w) % cave->w;
+    int yy = (y + dy + cave->h) % cave->h;
+    int tile = game->element_buffer[yy][xx];
+    int tile_last = game->last_element_buffer[yy][xx];
+    int xoffset = (dx > 0 ? cell_size - border_size : 0);
+    int yoffset = (dy > 0 ? cell_size - border_size : 0);
+    int xsize = (dx == 0 ? cell_size : border_size);
+    int ysize = (dy == 0 ? cell_size : border_size);
+    int dir_to = game->dir_buffer_to[yy][xx];
+    boolean is_moving_to = (dir_to != GD_MV_STILL);
+
+    // do not crumble sand that is just being digged away
+    if (tile_last == O_DIRT && is_moving_to)
+      continue;
+
+    if (tile == O_DIRT)
+      blit_bitmap(gfx->bitmap, dest, gfx->src_x + xoffset, gfx->src_y + yoffset,
+                  xsize, ysize, sx + xoffset, sy + yoffset);
+    else
+      blit_bitmap(crm->bitmap, dest, crm->src_x + xoffset, crm->src_y + yoffset,
+                  xsize, ysize, sx + xoffset, sy + yoffset);
+  }
+}
+
 static void gd_drawcave_tile(Bitmap *dest, GdGame *game, int x, int y, boolean draw_masked)
 {
   void (*blit_bitmap)(Bitmap *, Bitmap *, int, int, int, int, int, int) =
@@ -675,7 +724,10 @@ static void gd_drawcave_tile(Bitmap *dest, GdGame *game, int x, int y, boolean d
   {
     struct GraphicInfo_BD *g = &graphic_info_bd_object[draw][frame];
 
-    blit_bitmap(g->bitmap, dest, g->src_x, g->src_y, cell_size, cell_size, sx, sy);
+    if (draw == O_DIRT)
+      gd_drawcave_crumbled(dest, game, x, y, draw_masked);
+    else
+      blit_bitmap(g->bitmap, dest, g->src_x, g->src_y, cell_size, cell_size, sx, sy);
 
     return;
   }
@@ -792,6 +844,7 @@ int gd_drawcave(Bitmap *dest, GdGame *game, boolean force_redraw)
     for (x = cave->x1; x <= cave->x2; x++)
     {
       if (redraw_all ||
+         game->drawing_buffer[y][x] == O_DIRT ||
          game->gfx_buffer[y][x] & GD_REDRAW ||
          game->dir_buffer_from[y][x] != GD_MV_STILL ||
          game->dir_buffer_to[y][x]   != GD_MV_STILL)
index 89d065c83007ef0085a86de629383dd6846ecd9d..becf115229158ee0e7e3e696d52df77548319f8e 100644 (file)
@@ -11151,6 +11151,10 @@ void InitGraphicInfo_BD(void)
                                    g->anim_start_frame,
                                    sync_frame);
 
+      // add special definitions for crumbled sand
+      if (i == O_DIRT_CRUMBLED)
+        graphic = el_act2crm(EL_BDX_SAND, ACTION_DEFAULT);
+
       getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
 
       g_bd->bitmap = src_bitmap;