rnd-20060430-1-src
[rocksndiamonds.git] / src / tools.c
index f9b4f6394e41ce11db31acc447be9493a2835f3a..6f2c96e21840bccbc7aefb193e3f0d710fe6b253 100644 (file)
 #include "network.h"
 #include "tape.h"
 
+
+/* select level set with EMC X11 graphics before activating EM GFX debugging */
+#define DEBUG_EM_GFX   0
+
 /* tool button identifiers */
 #define TOOL_CTRL_ID_YES       0
 #define TOOL_CTRL_ID_NO                1
@@ -63,6 +67,12 @@ void DumpTile(int x, int y)
   int sx = SCREENX(x);
   int sy = SCREENY(y);
 
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  {
+    x--;
+    y--;
+  }
+
   printf_line("-", 79);
   printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
   printf_line("-", 79);
@@ -127,11 +137,9 @@ void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
   if (game_status == GAME_MODE_PLAYING &&
       level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
-#if 1
-    RedrawPlayfield_EM(force_redraw);
-#else
-    BlitScreenToBitmap_EM(backbuffer);
-#endif
+    /* currently there is no partial redraw -- always redraw whole playfield */
+
+    RedrawPlayfield_EM(TRUE);
   }
   else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
   {
@@ -233,7 +241,8 @@ void BackToFront()
   if (redraw_mask & REDRAW_ALL)
   {
     BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-    redraw_mask = 0;
+
+    redraw_mask = REDRAW_NONE;
   }
 
   if (redraw_mask & REDRAW_FIELD)
@@ -405,6 +414,114 @@ void FadeToFront()
   BackToFront();
 }
 
+#define FADE_MODE_FADE_IN      0
+#define FADE_MODE_FADE_OUT     1
+#define FADE_MODE_CROSSFADE    2
+
+static void FadeExt(Bitmap *bitmap_cross, int fade_ms, int fade_mode)
+{
+  SDL_Surface *surface_screen = backbuffer->surface;
+  SDL_Surface *surface_screen_copy = NULL;
+  SDL_Surface *surface_black = NULL;
+  SDL_Surface *surface_cross;          /* initialized later */
+  boolean fade_reverse;                        /* initialized later */
+  unsigned int flags = SDL_SRCALPHA;
+  unsigned int time_last, time_current;
+  float alpha;
+  int alpha_final;
+
+  /* use same surface type as screen surface */
+  if ((surface_screen->flags & SDL_HWSURFACE))
+    flags |= SDL_HWSURFACE;
+  else
+    flags |= SDL_SWSURFACE;
+
+  /* create surface for copy of screen buffer */
+  if ((surface_screen_copy =
+       SDL_CreateRGBSurface(flags,
+                           surface_screen->w,
+                           surface_screen->h,
+                           surface_screen->format->BitsPerPixel,
+                           surface_screen->format->Rmask,
+                           surface_screen->format->Gmask,
+                           surface_screen->format->Bmask,
+                           surface_screen->format->Amask)) == NULL)
+    Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+
+  SDL_BlitSurface(surface_screen, NULL, surface_screen_copy, NULL);
+
+  /* create black surface for fading from/to black */
+  if ((surface_black =
+       SDL_CreateRGBSurface(flags,
+                           surface_screen->w,
+                           surface_screen->h,
+                           surface_screen->format->BitsPerPixel,
+                           surface_screen->format->Rmask,
+                           surface_screen->format->Gmask,
+                           surface_screen->format->Bmask,
+                           surface_screen->format->Amask)) == NULL)
+    Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+
+  SDL_FillRect(surface_black, NULL, SDL_MapRGB(surface_screen->format, 0,0,0));
+
+  fade_reverse = (fade_mode == FADE_MODE_FADE_IN ? TRUE : FALSE);
+  surface_cross = (fade_mode == FADE_MODE_CROSSFADE ? bitmap_cross->surface :
+                  surface_black);
+
+  time_current = SDL_GetTicks();
+
+  for (alpha = 0.0; alpha < 255.0;)
+  {
+    time_last = time_current;
+    time_current = SDL_GetTicks();
+    alpha += 255 * ((float)(time_current - time_last) / fade_ms);
+    alpha_final = (int)(fade_reverse ? 255.0 - alpha : alpha);
+    alpha_final = MIN(MAX(0, alpha_final), 255);
+
+    /* draw existing image to screen buffer */
+    SDL_BlitSurface(surface_screen_copy, NULL, surface_screen, NULL);
+
+    /* draw new image to screen buffer using alpha blending */
+    SDL_SetAlpha(surface_cross, SDL_SRCALPHA, alpha_final);
+    SDL_BlitSurface(surface_cross, NULL, surface_screen, NULL);
+
+    /* draw screen buffer to visible display */
+    SDL_Flip(surface_screen);
+  }
+
+  SDL_FreeSurface(surface_screen_copy);
+  SDL_FreeSurface(surface_black);
+
+  redraw_mask = REDRAW_NONE;
+}
+
+void FadeIn(int fade_ms)
+{
+#ifdef TARGET_SDL
+  FadeExt(NULL, fade_ms, FADE_MODE_FADE_IN);
+#else
+  BackToFront();
+#endif
+}
+
+void FadeOut(int fade_ms)
+{
+#ifdef TARGET_SDL
+  FadeExt(NULL, fade_ms, FADE_MODE_FADE_OUT);
+#else
+  BackToFront();
+#endif
+}
+
+void FadeCross(Bitmap *bitmap, int fade_ms)
+{
+#ifdef TARGET_SDL
+  FadeExt(bitmap, fade_ms, FADE_MODE_CROSSFADE);
+#else
+  BackToFront();
+#endif
+}
+
 void SetMainBackgroundImageIfDefined(int graphic)
 {
   if (graphic_info[graphic].bitmap)
@@ -495,6 +612,17 @@ inline int getGraphicAnimationFrame(int graphic, int sync_frame)
   if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
     sync_frame = FrameCounter;
 
+#if 0
+  if (graphic == element_info[EL_CUSTOM_START + 255].graphic[ACTION_DEFAULT] &&
+      sync_frame == 0 &&
+      FrameCounter > 10)
+  {
+    int x = 1 / 0;
+
+    printf("::: FOO!\n");
+  }
+#endif
+
   return getAnimationFrame(graphic_info[graphic].anim_frames,
                           graphic_info[graphic].anim_delay,
                           graphic_info[graphic].anim_mode,
@@ -1037,6 +1165,8 @@ void DrawLevelFieldCrumbledSand(int x, int y)
     return;
 
 #if 1
+  /* !!! CHECK THIS !!! */
+
   /*
   if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
       GFX_CRUMBLED(GfxElement[x][y]))
@@ -1642,9 +1772,9 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart)
 
   /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
   /* redraw micro level label, if needed */
-  if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
-      strcmp(level.author, ANONYMOUS_NAME) != 0 &&
-      strcmp(level.author, leveldir_current->name) != 0 &&
+  if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
+      !strEqual(level.author, ANONYMOUS_NAME) &&
+      !strEqual(level.author, leveldir_current->name) &&
       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
   {
     int max_label_counter = 23;
@@ -2492,7 +2622,7 @@ unsigned int MoveDoor(unsigned int door_state)
     door_2.height = VYSIZE;
 
   if (door_state == DOOR_GET_STATE)
-    return(door1 | door2);
+    return (door1 | door2);
 
   if (door_state & DOOR_SET_STATE)
   {
@@ -2501,7 +2631,7 @@ unsigned int MoveDoor(unsigned int door_state)
     if (door_state & DOOR_ACTION_2)
       door2 = door_state & DOOR_ACTION_2;
 
-    return(door1 | door2);
+    return (door1 | door2);
   }
 
   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
@@ -2744,13 +2874,15 @@ unsigned int MoveDoor(unsigned int door_state)
        door_2_done = (a == VXSIZE);
       }
 
-      BackToFront();
+      if (!(door_state & DOOR_NO_DELAY))
+      {
+       BackToFront();
 
-      if (game_status == GAME_MODE_MAIN)
-       DoAnimation();
+       if (game_status == GAME_MODE_MAIN)
+         DoAnimation();
 
-      if (!(door_state & DOOR_NO_DELAY))
        WaitUntilDelayReached(&door_delay, door_delay_value);
+      }
     }
   }
 
@@ -4167,19 +4299,19 @@ em_object_mapping_list[] =
     EL_QUICKSAND_FULL,                 -1, -1
   },
   {
-    Xsand_stonein_1,                   FALSE,  FALSE,
+    Xsand_stonein_1,                   FALSE,  TRUE,
     EL_ROCK,                           ACTION_FILLING, -1
   },
   {
-    Xsand_stonein_2,                   FALSE,  FALSE,
+    Xsand_stonein_2,                   FALSE,  TRUE,
     EL_ROCK,                           ACTION_FILLING, -1
   },
   {
-    Xsand_stonein_3,                   FALSE,  FALSE,
+    Xsand_stonein_3,                   FALSE,  TRUE,
     EL_ROCK,                           ACTION_FILLING, -1
   },
   {
-    Xsand_stonein_4,                   FALSE,  FALSE,
+    Xsand_stonein_4,                   FALSE,  TRUE,
     EL_ROCK,                           ACTION_FILLING, -1
   },
   {
@@ -5125,6 +5257,7 @@ int font2baseimg(int font_nr)
   return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
 }
 
+#if 0
 void setCenteredPlayerNr_EM(int centered_player_nr)
 {
   game.centered_player_nr = game.centered_player_nr_next = centered_player_nr;
@@ -5153,6 +5286,7 @@ boolean getSetCenteredPlayer_EM()
 {
   return game.set_centered_player;
 }
+#endif
 
 int getNumActivePlayers_EM()
 {
@@ -5169,6 +5303,7 @@ int getNumActivePlayers_EM()
   return num_players;
 }
 
+#if 1
 int getGameFrameDelay_EM(int native_em_game_frame_delay)
 {
   int game_frame_delay_value;
@@ -5183,6 +5318,7 @@ int getGameFrameDelay_EM(int native_em_game_frame_delay)
 
   return game_frame_delay_value;
 }
+#endif
 
 unsigned int InitRND(long seed)
 {
@@ -5192,8 +5328,6 @@ unsigned int InitRND(long seed)
     return InitEngineRND(seed);
 }
 
-#define DEBUG_EM_GFX   0
-
 void InitGraphicInfo_EM(void)
 {
   struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
@@ -5201,12 +5335,16 @@ void InitGraphicInfo_EM(void)
   int i, j, p;
 
 #if DEBUG_EM_GFX
+  int num_em_gfx_errors = 0;
+
   if (graphic_info_em_object[0][0].bitmap == NULL)
   {
     /* EM graphics not yet initialized in em_open_all() */
 
     return;
   }
+
+  printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
 #endif
 
   /* always start with reliable default values */
@@ -5300,12 +5438,12 @@ void InitGraphicInfo_EM(void)
                               i == Ymagnify_eat ? element :
                               i == Ygrass_eat ? element :
                               i == Ydirt_eat ? element :
-                              i == Yspring_kill_e ? EL_SPRING :
-                              i == Yspring_kill_w ? EL_SPRING :
                               i == Yemerald_stone ? EL_EMERALD :
                               i == Ydiamond_stone ? EL_ROCK :
-                              i == Xsand_stonein_4 ? EL_EMPTY :
-                              i == Xsand_stoneout_2 ? EL_ROCK :
+                              i == Xsand_stonein_1 ? element :
+                              i == Xsand_stonein_2 ? element :
+                              i == Xsand_stonein_3 ? element :
+                              i == Xsand_stonein_4 ? element :
                               is_backside ? EL_EMPTY :
                               action_removing ? EL_EMPTY :
                               element);
@@ -5347,6 +5485,7 @@ void InitGraphicInfo_EM(void)
                                     direction));
       int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
       int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
+      boolean has_action_graphics = (graphic != base_graphic);
       boolean has_crumbled_graphics = (base_crumbled != base_graphic);
       struct GraphicInfo *g = &graphic_info[graphic];
       struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
@@ -5514,23 +5653,43 @@ void InitGraphicInfo_EM(void)
        g_em->crumbled_border_size = graphic_info[crumbled].border_size;
       }
 
-      if (!g->double_movement && (effective_action == ACTION_FALLING ||
-                                 effective_action == ACTION_MOVING  ||
-                                 effective_action == ACTION_PUSHING ||
-                                 effective_action == ACTION_EATING))
+#if 0
+      if (element == EL_ROCK &&
+         effective_action == ACTION_FILLING)
+       printf("::: has_action_graphics == %d\n", has_action_graphics);
+#endif
+
+      if ((!g->double_movement && (effective_action == ACTION_FALLING ||
+                                  effective_action == ACTION_MOVING  ||
+                                  effective_action == ACTION_PUSHING ||
+                                  effective_action == ACTION_EATING)) ||
+         (!has_action_graphics && (effective_action == ACTION_FILLING ||
+                                   effective_action == ACTION_EMPTYING)))
       {
        int move_dir =
-         (effective_action == ACTION_FALLING ? MV_DOWN : direction);
+         (effective_action == ACTION_FALLING ||
+          effective_action == ACTION_FILLING ||
+          effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
        int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
        int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? 1 : 0);
-       int num_steps = (i == Ydrip_s1 ||
-                        i == Ydrip_s1B ||
-                        i == Ydrip_s2 ||
-                        i == Ydrip_s2B ? 16 : 8);
+       int num_steps = (i == Ydrip_s1  ? 16 :
+                        i == Ydrip_s1B ? 16 :
+                        i == Ydrip_s2  ? 16 :
+                        i == Ydrip_s2B ? 16 :
+                        i == Xsand_stonein_1 ? 32 :
+                        i == Xsand_stonein_2 ? 32 :
+                        i == Xsand_stonein_3 ? 32 :
+                        i == Xsand_stonein_4 ? 32 :
+                        i == Xsand_stoneout_1 ? 16 :
+                        i == Xsand_stoneout_2 ? 16 : 8);
        int cx = ABS(dx) * (TILEX / num_steps);
        int cy = ABS(dy) * (TILEY / num_steps);
-       int step_frame = (i == Ydrip_s2 ||
-                         i == Ydrip_s2B ? j + 8 : j) + 1;
+       int step_frame = (i == Ydrip_s2         ? j + 8 :
+                         i == Ydrip_s2B        ? j + 8 :
+                         i == Xsand_stonein_2  ? j + 8 :
+                         i == Xsand_stonein_3  ? j + 16 :
+                         i == Xsand_stonein_4  ? j + 24 :
+                         i == Xsand_stoneout_2 ? j + 8 : j) + 1;
        int step = (is_backside ? step_frame : num_steps - step_frame);
 
        if (is_backside)        /* tile where movement starts */
@@ -5652,6 +5811,8 @@ void InitGraphicInfo_EM(void)
          printf("    %d (%d): size %d,%d should be %d,%d\n",
                 j, is_backside,
                 g_em->width, g_em->height, TILEX, TILEY);
+
+       num_em_gfx_errors++;
       }
 #endif
 
@@ -5798,6 +5959,8 @@ void InitGraphicInfo_EM(void)
                   g_em->src_x / 32, g_em->src_y / 32,
                   debug_src_x, debug_src_y,
                   debug_src_x / 32, debug_src_y / 32);
+
+         num_em_gfx_errors++;
        }
 #endif
 
@@ -5806,6 +5969,9 @@ void InitGraphicInfo_EM(void)
   }
 
 #if DEBUG_EM_GFX
+  printf("\n");
+  printf("::: [%d errors found]\n", num_em_gfx_errors);
+
   exit(0);
 #endif
 }