X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ftools.c;h=a7867f87965b5b953e405fa9d0dab83e6cf641f6;hb=cc1d6b89872ea3d6ae3e53023653ab86dd76c2ea;hp=39a0d68140e3f6e47f374e489a15767d7eb27e10;hpb=8ad235d4df77b4c54322b6f2173d3bc30f77c92e;p=rocksndiamonds.git diff --git a/src/tools.c b/src/tools.c index 39a0d681..a7867f87 100644 --- a/src/tools.c +++ b/src/tools.c @@ -419,18 +419,30 @@ void BlitScreenToBitmap(Bitmap *target_bitmap) redraw_mask |= REDRAW_FIELD; } +void DrawFramesPerSecond() +{ + char text[100]; + int font_nr = FONT_TEXT_2; + int font_width = getFontWidth(font_nr); + + sprintf(text, "%04.1f fps", global.frames_per_second); + + DrawTextExt(backbuffer, WIN_XSIZE - font_width * strlen(text), 0, text, + font_nr, BLIT_OPAQUE); +} + void BackToFront() { if (redraw_mask == REDRAW_NONE) return; - // redraw playfield if anything inside main playfield area needs redraw - if (redraw_mask & REDRAW_MAIN) - redraw_mask |= REDRAW_FIELD; - // draw masked border to all viewports, if defined DrawMaskedBorder(redraw_mask); + // draw frames per second (only if debug mode is enabled) + if (redraw_mask & REDRAW_FPS) + DrawFramesPerSecond(); + // redraw complete window if both playfield and (some) doors need redraw if (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS) redraw_mask = REDRAW_ALL; @@ -469,6 +481,11 @@ static void FadeCrossSaveBackbuffer() BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); } +static void FadeCrossRestoreBackbuffer() +{ + BlitBitmap(bitmap_db_cross, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); +} + static void FadeExt(int fade_mask, int fade_mode, int fade_type) { static int fade_type_skip = FADE_TYPE_NONE; @@ -488,9 +505,15 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type) return; } +#if 1 + FadeCrossSaveBackbuffer(); +#endif + if (fading.fade_mode & FADE_TYPE_TRANSFORM) { +#if 0 FadeCrossSaveBackbuffer(); +#endif return; } @@ -559,6 +582,9 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type) FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay, draw_border_function); + if (fade_type == FADE_TYPE_FADE_OUT) + FadeCrossRestoreBackbuffer(); + redraw_mask &= ~fade_mask; } @@ -738,8 +764,122 @@ void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic) DrawBackground(x, y, width, height); } +static int game_status_last = -1; +static Bitmap *global_border_bitmap_last = NULL; +static Bitmap *global_border_bitmap = NULL; +static int real_sx_last = -1, real_sy_last = -1; +static int full_sxsize_last = -1, full_sysize_last = -1; +static int dx_last = -1, dy_last = -1; +static int dxsize_last = -1, dysize_last = -1; +static int vx_last = -1, vy_last = -1; +static int vxsize_last = -1, vysize_last = -1; + +boolean CheckIfRedrawGlobalBorderIsNeeded() +{ + int global_border_graphic; + + if (game_status == game_status_last) + return FALSE; + + global_border_graphic = + (game_status == GAME_MODE_MAIN ? IMG_GLOBAL_BORDER_MAIN : + game_status == GAME_MODE_SCORES ? IMG_GLOBAL_BORDER_SCORES : + game_status == GAME_MODE_EDITOR ? IMG_GLOBAL_BORDER_EDITOR : + game_status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING : + IMG_GLOBAL_BORDER); + + global_border_bitmap = + (graphic_info[global_border_graphic].bitmap ? + graphic_info[global_border_graphic].bitmap : + graphic_info[IMG_GLOBAL_BORDER].bitmap); + + // redraw if global screen border has changed + if (global_border_bitmap_last != global_border_bitmap) + return TRUE; + + // redraw if position or size of playfield area has changed + if (real_sx_last != REAL_SX || real_sy_last != REAL_SY || + full_sxsize_last != FULL_SXSIZE || full_sysize_last != FULL_SYSIZE) + return TRUE; + + // redraw if position or size of door area has changed + if (dx_last != DX || dy_last != DY || + dxsize_last != DXSIZE || dysize_last != DYSIZE) + return TRUE; + + // redraw if position or size of tape area has changed + if (vx_last != VX || vy_last != VY || + vxsize_last != VXSIZE || vysize_last != VYSIZE) + return TRUE; + + return FALSE; +} + +static void RedrawGlobalBorderIfNeeded() +{ + if (game_status == game_status_last) + return; + + // copy current draw buffer to later copy back areas that have not changed + BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + + if (CheckIfRedrawGlobalBorderIsNeeded()) + { + // redraw global screen border (or clear, if defined to be empty) + + if (global_border_bitmap) + BlitBitmap(global_border_bitmap, backbuffer, + 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + else + ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE); + + // copy previous playfield and door areas, if they are defined on both + // previous and current screen and if they still have the same size + + if (real_sx_last != -1 && real_sy_last != -1 && + REAL_SX != -1 && REAL_SY != -1 && + full_sxsize_last == FULL_SXSIZE && full_sysize_last == FULL_SYSIZE) + BlitBitmap(bitmap_db_store, backbuffer, + real_sx_last, real_sy_last, FULL_SXSIZE, FULL_SYSIZE, + REAL_SX, REAL_SY); + + if (dx_last != -1 && dy_last != -1 && + DX != -1 && DY != -1 && + dxsize_last == DXSIZE && dysize_last == DYSIZE) + BlitBitmap(bitmap_db_store, backbuffer, + dx_last, dy_last, DXSIZE, DYSIZE, DX, DY); + + if (vx_last != -1 && vy_last != -1 && + VX != -1 && VY != -1 && + vxsize_last == VXSIZE && vysize_last == VYSIZE) + BlitBitmap(bitmap_db_store, backbuffer, + vx_last, vy_last, VXSIZE, VYSIZE, VX, VY); + + redraw_mask = REDRAW_ALL; + } + + game_status_last = game_status; + + global_border_bitmap_last = global_border_bitmap; + + real_sx_last = REAL_SX; + real_sy_last = REAL_SY; + full_sxsize_last = FULL_SXSIZE; + full_sysize_last = FULL_SYSIZE; + dx_last = DX; + dy_last = DY; + dxsize_last = DXSIZE; + dysize_last = DYSIZE; + vx_last = VX; + vy_last = VY; + vxsize_last = VXSIZE; + vysize_last = VYSIZE; +} + void ClearField() { + RedrawGlobalBorderIfNeeded(); + /* !!! "drawto" might still point to playfield buffer here (see above) !!! */ /* (when entering hall of fame after playing) */ DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE); @@ -1959,7 +2099,7 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) level.envelope[envelope_nr].autowrap, level.envelope[envelope_nr].centered, FALSE); - redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; + redraw_mask |= REDRAW_FIELD; BackToFront(); SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame); @@ -2010,25 +2150,57 @@ void ShowEnvelope(int envelope_nr) BackToFront(); } -static void setRequestCenterPosition(int *x, int *y) +static void setRequestBasePosition(int *x, int *y) { - int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2); - int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2); + int sx_base, sy_base; + + if (request.x != -1) + sx_base = request.x; + else if (request.align == ALIGN_LEFT) + sx_base = SX; + else if (request.align == ALIGN_RIGHT) + sx_base = SX + SXSIZE; + else + sx_base = SX + SXSIZE / 2; + + if (request.y != -1) + sy_base = request.y; + else if (request.valign == VALIGN_TOP) + sy_base = SY; + else if (request.valign == VALIGN_BOTTOM) + sy_base = SY + SYSIZE; + else + sy_base = SY + SYSIZE / 2; - *x = sx_center; - *y = sy_center; + *x = sx_base; + *y = sy_base; } -static void setRequestPosition(int *x, int *y, boolean add_border_size) +static void setRequestPositionExt(int *x, int *y, int width, int height, + boolean add_border_size) { int border_size = request.border_size; - int sx_center, sy_center; + int sx_base, sy_base; int sx, sy; - setRequestCenterPosition(&sx_center, &sy_center); + setRequestBasePosition(&sx_base, &sy_base); + + if (request.align == ALIGN_LEFT) + sx = sx_base; + else if (request.align == ALIGN_RIGHT) + sx = sx_base - width; + else + sx = sx_base - width / 2; + + if (request.valign == VALIGN_TOP) + sy = sy_base; + else if (request.valign == VALIGN_BOTTOM) + sy = sy_base - height; + else + sy = sy_base - height / 2; - sx = sx_center - request.width / 2; - sy = sy_center - request.height / 2; + sx = MAX(0, MIN(sx, WIN_XSIZE - width)); + sy = MAX(0, MIN(sy, WIN_YSIZE - height)); if (add_border_size) { @@ -2040,6 +2212,11 @@ static void setRequestPosition(int *x, int *y, boolean add_border_size) *y = sy; } +static void setRequestPosition(int *x, int *y, boolean add_border_size) +{ + setRequestPositionExt(x, y, request.width, request.height, add_border_size); +} + void DrawEnvelopeRequest(char *text) { char *text_final = text; @@ -2128,11 +2305,9 @@ void AnimateEnvelopeRequest(int anim_mode, int action) int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0) / 2; unsigned int anim_delay = 0; - int width = request.width; - int height = request.height; int tile_size = request.step_offset; - int max_xsize = width / tile_size; - int max_ysize = height / tile_size; + int max_xsize = request.width / tile_size; + int max_ysize = request.height / tile_size; int max_xsize_inner = max_xsize - 2; int max_ysize_inner = max_ysize - 2; @@ -2171,17 +2346,14 @@ void AnimateEnvelopeRequest(int anim_mode, int action) int ysize_size_top = (ysize - 1) * tile_size; int max_xsize_pos = (max_xsize - 1) * tile_size; int max_ysize_pos = (max_ysize - 1) * tile_size; - int sx_center, sy_center; + int width = xsize * tile_size; + int height = ysize * tile_size; int src_x, src_y; int dst_x, dst_y; int xx, yy; - setRequestCenterPosition(&sx_center, &sy_center); - - src_x = sx_center - width / 2; - src_y = sy_center - height / 2; - dst_x = sx_center - xsize * tile_size / 2; - dst_y = sy_center - ysize * tile_size / 2; + setRequestPosition(&src_x, &src_y, FALSE); + setRequestPositionExt(&dst_x, &dst_y, width, height, FALSE); BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); @@ -2205,7 +2377,7 @@ void AnimateEnvelopeRequest(int anim_mode, int action) } } - redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; + redraw_mask |= REDRAW_FIELD; DoAnimation(); BackToFront(); @@ -2220,7 +2392,9 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action) int graphic = IMG_BACKGROUND_REQUEST; int sound_opening = SND_REQUEST_OPENING; int sound_closing = SND_REQUEST_CLOSING; - int anim_mode = graphic_info[graphic].anim_mode; + int anim_mode_1 = request.anim_mode; /* (higher priority) */ + int anim_mode_2 = graphic_info[graphic].anim_mode; /* (lower priority) */ + int anim_mode = (anim_mode_1 != ANIM_DEFAULT ? anim_mode_1 : anim_mode_2); int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL: anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode); @@ -2397,7 +2571,7 @@ static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y) } } - redraw_mask |= REDRAW_MICROLEVEL; + redraw_mask |= REDRAW_FIELD; } #define MICROLABEL_EMPTY 0 @@ -2466,7 +2640,7 @@ static void DrawPreviewLevelLabelExt(int mode) if (strlen(label_text) > 0) DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align); - redraw_mask |= REDRAW_MICROLEVEL; + redraw_mask |= REDRAW_FIELD; } static void DrawPreviewLevelExt(boolean restart)