rnd-20100325-1-src
[rocksndiamonds.git] / src / tools.c
index 270b153c9579b5614a8a325ef2d05e9812c4465a..5dd629239729c57b9b1088d92a31f5a0dd719226 100644 (file)
@@ -1442,14 +1442,111 @@ void DrawLevelFieldThruMask(int x, int y)
                             (e) == EL_QUICKSAND_EMPTYING ||            \
                             (e) == EL_QUICKSAND_FAST_EMPTYING))
 
-static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
+inline static void DrawLevelFieldCrumbledSandExtBlit(int x, int y,
+                                                    int graphic, int frame,
+                                                    int dir)
 {
   Bitmap *src_bitmap;
   int src_x, src_y;
+  int width, height, bx, by, cx, cy;
   int sx = SCREENX(x), sy = SCREENY(y);
-  int element;
-  int width, height, cx, cy, i;
   int crumbled_border_size = graphic_info[graphic].border_size;
+  int i;
+
+  getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+
+  /* draw simple, sloppy, non-corner-accurate crumbled border */
+
+  if (dir == 1 || dir == 2)            /* left or right crumbled border */
+  {
+    width = crumbled_border_size;
+    height = TILEY;
+    cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
+    cy = 0;
+  }
+  else                                 /* top or bottom crumbled border */
+  {
+    width = TILEX;
+    height = crumbled_border_size;
+    cx = 0;
+    cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
+  }
+
+  BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+            width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
+
+  /* (remaining middle border part must be at least as big as corner part) */
+  if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
+      crumbled_border_size >= TILESIZE / 3)
+    return;
+
+  /* correct corners of crumbled border, if needed */
+
+  if (dir == 1 || dir == 2)            /* left or right crumbled border */
+  {
+    for (i = -1; i <= 1; i+=2)
+    {
+      int xx = x;
+      int yy = y + i;
+      int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
+                    BorderElement);
+
+      /* check if neighbour field is of same crumble type */
+      if (IS_CRUMBLED_TILE(xx, yy, element) &&
+         graphic_info[graphic].class ==
+         graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
+      {
+       /* no crumbled corner, but continued crumbled border */
+
+       width  = crumbled_border_size;
+       height = crumbled_border_size;
+       cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
+       cy = (i == 1 ? TILEX - crumbled_border_size : 0);
+       bx = cx;
+       by = (i == 1 ? crumbled_border_size :
+             TILEY - 2 * crumbled_border_size);
+
+       BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
+                  width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
+      }
+    }
+  }
+  else                         /* top or bottom crumbled border */
+  {
+    for (i = -1; i <= 1; i+=2)
+    {
+      int xx = x + i;
+      int yy = y;
+      int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
+                    BorderElement);
+
+      /* check if neighbour field is of same crumble type */
+      if (IS_CRUMBLED_TILE(xx, yy, element) &&
+         graphic_info[graphic].class ==
+         graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
+      {
+       /* no crumbled corner, but continued crumbled border */
+
+       width  = crumbled_border_size;
+       height = crumbled_border_size;
+       cx = (i == 1 ? TILEX - crumbled_border_size : 0);
+       cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
+       bx = (i == 1 ? crumbled_border_size :
+             TILEY - 2 * crumbled_border_size);
+       by = cy;
+
+       BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
+                  width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
+      }
+    }
+  }
+}
+
+static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
+{
+  int sx = SCREENX(x), sy = SCREENY(y);
+  int element;
+  int i;
   static int xy[4][2] =
   {
     { 0, -1 },
@@ -1464,17 +1561,11 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
   element = TILE_GFX_ELEMENT(x, y);
 
   /* crumble field itself */
-#if 1
   if (IS_CRUMBLED_TILE(x, y, element))
-#else
-  if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
-#endif
   {
     if (!IN_SCR_FIELD(sx, sy))
       return;
 
-    getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
-
     for (i = 0; i < 4; i++)
     {
       int xx = x + xy[i][0];
@@ -1483,37 +1574,23 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
       element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
                 BorderElement);
 
-      /* check if neighbour field is of same type */
+      /* check if neighbour field is of same crumble type */
 #if 1
-      if (IS_CRUMBLED_TILE(xx, yy, element))
+      if (IS_CRUMBLED_TILE(xx, yy, element) &&
+         graphic_info[graphic].class ==
+         graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
        continue;
 #else
-      if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
+      if (IS_CRUMBLED_TILE(xx, yy, element))
        continue;
 #endif
 
-      if (i == 1 || i == 2)
-      {
-       width = crumbled_border_size;
-       height = TILEY;
-       cx = (i == 2 ? TILEX - crumbled_border_size : 0);
-       cy = 0;
-      }
-      else
-      {
-       width = TILEX;
-       height = crumbled_border_size;
-       cx = 0;
-       cy = (i == 3 ? TILEY - crumbled_border_size : 0);
-      }
-
-      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-                width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
+      DrawLevelFieldCrumbledSandExtBlit(x, y, graphic, frame, i);
     }
 
     MarkTileDirty(sx, sy);
   }
-  else         /* crumble neighbour fields */
+  else         /* center field not crumbled -- crumble neighbour fields */
   {
     for (i = 0; i < 4; i++)
     {
@@ -1522,52 +1599,21 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
       int sxx = sx + xy[i][0];
       int syy = sy + xy[i][1];
 
-#if 1
       if (!IN_LEV_FIELD(xx, yy) ||
          !IN_SCR_FIELD(sxx, syy))
        continue;
-#else
-      if (!IN_LEV_FIELD(xx, yy) ||
-         !IN_SCR_FIELD(sxx, syy) ||
-         IS_MOVING(xx, yy))
-       continue;
-#endif
 
       if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
        continue;
 
       element = TILE_GFX_ELEMENT(xx, yy);
 
-#if 1
       if (!IS_CRUMBLED_TILE(xx, yy, element))
        continue;
-#else
-      if (!GFX_CRUMBLED(element))
-       continue;
-#endif
 
       graphic = el_act2crm(element, ACTION_DEFAULT);
-      crumbled_border_size = graphic_info[graphic].border_size;
-
-      getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
-
-      if (i == 1 || i == 2)
-      {
-       width = crumbled_border_size;
-       height = TILEY;
-       cx = (i == 1 ? TILEX - crumbled_border_size : 0);
-       cy = 0;
-      }
-      else
-      {
-       width = TILEX;
-       height = crumbled_border_size;
-       cx = 0;
-       cy = (i == 0 ? TILEY - crumbled_border_size : 0);
-      }
 
-      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-                width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
+      DrawLevelFieldCrumbledSandExtBlit(xx, yy, graphic, 0, 3 - i);
 
       MarkTileDirty(sxx, syy);
     }
@@ -2719,8 +2765,27 @@ void DrawPlayer(struct PlayerInfo *player)
 #endif
 
     /* draw background element under pushed element (like the Sokoban field) */
+#if 1
+    if (game.use_masked_pushing && IS_MOVING(jx, jy))
+    {
+      /* this allows transparent pushing animation over non-black background */
+
+      if (Back[jx][jy])
+       DrawLevelElement(jx, jy, Back[jx][jy]);
+      else
+       DrawLevelElement(jx, jy, EL_EMPTY);
+
+      if (Back[next_jx][next_jy])
+       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+      else
+       DrawLevelElement(next_jx, next_jy, EL_EMPTY);
+    }
+    else if (Back[next_jx][next_jy])
+      DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+#else
     if (Back[next_jx][next_jy])
       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+#endif
 
 #if 0
     printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
@@ -5881,6 +5946,52 @@ int map_direction_EM_to_RND(int direction)
          MV_NONE);
 }
 
+int map_element_RND_to_SP(int element_rnd)
+{
+  int element_sp = 0x20;       /* map unknown elements to yellow "hardware" */
+
+  if (element_rnd >= EL_SP_START &&
+      element_rnd <= EL_SP_END)
+    element_sp = element_rnd - EL_SP_START;
+  else if (element_rnd == EL_EMPTY_SPACE)
+    element_sp = 0x00;
+  else if (element_rnd == EL_INVISIBLE_WALL)
+    element_sp = 0x28;
+
+  return element_sp;
+}
+
+int map_element_SP_to_RND(int element_sp)
+{
+  int element_rnd = EL_UNKNOWN;
+
+  if (element_sp >= 0x00 &&
+      element_sp <= 0x27)
+    element_rnd = EL_SP_START + element_sp;
+  else if (element_sp == 0x28)
+    element_rnd = EL_INVISIBLE_WALL;
+
+  return element_rnd;
+}
+
+int map_action_SP_to_RND(int action_sp)
+{
+  switch (action_sp)
+  {
+    case actActive:            return ACTION_ACTIVE;
+    case actImpact:            return ACTION_IMPACT;
+    case actExploding:         return ACTION_EXPLODING;
+    case actDigging:           return ACTION_DIGGING;
+    case actSnapping:          return ACTION_SNAPPING;
+    case actCollecting:                return ACTION_COLLECTING;
+    case actPassing:           return ACTION_PASSING;
+    case actPushing:           return ACTION_PUSHING;
+    case actDropping:          return ACTION_DROPPING;
+
+    default:                   return ACTION_DEFAULT;
+  }
+}
+
 int get_next_element(int element)
 {
   switch (element)
@@ -7716,6 +7827,24 @@ void InitGraphicInfo_EM(void)
 #endif
 }
 
+void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
+                        int graphic, int sync_frame, int x, int y)
+{
+  int frame = getGraphicAnimationFrame(graphic, sync_frame);
+
+  getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
+}
+
+boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
+{
+  return (IS_NEXT_FRAME(sync_frame, graphic));
+}
+
+int getGraphicInfo_Delay(int graphic)
+{
+  return graphic_info[graphic].anim_delay;
+}
+
 void PlayMenuSoundExt(int sound)
 {
   if (sound == SND_UNDEFINED)