added showing scrolling title screen background for native BD cavesets
authorHolger Schemel <info@artsoft.org>
Thu, 4 Apr 2024 18:31:13 +0000 (20:31 +0200)
committerHolger Schemel <info@artsoft.org>
Thu, 4 Apr 2024 18:31:15 +0000 (20:31 +0200)
src/game_bd/bd_graphics.c
src/game_bd/bd_graphics.h
src/game_bd/export_bd.h
src/game_bd/main_bd.c
src/screens.c

index 2dce22248f7dbf09cbd0900d58cbd8f8f4c3460e..fe2e6b45b87ef1dd191dfe66bb81331d987c2830 100644 (file)
@@ -44,8 +44,8 @@ static Bitmap *gd_tile_bitmap = NULL;
 // pointer to reference tile bitmap (without level-specific colors)
 static Bitmap *gd_tile_bitmap_reference = NULL;
 
-// optional title screen bitmap
-static Bitmap *gd_title_screen_bitmap = NULL;
+// optional title screen bitmaps (foreground and background)
+static Bitmap *gd_title_screen_bitmaps[2] = { NULL, NULL };
 
 // screen area
 Bitmap *gd_screen_bitmap = NULL;
@@ -780,60 +780,66 @@ static SDL_Surface *get_surface_from_base64(const char *base64_data)
   return surface;
 }
 
-static SDL_Surface *get_title_screen_surface(void)
+static SDL_Surface *get_title_screen_background_surface(SDL_Surface *tile)
 {
-  if (gd_caveset_data == NULL || gd_caveset_data->title_screen == NULL)
+  if (tile == NULL)
     return NULL;
 
-  SDL_Surface *surface = get_surface_from_base64(gd_caveset_data->title_screen);
+  SDL_Surface *foreground_surface = gd_title_screen_bitmaps[0]->surface_masked;
 
-  if (surface == NULL)
+  // if foreground image has no transparency, no background image needed
+  if (foreground_surface->format->Amask == 0)
     return NULL;
 
-  // create target surface
-  SDL_Surface *target = SDL_CreateRGBSurface(0, surface->w, surface->h, 32, 0, 0, 0, 0);
+  // use foreground image size for background image size
+  int w = foreground_surface->w;
+  int h = foreground_surface->h + tile->h;     // background is one scrolling tile higher
 
-  // check for transparency and background tile
-  if (surface->format->Amask != 0 && gd_caveset_data->title_screen_scroll != NULL)
-  {
-    SDL_Surface *tile = get_surface_from_base64(gd_caveset_data->title_screen_scroll);
+  // create background surface
+  SDL_Surface *back = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0);
+  int x, y;
 
-    if (tile != NULL)
-    {
-      int x, y;
+  // fill background surface with tile
+  for (y = 0; y < h; y += tile->h)
+    for (x = 0; x < w; x += tile->w)
+      SDLBlitSurface(tile, back, 0, 0, tile->w, tile->h, x, y);
 
-      // create background surface
-      SDL_Surface *back = SDL_CreateRGBSurface(0, surface->w, surface->h, 32, 0, 0, 0, 0);
+  // background tile surface not needed anymore
+  SDL_FreeSurface(tile);
 
-      // fill background surface with tile
-      for (y = 0; y < surface->h; y += tile->h)
-        for (x = 0; x < surface->w; x += tile->w)
-         SDLBlitSurface(tile, back, 0, 0, tile->w, tile->h, x, y);
+  return back;
+}
 
-      // copy masked screen over background surface
-      SDLBlitSurface(back, target, 0, 0, surface->w, surface->h, 0, 0);
+static SDL_Surface *get_title_screen_surface(int nr)
+{
+  if (gd_caveset_data == NULL)
+    return NULL;
 
-      // free temporary surfaces
-      SDL_FreeSurface(tile);
-      SDL_FreeSurface(back);
-    }
-  }
+  // do not use title screen background without foreground image
+  if (nr == 1 && gd_title_screen_bitmaps[0] == NULL)
+    return NULL;
 
-  SDLBlitSurface(surface, target, 0, 0, surface->w, surface->h, 0, 0);
+  char *data = (nr == 0 ? gd_caveset_data->title_screen : gd_caveset_data->title_screen_scroll);
 
-  SDL_FreeSurface(surface);
+  if (data == NULL)
+    return NULL;
+
+  SDL_Surface *surface = get_surface_from_base64(data);
+
+  if (surface == NULL)
+    return NULL;
 
-  return target;
+  return (nr == 0 ? surface : get_title_screen_background_surface(surface));
 }
 
-static void set_title_screen_bitmap(void)
+static void set_title_screen_bitmap(int nr)
 {
-  if (gd_title_screen_bitmap != NULL)
-    FreeBitmap(gd_title_screen_bitmap);
+  if (gd_title_screen_bitmaps[nr] != NULL)
+    FreeBitmap(gd_title_screen_bitmaps[nr]);
 
-  gd_title_screen_bitmap = NULL;
+  gd_title_screen_bitmaps[nr] = NULL;
 
-  SDL_Surface *surface = get_title_screen_surface();
+  SDL_Surface *surface = get_title_screen_surface(nr);
 
   if (surface == NULL)
     return;
@@ -842,13 +848,21 @@ static void set_title_screen_bitmap(void)
   int height_scaled = surface->h * 2;
   SDL_Surface *surface_scaled = SDLZoomSurface(surface, width_scaled, height_scaled);
 
-  gd_title_screen_bitmap = SDLGetBitmapFromSurface(surface_scaled);
+  gd_title_screen_bitmaps[nr] = SDLGetBitmapFromSurface(surface_scaled);
 
   SDL_FreeSurface(surface);
   SDL_FreeSurface(surface_scaled);
 }
 
-Bitmap *gd_get_title_screen_bitmap(void)
+static void set_title_screen_bitmaps(void)
+{
+  int i;
+
+  for (i = 0; i < 2; i++)
+    set_title_screen_bitmap(i);
+}
+
+Bitmap **gd_get_title_screen_bitmaps(void)
 {
   static char *levelset_subdir_last = NULL;
 
@@ -861,9 +875,9 @@ Bitmap *gd_get_title_screen_bitmap(void)
 
   // check if stored cave set has changed
   if (!strEqual(gd_caveset_data->levelset_subdir, levelset_subdir_last))
-    set_title_screen_bitmap();
+    set_title_screen_bitmaps();
 
   setString(&levelset_subdir_last, gd_caveset_data->levelset_subdir);
 
-  return gd_title_screen_bitmap;
+  return gd_title_screen_bitmaps;
 }
index ce38a7e03cd8c221fdea271c0013b2af8ef146da..dd9eed1ab1c66637d3a814fc7ff0c057e1c56e9b 100644 (file)
@@ -45,6 +45,6 @@ void gd_scroll_to_origin(void);
 int get_scroll_x(void);
 int get_scroll_y(void);
 
-Bitmap *gd_get_title_screen_bitmap(void);
+Bitmap **gd_get_title_screen_bitmaps(void);
 
 #endif // BD_GRAPHICS_H
index 3b8c77217a1db58881156841286f321035070df1..688d506ef9072309a2c8537c18687dd8e2876ed3 100644 (file)
@@ -112,7 +112,7 @@ unsigned int InitEngineRandom_BD(int);
 void InitGameEngine_BD(void);
 void GameActions_BD(byte[MAX_PLAYERS]);
 
-Bitmap *GetTitleScreen_BD(void);
+Bitmap **GetTitleScreenBitmaps_BD(void);
 void CoverScreen_BD(void);
 
 void BlitScreenToBitmap_BD(Bitmap *);
index 77af13a28c158a4e59ce6f43e1607d09af895325..1a7705b6de73795c6a0d15ca25a89a03302a9a34 100644 (file)
@@ -426,9 +426,14 @@ void GameActions_BD(byte action[MAX_PLAYERS])
 // graphics functions
 // ============================================================================
 
-Bitmap *GetTitleScreen_BD(void)
+Bitmap **GetTitleScreenBitmaps_BD(void)
 {
-  return gd_get_title_screen_bitmap();
+  Bitmap **title_screen_bitmaps = gd_get_title_screen_bitmaps();
+
+  if (title_screen_bitmaps == NULL || title_screen_bitmaps[0] == NULL)
+    return NULL;
+
+  return title_screen_bitmaps;
 }
 
 void CoverScreen_BD(void)
index 29e4f3cb7fe53435d4a88343eb94dca0d3b7717d..adeebb132af4e4117bc8d028af9ee42403b3ecb6 100644 (file)
@@ -1119,6 +1119,27 @@ static int compareTitleControlInfo(const void *object1, const void *object2)
   return compare_result;
 }
 
+static boolean CheckTitleScreen_BD(int nr, boolean initial)
+{
+  // only show BD style title screen for native BD level sets
+  if (level.game_engine_type != GAME_ENGINE_TYPE_BD)
+    return FALSE;
+
+  // only show BD style title screen for first title screen of a level set
+  if (initial || nr != 0)
+    return FALSE;
+
+  int graphic = getTitleScreenGraphic(nr, initial);
+  Bitmap *bitmap = graphic_info[graphic].bitmap;
+
+  // only show BD style title screen if no other title screen defined
+  if (bitmap != NULL)
+    return FALSE;
+
+  // check if BD style title screen defined
+  return (GetTitleScreenBitmaps_BD() != NULL);
+}
+
 static void InitializeTitleControlsExt_AddTitleInfo(boolean is_image,
                                                    boolean initial,
                                                    int nr, int sort_priority)
@@ -1145,8 +1166,8 @@ static void InitializeTitleControls_CheckTitleInfo(boolean initial)
     boolean has_title_screen = (bitmap != NULL);
 
     // check for optional title screen of native BD style level set
-    if (!has_title_screen && level.game_engine_type == GAME_ENGINE_TYPE_BD && !initial && i == 0)
-      has_title_screen = (GetTitleScreen_BD() != NULL);
+    if (CheckTitleScreen_BD(i, initial))
+      has_title_screen = TRUE;
 
     if (has_title_screen)
       InitializeTitleControlsExt_AddTitleInfo(TRUE, initial, i, sort_priority);
@@ -1601,8 +1622,10 @@ static void DrawInfoScreen_Headline(int screen_nr, int num_screens,
 
 static void DrawTitleScreenImage(int nr, boolean initial)
 {
+  static int frame_counter = 0;
   int graphic = getTitleScreenGraphic(nr, initial);
   Bitmap *bitmap = graphic_info[graphic].bitmap;
+  Bitmap *bitmap_background = NULL;
   int draw_masked = graphic_info[graphic].draw_masked;
   int width  = graphic_info[graphic].width;
   int height = graphic_info[graphic].height;
@@ -1611,9 +1634,12 @@ static void DrawTitleScreenImage(int nr, boolean initial)
   int dst_x, dst_y;
 
   // check for optional title screen of native BD style level set
-  if (bitmap == NULL && level.game_engine_type == GAME_ENGINE_TYPE_BD && !initial && nr == 0)
+  if (CheckTitleScreen_BD(nr, initial))
   {
-    bitmap = GetTitleScreen_BD();
+    Bitmap **title_screen_bitmaps = GetTitleScreenBitmaps_BD();
+
+    bitmap            = title_screen_bitmaps[0];
+    bitmap_background = title_screen_bitmaps[1];
 
     if (bitmap != NULL)
     {
@@ -1650,7 +1676,19 @@ static void DrawTitleScreenImage(int nr, boolean initial)
 
   ClearRectangleOnBackground(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
 
-  if (DrawingOnBackground(dst_x, dst_y) && draw_masked)
+  boolean draw_masked_final = (DrawingOnBackground(dst_x, dst_y) && draw_masked);
+
+  if (bitmap_background != NULL)
+  {
+    int size = bitmap_background->height - bitmap->height;
+    int offset = frame_counter++ % size;
+
+    BlitBitmap(bitmap_background, drawto, src_x, src_y + offset, width, height, dst_x, dst_y);
+
+    draw_masked_final = TRUE;
+  }
+
+  if (draw_masked_final)
     BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y);
   else
     BlitBitmap(bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y);
@@ -2096,6 +2134,21 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button)
       return_to_main_menu = TRUE;
     }
   }
+  else
+  {
+    tci = &title_controls[title_screen_nr];
+
+    // check for optional title screen of native BD style level set
+    if (tci->is_image && CheckTitleScreen_BD(tci->local_nr, tci->initial))
+    {
+      Bitmap **title_screen_bitmaps = GetTitleScreenBitmaps_BD();
+
+      // if title screen is animated, draw title screen animation
+      if (title_screen_bitmaps[0] != NULL &&
+         title_screen_bitmaps[1] != NULL)
+       DrawTitleScreenImage(tci->local_nr, tci->initial);
+    }
+  }
 
   if (return_to_main_menu)
   {