rnd-20060216-1-src
[rocksndiamonds.git] / src / game_em / graphics.c
index 06f974a2e935777387583b68373e7897e55b2ff6..236b8289bfbdff7a8b837e2e338d2ef0613c968d 100644 (file)
@@ -7,14 +7,43 @@
 #include "display.h"
 #include "level.h"
 
-
-unsigned int frame;            /* current screen frame */
-unsigned int screen_x;         /* current scroll position */
-unsigned int screen_y;
+#define MIN_SCREEN_XPOS                1
+#define MIN_SCREEN_YPOS                1
+#define MAX_SCREEN_XPOS                MAX(1, lev.width  - (SCR_FIELDX - 1))
+#define MAX_SCREEN_YPOS                MAX(1, lev.height - (SCR_FIELDY - 1))
+
+#define MIN_SCREEN_X           (MIN_SCREEN_XPOS * TILEX)
+#define MIN_SCREEN_Y           (MIN_SCREEN_YPOS * TILEY)
+#define MAX_SCREEN_X           (MAX_SCREEN_XPOS * TILEX)
+#define MAX_SCREEN_Y           (MAX_SCREEN_YPOS * 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)
+
+
+int frame;                     /* current screen frame */
+#if 0
+int screen_x;                  /* current scroll position */
+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 int screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
+static 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
@@ -24,8 +53,8 @@ static unsigned int crumbled_state[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
 
 void BlitScreenToBitmap_EM(Bitmap *target_bitmap)
 {
-  unsigned int x = screen_x % (MAX_BUF_XSIZE * TILEX);
-  unsigned int y = screen_y % (MAX_BUF_YSIZE * TILEY);
+  int x = screen_x % (MAX_BUF_XSIZE * TILEX);
+  int y = screen_y % (MAX_BUF_YSIZE * TILEY);
 
   if (x < 2 * TILEX && y < 2 * TILEY)
   {
@@ -69,7 +98,54 @@ void BlitScreenToBitmap_EM(Bitmap *target_bitmap)
 
 void blitscreen(void)
 {
+#if 1
+
+  static boolean scrolling_last = FALSE;
+  int left = screen_x / TILEX;
+  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,
@@ -110,7 +186,7 @@ static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
 {
   int tile = Draw[y][x];
   struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
-  unsigned int i;
+  int i;
 
   if (crm == 0)                /* no crumbled edges for this tile */
     return;
@@ -223,9 +299,9 @@ static void DrawLevelPlayer_EM(int x1, int y1, int player_nr, int anim,
 
 static void animscreen(void)
 {
-  unsigned int x, y, i;
-  unsigned int left = screen_x / TILEX;
-  unsigned int top = screen_y / TILEY;
+  int x, y, i;
+  int left = screen_x / TILEX;
+  int top  = screen_y / TILEY;
   static int xy[4][2] =
   {
     { 0, -1 },
@@ -242,8 +318,8 @@ static void animscreen(void)
       int sy = y % MAX_BUF_YSIZE;    
       int tile = Draw[y][x];
       struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
-      unsigned int obj = g->unique_identifier;
-      unsigned int crm = 0;
+      int obj = g->unique_identifier;
+      int crm = 0;
 
       /* re-calculate crumbled state of this tile */
       if (g->has_crumbled_graphics)
@@ -273,6 +349,9 @@ static void animscreen(void)
 
        screentiles[sy][sx] = obj;
        crumbled_state[sy][sx] = crm;
+
+       redraw[sx][sy] = TRUE;
+       redraw_tiles++;
       }
     }
   }
@@ -286,7 +365,7 @@ static void animscreen(void)
 
 static void blitplayer(struct PLAYER *ply)
 {
-  unsigned int x1, y1, x2, y2;
+  int x1, y1, x2, y2;
 
   if (!ply->alive)
     return;
@@ -297,8 +376,8 @@ static void blitplayer(struct PLAYER *ply)
   x2 = x1 + TILEX - 1;
   y2 = y1 + TILEY - 1;
 
-  if ((unsigned int)(x2 - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) &&
-      (unsigned int)(y2 - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1))
+  if ((int)(x2 - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) &&
+      (int)(y2 - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1))
   {
     /* some casts to "int" are needed because of negative calculation values */
     int dx = (int)ply->x - (int)ply->oldx;
@@ -364,11 +443,19 @@ static void blitplayer(struct PLAYER *ply)
 
 void game_initscreen(void)
 {
-  unsigned int x,y;
+  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++)
   {
@@ -380,8 +467,8 @@ void game_initscreen(void)
   }
 
 #if 1
-  DrawAllGameValues(lev.required, ply1.dynamite, lev.score,
-                   lev.time, ply1.keys | ply2.keys);
+  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);
@@ -390,29 +477,43 @@ void game_initscreen(void)
 
 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
 
-  if (x > lev.width * TILEX)
-    x = lev.width * TILEX;
-  if (y > lev.height * TILEY)
-    y = lev.height * TILEY;
+  int offset = (setup.scroll_delay ? 3 : 0) * TILEX;
 
-  if (x < SCR_FIELDX * TILEX)
-    x = SCR_FIELDX * TILEY;
-  if (y < SCR_FIELDY * TILEY)
-    y = SCR_FIELDY * TILEY;
+  /* calculate new screen scrolling position, with regard to scroll delay */
+  screen_x = VALID_SCREEN_X(sx + offset < screen_x ? sx + offset :
+                           sx - offset > screen_x ? sx - offset : screen_x);
+  screen_y = VALID_SCREEN_Y(sy + offset < screen_y ? sy + offset :
+                           sy - offset > screen_y ? sy - offset : screen_y);
 
-  screen_x = x - (SCR_FIELDX - 1) * TILEX;
-  screen_y = y - (SCR_FIELDY - 1) * TILEY;
+#else
+
+  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;
+
+  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();
@@ -425,9 +526,12 @@ 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, ply1.dynamite, lev.score,
-                   lev.time, ply1.keys | ply2.keys);
+  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);