rnd-20060207-2-src
[rocksndiamonds.git] / src / game_em / graphics.c
index 78fbe8b007ef3029590525283853cb664b8ce0e3..be63a3ba7b6ba28cadd862f2e117ef5321b2232c 100644 (file)
@@ -9,13 +9,20 @@
 
 
 unsigned int frame;            /* current screen frame */
+#if 0
 unsigned int screen_x;         /* current scroll position */
 unsigned int screen_y;
+#else
+int screen_x;                  /* current scroll position */
+int screen_y;
+#endif
 
 /* tiles currently on screen */
 static unsigned int screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
 static unsigned int crumbled_state[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
 
+static boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
+
 
 /* copy the entire screen to the window at the scroll position
  *
@@ -69,7 +76,54 @@ void BlitScreenToBitmap_EM(Bitmap *target_bitmap)
 
 void blitscreen(void)
 {
+#if 1
+
+  static boolean scrolling_last = FALSE;
+  unsigned int left = screen_x / TILEX;
+  unsigned int top  = screen_y / TILEY;
+  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 */
+    BlitScreenToBitmap_EM(backbuffer);
+
+    /* blit the completely updated backbuffer to the window (in one blit) */
+    BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY);
+  }
+  else
+  {
+    for (x = 0; x < SCR_FIELDX; x++)
+    {
+      for (y = 0; y < SCR_FIELDY; y++)
+      {
+       int xx = (left + x) % MAX_BUF_XSIZE;
+       int yy = (top  + y) % MAX_BUF_YSIZE;
+
+       if (redraw[xx][yy])
+         BlitBitmap(screenBitmap, window,
+                    xx * TILEX, yy * TILEY, TILEX, TILEY,
+                    SX + x * TILEX, SY + y * TILEY);
+      }
+    }
+  }
+
+  for (x = 0; x < MAX_BUF_XSIZE; x++)
+    for (y = 0; y < MAX_BUF_YSIZE; y++)
+      redraw[x][y] = FALSE;
+  redraw_tiles = 0;
+
+  scrolling_last = scrolling;
+
+#else
+
+  /* blit all (up to four) parts of the scroll buffer to the window */
   BlitScreenToBitmap_EM(window);
+
+#endif
 }
 
 static void DrawLevelField_EM(int x, int y, int sx, int sy,
@@ -81,25 +135,27 @@ static void DrawLevelField_EM(int x, int y, int sx, int sy,
   int src_y = g->src_y + g->src_offset_y;
   int dst_x = sx * TILEX + g->dst_offset_x;
   int dst_y = sy * TILEY + g->dst_offset_y;
+  int width = g->width;
+  int height = g->height;
 
   if (draw_masked)
   {
-    if (g->width > 0 && g->height > 0)
+    if (width > 0 && height > 0)
     {
       SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
                    dst_x - src_x, dst_y - src_y);
       BlitBitmapMasked(g->bitmap, screenBitmap,
-                      src_x, src_y, g->width, g->height, dst_x, dst_y);
+                      src_x, src_y, width, height, dst_x, dst_y);
     }
   }
   else
   {
-    if (g->width != TILEX || g->height != TILEY)
+    if ((width != TILEX || height != TILEY) && !g->preserve_background)
       ClearRectangle(screenBitmap, sx * TILEX, sy * TILEY, TILEX, TILEY);
 
-    if (g->width > 0 && g->height > 0)
+    if (width > 0 && height > 0)
       BlitBitmap(g->bitmap, screenBitmap,
-                src_x, src_y, g->width, g->height, dst_x, dst_y);
+                src_x, src_y, width, height, dst_x, dst_y);
   }
 }
 
@@ -223,7 +279,7 @@ static void animscreen(void)
 {
   unsigned int x, y, i;
   unsigned int left = screen_x / TILEX;
-  unsigned int top = screen_y / TILEY;
+  unsigned int top  = screen_y / TILEY;
   static int xy[4][2] =
   {
     { 0, -1 },
@@ -263,6 +319,7 @@ static void animscreen(void)
        }
       }
 
+      /* only redraw screen tiles if they (or their crumbled state) changed */
       if (screentiles[sy][sx] != obj || crumbled_state[sy][sx] != crm)
       {
        DrawLevelField_EM(x, y, sx, sy, FALSE);
@@ -270,6 +327,9 @@ static void animscreen(void)
 
        screentiles[sy][sx] = obj;
        crumbled_state[sy][sx] = crm;
+
+       redraw[sx][sy] = TRUE;
+       redraw_tiles++;
       }
     }
   }
@@ -308,11 +368,13 @@ static void blitplayer(struct PLAYER *ply)
     int old_sy = old_y % MAX_BUF_XSIZE;
     int new_sx = new_x % MAX_BUF_XSIZE;
     int new_sy = new_y % MAX_BUF_XSIZE;
+#if 0
     int old_crm = crumbled_state[old_sy][old_sx];
+#endif
     int new_crm = crumbled_state[new_sy][new_sx];
 
     /* only diggable elements can be crumbled in the classic EM engine */
-    boolean player_is_digging = (crumbled_state[new_sy][new_sx] != 0);
+    boolean player_is_digging = (new_crm != 0);
 
     x1 %= MAX_BUF_XSIZE * TILEX;
     y1 %= MAX_BUF_YSIZE * TILEY;
@@ -321,9 +383,11 @@ static void blitplayer(struct PLAYER *ply)
 
     if (player_is_digging)
     {
+#if 0
       /* draw the field the player is moving from (under the player) */
       DrawLevelField_EM(old_x, old_y, old_sx, old_sy, FALSE);
       DrawLevelFieldCrumbled_EM(old_x, old_y, old_sx, old_sy, old_crm, FALSE);
+#endif
 
       /* draw the field the player is moving to (under the player) */
       DrawLevelField_EM(new_x, new_y, new_sx, new_sy, FALSE);
@@ -331,6 +395,11 @@ static void blitplayer(struct PLAYER *ply)
 
       /* draw the player (masked) over the element he is just digging away */
       DrawLevelPlayer_EM(x1, y1, ply->num, ply->anim, TRUE);
+
+#if 1
+      /* draw the field the player is moving from (masked over the player) */
+      DrawLevelField_EM(old_x, old_y, old_sx, old_sy, TRUE);
+#endif
     }
     else
     {
@@ -353,6 +422,8 @@ static void blitplayer(struct PLAYER *ply)
 void game_initscreen(void)
 {
   unsigned int x,y;
+  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;
 
   frame = 6;
   screen_x = 0;
@@ -367,35 +438,74 @@ void game_initscreen(void)
     }
   }
 
+#if 1
+  DrawAllGameValues(lev.required, dynamite_state, lev.score,
+                   lev.time, all_keys_state);
+#else
   DrawAllGameValues(lev.required, ply1.dynamite, lev.score,
                    DISPLAY_TIME(lev.time + 4), ply1.keys | ply2.keys);
+#endif
 }
 
 void RedrawPlayfield_EM()
 {
-  unsigned int x,y;
-
-  x = (frame * ply1.oldx + (8 - frame) * ply1.x) * TILEX / 8
+  int i, sx, sy;
+
+#if 1
+
+  int screen_x_min = TILEX;
+  int screen_y_min = TILEY;
+  int screen_x_max = (lev.width  - (SCR_FIELDX - 1)) * TILEX;
+  int screen_y_max = (lev.height - (SCR_FIELDY - 1)) * TILEY;
+  int offset = (setup.scroll_delay ? 3 : 0) * TILEX;
+  int stepsize = TILEX / 8;
+  int nr = 0;          /* !!! FIX THIS (CENTERED TO PLAYER 1) !!! */
+
+  sx = (frame * ply[nr].oldx + (8 - frame) * ply[nr].x) * stepsize
+    - ((SCR_FIELDX - 1) * TILEX) / 2;
+  sy = (frame * ply[nr].oldy + (8 - frame) * ply[nr].y) * stepsize
+    - ((SCR_FIELDY - 1) * TILEY) / 2;
+
+  /* calculate new screen scrolling position, with regard to scroll delay */
+  screen_x = (sx < screen_x - offset ? sx + offset :
+             sx > screen_x + offset ? sx - offset : screen_x);
+  screen_y = (sy < screen_y - offset ? sy + offset :
+             sy > screen_y + offset ? sy - offset : screen_y);
+
+  /* check minimal and maximal boundaries for screen scrolling position */
+  screen_x = (screen_x < screen_x_min ? screen_x_min :
+             screen_x > screen_x_max ? screen_x_max : screen_x);
+  screen_y = (screen_y < screen_y_min ? screen_y_min :
+             screen_y > screen_y_max ? screen_y_max : screen_y);
+
+#else
+
+  /* !!! FIX THIS (CENTERED TO PLAYER 1) !!! */
+  sx = (frame * ply[0].oldx + (8 - frame) * ply[0].x) * TILEX / 8
     + ((SCR_FIELDX - 1) * TILEX) / 2;
-  y = (frame * ply1.oldy + (8 - frame) * ply1.y) * TILEY / 8
+  sy = (frame * ply[0].oldy + (8 - frame) * ply[0].y) * TILEY / 8
     + ((SCR_FIELDY - 1) * TILEY) / 2;
 
-  if (x > lev.width * TILEX)
-    x = lev.width * TILEX;
-  if (y > lev.height * TILEY)
-    y = lev.height * TILEY;
+  if (sx > lev.width * TILEX)
+    sx = lev.width * TILEX;
+  if (sy > lev.height * TILEY)
+    sy = lev.height * TILEY;
+
+  if (sx < SCR_FIELDX * TILEX)
+    sx = SCR_FIELDX * TILEY;
+  if (sy < SCR_FIELDY * TILEY)
+    sy = SCR_FIELDY * TILEY;
 
-  if (x < SCR_FIELDX * TILEX)
-    x = SCR_FIELDX * TILEY;
-  if (y < SCR_FIELDY * TILEY)
-    y = SCR_FIELDY * TILEY;
+  screen_x = sx - (SCR_FIELDX - 1) * TILEX;
+  screen_y = sy - (SCR_FIELDY - 1) * TILEY;
 
-  screen_x = x - (SCR_FIELDX - 1) * TILEX;
-  screen_y = y - (SCR_FIELDY - 1) * TILEY;
+#endif
 
   animscreen();
-  blitplayer(&ply1);
-  blitplayer(&ply2);
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    blitplayer(&ply[i]);
+
   blitscreen();
 
   FlushDisplay();
@@ -408,6 +518,14 @@ void game_animscreen(void)
 
 void DrawGameDoorValues_EM()
 {
+  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;
+
+#if 1
+  DrawAllGameValues(lev.required, dynamite_state, lev.score,
+                   lev.time, all_keys_state);
+#else
   DrawAllGameValues(lev.required, ply1.dynamite, lev.score,
                    DISPLAY_TIME(lev.time), ply1.keys | ply2.keys);
+#endif
 }