rnd-20070822-1-src
[rocksndiamonds.git] / src / game_em / graphics.c
index 2935096df72837bce39b572704bd103c2d39f1c0..a908126ccc1d142bd65701d91618abcefd7ac415 100644 (file)
@@ -27,6 +27,7 @@
                                  (8 - frame) * ply[p].y) * TILEY / 8   \
                                 - ((SCR_FIELDY - 1) * TILEY) / 2)
 
+#define USE_EXTENDED_GRAPHICS_ENGINE           1
 
 int frame;                     /* current screen frame */
 int screen_x;                  /* current scroll position */
@@ -93,7 +94,7 @@ void BlitScreenToBitmap_EM(Bitmap *target_bitmap)
   }
 }
 
-void blitscreen(void)
+void BackToFront_EM(void)
 {
   static boolean scrolling_last = FALSE;
   int left = screen_x / TILEX;
@@ -101,6 +102,8 @@ void blitscreen(void)
   boolean scrolling = (screen_x % TILEX != 0 || screen_y % TILEY != 0);
   int x, y;
 
+  SyncDisplay();
+
   if (redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last)
   {
     /* blit all (up to four) parts of the scroll buffer to the backbuffer */
@@ -126,6 +129,8 @@ void blitscreen(void)
     }
   }
 
+  FlushDisplay();
+
   for (x = 0; x < MAX_BUF_XSIZE; x++)
     for (y = 0; y < MAX_BUF_YSIZE; y++)
       redraw[x][y] = FALSE;
@@ -134,11 +139,38 @@ void blitscreen(void)
   scrolling_last = scrolling;
 }
 
-static void DrawLevelField_EM(int x, int y, int sx, int sy,
-                             boolean draw_masked)
+void blitscreen(void)
+{
+  BackToFront_EM();
+}
+
+static struct GraphicInfo_EM *getObjectGraphic(int x, int y)
 {
   int tile = Draw[y][x];
   struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
+
+  if (!game.use_native_emc_graphics_engine)
+    getGraphicSourceObjectExt_EM(tile, frame, &g->bitmap, &g->src_x, &g->src_y,
+                                &g->crumbled_bitmap,
+                                &g->crumbled_src_x, &g->crumbled_src_y,
+                                x - 2, y - 2);
+  return g;
+}
+
+static struct GraphicInfo_EM *getPlayerGraphic(int player_nr, int anim)
+{
+  struct GraphicInfo_EM *g = &graphic_info_em_player[player_nr][anim][frame];
+
+  if (!game.use_native_emc_graphics_engine)
+    getGraphicSourcePlayerExt_EM(player_nr, anim, frame,
+                                &g->bitmap, &g->src_x, &g->src_y);
+  return g;
+}
+
+static void DrawLevelField_EM(int x, int y, int sx, int sy,
+                             boolean draw_masked)
+{
+  struct GraphicInfo_EM *g = getObjectGraphic(x, y);
   int src_x = g->src_x + g->src_offset_x;
   int src_y = g->src_y + g->src_offset_y;
   int dst_x = sx * TILEX + g->dst_offset_x;
@@ -177,8 +209,7 @@ static void DrawLevelField_EM(int x, int y, int sx, int sy,
 static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
                                      int crm, boolean draw_masked)
 {
-  int tile = Draw[y][x];
-  struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
+  struct GraphicInfo_EM *g = getObjectGraphic(x, y);
   int left = screen_x / TILEX;
   int top  = screen_y / TILEY;
   int i;
@@ -191,6 +222,13 @@ static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
   if (crm == 0)                /* no crumbled edges for this tile */
     return;
 
+#if 0
+  if (x == 3 && y == 3 && frame == 0)
+    printf("::: %d, %d\n",
+          graphic_info_em_object[207][0].crumbled_src_x,
+          graphic_info_em_object[207][0].crumbled_src_y);
+#endif
+
   for (i = 0; i < 4; i++)
   {
     if (crm & (1 << i))
@@ -237,8 +275,7 @@ static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
 static void DrawLevelPlayer_EM(int x1, int y1, int player_nr, int anim,
                               boolean draw_masked)
 {
-  struct GraphicInfo_EM *g = &graphic_info_em_player[player_nr][anim][frame];
-
+  struct GraphicInfo_EM *g = getPlayerGraphic(player_nr, anim);
   int src_x = g->src_x, src_y = g->src_y;
   int dst_x, dst_y;
 
@@ -316,6 +353,11 @@ static void animscreen(void)
     { 0, +1 }
   };
 
+  if (!game.use_native_emc_graphics_engine)
+    for (y = 2; y < EM_MAX_CAVE_HEIGHT - 2; y++)
+      for (x = 2; x < EM_MAX_CAVE_WIDTH - 2; x++)
+       SetGfxAnimation_EM(Draw[y][x], frame, x - 2, y - 2);
+
   for (y = top; y < top + MAX_BUF_YSIZE; y++)
   {
     for (x = left; x < left + MAX_BUF_XSIZE; x++)
@@ -326,6 +368,7 @@ static void animscreen(void)
       struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
       int obj = g->unique_identifier;
       int crm = 0;
+      boolean redraw_screen_tile = FALSE;
 
       /* re-calculate crumbled state of this tile */
       if (g->has_crumbled_graphics)
@@ -347,8 +390,15 @@ static void animscreen(void)
        }
       }
 
+      redraw_screen_tile = (screentiles[sy][sx]    != obj ||
+                           crumbled_state[sy][sx] != crm);
+
+      /* !!! TEST ONLY -- CHANGE THIS !!! */
+      if (!game.use_native_emc_graphics_engine)
+       redraw_screen_tile = TRUE;
+
       /* only redraw screen tiles if they (or their crumbled state) changed */
-      if (screentiles[sy][sx] != obj || crumbled_state[sy][sx] != crm)
+      if (redraw_screen_tile)
       {
        DrawLevelField_EM(x, y, sx, sy, FALSE);
        DrawLevelFieldCrumbled_EM(x, y, sx, sy, crm, FALSE);
@@ -443,9 +493,14 @@ static void blitplayer(struct PLAYER *ply)
       DrawLevelField_EM(new_x, new_y, new_sx, new_sy, TRUE);
     }
 
-    /* mark screen tiles as dirty */
+    /* redraw screen tiles in the next frame (player may have left the tiles) */
     screentiles[old_sy][old_sx] = -1;
     screentiles[new_sy][new_sx] = -1;
+
+    /* mark screen tiles as dirty (force screen refresh with changed content) */
+    redraw[old_sx][old_sy] = TRUE;
+    redraw[new_sx][new_sy] = TRUE;
+    redraw_tiles += 2;
   }
 }
 
@@ -492,7 +547,7 @@ void DrawRelocatePlayer(struct PlayerInfo *player, boolean quick_relocation)
 
   if (quick_relocation)
   {
-    int offset = (setup.scroll_delay ? 3 : 0);
+    int offset = game.scroll_delay_value;
 
     if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy)))
     {
@@ -690,11 +745,13 @@ void RedrawPlayfield_EM(boolean force_redraw)
   int game.centered_player_nr_next = getCenteredPlayerNr_EM();
 #endif
 #if 1
-  int player_nr = getMaxCenterDistancePlayerNr(screen_x, screen_y);
+  int max_center_distance_player_nr =
+    getMaxCenterDistancePlayerNr(screen_x, screen_y);
 #else
   int player_nr = game_em.last_moving_player;
 #endif
-  int offset = (setup.scroll_delay ? 3 : 0) * TILEX;
+  int stepsize = TILEX / 8;
+  int offset = game.scroll_delay_value * TILEX;
   int offset_x = offset;
   int offset_y = offset;
   int screen_x_old = screen_x;
@@ -745,15 +802,19 @@ void RedrawPlayfield_EM(boolean force_redraw)
 
   if (game.centered_player_nr == -1)
   {
+#if 1
+    if (draw_new_player_location || offset == 0)
+#else
     if (draw_new_player_location)
+#endif
     {
       setScreenCenteredToAllPlayers(&sx, &sy);
     }
     else
     {
 #if 1
-      sx = PLAYER_SCREEN_X(player_nr);
-      sy = PLAYER_SCREEN_Y(player_nr);
+      sx = PLAYER_SCREEN_X(max_center_distance_player_nr);
+      sy = PLAYER_SCREEN_Y(max_center_distance_player_nr);
 #else
       sx = PLAYER_SCREEN_X(game_em.last_moving_player);
       sy = PLAYER_SCREEN_Y(game_em.last_moving_player);
@@ -863,14 +924,16 @@ void RedrawPlayfield_EM(boolean force_redraw)
        blitplayer(&ply[i]);
 
       blitscreen();
-      FlushDisplay();
+
       Delay(wait_delay_value);
 
       /* scroll second step to align at full tile size */
       screen_x -= dxx;
       screen_y -= dyy;
 
+#if 0
       SyncDisplay();
+#endif
 
       animscreen();
 
@@ -878,7 +941,7 @@ void RedrawPlayfield_EM(boolean force_redraw)
        blitplayer(&ply[i]);
 
       blitscreen();
-      FlushDisplay();
+
       Delay(wait_delay_value);
     }
 
@@ -906,23 +969,68 @@ void RedrawPlayfield_EM(boolean force_redraw)
                            sy - offset_y > screen_y ? sy - offset_y :
                            screen_y);
 
-  /* prevent scrolling further than player step size screen when scrolling */
-  if (ABS(screen_x - screen_x_old) > TILEX / 8 ||
-      ABS(screen_y - screen_y_old) > TILEY / 8)
+#if 0
+  printf("::: (%d, %d) => (%d, %d) [(%d, %d), (%d, %d)] [%d, %d] [%d / %d]\n",
+        screen_x_old, screen_y_old,
+        screen_x, screen_y,
+        ply[max_center_distance_player_nr].oldx,
+        ply[max_center_distance_player_nr].x,
+        ply[max_center_distance_player_nr].oldy,
+        ply[max_center_distance_player_nr].y,
+        sx, sy,
+        ABS(screen_x - screen_x_old),
+        ABS(screen_y - screen_y_old));
+#endif
+
+#if 1
+
+#if 1
+  /* prevent scrolling further than double player step size when scrolling */
+  if (ABS(screen_x - screen_x_old) > 2 * stepsize)
+  {
+    int dx = SIGN(screen_x - screen_x_old);
+
+    screen_x = screen_x_old + dx * 2 * stepsize;
+  }
+  if (ABS(screen_y - screen_y_old) > 2 * stepsize)
+  {
+    int dy = SIGN(screen_y - screen_y_old);
+
+    screen_y = screen_y_old + dy * 2 * stepsize;
+  }
+#else
+  /* prevent scrolling further than double player step size when scrolling */
+  if (ABS(screen_x - screen_x_old) > 2 * stepsize ||
+      ABS(screen_y - screen_y_old) > 2 * stepsize)
+  {
+    int dx = SIGN(screen_x - screen_x_old);
+    int dy = SIGN(screen_y - screen_y_old);
+
+    screen_x = screen_x_old + dx * 2 * stepsize;
+    screen_y = screen_y_old + dy * 2 * stepsize;
+  }
+#endif
+
+#else
+  /* prevent scrolling further than player step size when scrolling */
+  if (ABS(screen_x - screen_x_old) > stepsize ||
+      ABS(screen_y - screen_y_old) > stepsize)
   {
     int dx = SIGN(screen_x - screen_x_old);
     int dy = SIGN(screen_y - screen_y_old);
 
-    screen_x = screen_x_old + dx * TILEX / 8;
-    screen_y = screen_y_old + dy * TILEY / 8;
+    screen_x = screen_x_old + dx * stepsize;
+    screen_y = screen_y_old + dy * stepsize;
   }
+#endif
 
   /* prevent scrolling away from the other players when focus on all players */
   if (game.centered_player_nr == -1)
   {
 #if 1
     /* check if all players are still visible with new scrolling position */
-    if (!checkIfAllPlayersAreVisible(screen_x, screen_y))
+    if (checkIfAllPlayersAreVisible(screen_x_old, screen_y_old) &&
+       !checkIfAllPlayersAreVisible(screen_x, screen_y))
     {
       /* reset horizontal scroll position to last value, if needed */
       if (!checkIfAllPlayersAreVisible(screen_x, screen_y_old))
@@ -957,6 +1065,8 @@ void RedrawPlayfield_EM(boolean force_redraw)
 #if 0
     int player_nr = game_em.last_moving_player;
 #endif
+    int player_nr = (game.centered_player_nr == -1 ?
+                    max_center_distance_player_nr : game.centered_player_nr);
     int player_move_dir = game_em.last_player_direction[player_nr];
     int dx = SIGN(screen_x - screen_x_old);
     int dy = SIGN(screen_y - screen_y_old);
@@ -975,11 +1085,13 @@ void RedrawPlayfield_EM(boolean force_redraw)
   for (i = 0; i < MAX_PLAYERS; i++)
     blitplayer(&ply[i]);
 
+#if 0
+#if 0
   SyncDisplay();
+#endif
 
   blitscreen();
-
-  FlushDisplay();
+#endif
 }
 
 void game_animscreen(void)
@@ -989,12 +1101,47 @@ void game_animscreen(void)
 
 void DrawGameDoorValues_EM()
 {
+#if 1
+  int dynamite_state;
+  int key_state;
+#else
   int dynamite_state = ply[0].dynamite;                /* !!! ONLY PLAYER 1 !!! */
-  int all_keys_state = ply[0].keys | ply[1].keys | ply[2].keys | ply[3].keys;
+  int key_state = ply[0].keys | ply[1].keys | ply[2].keys | ply[3].keys;
+#endif
+
+#if 1
+  if (game.centered_player_nr == -1)
+  {
+#if 1
+    int i;
+
+    dynamite_state = 0;
+    key_state = 0;
+
+    for (i = 0; i < MAX_PLAYERS; i++)
+    {
+      dynamite_state += ply[i].dynamite;
+      key_state |= ply[i].keys;
+    }
+
+#else
+
+    dynamite_state = ply[0].dynamite;          /* !!! ONLY PLAYER 1 !!! */
+    key_state = ply[0].keys | ply[1].keys | ply[2].keys | ply[3].keys;
+#endif
+  }
+  else
+  {
+    int player_nr = game.centered_player_nr;
+
+    dynamite_state = ply[player_nr].dynamite;
+    key_state = ply[player_nr].keys;
+  }
+#endif
 
 #if 1
   DrawAllGameValues(lev.required, dynamite_state, lev.score,
-                   lev.time, all_keys_state);
+                   lev.time, key_state);
 #else
   DrawAllGameValues(lev.required, ply1.dynamite, lev.score,
                    DISPLAY_TIME(lev.time), ply1.keys | ply2.keys);