rnd-19990122-2
[rocksndiamonds.git] / src / tools.c
index d2fd2c6a6189cf2ec974f5e105d38169116061c7..900e5ef7078e610454db0973d6b92b0e898d237d 100644 (file)
@@ -122,10 +122,26 @@ void BackToFront()
       }
 
       if (setup.soft_scrolling ||
-         ABS(ScreenGfxPos) + ScrollStepSize == TILEX ||
-         ABS(ScreenGfxPos) == ScrollStepSize ||
+         ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
+         ABS(ScreenMovPos) == ScrollStepSize ||
          redraw_tiles > REDRAWTILES_THRESHOLD)
+      {
        XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
+
+#ifdef DEBUG
+#if 0
+       printf("redrawing all (ScreenGfxPos == %d) because %s\n",
+              ScreenGfxPos,
+              (setup.soft_scrolling ?
+               "setup.soft_scrolling" :
+               ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
+               "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
+               ABS(ScreenGfxPos) == ScrollStepSize ?
+               "ABS(ScreenGfxPos) == ScrollStepSize" :
+               "redraw_tiles > REDRAWTILES_THRESHOLD"));
+#endif
+#endif
+      }
     }
     redraw_mask &= ~REDRAW_MAIN;
   }
@@ -168,15 +184,20 @@ void BackToFront()
     redraw_mask &= ~REDRAW_DOORS;
   }
 
-  if (redraw_mask & REDRAW_MICROLEV)
+  if (redraw_mask & REDRAW_MICROLEVEL)
   {
     XCopyArea(display,backbuffer,window,gc,
-             MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
-             MICROLEV_XPOS,MICROLEV_YPOS);
+             MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
+             MICROLEV_XPOS, MICROLEV_YPOS);
+    redraw_mask &= ~REDRAW_MICROLEVEL;
+  }
+
+  if (redraw_mask & REDRAW_MICROLEVEL_LABEL)
+  {
     XCopyArea(display,backbuffer,window,gc,
-             SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
-             SX,MICROLABEL_YPOS);
-    redraw_mask &= ~REDRAW_MICROLEV;
+             SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
+             SX, MICROLABEL_YPOS);
+    redraw_mask &= ~REDRAW_MICROLEVEL_LABEL;
   }
 
   if (redraw_mask & REDRAW_TILES)
@@ -333,6 +354,7 @@ void DrawTextExt(Drawable d, GC gc, int x, int y,
 {
   int font_width, font_height, font_start;
   int font_pixmap;
+  boolean print_inverse = FALSE;
 
   if (font_size != FS_SMALL && font_size != FS_BIG)
     font_size = FS_SMALL;
@@ -348,10 +370,16 @@ void DrawTextExt(Drawable d, GC gc, int x, int y,
   font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
                FONT_LINES_PER_FONT);
 
-  while(*text)
+  while (*text)
   {
     char c = *text++;
 
+    if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
+    {
+      print_inverse = TRUE;
+      continue;
+    }
+
     if (c >= 'a' && c <= 'z')
       c = 'A' + (c - 'a');
     else if (c == 'ä' || c == 'Ä')
@@ -362,10 +390,27 @@ void DrawTextExt(Drawable d, GC gc, int x, int y,
       c = 93;
 
     if (c >= 32 && c <= 95)
-      XCopyArea(display, pix[font_pixmap], d, gc,
-               ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
-               ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
-               font_width, font_height, x, y);
+    {
+      int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
+      int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
+      int dest_x = x, dest_y = y;
+
+      if (print_inverse)
+      {
+       XCopyArea(display, pix[font_pixmap], d, gc,
+                 FONT_CHARS_PER_LINE * font_width,
+                 3 * font_height + font_start,
+                 font_width, font_height, x, y);
+
+       XSetClipOrigin(display, clip_gc[font_pixmap],
+                      dest_x - src_x, dest_y - src_y);
+       XCopyArea(display, pix[font_pixmap], drawto, clip_gc[font_pixmap],
+                 0, 0, font_width, font_height, dest_x, dest_y);
+      }
+      else
+       XCopyArea(display, pix[font_pixmap], d, gc,
+                 src_x, src_y, font_width, font_height, dest_x, dest_y);
+    }
 
     x += font_width;
   }
@@ -527,7 +572,10 @@ void DrawPlayer(struct PlayerInfo *player)
        phase = 7 - phase;
     }
 
-    DrawGraphicThruMask(sx, sy, graphic + phase);
+    if (game_emulation == EMU_SUPAPLEX)
+      DrawGraphic(sx, sy, GFX_SP_DISK_RED);
+    else
+      DrawGraphicThruMask(sx, sy, graphic + phase);
   }
 
   if ((last_jx != jx || last_jy != jy) &&
@@ -920,13 +968,14 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
 {
   int ux = LEVELX(x), uy = LEVELY(y);
   int graphic = el2gfx(element);
-  int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
-  int phase  = phase4 / 2;
+  int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
+  int phase4 = phase8 / 2;
+  int phase2  = phase8 / 4;
   int dir = MovDir[ux][uy];
 
   if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
   {
-    graphic += 4*!phase;
+    graphic += 4 * !phase2;
 
     if (dir == MV_UP)
       graphic += 1;
@@ -935,6 +984,23 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
     else if (dir == MV_DOWN)
       graphic += 3;
   }
+  else if (element == EL_SP_SNIKSNAK)
+  {
+    if (dir == MV_LEFT)
+      graphic = GFX_SP_SNIKSNAK_LEFT;
+    else if (dir == MV_RIGHT)
+      graphic = GFX_SP_SNIKSNAK_RIGHT;
+    else if (dir == MV_UP)
+      graphic = GFX_SP_SNIKSNAK_UP;
+    else
+      graphic = GFX_SP_SNIKSNAK_DOWN;
+
+    graphic += (phase8 < 4 ? phase8 : 7 - phase8);
+  }
+  else if (element == EL_SP_ELECTRON)
+  {
+    graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
+  }
   else if (element == EL_MAULWURF || element == EL_PINGUIN ||
           element == EL_SCHWEIN || element == EL_DRACHE)
   {
@@ -967,16 +1033,17 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
   }
   else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
   {
-    graphic += !phase;
+    graphic += !phase2;
   }
   else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
   {
-    graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
+    if (element != EL_SP_INFOTRON)
+      graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
   }
-  else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
-           element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
+  else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
+          element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
   {
-    graphic += 3 - (SiebAktiv % 8) / 2;
+    graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
   }
   else if (IS_AMOEBOID(element))
   {
@@ -1167,7 +1234,12 @@ void DrawScreenField(int x, int y)
 
   if (!IN_LEV_FIELD(ux, uy))
   {
-    DrawScreenElement(x, y, EL_BETON);
+    if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
+      element = EL_LEERRAUM;
+    else
+      element = BorderElement;
+
+    DrawScreenElement(x, y, element);
     return;
   }
 
@@ -1292,10 +1364,13 @@ void DrawMicroElement(int xpos, int ypos, int element)
   graphic = el2gfx(element);
 
   if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
+  {
+    graphic -= GFX_START_ROCKSMORE;
     XCopyArea(display, pix[PIX_MORE], drawto, gc,
              MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
              MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
              MICRO_TILEX, MICRO_TILEY, xpos, ypos);
+  }
   else
     XCopyArea(display, pix[PIX_BACK], drawto, gc,
              MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
@@ -1324,49 +1399,120 @@ void DrawMiniLevel(int scroll_x, int scroll_y)
 {
   int x,y;
 
-  ClearWindow();
-
-  for(x=0; x<2*SCR_FIELDX; x++)
-    for(y=0; y<2*SCR_FIELDY; y++)
+  for(x=0; x<ED_FIELDX; x++)
+    for(y=0; y<ED_FIELDY; y++)
       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
 
   redraw_mask |= REDRAW_FIELD;
 }
 
-void DrawMicroLevel(int xpos, int ypos)
+static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
 {
-  int x,y;
+  int x, y;
+
+  /* determine border element for this level */
+  SetBorderElement();
 
   XFillRectangle(display, drawto, gc,
-                xpos - MICRO_TILEX, ypos - MICRO_TILEY,
-                MICRO_TILEX * (STD_LEV_FIELDX + 2),
-                MICRO_TILEY * (STD_LEV_FIELDY + 2));
+                xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
+
   if (lev_fieldx < STD_LEV_FIELDX)
-    xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
+    xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
   if (lev_fieldy < STD_LEV_FIELDY)
-    ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
+    ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
+
+  xpos += MICRO_TILEX;
+  ypos += MICRO_TILEY;
 
   for(x=-1; x<=STD_LEV_FIELDX; x++)
+  {
     for(y=-1; y<=STD_LEV_FIELDY; y++)
-      if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
+    {
+      int lx = from_x + x, ly = from_y + y;
+
+      if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
        DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
-                        Ur[x][y]);
-      else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
+                        Ur[lx][ly]);
+      else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
        DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
-                        EL_BETON);
+                        BorderElement);
+    }
+  }
 
-  XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
+  redraw_mask |= REDRAW_MICROLEVEL;
+}
+
+void DrawMicroLevel(int xpos, int ypos, boolean restart)
+{
+  static unsigned long scroll_delay = 0;
+  static int from_x, from_y, scroll_direction;
 
-  if (level.name)
+  if (restart)
   {
-    int len = strlen(level.name);
-    int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
-    int lypos = MICROLABEL_YPOS;
+    from_x = from_y = 0;
+    scroll_direction = MV_RIGHT;
+
+    DrawMicroLevelExt(xpos, ypos, from_x, from_y);
+
+    XFillRectangle(display, drawto,gc,
+                  SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
 
-    DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
+    if (level.name && restart)
+    {
+      int len = strlen(level.name);
+      int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
+      int lypos = MICROLABEL_YPOS;
+
+      DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
+    }
+
+    /* initialize delay counter */
+    DelayReached(&scroll_delay, 0);
+
+    redraw_mask |= REDRAW_MICROLEVEL_LABEL;
   }
+  else
+  {
+    if ((lev_fieldx <= STD_LEV_FIELDX && lev_fieldy <= STD_LEV_FIELDY) ||
+       !DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
+      return;
 
-  redraw_mask |= REDRAW_MICROLEV;
+    switch (scroll_direction)
+    {
+      case MV_LEFT:
+       if (from_x > 0)
+         from_x--;
+       else
+         scroll_direction = MV_UP;
+       break;
+
+      case MV_RIGHT:
+       if (from_x < lev_fieldx - STD_LEV_FIELDX)
+         from_x++;
+       else
+         scroll_direction = MV_DOWN;
+       break;
+
+      case MV_UP:
+       if (from_y > 0)
+         from_y--;
+       else
+         scroll_direction = MV_RIGHT;
+       break;
+
+      case MV_DOWN:
+       if (from_y < lev_fieldy - STD_LEV_FIELDY)
+         from_y++;
+       else
+         scroll_direction = MV_LEFT;
+       break;
+
+      default:
+       break;
+    }
+
+    DrawMicroLevelExt(xpos, ypos, from_x, from_y);
+  }
 }
 
 int REQ_in_range(int x, int y)
@@ -1832,6 +1978,7 @@ int el2gfx(int element)
     case EL_MORAST_VOLL:       return GFX_MORAST_VOLL;
     case EL_TROPFEN:           return GFX_TROPFEN;
     case EL_BOMBE:             return GFX_BOMBE;
+    case EL_SIEB_INAKTIV:      return GFX_SIEB_INAKTIV;
     case EL_SIEB_LEER:         return GFX_SIEB_LEER;
     case EL_SIEB_VOLL:         return GFX_SIEB_VOLL;
     case EL_SIEB_TOT:          return GFX_SIEB_TOT;
@@ -1892,6 +2039,7 @@ int el2gfx(int element)
     case EL_ERZ_EDEL_ROT:      return GFX_ERZ_EDEL_ROT;
     case EL_ERZ_EDEL_LILA:     return GFX_ERZ_EDEL_LILA;
     case EL_MAMPFER2:          return GFX_MAMPFER2;
+    case EL_SIEB2_INAKTIV:     return GFX_SIEB2_INAKTIV;
     case EL_SIEB2_LEER:                return GFX_SIEB2_LEER;
     case EL_SIEB2_VOLL:                return GFX_SIEB2_VOLL;
     case EL_SIEB2_TOT:         return GFX_SIEB2_TOT;
@@ -1911,12 +2059,25 @@ int el2gfx(int element)
     case EL_PFEIL_R:           return GFX_PFEIL_R;
     case EL_PFEIL_O:           return GFX_PFEIL_O;
     case EL_PFEIL_U:           return GFX_PFEIL_U;
+    case EL_SPEED_PILL:                return GFX_SPEED_PILL;
+    case EL_SP_TERMINAL_ACTIVE:        return GFX_SP_TERMINAL;
+    case EL_SP_BUG_ACTIVE:     return GFX_SP_BUG_ACTIVE;
+    case EL_INVISIBLE_STEEL:   return GFX_INVISIBLE_STEEL;
+
     default:
     {
       if (IS_CHAR(element))
        return GFX_CHAR_START + (element - EL_CHAR_START);
       else if (element >= EL_SP_START && element <= EL_SP_END)
-       return GFX_START_ROCKSMORE + (element - EL_SP_START);
+      {
+       int nr_element = element - EL_SP_START;
+       int gfx_per_line = 8;
+       int nr_graphic =
+         (nr_element / gfx_per_line) * MORE_PER_LINE +
+         (nr_element % gfx_per_line);
+
+       return GFX_START_ROCKSMORE + nr_graphic;
+      }
       else
        return -1;
     }