rnd-20060207-3-src
[rocksndiamonds.git] / src / game_em / graphics.c
index bd9331755b0334896e5046266b7fd4c37a47905d..5682a24ea9d5e2eba4c18766ec470a6bf05bc7c1 100644 (file)
@@ -8,14 +8,39 @@
 #include "level.h"
 
 
+#define MIN_SCREEN_X           (TILEX)
+#define MIN_SCREEN_Y           (TILEY)
+#define MAX_SCREEN_X           ((lev.width  - (SCR_FIELDX - 1)) * TILEX)
+#define MAX_SCREEN_Y           ((lev.height - (SCR_FIELDY - 1)) * TILEY)
+
+#define VALID_SCREEN_X(x)      ((x) < MIN_SCREEN_X ? MIN_SCREEN_X :    \
+                                (x) > MAX_SCREEN_X ? MAX_SCREEN_X : (x))
+#define VALID_SCREEN_Y(y)      ((y) < MIN_SCREEN_Y ? MIN_SCREEN_Y :    \
+                                (y) > MAX_SCREEN_Y ? MAX_SCREEN_Y : (y))
+
+#define PLAYER_SCREEN_X(p)     (((    frame) * ply[p].oldx +           \
+                                 (8 - frame) * ply[p].x) * TILEX / 8   \
+                                - ((SCR_FIELDX - 1) * TILEX) / 2)
+#define PLAYER_SCREEN_Y(p)     (((    frame) * ply[p].oldy +           \
+                                 (8 - frame) * ply[p].y) * TILEY / 8   \
+                                - ((SCR_FIELDY - 1) * TILEY) / 2)
+
+
 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 +94,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,
@@ -225,7 +297,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 },
@@ -273,6 +345,9 @@ static void animscreen(void)
 
        screentiles[sy][sx] = obj;
        crumbled_state[sy][sx] = crm;
+
+       redraw[sx][sy] = TRUE;
+       redraw_tiles++;
       }
     }
   }
@@ -365,10 +440,18 @@ 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;
+  int player_nr = 0;           /* !!! FIX THIS (CENTERED TO PLAYER 1) !!! */
 
   frame = 6;
+#if 1
+  screen_x = VALID_SCREEN_X(PLAYER_SCREEN_X(player_nr));
+  screen_y = VALID_SCREEN_Y(PLAYER_SCREEN_Y(player_nr));
+#else
   screen_x = 0;
   screen_y = 0;
+#endif
 
   for (y = 0; y < MAX_BUF_YSIZE; y++)
   {
@@ -379,35 +462,54 @@ 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;
+  int player_nr = 0;           /* !!! FIX THIS (CENTERED TO PLAYER 1) !!! */
+  int sx = PLAYER_SCREEN_X(player_nr);
+  int sy = PLAYER_SCREEN_Y(player_nr);
+  int i;
 
-  x = (frame * ply1.oldx + (8 - frame) * ply1.x) * TILEX / 8
-    + ((SCR_FIELDX - 1) * TILEX) / 2;
-  y = (frame * ply1.oldy + (8 - frame) * ply1.y) * TILEY / 8
-    + ((SCR_FIELDY - 1) * TILEY) / 2;
+#if 1
+
+  int offset = (setup.scroll_delay ? 3 : 0) * TILEX;
+
+  /* calculate new screen scrolling position, with regard to scroll delay */
+  screen_x = VALID_SCREEN_X(sx < screen_x - offset ? sx + offset :
+                           sx > screen_x + offset ? sx - offset : screen_x);
+  screen_y = VALID_SCREEN_Y(sy < screen_y - offset ? sy + offset :
+                           sy > screen_y + offset ? sy - offset : screen_y);
 
-  if (x > lev.width * TILEX)
-    x = lev.width * TILEX;
-  if (y > lev.height * TILEY)
-    y = lev.height * TILEY;
+#else
 
-  if (x < SCR_FIELDX * TILEX)
-    x = SCR_FIELDX * TILEY;
-  if (y < SCR_FIELDY * TILEY)
-    y = SCR_FIELDY * TILEY;
+  if (sx > lev.width * TILEX)
+    sx = lev.width * TILEX;
+  if (sy > lev.height * TILEY)
+    sy = lev.height * TILEY;
 
-  screen_x = x - (SCR_FIELDX - 1) * TILEX;
-  screen_y = y - (SCR_FIELDY - 1) * TILEY;
+  if (sx < SCR_FIELDX * TILEX)
+    sx = SCR_FIELDX * TILEY;
+  if (sy < SCR_FIELDY * TILEY)
+    sy = SCR_FIELDY * TILEY;
+
+  screen_x = sx - (SCR_FIELDX - 1) * TILEX;
+  screen_y = sy - (SCR_FIELDY - 1) * TILEY;
+
+#endif
 
   animscreen();
-  blitplayer(&ply1);
-  blitplayer(&ply2);
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    blitplayer(&ply[i]);
+
   blitscreen();
 
   FlushDisplay();
@@ -420,6 +522,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
 }