rnd-19980909
[rocksndiamonds.git] / src / tools.c
index 85c9009f2be9c75079af182617834dbbc8d9bd7d..499469d696a4972e429ac92e9185ab8161725c36 100644 (file)
 
 #include <math.h>
 
+#ifdef MSDOS
+extern BOOL wait_for_vsync;
+#endif
+
 void SetDrawtoField(int mode)
 {
   if (mode == DRAW_BUFFERED && soft_scrolling_on)
@@ -65,70 +69,25 @@ void BackToFront()
   if (direct_draw_on && game_status == PLAYING)
     redraw_mask &= ~REDRAW_MAIN;
 
-
-
-  /*
-  if (ScreenMovPos && redraw_mask & REDRAW_FIELD)
-  {
-    redraw_mask |= REDRAW_FIELD;
-
-    printf("FULL SCREEN REDRAW FORCED by ScreenMovPos == %d\n", ScreenMovPos);
-  }
-  */
-
-
-
-  /*
-  if (ScreenMovPos && redraw_mask & REDRAW_TILES)
-  {
-    redraw_mask |= REDRAW_FIELD;
-
-    printf("FULL SCREEN REDRAW FORCED by ScreenMovPos == %d\n", ScreenMovPos);
-  }
-  */
-
-
-  /*
-  if (ScreenMovPos && !(redraw_mask & REDRAW_FIELD))
-  {
-    printf("OOPS!\n");
-
-    *((int *)NULL) = 0;
-  }
-  */
-
-  /*
-  if (IN_SCR_FIELD(lastJX,lastJY))
-    redraw[redraw_x1 + lastJX][redraw_y1 + lastJY] = 0;
-    */
-
-
   if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
     redraw_mask |= REDRAW_FIELD;
 
-  if (redraw_mask & REDRAW_FIELD)
+  if (redraw_mask & REDRAW_FIELD || ScreenMovPos)
     redraw_mask &= ~REDRAW_TILES;
 
-  /*
-  {
-    static int lastFrame = 0;
-
-    printf("FrameCounter: %d\n", FrameCounter);
-
-    if (FrameCounter != lastFrame + 1)
-    {
-      printf("SYNC LOST! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+  if (!redraw_mask)
+    return;
 
-      if (FrameCounter > 100)
-       *((int *)NULL) = 0;
-    }
+  /* synchronize X11 graphics at this point; if we would synchronize the
+     display immediately after the buffer switching (after the XFlush),
+     this could mean that we have to wait for the graphics to complete,
+     although we could go on doing calculations for the next frame */
 
-    lastFrame = FrameCounter;
-  }
-  */
+  XSync(display,FALSE);
 
-  if (!redraw_mask)
-    return;
+#ifdef MSDOS
+  wait_for_vsync = TRUE;
+#endif
 
   if (redraw_mask & REDRAW_ALL)
   {
@@ -140,29 +99,24 @@ void BackToFront()
 
   if (redraw_mask & REDRAW_FIELD)
   {
-    int fx = FX, fy = FY;
-
-    if (soft_scrolling_on)
+    if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
+      XCopyArea(display,backbuffer,window,gc,
+               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+               REAL_SX,REAL_SY);
+    else
     {
-      fx += (PlayerMovDir & (MV_LEFT|MV_RIGHT) ? ScreenMovPos : 0);
-      fy += (PlayerMovDir & (MV_UP|MV_DOWN)    ? ScreenMovPos : 0);
-    }
+      int fx = FX, fy = FY;
+
+      if (soft_scrolling_on)
+      {
+       fx += (PlayerMovDir & (MV_LEFT|MV_RIGHT) ? ScreenMovPos : 0);
+       fy += (PlayerMovDir & (MV_UP|MV_DOWN)    ? ScreenMovPos : 0);
+      }
 
-    if (game_status == PLAYING && !(redraw_mask & REDRAW_FROM_BACKBUFFER))
-    {
       XCopyArea(display,buffer,window,gc,
                fx,fy, SXSIZE,SYSIZE,
                SX,SY);
-
-      /*
-      printf("FULL SCREEN REDRAW / ScreenMovPos == %d\n", ScreenMovPos);
-      */
-
     }
-    else
-      XCopyArea(display,backbuffer,window,gc,
-               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
-               REAL_SX,REAL_SY);
     redraw_mask &= ~REDRAW_MAIN;
   }
 
@@ -232,7 +186,6 @@ void BackToFront()
 
 void FadeToFront()
 {
-
 /*
   long fading_delay = 300000;
 
@@ -391,11 +344,6 @@ void DrawPlayerField()
   if (PlayerGone)
     return;
 
-  /*
-  printf("INFO: DrawPlayerField(): x = %d, y = %d\n",x,y);
-  */
-
-
 #if DEBUG
   if (!IN_LEV_FIELD(x,y) || !IN_SCR_FIELD(sx,sy))
   {
@@ -460,39 +408,21 @@ void DrawPlayerField()
   graphic += PlayerFrame;
 
 
-  if (PlayerMovPos)
+  if (PlayerGfxPos)
   {
     if (PlayerMovDir == MV_LEFT || PlayerMovDir == MV_RIGHT)
-      sxx = PlayerMovPos;
+      sxx = PlayerGfxPos;
     else
-      syy = PlayerMovPos;
+      syy = PlayerGfxPos;
   }
 
-#if 0
-  if (!soft_scrolling_on)
-  {
-    int old_scroll_x=scroll_x, old_scroll_y=scroll_y;
-    int new_scroll_x=scroll_x, new_scroll_y=scroll_y;
-    int offset = (scroll_delay_on ? 3 : 0);
 
-    if ((scroll_x < lastJX-MIDPOSX-offset || scroll_x > lastJX-MIDPOSX+offset) &&
-       lastJX>=MIDPOSX-1-offset && lastJX<=lev_fieldx-(MIDPOSX-offset))
-      new_scroll_x = lastJX-MIDPOSX + (scroll_x < lastJX-MIDPOSX ? -offset : offset);
-    if ((scroll_y < lastJY-MIDPOSY-offset || scroll_y > lastJY-MIDPOSY+offset) &&
-       JY>=MIDPOSY-1-offset && JY<=lev_fieldy-(MIDPOSY-offset))
-      new_scroll_y = lastJY-MIDPOSY + (scroll_y < lastJY-MIDPOSY ? -offset : offset);
+  if (!soft_scrolling_on && ScreenMovPos)
+    sxx = syy = 0;
+
 
-    if (new_scroll_x!=old_scroll_x || new_scroll_y!=old_scroll_y)
-      /*
-      ScrollLevel(old_scroll_x-scroll_x,old_scroll_y-scroll_y);
-      */
-      sxx = syy = 0;
-  }
-#endif
 
 
-  if (!soft_scrolling_on && ScreenMovPos)
-    sxx = syy = 0;
 
 
   if (draw_thru_mask)
@@ -508,7 +438,11 @@ void DrawPlayerField()
 
 
 
-  if (PlayerPushing && PlayerMovPos)
+  MarkTileDirty(sx,sy);
+
+
+
+  if (PlayerPushing && PlayerGfxPos)
   {
     int nextJX = JX + (JX - lastJX);
     int nextJY = JY + (JY - lastJY);
@@ -520,9 +454,29 @@ void DrawPlayerField()
                                 GFX_SOKOBAN_OBJEKT,
                                 CUT_NO_CUTTING);
     else
-      DrawGraphicShifted(px,py,sxx,syy,
-                        el2gfx(Feld[nextJX][nextJY]),
-                        CUT_NO_CUTTING);
+    {
+      int element = Feld[nextJX][nextJY];
+      int graphic = el2gfx(element);
+
+      if (element == EL_FELSBROCKEN && sxx)
+      {
+       int phase = (PlayerGfxPos / (TILEX/4));
+
+       if (PlayerMovDir == MV_LEFT)
+         graphic += phase;
+       else
+         graphic += (phase+4)%4;
+
+
+       /*
+       printf("----> (%d, %d, %d)\n",
+              PlayerGfxPos, phase, graphic);
+              */
+
+      }
+
+      DrawGraphicShifted(px,py, sxx,syy, graphic, CUT_NO_CUTTING);
+    }
   }
 
 
@@ -535,12 +489,12 @@ void DrawPlayerField()
 
     if (element == EL_DYNAMIT)
     {
-      if ((phase = (48-MovDelay[x][y])/6) > 6)
+      if ((phase = (96-MovDelay[x][y])/12) > 6)
        phase = 6;
     }
     else
     {
-      if ((phase = ((48-MovDelay[x][y])/3) % 8) > 3)
+      if ((phase = ((96-MovDelay[x][y])/6) % 8) > 3)
        phase = 7-phase;
     }
 
@@ -551,9 +505,19 @@ void DrawPlayerField()
   {
     int dest_x = SX+SCROLLX(x)*TILEX;
     int dest_y = SY+SCROLLY(y)*TILEY;
+    int x_size = TILEX;
+    int y_size = TILEY;
+
+    if (!ScreenMovPos)
+    {
+      dest_x = SX + SCROLLX(MIN(JX,lastJX))*TILEX;
+      dest_y = SY + SCROLLY(MIN(JY,lastJY))*TILEY;
+      x_size = TILEX * (1 + ABS(JX - lastJX));
+      y_size = TILEY * (1 + ABS(JY - lastJY));
+    }
 
     XCopyArea(display,drawto_field,window,gc,
-             dest_x,dest_y, TILEX,TILEY, dest_x,dest_y);
+             dest_x,dest_y, x_size,y_size, dest_x,dest_y);
     SetDrawtoField(DRAW_DIRECT);
   }
 }
@@ -571,6 +535,9 @@ static int getGraphicAnimationPhase(int frames, int delay, int mode)
   else
     phase = (FrameCounter % (delay * frames)) / delay;
 
+  if (mode == ANIM_REVERSE)
+    phase = -phase;
+
   return(phase);
 }
 
@@ -579,19 +546,6 @@ void DrawGraphicAnimation(int x, int y, int graphic,
 {
   int phase = getGraphicAnimationPhase(frames, delay, mode);
 
-/*
-  int phase;
-
-  if (mode == ANIM_OSCILLATE)
-  {
-    int max_anim_frames = frames*2 - 2;
-    phase = (FrameCounter % (delay * max_anim_frames)) / delay;
-    phase = (phase < frames ? phase : max_anim_frames - phase);
-  }
-  else
-    phase = (FrameCounter % (delay * frames)) / delay;
-*/
-
   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
     DrawGraphic(SCROLLX(x),SCROLLY(y), graphic + phase);
 }
@@ -609,9 +563,7 @@ void DrawGraphic(int x, int y, int graphic)
 #endif
 
   DrawGraphicExt(drawto_field, gc, x, y, graphic);
-  redraw_tiles++;
-  redraw[redraw_x1 + x][redraw_y1 + y] = TRUE;
-  redraw_mask |= REDRAW_TILES;
+  MarkTileDirty(x,y);
 }
 
 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
@@ -693,9 +645,7 @@ void DrawGraphicThruMask(int x, int y, int graphic)
     return;
   }
 
-  redraw_tiles++;
-  redraw[redraw_x1 + x][redraw_y1 + y]=TRUE;
-  redraw_mask|=REDRAW_TILES;
+  MarkTileDirty(x,y);
 }
 
 void DrawElementThruMask(int x, int y, int element)
@@ -706,9 +656,7 @@ void DrawElementThruMask(int x, int y, int element)
 void DrawMiniGraphic(int x, int y, int graphic)
 {
   DrawMiniGraphicExt(drawto, gc, x, y, graphic);
-  redraw_tiles++;
-  redraw[x/2][y/2]=TRUE;
-  redraw_mask|=REDRAW_TILES;
+  MarkTileDirty(x/2, y/2);
 }
 
 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
@@ -774,7 +722,7 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int cut_mode)
     else if (x==BX2 && dx>0)   /* Element verläßt rechts das Bild */
       width -= dx;
     else if (dx)               /* allg. Bewegung in x-Richtung */
-      redraw[redraw_x1 + x + SIGN(dx)][redraw_y1 + y] = TRUE;
+      MarkTileDirty(x + SIGN(dx), y);
 
     if (y < BY1)               /* Element kommt von oben ins Bild */
     {
@@ -806,12 +754,12 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int cut_mode)
       height = dy;
       cy = TILEY-dy;
       dy = TILEY;
-      redraw[redraw_x1 + x][redraw_y1 + y + 1] = TRUE;
+      MarkTileDirty(x, y + 1);
     }                          /* Element verläßt unten das Bild */
     else if (dy > 0 && (y == BY2 || cut_mode==CUT_BELOW))
       height -= dy;
     else if (dy)               /* allg. Bewegung in y-Richtung */
-      redraw[redraw_x1 + x][redraw_y1 + y + SIGN(dy)] = TRUE;
+      MarkTileDirty(x, y + SIGN(dy));
   }
 
   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
@@ -840,9 +788,7 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int cut_mode)
   }
 #endif
 
-  redraw_tiles++;
-  redraw[redraw_x1 + x][redraw_y1 + y] = TRUE;
-  redraw_mask |= REDRAW_TILES;
+  MarkTileDirty(x,y);
 }
 
 void DrawElementShifted(int x, int y, int dx, int dy, int element,int cut_mode)
@@ -968,7 +914,7 @@ void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
     else if (x==BX2 && dx>0)   /* Element verläßt rechts das Bild */
       width -= dx;
     else if (dx)               /* allg. Bewegung in x-Richtung */
-      redraw[redraw_x1 + x + SIGN(dx)][redraw_y1 + y] = TRUE;
+      MarkTileDirty(x + SIGN(dx), y);
 
     if (y < BY1)               /* Element kommt von oben ins Bild */
     {
@@ -1000,12 +946,12 @@ void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
       height = dy;
       cy = TILEY-dy;
       dy = TILEY;
-      redraw[redraw_x1 + x][redraw_y1 + y + 1] = TRUE;
+      MarkTileDirty(x, y + 1);
     }                          /* Element verläßt unten das Bild */
     else if (dy > 0 && (y == BY2 || cut_mode==CUT_BELOW))
       height -= dy;
     else if (dy)               /* allg. Bewegung in y-Richtung */
-      redraw[redraw_x1 + x][redraw_y1 + y + SIGN(dy)] = TRUE;
+      MarkTileDirty(x, y + SIGN(dy));
   }
 
   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
@@ -1043,9 +989,7 @@ void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
   }
 #endif
 
-  redraw_tiles++;
-  redraw[redraw_x1 + x][redraw_y1 + y] = TRUE;
-  redraw_mask |= REDRAW_TILES;
+  MarkTileDirty(x,y);
 }
 
 void ErdreichAnbroeckeln(int x, int y)
@@ -1113,8 +1057,7 @@ void ErdreichAnbroeckeln(int x, int y)
                width,height, FX+x*TILEX+cx,FY+y*TILEY+cy);
     }
 
-    redraw_tiles++;
-    redraw[redraw_x1 + x][redraw_y1 + y] = TRUE;
+    MarkTileDirty(x,y);
   }
   else
   {
@@ -1158,8 +1101,7 @@ void ErdreichAnbroeckeln(int x, int y)
                SY+(graphic / GFX_PER_LINE)*TILEY+cy,
                width,height, FX+xx*TILEX+cx,FY+yy*TILEY+cy);
 
-      redraw_tiles++;
-      redraw[redraw_x1 + xx][redraw_y1 + yy] = TRUE;
+      MarkTileDirty(xx,yy);
     }
   }
 }
@@ -1281,10 +1223,6 @@ void DrawMiniElement(int x, int y, int element)
 
   graphic = el2gfx(element);
   DrawMiniGraphic(x,y,graphic);
-
-  redraw_tiles++;
-  redraw[x/2][y/2]=TRUE;
-  redraw_mask|=REDRAW_TILES;
 }
 
 void DrawMiniElementOrWall(int x, int y, int scroll_x, int scroll_y)
@@ -1533,10 +1471,16 @@ BOOL AreYouSure(char *text, unsigned int ays_state)
              break;
          }
          break;
+       case KeyRelease:
+         key_joystick_mapping = 0;
+         break;
        case FocusIn:
        case FocusOut:
          HandleFocusEvent((XFocusChangeEvent *) &event);
          break;
+        case ClientMessage:
+         HandleClientMessageEvent((XClientMessageEvent *) &event);
+         break;
        default:
          break;
       }
@@ -1585,10 +1529,6 @@ unsigned int OpenDoor(unsigned int door_state)
 
   new_door_state = MoveDoor(door_state);
 
-/*
-  ClearEventQueue();
-*/
-
   return(new_door_state);
 }
 
@@ -1603,10 +1543,6 @@ unsigned int CloseDoor(unsigned int door_state)
 
   new_door_state = MoveDoor(door_state);
 
-/*
-  ClearEventQueue();
-*/
-
   return(new_door_state);
 }
 
@@ -1619,7 +1555,9 @@ unsigned int MoveDoor(unsigned int door_state)
 {
   static unsigned int door1 = DOOR_OPEN_1;
   static unsigned int door2 = DOOR_CLOSE_2;
-  int x, start, stepsize = 4, door_anim_delay = stepsize*5000;
+  static long door_delay = 0;
+  int x, start, stepsize = 2;
+  long door_delay_value = stepsize * 5000;
 
   if (door_state == DOOR_GET_STATE)
     return(door1 | door2);
@@ -1636,7 +1574,7 @@ unsigned int MoveDoor(unsigned int door_state)
   if (quick_doors)
   {
     stepsize = 20;
-    door_anim_delay = 0;
+    door_delay_value = 0;
     StopSound(SND_OEFFNEN);
   }
 
@@ -1647,8 +1585,11 @@ unsigned int MoveDoor(unsigned int door_state)
 
     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
 
-    for(x=start;x<=DXSIZE;x+=stepsize)
+    for(x=start; x<=DXSIZE; x+=stepsize)
     {
+      while(!DelayReached(&door_delay, door_delay_value/10000))
+       Delay(1000);
+
       if (door_state & DOOR_ACTION_1)
       {
        int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
@@ -1724,7 +1665,6 @@ unsigned int MoveDoor(unsigned int door_state)
       }
 
       BackToFront();
-      Delay(door_anim_delay);
 
       if (game_status==MAINMENU)
        DoAnimation();