From 76ae1ac5119938169d8201d94bd44fedaa4e298b Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Wed, 8 Oct 2014 00:06:00 +0200 Subject: [PATCH] fixed bug when changing between graphic sets with different tile size --- ChangeLog | 5 ++ src/conftime.h | 2 +- src/init.c | 26 +++++-- src/libgame/image.c | 48 ++++++++---- src/libgame/image.h | 22 +++++- src/libgame/system.c | 175 +++++++++++++++++++------------------------ src/libgame/system.h | 5 +- src/main.h | 4 +- src/tools.c | 68 ++++------------- 9 files changed, 177 insertions(+), 178 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0011bfac..34e424d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-10-07 + * fixed bug when changing between graphic sets with different tile size + * cleanup of handling the various graphic sizes for different purposes + (like 32x32, 16x16 etc.); this change was needed for the bugfix above + 2014-10-02 * added virtual keyboard on Android port when entering player name diff --git a/src/conftime.h b/src/conftime.h index 72f21842..8190acfe 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "2014-10-02 10:57" +#define COMPILE_DATE_STRING "2014-10-07 23:54" diff --git a/src/init.c b/src/init.c index 83d01ab6..401e59ea 100644 --- a/src/init.c +++ b/src/init.c @@ -153,8 +153,14 @@ void InitGadgets() inline void InitElementSmallImagesScaledUp(int graphic) { - CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor, - graphic_info[graphic].tile_size); + struct GraphicInfo *g = &graphic_info[graphic]; + + // create small and game tile sized bitmaps (and scale up, if needed) + CreateImageWithSmallImages(graphic, g->scale_up_factor, g->tile_size); + + // default (standard sized) bitmap may have changed now -- update it + if (g->bitmaps) + g->bitmap = g->bitmaps[IMG_BITMAP_STANDARD]; } void InitElementSmallImages() @@ -976,9 +982,10 @@ static int get_scaled_graphic_height(int graphic) } static void set_graphic_parameters_ext(int graphic, int *parameter, - Bitmap *src_bitmap) + Bitmap **src_bitmaps) { struct GraphicInfo *g = &graphic_info[graphic]; + Bitmap *src_bitmap = (src_bitmaps ? src_bitmaps[IMG_BITMAP_STANDARD] : NULL); int anim_frames_per_row = 1, anim_frames_per_col = 1; int anim_frames_per_line = 1; @@ -1014,6 +1021,7 @@ static void set_graphic_parameters_ext(int graphic, int *parameter, g->class = 0; g->style = STYLE_DEFAULT; + g->bitmaps = src_bitmaps; g->bitmap = src_bitmap; /* optional zoom factor for scaling up the image to a larger size */ @@ -1263,7 +1271,7 @@ static void set_graphic_parameters(int graphic) { struct FileInfo *image = getImageListEntryFromImageID(graphic); char **parameter_raw = image->parameter; - Bitmap *src_bitmap = getBitmapFromImageID(graphic); + Bitmap **src_bitmaps = getBitmapsFromImageID(graphic); int parameter[NUM_GFX_ARGS]; int i; @@ -1277,7 +1285,7 @@ static void set_graphic_parameters(int graphic) image_config_suffix[i].token, image_config_suffix[i].type); - set_graphic_parameters_ext(graphic, parameter, src_bitmap); + set_graphic_parameters_ext(graphic, parameter, src_bitmaps); UPDATE_BUSY_STATE(); } @@ -5061,11 +5069,15 @@ void InitGfx() if (filename_anim_initial == NULL) /* should not happen */ Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY); - anim_initial.bitmap = LoadCustomImage(filename_anim_initial); + anim_initial.bitmaps = + checked_calloc(sizeof(Bitmap *) * NUM_IMG_BITMAP_POINTERS); + + anim_initial.bitmaps[IMG_BITMAP_STANDARD] = + LoadCustomImage(filename_anim_initial); graphic_info = &anim_initial; /* graphic == 0 => anim_initial */ - set_graphic_parameters_ext(0, parameter, anim_initial.bitmap); + set_graphic_parameters_ext(0, parameter, anim_initial.bitmaps); graphic_info = graphic_info_last; diff --git a/src/libgame/image.c b/src/libgame/image.c index 4546d436..799b28bb 100644 --- a/src/libgame/image.c +++ b/src/libgame/image.c @@ -19,13 +19,15 @@ struct ImageInfo char *source_filename; int num_references; - Bitmap *bitmap; + Bitmap *bitmaps[NUM_IMG_BITMAP_POINTERS]; int original_width; /* original image file width */ int original_height; /* original image file height */ boolean contains_small_images; /* set after adding small images */ boolean scaled_up; /* set after scaling up */ + + int game_tile_size; /* size of in-game sized bitmap */ }; typedef struct ImageInfo ImageInfo; @@ -33,38 +35,42 @@ static struct ArtworkListInfo *image_info = NULL; static void *Load_Image(char *filename) { - ImageInfo *img_info; - - img_info = checked_calloc(sizeof(ImageInfo)); + ImageInfo *img_info = checked_calloc(sizeof(ImageInfo)); - if ((img_info->bitmap = LoadImage(filename)) == NULL) + if ((img_info->bitmaps[IMG_BITMAP_STANDARD] = LoadImage(filename)) == NULL) { Error(ERR_WARN, "cannot load image file '%s': LoadImage() failed: %s", filename, GetError()); + free(img_info); + return NULL; } img_info->source_filename = getStringCopy(filename); - img_info->original_width = img_info->bitmap->width; - img_info->original_height = img_info->bitmap->height; + img_info->original_width = img_info->bitmaps[IMG_BITMAP_STANDARD]->width; + img_info->original_height = img_info->bitmaps[IMG_BITMAP_STANDARD]->height; img_info->contains_small_images = FALSE; img_info->scaled_up = FALSE; + img_info->game_tile_size = 0; // will be set later + return img_info; } static void FreeImage(void *ptr) { ImageInfo *image = (ImageInfo *)ptr; + int i; if (image == NULL) return; - if (image->bitmap) - FreeBitmap(image->bitmap); + for (i = 0; i < NUM_IMG_BITMAPS; i++) + if (image->bitmaps[i]) + FreeBitmap(image->bitmaps[i]); if (image->source_filename) free(image->source_filename); @@ -98,11 +104,11 @@ static ImageInfo *getImageInfoEntryFromImageID(int pos) return img_info[list_pos]; } -Bitmap *getBitmapFromImageID(int pos) +Bitmap **getBitmapsFromImageID(int pos) { ImageInfo *img_info = getImageInfoEntryFromImageID(pos); - return (img_info != NULL ? img_info->bitmap : NULL); + return (img_info != NULL ? img_info->bitmaps : NULL); } int getOriginalImageWidthFromImageID(int pos) @@ -246,13 +252,25 @@ void CreateImageWithSmallImages(int pos, int zoom_factor, int tile_size) { ImageInfo *img_info = getImageInfoEntryFromImageID(pos); - if (img_info == NULL || img_info->contains_small_images) + if (img_info == NULL) + return; + + if (img_info->contains_small_images) + { + if (img_info->game_tile_size != gfx.game_tile_size) + ReCreateGameTileSizeBitmap(img_info->bitmaps); + + img_info->game_tile_size = gfx.game_tile_size; + return; + } - CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor, tile_size); + CreateBitmapWithSmallBitmaps(img_info->bitmaps, zoom_factor, tile_size); img_info->contains_small_images = TRUE; - img_info->scaled_up = TRUE; + img_info->scaled_up = TRUE; // scaling was also done here + + img_info->game_tile_size = gfx.game_tile_size; } void ScaleImage(int pos, int zoom_factor) @@ -263,7 +281,7 @@ void ScaleImage(int pos, int zoom_factor) return; if (zoom_factor != 1) - ScaleBitmap(img_info->bitmap, zoom_factor); + ScaleBitmap(img_info->bitmaps, zoom_factor); img_info->scaled_up = TRUE; } diff --git a/src/libgame/image.h b/src/libgame/image.h index a45888ac..adcc9e65 100644 --- a/src/libgame/image.h +++ b/src/libgame/image.h @@ -15,9 +15,29 @@ #include "system.h" +// these bitmap pointers either point to allocated bitmaps or are NULL +#define IMG_BITMAP_32x32 0 +#define IMG_BITMAP_16x16 1 +#define IMG_BITMAP_8x8 2 +#define IMG_BITMAP_4x4 3 +#define IMG_BITMAP_2x2 4 +#define IMG_BITMAP_1x1 5 +#define IMG_BITMAP_CUSTOM 6 + +#define NUM_IMG_BITMAPS 7 + +// this bitmap pointer points to one of the above bitmaps (do not free it) +#define IMG_BITMAP_GAME 7 + +#define NUM_IMG_BITMAP_POINTERS 8 + +// this bitmap pointer points to the bitmap with default image size +#define IMG_BITMAP_STANDARD IMG_BITMAP_32x32 + + int getImageListSize(); struct FileInfo *getImageListEntryFromImageID(int); -Bitmap *getBitmapFromImageID(int); +Bitmap **getBitmapsFromImageID(int); int getOriginalImageWidthFromImageID(int); int getOriginalImageHeightFromImageID(int); char *getTokenFromImageID(int); diff --git a/src/libgame/system.c b/src/libgame/system.c index aa344da5..9484cbd2 100644 --- a/src/libgame/system.c +++ b/src/libgame/system.c @@ -896,11 +896,57 @@ Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height) return dst_bitmap; } -static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor, +static void SetMaskedBitmapSurface(Bitmap *bitmap) +{ + if (bitmap == NULL) + return; + + SDL_Surface *surface = bitmap->surface; + + if (bitmap->surface_masked) + SDL_FreeSurface(bitmap->surface_masked); + + SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL, + SDL_MapRGB(surface->format, 0x00, 0x00, 0x00)); + + if ((bitmap->surface_masked = SDLGetNativeSurface(surface)) == NULL) + Error(ERR_EXIT, "SDL_DisplayFormat() failed"); + + SDL_SetColorKey(surface, UNSET_TRANSPARENT_PIXEL, 0); +} + +void ReCreateGameTileSizeBitmap(Bitmap **bitmaps) +{ + if (bitmaps[IMG_BITMAP_CUSTOM]) + { + FreeBitmap(bitmaps[IMG_BITMAP_CUSTOM]); + + bitmaps[IMG_BITMAP_CUSTOM] = NULL; + } + + if (gfx.game_tile_size == gfx.standard_tile_size) + { + bitmaps[IMG_BITMAP_GAME] = bitmaps[IMG_BITMAP_STANDARD]; + + return; + } + + Bitmap *bitmap = bitmaps[IMG_BITMAP_STANDARD]; + int width = bitmap->width * gfx.game_tile_size / gfx.standard_tile_size;; + int height = bitmap->height * gfx.game_tile_size / gfx.standard_tile_size;; + + Bitmap *bitmap_new = ZoomBitmap(bitmap, width, height); + + bitmaps[IMG_BITMAP_CUSTOM] = bitmap_new; + bitmaps[IMG_BITMAP_GAME] = bitmap_new; + + SetMaskedBitmapSurface(bitmap_new); +} + +static void CreateScaledBitmaps(Bitmap **bitmaps, int zoom_factor, int tile_size, boolean create_small_bitmaps) { - Bitmap swap_bitmap; - Bitmap *new_bitmap; + Bitmap *old_bitmap = bitmaps[IMG_BITMAP_STANDARD]; Bitmap *tmp_bitmap_final = NULL; Bitmap *tmp_bitmap_0 = NULL; Bitmap *tmp_bitmap_1 = NULL; @@ -918,7 +964,7 @@ static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor, int width_16, height_16; int width_32, height_32; int old_width, old_height; - int new_width, new_height; + int i; print_timestamp_init("CreateScaledBitmaps"); @@ -980,10 +1026,7 @@ static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor, UPDATE_BUSY_STATE(); } - } - if (create_small_bitmaps) - { /* calculate new image dimensions for small images */ width_2 = width_1 / 2; height_2 = height_1 / 2; @@ -1035,118 +1078,56 @@ static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor, tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_32, height_32); UPDATE_BUSY_STATE(); - } - if (create_small_bitmaps) - { - new_width = width_1; - new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */ + bitmaps[IMG_BITMAP_32x32] = tmp_bitmap_1; + bitmaps[IMG_BITMAP_16x16] = tmp_bitmap_2; + bitmaps[IMG_BITMAP_8x8] = tmp_bitmap_4; + bitmaps[IMG_BITMAP_4x4] = tmp_bitmap_8; + bitmaps[IMG_BITMAP_2x2] = tmp_bitmap_16; + bitmaps[IMG_BITMAP_1x1] = tmp_bitmap_32; if (width_0 != width_1) - { - new_width += width_0; - new_height = MAX(new_height, height_0); - } + bitmaps[IMG_BITMAP_CUSTOM] = tmp_bitmap_0; - new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH); + if (bitmaps[IMG_BITMAP_CUSTOM]) + bitmaps[IMG_BITMAP_GAME] = bitmaps[IMG_BITMAP_CUSTOM]; + else + bitmaps[IMG_BITMAP_GAME] = bitmaps[IMG_BITMAP_STANDARD]; - if (width_0 != width_1) - BlitBitmap(tmp_bitmap_0, new_bitmap, 0, 0, width_0, height_0, width_1, 0); - - BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0); - BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2, - 0, height_1); - BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4, - width_1 / 2, height_1); - BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8, - 3 * width_1 / 4, height_1); - BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16, - 7 * width_1 / 8, height_1); - BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32, - 15 * width_1 / 16, height_1); + boolean free_old_bitmap = TRUE; - UPDATE_BUSY_STATE(); - } - else - { - new_width = width_1; - new_height = height_1; + for (i = 0; i < NUM_IMG_BITMAPS; i++) + if (bitmaps[i] == old_bitmap) + free_old_bitmap = FALSE; - new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */ + if (free_old_bitmap) + FreeBitmap(old_bitmap); } - - if (create_small_bitmaps) + else { - /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */ - - if (tmp_bitmap_final != old_bitmap) - FreeBitmap(tmp_bitmap_final); - - if (tmp_bitmap_0 != old_bitmap && - tmp_bitmap_0 != tmp_bitmap_final) - FreeBitmap(tmp_bitmap_0); - - if (tmp_bitmap_1 != old_bitmap && - tmp_bitmap_1 != tmp_bitmap_final && - tmp_bitmap_1 != tmp_bitmap_0) - FreeBitmap(tmp_bitmap_1); - - if (tmp_bitmap_2 != old_bitmap) - FreeBitmap(tmp_bitmap_2); - - if (tmp_bitmap_4 != old_bitmap) - FreeBitmap(tmp_bitmap_4); - - if (tmp_bitmap_8 != old_bitmap) - FreeBitmap(tmp_bitmap_8); - - if (tmp_bitmap_16 != old_bitmap) - FreeBitmap(tmp_bitmap_16); - - if (tmp_bitmap_32 != old_bitmap) - FreeBitmap(tmp_bitmap_32); + bitmaps[IMG_BITMAP_32x32] = tmp_bitmap_1; } - /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */ - swap_bitmap.surface = old_bitmap->surface; - old_bitmap->surface = new_bitmap->surface; - new_bitmap->surface = swap_bitmap.surface; - - old_bitmap->width = new_bitmap->width; - old_bitmap->height = new_bitmap->height; - - /* this replaces all blit masks created when loading -- maybe optimize this */ - { - SDL_Surface *old_surface = old_bitmap->surface; - - if (old_bitmap->surface_masked) - SDL_FreeSurface(old_bitmap->surface_masked); - - SDL_SetColorKey(old_surface, SET_TRANSPARENT_PIXEL, - SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00)); - - if ((old_bitmap->surface_masked = SDLGetNativeSurface(old_surface)) == NULL) - Error(ERR_EXIT, "SDL_DisplayFormat() failed"); - - SDL_SetColorKey(old_surface, UNSET_TRANSPARENT_PIXEL, 0); - } + // create corresponding bitmaps for masked blitting + for (i = 0; i < NUM_IMG_BITMAPS; i++) + if (bitmaps[i] != NULL && + bitmaps[i] != old_bitmap) + SetMaskedBitmapSurface(bitmaps[i]); UPDATE_BUSY_STATE(); - FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */ - print_timestamp_done("CreateScaledBitmaps"); } -void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor, +void CreateBitmapWithSmallBitmaps(Bitmap **bitmaps, int zoom_factor, int tile_size) { - CreateScaledBitmaps(old_bitmap, zoom_factor, tile_size, TRUE); + CreateScaledBitmaps(bitmaps, zoom_factor, tile_size, TRUE); } -void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor) +void ScaleBitmap(Bitmap **bitmaps, int zoom_factor) { - CreateScaledBitmaps(old_bitmap, zoom_factor, 0, FALSE); + CreateScaledBitmaps(bitmaps, zoom_factor, 0, FALSE); } diff --git a/src/libgame/system.h b/src/libgame/system.h index 1a469a19..671a0e73 100644 --- a/src/libgame/system.h +++ b/src/libgame/system.h @@ -1332,8 +1332,9 @@ Bitmap *LoadCustomImage(char *); void ReloadCustomImage(Bitmap *, char *); Bitmap *ZoomBitmap(Bitmap *, int, int); -void CreateBitmapWithSmallBitmaps(Bitmap *, int, int); -void ScaleBitmap(Bitmap *, int); +void ReCreateGameTileSizeBitmap(Bitmap **); +void CreateBitmapWithSmallBitmaps(Bitmap **, int, int); +void ScaleBitmap(Bitmap **, int); void SetMouseCursor(int); diff --git a/src/main.h b/src/main.h index 4f907998..c4b43f79 100644 --- a/src/main.h +++ b/src/main.h @@ -2658,7 +2658,9 @@ struct FontInfo struct GraphicInfo { - Bitmap *bitmap; + Bitmap **bitmaps; /* bitmaps in all required sizes */ + Bitmap *bitmap; /* bitmap in default size */ + int src_image_width; /* scaled bitmap size, but w/o small images */ int src_image_height; /* scaled bitmap size, but w/o small images */ diff --git a/src/tools.c b/src/tools.c index 335d983a..36f01f8a 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1049,64 +1049,24 @@ void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw, Bitmap **bitmap, int *x, int *y, boolean get_backside) { - struct - { - int width_mult, width_div; - int height_mult, height_div; - } - offset_calc[6] = - { - { 15, 16, 2, 3 }, /* 1 x 1 */ - { 7, 8, 2, 3 }, /* 2 x 2 */ - { 3, 4, 2, 3 }, /* 4 x 4 */ - { 1, 2, 2, 3 }, /* 8 x 8 */ - { 0, 1, 2, 3 }, /* 16 x 16 */ - { 0, 1, 0, 1 }, /* 32 x 32 */ - }; struct GraphicInfo *g = &graphic_info[graphic]; Bitmap *src_bitmap = g->bitmap; int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE); - int offset_calc_pos = log_2(tilesize); - int bitmap_width = src_bitmap->width; - int bitmap_height = src_bitmap->height; - int width_mult = offset_calc[offset_calc_pos].width_mult; - int width_div = offset_calc[offset_calc_pos].width_div; - int height_mult = offset_calc[offset_calc_pos].height_mult; - int height_div = offset_calc[offset_calc_pos].height_div; - int startx = bitmap_width * width_mult / width_div; - int starty = bitmap_height * height_mult / height_div; - int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) * - tilesize_raw / TILESIZE; - int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) * - tilesize_raw / TILESIZE; - int width = g->width * tilesize_raw / TILESIZE; - int height = g->height * tilesize_raw / TILESIZE; int offset_x = g->offset_x * tilesize_raw / TILESIZE; int offset_y = g->offset_y * tilesize_raw / TILESIZE; + int offset2_x = (get_backside ? g->offset2_x : 0); + int offset2_y = (get_backside ? g->offset2_y : 0); + int src_x = (g->src_x + offset2_x) * tilesize_raw / TILESIZE; + int src_y = (g->src_y + offset2_y) * tilesize_raw / TILESIZE; + int width = g->width * tilesize_raw / TILESIZE; + int height = g->height * tilesize_raw / TILESIZE; - if (game.tile_size != TILESIZE) - { - int bitmap_width_std = - bitmap_width * TILESIZE / (TILESIZE + game.tile_size); - int bitmap_height_std = - bitmap_height * TILESIZE / game.tile_size * 3 / 2; - - if (tilesize_raw == game.tile_size) - { - startx = bitmap_width_std; - starty = 0; - } - else - { - bitmap_width = bitmap_width_std; - - if (game.tile_size > TILESIZE * 3 / 2) - bitmap_height = bitmap_height_std; - - startx = bitmap_width * width_mult / width_div; - starty = bitmap_height * height_mult / height_div; - } - } + if (tilesize_raw == gfx.standard_tile_size) + src_bitmap = g->bitmaps[IMG_BITMAP_STANDARD]; + else if (tilesize_raw == game.tile_size) + src_bitmap = g->bitmaps[IMG_BITMAP_GAME]; + else + src_bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize)]; if (g->offset_y == 0) /* frames are ordered horizontally */ { @@ -1131,8 +1091,8 @@ void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw, } *bitmap = src_bitmap; - *x = startx + src_x; - *y = starty + src_y; + *x = src_x; + *y = src_y; } void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap, -- 2.34.1