rnd-20100214-2-src
[rocksndiamonds.git] / src / tools.c
index dba82c010ae8940b40af2627ff32c33e360aa8b1..773a59db1efd0efbe2a2ab69b5d6cf566ff7c37a 100644 (file)
@@ -144,7 +144,17 @@ void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
     /* blit playfield from scroll buffer to normal back buffer for fading in */
     BlitScreenToBitmap_EM(backbuffer);
   }
-  else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
+  else if (game_status == GAME_MODE_PLAYING &&
+          level.game_engine_type == GAME_ENGINE_TYPE_SP)
+  {
+    /* currently there is no partial redraw -- always redraw whole playfield */
+    RedrawPlayfield_SP(TRUE);
+
+    /* blit playfield from scroll buffer to normal back buffer for fading in */
+    BlitScreenToBitmap_SP(backbuffer);
+  }
+  else if (game_status == GAME_MODE_PLAYING &&
+          !game.envelope_active)
   {
     if (force_redraw)
     {
@@ -548,7 +558,7 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
   }
 #endif
 
-  /* !!! what abount fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
+  /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
 
 #if 0
   printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
@@ -1232,14 +1242,43 @@ inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
   int y1 = y;
   int x2 = x + SIGN(dx);
   int y2 = y + SIGN(dy);
+#if 0
+  /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
+  int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
+#else
+  /* movement with two-tile animations must be sync'ed with movement position,
+     not with current GfxFrame (which can be higher when using slow movement) */
+  int anim_pos = (dx ? ABS(dx) : ABS(dy));
   int anim_frames = graphic_info[graphic].anim_frames;
-  int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
+#if 1
+  /* (we also need anim_delay here for movement animations with less frames) */
+  int anim_delay = graphic_info[graphic].anim_delay;
+  int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
+#else
+  int sync_frame = anim_pos * anim_frames / TILESIZE;
+#endif
+#endif
   boolean draw_start_tile = (cut_mode != CUT_ABOVE);   /* only for falling! */
   boolean draw_end_tile   = (cut_mode != CUT_BELOW);   /* only for falling! */
 
   /* re-calculate animation frame for two-tile movement animation */
   frame = getGraphicAnimationFrame(graphic, sync_frame);
 
+#if 0
+#if 0
+  printf("::: %d, %d, %d => %d [%d]\n",
+        anim_pos, anim_frames, anim_delay, sync_frame, graphic);
+#else
+  printf("::: %d, %d => %d\n",
+        anim_pos, anim_frames, sync_frame);
+#endif
+#endif
+
+#if 0
+  printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
+        GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
+#endif
+
   /* check if movement start graphic inside screen area and should be drawn */
   if (draw_start_tile && IN_SCR_FIELD(x1, y1))
   {
@@ -2451,6 +2490,8 @@ void DrawPlayerField(int x, int y)
   DrawPlayer(PLAYERINFO(x, y));
 }
 
+#define DRAW_PLAYER_OVER_PUSHED_ELEMENT        1
+
 void DrawPlayer(struct PlayerInfo *player)
 {
   int jx = player->jx;
@@ -2590,6 +2631,7 @@ void DrawPlayer(struct PlayerInfo *player)
     }
   }
 
+#if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
   /* ----------------------------------------------------------------------- */
   /* draw player himself                                                     */
   /* ----------------------------------------------------------------------- */
@@ -2627,6 +2669,17 @@ void DrawPlayer(struct PlayerInfo *player)
 
     DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
   }
+#endif
+
+#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
+  if (player->GfxPos)
+  {
+    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+      sxx = player->GfxPos;
+    else
+      syy = player->GfxPos;
+  }
+#endif
 
   /* ----------------------------------------------------------------------- */
   /* draw things the player is pushing, if needed                            */
@@ -2666,11 +2719,90 @@ 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",
+          jx, px, player->GfxPos, player->StepFrame,
+          player->is_pushing,
+          dx, sxx, pxx,
+          IS_MOVING(jx, jy),
+          graphic, frame,
+          GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
+#endif
+
+#if 1
+    /* do not draw (EM style) pushing animation when pushing is finished */
+    /* (two-tile animations usually do not contain start and end frame) */
+    if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
+      DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
+    else
+      DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
+#else
     /* masked drawing is needed for EMC style (double) movement graphics */
+    /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
     DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
+#endif
+  }
+#endif
+
+#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
+  /* ----------------------------------------------------------------------- */
+  /* draw player himself                                                     */
+  /* ----------------------------------------------------------------------- */
+
+  graphic = getPlayerGraphic(player, move_dir);
+
+  /* in the case of changed player action or direction, prevent the current
+     animation frame from being restarted for identical animations */
+  if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
+    player->Frame = last_player_frame;
+
+  frame = getGraphicAnimationFrame(graphic, player->Frame);
+
+  if (player->GfxPos)
+  {
+    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+      sxx = player->GfxPos;
+    else
+      syy = player->GfxPos;
+  }
+
+  if (!setup.soft_scrolling && ScreenMovPos)
+    sxx = syy = 0;
+
+  if (player_is_opaque)
+    DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
+  else
+    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+
+  if (SHIELD_ON(player))
+  {
+    int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
+                  IMG_SHIELD_NORMAL_ACTIVE);
+    int frame = getGraphicAnimationFrame(graphic, -1);
+
+    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
   }
 #endif
 
@@ -2811,9 +2943,13 @@ boolean Request(char *text, unsigned int req_state)
     }
   }
 
-  if (game_status == GAME_MODE_PLAYING &&
-      level.game_engine_type == GAME_ENGINE_TYPE_EM)
-    BlitScreenToBitmap_EM(backbuffer);
+  if (game_status == GAME_MODE_PLAYING)
+  {
+    if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+      BlitScreenToBitmap_EM(backbuffer);
+    else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+      BlitScreenToBitmap_SP(backbuffer);
+  }
 
   /* disable deactivated drawing when quick-loading level tape recording */
   if (tape.playing && tape.deactivate_display)
@@ -6044,6 +6180,8 @@ unsigned int InitRND(long seed)
 {
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
     return InitEngineRandom_EM(seed);
+  else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+    return InitEngineRandom_SP(seed);
   else
     return InitEngineRandom_RND(seed);
 }
@@ -7597,6 +7735,29 @@ 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 isRandomAnimation_SP(int graphic)
+{
+  return (ANIM_MODE(graphic) == ANIM_RANDOM);
+}
+
+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)