void SetDrawtoField(int mode)
{
- if (mode == DRAW_BUFFERED && setup.soft_scrolling)
+ if (mode == DRAW_FIELDBUFFER)
{
FX = 2 * TILEX_VAR;
FY = 2 * TILEY_VAR;
BY1 = -2;
BX2 = SCR_FIELDX + 1;
BY2 = SCR_FIELDY + 1;
- redraw_x1 = 2;
- redraw_y1 = 2;
drawto_field = fieldbuffer;
}
BY1 = 0;
BX2 = SCR_FIELDX - 1;
BY2 = SCR_FIELDY - 1;
- redraw_x1 = 0;
- redraw_y1 = 0;
drawto_field = backbuffer;
}
void DrawMaskedBorder_Rect(int x, int y, int width, int height)
{
- Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
+ Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus();
- SetClipOrigin(bitmap, bitmap->stored_clip_gc, 0, 0);
BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
}
effectiveGameStatus() == GAME_MODE_TITLE)
return;
- /* never draw masked screen borders when displaying request outside door */
- if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR &&
- global.use_envelope_request)
- return;
-
if (redraw_mask & REDRAW_ALL)
DrawMaskedBorder_ALL();
else
}
}
-static void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
+void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
{
- DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
int fx = FX, fy = FY;
int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0);
}
- if (border.draw_masked[GAME_MODE_PLAYING])
- {
- if (buffer != backbuffer)
- {
- /* copy playfield buffer to backbuffer to add masked border */
- BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
- DrawMaskedBorder(REDRAW_FIELD);
- }
-
- BlitBitmap(backbuffer, target_bitmap,
- REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
- REAL_SX, REAL_SY);
- }
- else
- {
- BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
- }
+ BlitBitmap(drawto_field, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
}
void BlitScreenToBitmap(Bitmap *target_bitmap)
BlitScreenToBitmap_SP(target_bitmap);
else if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
BlitScreenToBitmap_RND(target_bitmap);
+
+ redraw_mask |= REDRAW_FIELD;
}
-void BackToFront()
+void DrawFramesPerSecond()
{
- int x, y;
- DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
-
- if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
- redraw_mask |= REDRAW_FIELD;
-
-#if 0
- // never redraw single tiles, always redraw the whole field
- // (redrawing single tiles up to a certain threshold was faster on old,
- // now legacy graphics, but slows things down on modern graphics now)
- // UPDATE: this is now globally defined by value of REDRAWTILES_THRESHOLD
- if (redraw_mask & REDRAW_TILES)
- redraw_mask |= REDRAW_FIELD;
-#endif
+ char text[100];
+ int font_nr = FONT_TEXT_2;
+ int font_width = getFontWidth(font_nr);
-#if 0
- /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
- /* (force full redraw) */
- if (game_status == GAME_MODE_PLAYING)
- redraw_mask |= REDRAW_FIELD;
-#endif
+ sprintf(text, "%04.1f fps", global.frames_per_second);
- if (redraw_mask & REDRAW_FIELD)
- redraw_mask &= ~REDRAW_TILES;
+ DrawTextExt(backbuffer, WIN_XSIZE - font_width * strlen(text), 0, text,
+ font_nr, BLIT_OPAQUE);
+}
+void BackToFront()
+{
if (redraw_mask == REDRAW_NONE)
return;
-#if 0
- printf("::: ");
- if (redraw_mask & REDRAW_ALL)
- printf("[REDRAW_ALL]");
- if (redraw_mask & REDRAW_FIELD)
- printf("[REDRAW_FIELD]");
- if (redraw_mask & REDRAW_TILES)
- printf("[REDRAW_TILES]");
- if (redraw_mask & REDRAW_DOOR_1)
- printf("[REDRAW_DOOR_1]");
- if (redraw_mask & REDRAW_DOOR_2)
- printf("[REDRAW_DOOR_2]");
- if (redraw_mask & REDRAW_FROM_BACKBUFFER)
- printf("[REDRAW_FROM_BACKBUFFER]");
- printf(" [%d]\n", FrameCounter);
-#endif
-
- if (redraw_mask & REDRAW_TILES &&
- game_status == GAME_MODE_PLAYING &&
- border.draw_masked[GAME_MODE_PLAYING])
- redraw_mask |= REDRAW_FIELD;
-
- if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
- {
- static boolean last_frame_skipped = FALSE;
- boolean skip_even_when_not_scrolling = TRUE;
- boolean just_scrolling = (ScreenMovDir != 0);
- boolean verbose = FALSE;
-
- if (global.fps_slowdown_factor > 1 &&
- (FrameCounter % global.fps_slowdown_factor) &&
- (just_scrolling || skip_even_when_not_scrolling))
- {
- redraw_mask &= ~REDRAW_MAIN;
-
- last_frame_skipped = TRUE;
+ // draw masked border to all viewports, if defined
+ DrawMaskedBorder(redraw_mask);
- if (verbose)
- printf("FRAME SKIPPED\n");
- }
- else
- {
- if (last_frame_skipped)
- redraw_mask |= REDRAW_FIELD;
-
- last_frame_skipped = FALSE;
-
- if (verbose)
- printf("frame not skipped\n");
- }
- }
+ // draw frames per second (only if debug mode is enabled)
+ if (redraw_mask & REDRAW_FPS)
+ DrawFramesPerSecond();
- /* synchronize X11 graphics at this point; if we would synchronize the
- display immediately after the buffer switching (after the XFlush),
- this could mean that we have to wait for the graphics to complete,
- although we could go on doing calculations for the next frame */
+ // redraw complete window if both playfield and (some) doors need redraw
+ if (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS)
+ redraw_mask = REDRAW_ALL;
- SyncDisplay();
-
- /* never draw masked border to backbuffer when using playfield buffer */
- if (game_status != GAME_MODE_PLAYING ||
- redraw_mask & REDRAW_FROM_BACKBUFFER ||
- buffer == backbuffer)
- DrawMaskedBorder(redraw_mask);
- else
- DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
+ /* although redrawing the whole window would be fine for normal gameplay,
+ being able to only redraw the playfield is required for deactivating
+ certain drawing areas (mainly playfield) to work, which is needed for
+ warp-forward to be fast enough (by skipping redraw of most frames) */
if (redraw_mask & REDRAW_ALL)
{
BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-
- redraw_mask = REDRAW_NONE;
}
-
- if (redraw_mask & REDRAW_FIELD)
+ else if (redraw_mask & REDRAW_FIELD)
{
- if (game_status != GAME_MODE_PLAYING ||
- redraw_mask & REDRAW_FROM_BACKBUFFER)
- {
- BlitBitmap(backbuffer, window,
- REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
- }
- else
- {
- BlitScreenToBitmap_RND(window);
- }
-
- redraw_mask &= ~REDRAW_MAIN;
+ BlitBitmap(backbuffer, window,
+ REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
}
-
- if (redraw_mask & REDRAW_DOORS)
+ else if (redraw_mask & REDRAW_DOORS)
{
if (redraw_mask & REDRAW_DOOR_1)
BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
if (redraw_mask & REDRAW_DOOR_3)
BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
-
- redraw_mask &= ~REDRAW_DOORS;
- }
-
- if (redraw_mask & REDRAW_MICROLEVEL)
- {
- BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
- SX, SY + 10 * TILEY);
-
- redraw_mask &= ~REDRAW_MICROLEVEL;
}
- if (redraw_mask & REDRAW_TILES)
- {
- int sx = SX;
- int sy = SY;
-
- int dx = 0, dy = 0;
- int dx_var = dx * TILESIZE_VAR / TILESIZE;
- int dy_var = dy * TILESIZE_VAR / TILESIZE;
- int ffx, ffy;
- int fx = FX, fy = FY;
-
- int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0);
- int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0);
-
- InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
-
- ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
- ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
-
- if (EVEN(SCR_FIELDX))
- {
- if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
- {
- fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
-
- if (fx % TILEX_VAR)
- sx -= TILEX_VAR / 2;
- else
- sx -= TILEX_VAR;
- }
- else
- {
- fx += (dx_var > 0 ? TILEX_VAR : 0);
- }
- }
-
- if (EVEN(SCR_FIELDY))
- {
- if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
- {
- fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
-
- if (fy % TILEY_VAR)
- sy -= TILEY_VAR / 2;
- else
- sy -= TILEY_VAR;
- }
- else
- {
- fy += (dy_var > 0 ? TILEY_VAR : 0);
- }
- }
-
- for (x = 0; x < scr_fieldx; x++)
- for (y = 0 ; y < scr_fieldy; y++)
- if (redraw[redraw_x1 + x][redraw_y1 + y])
- BlitBitmap(buffer, window,
- FX + x * TILEX_VAR, FY + y * TILEY_VAR,
- TILEX_VAR, TILEY_VAR,
- sx + x * TILEX_VAR, sy + y * TILEY_VAR);
-
- InitGfxClipRegion(FALSE, -1, -1, -1, -1);
- }
-
- if (redraw_mask & REDRAW_FPS) /* display frames per second */
- {
- char text[100];
- char info1[100];
-
- sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
- if (!global.fps_slowdown)
- info1[0] = '\0';
-
- sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
-
- DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
- }
-
- FlushDisplay();
-
- for (x = 0; x < MAX_BUF_XSIZE; x++)
- for (y = 0; y < MAX_BUF_YSIZE; y++)
- redraw[x][y] = 0;
- redraw_tiles = 0;
redraw_mask = REDRAW_NONE;
}
BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
}
+static void FadeCrossRestoreBackbuffer()
+{
+ int redraw_mask_last = redraw_mask;
+
+ BlitBitmap(bitmap_db_cross, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+ // do not change redraw mask when restoring backbuffer after cross-fading
+ redraw_mask = redraw_mask_last;
+}
+
static void FadeExt(int fade_mask, int fade_mode, int fade_type)
{
static int fade_type_skip = FADE_TYPE_NONE;
return;
}
+#if 1
+ FadeCrossSaveBackbuffer();
+#endif
+
if (fading.fade_mode & FADE_TYPE_TRANSFORM)
{
+#if 0
FadeCrossSaveBackbuffer();
+#endif
return;
}
if (fade_mask == REDRAW_FIELD)
{
- x = REAL_SX;
- y = REAL_SY;
- width = FULL_SXSIZE;
- height = FULL_SYSIZE;
+ x = FADE_SX;
+ y = FADE_SY;
+ width = FADE_SXSIZE;
+ height = FADE_SYSIZE;
if (border.draw_masked_when_fading)
draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
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;
}
FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
else
FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
+
+ FADE_SX = REAL_SX;
+ FADE_SY = REAL_SY;
+ FADE_SXSIZE = FULL_SXSIZE;
+ FADE_SYSIZE = FULL_SYSIZE;
}
void FadeOut(int fade_mask)
FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
}
+Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
+{
+ boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
+
+ return (graphic == IMG_UNDEFINED ? NULL :
+ graphic_info[graphic].bitmap != NULL || redefined ?
+ graphic_info[graphic].bitmap :
+ graphic_info[default_graphic].bitmap);
+}
+
+Bitmap *getBackgroundBitmap(int graphic)
+{
+ return getBitmapFromGraphicOrDefault(graphic, IMG_BACKGROUND);
+}
+
+Bitmap *getGlobalBorderBitmap(int graphic)
+{
+ return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER);
+}
+
+Bitmap *getGlobalBorderBitmapFromGameStatus()
+{
+ int graphic =
+ (game_status == GAME_MODE_MAIN ||
+ game_status == GAME_MODE_PSEUDO_TYPENAME ? 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);
+
+ return getGlobalBorderBitmap(graphic);
+}
+
void SetWindowBackgroundImageIfDefined(int graphic)
{
if (graphic_info[graphic].bitmap)
void SetWindowBackgroundImage(int graphic)
{
- SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
- graphic_info[graphic].bitmap ?
- graphic_info[graphic].bitmap :
- graphic_info[IMG_BACKGROUND].bitmap);
+ SetWindowBackgroundBitmap(getBackgroundBitmap(graphic));
}
void SetMainBackgroundImage(int graphic)
{
- SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
- graphic_info[graphic].bitmap ?
- graphic_info[graphic].bitmap :
- graphic_info[IMG_BACKGROUND].bitmap);
+ SetMainBackgroundBitmap(getBackgroundBitmap(graphic));
}
void SetDoorBackgroundImage(int graphic)
{
- SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
- graphic_info[graphic].bitmap ?
- graphic_info[graphic].bitmap :
- graphic_info[IMG_BACKGROUND].bitmap);
+ SetDoorBackgroundBitmap(getBackgroundBitmap(graphic));
}
void SetPanelBackground()
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 CheckIfGlobalBorderHasChanged()
+{
+ // if game status has not changed, global border has not changed either
+ if (game_status == game_status_last)
+ return FALSE;
+
+ // determine and store new global border bitmap for current game status
+ global_border_bitmap = getGlobalBorderBitmapFromGameStatus();
+
+ return (global_border_bitmap_last != global_border_bitmap);
+}
+
+boolean CheckIfGlobalBorderRedrawIsNeeded()
+{
+ // if game status has not changed, nothing has to be redrawn
+ if (game_status == game_status_last)
+ return FALSE;
+
+ // redraw if global screen border has changed
+ if (CheckIfGlobalBorderHasChanged())
+ 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;
+}
+
+void RedrawGlobalBorderFromBitmap(Bitmap *bitmap)
+{
+ if (bitmap)
+ BlitBitmap(bitmap, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ else
+ ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
+}
+
+void RedrawGlobalBorder()
+{
+ Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus();
+
+ RedrawGlobalBorderFromBitmap(bitmap);
+
+ redraw_mask = REDRAW_ALL;
+}
+
+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 (CheckIfGlobalBorderRedrawIsNeeded())
+ {
+ // redraw global screen border (or clear, if defined to be empty)
+ RedrawGlobalBorderFromBitmap(global_border_bitmap);
+
+ // 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);
/* !!! maybe this should be done before clearing the background !!! */
- if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
+ if (game_status == GAME_MODE_PLAYING)
{
ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
- SetDrawtoField(DRAW_BUFFERED);
+ SetDrawtoField(DRAW_FIELDBUFFER);
}
else
+ {
SetDrawtoField(DRAW_BACKBUFFER);
+ }
}
void MarkTileDirty(int x, int y)
{
- int xx = redraw_x1 + x;
- int yy = redraw_y1 + y;
-
- if (!redraw[xx][yy])
- redraw_tiles++;
-
- redraw[xx][yy] = TRUE;
- redraw_mask |= REDRAW_TILES;
+ redraw_mask |= REDRAW_FIELD;
}
void SetBorderElement()
gfx.anim_random_frame = GfxRandom[x][y];
}
-inline int getGraphicAnimationFrame(int graphic, int sync_frame)
+int getGraphicAnimationFrame(int graphic, int sync_frame)
{
/* animation synchronized with global frame counter, not move position */
if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
sync_frame);
}
-void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
+void getSizedGraphicSourceExt(int graphic, int frame, int tilesize,
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;
-
- 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;
+ int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
+ int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
+ int tilesize_capped = MIN(MAX(1, tilesize), TILESIZE);
- if (game.tile_size > TILESIZE * 3 / 2)
- bitmap_height = bitmap_height_std;
+ // if no in-game graphics defined, always use standard graphic size
+ if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
+ tilesize = TILESIZE;
- startx = bitmap_width * width_mult / width_div;
- starty = bitmap_height * height_mult / height_div;
- }
- }
+ if (tilesize == gfx.standard_tile_size)
+ src_bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
+ else if (tilesize == game.tile_size)
+ src_bitmap = g->bitmaps[IMG_BITMAP_GAME];
+ else
+ src_bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
if (g->offset_y == 0) /* frames are ordered horizontally */
{
- int max_width = g->anim_frames_per_line * width;
- int pos = (src_y / height) * max_width + src_x + frame * offset_x;
+ int max_width = g->anim_frames_per_line * g->width;
+ int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
src_x = pos % max_width;
- src_y = src_y % height + pos / max_width * height;
+ src_y = src_y % g->height + pos / max_width * g->height;
}
else if (g->offset_x == 0) /* frames are ordered vertically */
{
- int max_height = g->anim_frames_per_line * height;
- int pos = (src_x / width) * max_height + src_y + frame * offset_y;
+ int max_height = g->anim_frames_per_line * g->height;
+ int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
- src_x = src_x % width + pos / max_height * width;
+ src_x = src_x % g->width + pos / max_height * g->width;
src_y = pos % max_height;
}
else /* frames are ordered diagonally */
{
- src_x = src_x + frame * offset_x;
- src_y = src_y + frame * offset_y;
+ src_x = src_x + frame * g->offset_x;
+ src_y = src_y + frame * g->offset_y;
}
*bitmap = src_bitmap;
- *x = startx + src_x;
- *y = starty + src_y;
+ *x = src_x * tilesize / TILESIZE;
+ *y = src_y * tilesize / TILESIZE;
}
void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
get_backside);
}
-void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
+void getSizedGraphicSource(int graphic, int frame, int tilesize,
Bitmap **bitmap, int *x, int *y)
{
- getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
+ getSizedGraphicSourceExt(graphic, frame, tilesize, bitmap, x, y, FALSE);
}
void getFixedGraphicSource(int graphic, int frame,
getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
}
-inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
- int *x, int *y, boolean get_backside)
+inline static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
+ int *x, int *y, boolean get_backside)
{
struct GraphicInfo *g = &graphic_info[graphic];
int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
- SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
- dst_x - src_x, dst_y - src_y);
-
BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
dst_x, dst_y);
}
void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
int graphic, int frame)
{
+ struct GraphicInfo *g = &graphic_info[graphic];
Bitmap *src_bitmap;
int src_x, src_y;
getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
- SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
- dst_x - src_x, dst_y - src_y);
- BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
+ BlitBitmapMasked(src_bitmap, d, src_x, src_y, g->width, g->height,
+ dst_x, dst_y);
}
void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
dst_y = FY + y * TILEY_VAR + dy;
if (mask_mode == USE_MASKING)
- {
- SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
- dst_x - src_x, dst_y - src_y);
BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
dst_x, dst_y);
- }
else
BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
dst_x, dst_y);
dst_y = FY + y1 * TILEY_VAR;
if (mask_mode == USE_MASKING)
- {
- SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
- dst_x - src_x, dst_y - src_y);
BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
dst_x, dst_y);
- }
else
BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
dst_x, dst_y);
dst_y = FY + y2 * TILEY_VAR;
if (mask_mode == USE_MASKING)
- {
- SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
- dst_x - src_x, dst_y - src_y);
BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
dst_x, dst_y);
- }
else
BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
dst_x, dst_y);
}
}
+void DrawSizedElement(int x, int y, int element, int tilesize)
+{
+ int graphic;
+
+ graphic = el2edimg(element);
+ DrawSizedGraphic(x, y, graphic, 0, tilesize);
+}
+
void DrawMiniElement(int x, int y, int element)
{
int graphic;
DrawMiniGraphic(x, y, graphic);
}
+void DrawSizedElementOrWall(int sx, int sy, int scroll_x, int scroll_y,
+ int tilesize)
+{
+ int x = sx + scroll_x, y = sy + scroll_y;
+
+ if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
+ DrawSizedElement(sx, sy, EL_EMPTY, tilesize);
+ else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
+ DrawSizedElement(sx, sy, Feld[x][y], tilesize);
+ else
+ DrawSizedGraphic(sx, sy, el2edimg(getBorderElement(x, y)), 0, tilesize);
+}
+
void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
{
int x = sx + scroll_x, y = sy + scroll_y;
inner_sy + (y - 1) * tile_height % inner_height);
if (draw_masked)
- {
- SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
- dst_x - src_x, dst_y - src_y);
BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
dst_x, dst_y);
- }
else
BlitBitmap(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
dst_x, dst_y);
boolean no_delay = (tape.warp_forward);
unsigned int anim_delay = 0;
int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
- int anim_delay_value = (no_delay ? 0 : frame_delay_value);
+ int anim_delay_value = (no_delay ? 0 : frame_delay_value) / 2;
int font_nr = FONT_ENVELOPE_1 + envelope_nr;
int font_width = getFontWidth(font_nr);
int font_height = getFontHeight(font_nr);
int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
int xstep = (xstart < xend ? 1 : 0);
int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
- int x, y;
+ int start = 0;
+ int end = MAX(xend - xstart, yend - ystart);
+ int i;
- for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
+ for (i = start; i <= end; i++)
{
+ int last_frame = end; // last frame of this "for" loop
+ int x = xstart + i * xstep;
+ int y = ystart + i * ystep;
int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
int sx = SX + (SXSIZE - xsize * font_width) / 2;
int sy = SY + (SYSIZE - ysize * font_height) / 2;
int xx, yy;
- SetDrawtoField(DRAW_BUFFERED);
+ SetDrawtoField(DRAW_FIELDBUFFER);
BlitScreenToBitmap(backbuffer);
level.envelope[envelope_nr].autowrap,
level.envelope[envelope_nr].centered, FALSE);
- redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+ redraw_mask |= REDRAW_FIELD;
BackToFront();
- WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
+ SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
}
}
game.envelope_active = FALSE;
- SetDrawtoField(DRAW_BUFFERED);
+ SetDrawtoField(DRAW_FIELDBUFFER);
redraw_mask |= REDRAW_FIELD;
BackToFront();
}
-static void setRequestPosition(int *x, int *y, boolean add_border_size)
+static void setRequestBasePosition(int *x, int *y)
+{
+ 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_base;
+ *y = sy_base;
+}
+
+static void setRequestPositionExt(int *x, int *y, int width, int height,
+ boolean add_border_size)
{
int border_size = request.border_size;
- int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
- int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
- int sx = sx_center - request.width / 2;
- int sy = sy_center - request.height / 2;
+ int sx_base, sy_base;
+ int sx, sy;
+
+ 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 = MAX(0, MIN(sx, WIN_XSIZE - width));
+ sy = MAX(0, MIN(sy, WIN_YSIZE - height));
if (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)
{
+ int last_game_status = game_status; /* save current game status */
char *text_final = text;
char *text_door_style = NULL;
int graphic = IMG_BACKGROUND_REQUEST;
x, y, x_steps, y_steps,
tile_size, tile_size);
+ /* force DOOR font inside door area */
+ game_status = GAME_MODE_PSEUDO_DOOR;
+
DrawTextBuffer(sx + border_size, sy + border_size, text_final, font_nr,
line_length, -1, max_lines, line_spacing, mask_mode,
request.autowrap, request.centered, FALSE);
+ game_status = last_game_status; /* restore current game status */
+
for (i = 0; i < NUM_TOOL_BUTTONS; i++)
RedrawGadget(tool_gadget[i]);
boolean ffwd_delay = (tape.playing && tape.fast_forward);
boolean no_delay = (tape.warp_forward);
int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
- int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0);
+ 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;
int yend = (anim_mode != ANIM_DEFAULT ? max_ysize_inner : 0);
int xstep = (xstart < xend ? 1 : 0);
int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
- int x, y;
+ int start = 0;
+ int end = MAX(xend - xstart, yend - ystart);
+ int i;
- for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
+ if (setup.quick_doors)
{
+ xstart = xend;
+ ystart = yend;
+ end = 0;
+ }
+ else
+ {
+ if (action == ACTION_OPENING)
+ PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
+ else if (action == ACTION_CLOSING)
+ PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
+ }
+
+ for (i = start; i <= end; i++)
+ {
+ int last_frame = end; // last frame of this "for" loop
+ int x = xstart + i * xstep;
+ int y = ystart + i * ystep;
int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
- int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
- int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
- int src_x = sx_center - width / 2;
- int src_y = sy_center - height / 2;
- int dst_x = sx_center - xsize * tile_size / 2;
- int dst_y = sy_center - ysize * tile_size / 2;
int xsize_size_left = (xsize - 1) * tile_size;
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 width = xsize * tile_size;
+ int height = ysize * tile_size;
+ int src_x, src_y;
+ int dst_x, dst_y;
int xx, yy;
+ 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);
for (yy = 0; yy < 2; yy++)
}
}
- redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+ redraw_mask |= REDRAW_FIELD;
DoAnimation();
BackToFront();
- WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
+ SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
}
}
-
void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
{
- int last_game_status = game_status; /* save current game status */
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);
InitAnimation();
}
- /* force DOOR font inside door area */
- game_status = GAME_MODE_PSEUDO_DOOR;
-
game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
if (action == ACTION_OPENING)
AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
-
}
else
{
game.envelope_active = FALSE;
- game_status = last_game_status; /* restore current game status */
-
if (action == ACTION_CLOSING)
{
if (game_status != GAME_MODE_MAIN)
if (action == ACTION_CLOSING &&
game_status == GAME_MODE_PLAYING &&
level.game_engine_type == GAME_ENGINE_TYPE_RND)
- SetDrawtoField(DRAW_BUFFERED);
+ SetDrawtoField(DRAW_FIELDBUFFER);
}
void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
redraw_mask |= REDRAW_FIELD;
}
+void DrawSizedLevel(int size_x, int size_y, int scroll_x, int scroll_y,
+ int tilesize)
+{
+ int x,y;
+
+ for (x = 0; x < size_x; x++)
+ for (y = 0; y < size_y; y++)
+ DrawSizedElementOrWall(x, y, scroll_x, scroll_y, tilesize);
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
{
int x,y;
}
}
- redraw_mask |= REDRAW_MICROLEVEL;
+ redraw_mask |= REDRAW_FIELD;
}
#define MICROLABEL_EMPTY 0
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)
DrawPreviewLevelExt(FALSE);
}
-inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
- int graphic, int sync_frame, int mask_mode)
+inline static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+ int graphic, int sync_frame,
+ int mask_mode)
{
int frame = getGraphicAnimationFrame(graphic, sync_frame);
DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
}
-inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
- int graphic, int sync_frame,
- int mask_mode)
+void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+ int graphic, int sync_frame, int mask_mode)
{
int frame = getGraphicAnimationFrame(graphic, sync_frame);
DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
}
-inline void DrawGraphicAnimation(int x, int y, int graphic)
+inline static void DrawGraphicAnimation(int x, int y, int graphic)
{
int lx = LEVELX(x), ly = LEVELY(y);
MarkTileDirty(x, y);
}
-inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
+void DrawFixedGraphicAnimation(int x, int y, int graphic)
{
int lx = LEVELX(x), ly = LEVELY(y);
DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
}
-inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
+void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
{
int sx = SCREENX(x), sy = SCREENY(y);
syy = player->GfxPos;
}
- if (!setup.soft_scrolling && ScreenMovPos)
- sxx = syy = 0;
-
if (player_is_opaque)
DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
else
syy = player->GfxPos;
}
- if (!setup.soft_scrolling && ScreenMovPos)
- sxx = syy = 0;
-
if (player_is_opaque)
DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
else
static int RequestHandleEvents(unsigned int req_state)
{
- int last_game_status = game_status; /* save current game status */
+ boolean level_solved = (game_status == GAME_MODE_PLAYING &&
+ local_player->LevelSolved_GameEnd);
+ int width = request.width;
+ int height = request.height;
+ int sx, sy;
int result;
- int mx, my;
+
+ setRequestPosition(&sx, &sy, FALSE);
button_status = MB_RELEASED;
while (result < 0)
{
+ if (level_solved)
+ {
+ SetDrawtoField(DRAW_FIELDBUFFER);
+
+ HandleGameActions();
+
+ SetDrawtoField(DRAW_BACKBUFFER);
+
+ if (global.use_envelope_request)
+ {
+ /* copy current state of request area to middle of playfield area */
+ BlitBitmap(bitmap_db_cross, drawto, sx, sy, width, height, sx, sy);
+ }
+ }
+
if (PendingEvent())
{
Event event;
- NextEvent(&event);
-
- switch (event.type)
+ while (NextValidEvent(&event))
{
- case EVENT_BUTTONPRESS:
- case EVENT_BUTTONRELEASE:
- case EVENT_MOTIONNOTIFY:
+ switch (event.type)
{
- if (event.type == EVENT_MOTIONNOTIFY)
+ case EVENT_BUTTONPRESS:
+ case EVENT_BUTTONRELEASE:
+ case EVENT_MOTIONNOTIFY:
{
- if (!PointerInWindow(window))
- continue; /* window and pointer are on different screens */
+ int mx, my;
- if (!button_status)
- continue;
+ if (event.type == EVENT_MOTIONNOTIFY)
+ {
+ if (!button_status)
+ continue;
- motion_status = TRUE;
- mx = ((MotionEvent *) &event)->x;
- my = ((MotionEvent *) &event)->y;
- }
- else
- {
- motion_status = FALSE;
- mx = ((ButtonEvent *) &event)->x;
- my = ((ButtonEvent *) &event)->y;
- if (event.type == EVENT_BUTTONPRESS)
- button_status = ((ButtonEvent *) &event)->button;
+ motion_status = TRUE;
+ mx = ((MotionEvent *) &event)->x;
+ my = ((MotionEvent *) &event)->y;
+ }
else
- button_status = MB_RELEASED;
- }
-
- /* this sets 'request_gadget_id' */
- HandleGadgets(mx, my, button_status);
-
- switch (request_gadget_id)
- {
- case TOOL_CTRL_ID_YES:
- result = TRUE;
- break;
- case TOOL_CTRL_ID_NO:
- result = FALSE;
- break;
- case TOOL_CTRL_ID_CONFIRM:
- result = TRUE | FALSE;
- break;
-
- case TOOL_CTRL_ID_PLAYER_1:
- result = 1;
- break;
- case TOOL_CTRL_ID_PLAYER_2:
- result = 2;
- break;
- case TOOL_CTRL_ID_PLAYER_3:
- result = 3;
- break;
- case TOOL_CTRL_ID_PLAYER_4:
- result = 4;
- break;
-
- default:
- break;
+ {
+ motion_status = FALSE;
+ mx = ((ButtonEvent *) &event)->x;
+ my = ((ButtonEvent *) &event)->y;
+ if (event.type == EVENT_BUTTONPRESS)
+ button_status = ((ButtonEvent *) &event)->button;
+ else
+ button_status = MB_RELEASED;
+ }
+
+ /* this sets 'request_gadget_id' */
+ HandleGadgets(mx, my, button_status);
+
+ switch (request_gadget_id)
+ {
+ case TOOL_CTRL_ID_YES:
+ result = TRUE;
+ break;
+ case TOOL_CTRL_ID_NO:
+ result = FALSE;
+ break;
+ case TOOL_CTRL_ID_CONFIRM:
+ result = TRUE | FALSE;
+ break;
+
+ case TOOL_CTRL_ID_PLAYER_1:
+ result = 1;
+ break;
+ case TOOL_CTRL_ID_PLAYER_2:
+ result = 2;
+ break;
+ case TOOL_CTRL_ID_PLAYER_3:
+ result = 3;
+ break;
+ case TOOL_CTRL_ID_PLAYER_4:
+ result = 4;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
}
- break;
- }
+ case EVENT_KEYPRESS:
+ switch (GetEventKey((KeyEvent *)&event, TRUE))
+ {
+ case KSYM_space:
+ if (req_state & REQ_CONFIRM)
+ result = 1;
+ break;
- case EVENT_KEYPRESS:
- switch (GetEventKey((KeyEvent *)&event, TRUE))
- {
- case KSYM_space:
- if (req_state & REQ_CONFIRM)
- result = 1;
- break;
-
- case KSYM_Return:
+ case KSYM_Return:
#if defined(TARGET_SDL2)
- case KSYM_Menu:
+ case KSYM_Menu:
#endif
- result = 1;
- break;
+ result = 1;
+ break;
- case KSYM_Escape:
+ case KSYM_Escape:
#if defined(TARGET_SDL2)
- case KSYM_Back:
+ case KSYM_Back:
#endif
- result = 0;
- break;
+ result = 0;
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
- if (req_state & REQ_PLAYER)
- result = 0;
- break;
+ if (req_state & REQ_PLAYER)
+ result = 0;
+ break;
- case EVENT_KEYRELEASE:
- ClearPlayerAction();
- break;
+ case EVENT_KEYRELEASE:
+ ClearPlayerAction();
+ break;
- default:
- HandleOtherEvents(&event);
- break;
+ default:
+ HandleOtherEvents(&event);
+ break;
+ }
}
}
else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
result = 0;
}
- if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
+ if (level_solved)
{
- HandleGameActions();
+ if (global.use_envelope_request)
+ {
+ /* copy back current state of pressed buttons inside request area */
+ BlitBitmap(drawto, bitmap_db_cross, sx, sy, width, height, sx, sy);
+ }
}
else
{
Delay(10);
}
- game_status = GAME_MODE_PSEUDO_DOOR;
-
BackToFront();
-
- game_status = last_game_status; /* restore current game status */
}
return result;
{
num_panel_steps = 2 * door_rect->height / door->step_offset;
door->panel.start_step = num_panel_steps - num_door_steps;
+ door->panel.start_step_closing = door->panel.start_step;
}
else
{
num_panel_steps = door_rect->height / door->step_offset;
door->panel.start_step = num_panel_steps - num_door_steps / 2;
+ door->panel.start_step_closing = door->panel.start_step;
door->panel.step_delay *= 2;
}
}
unsigned int door_delay_value;
int i;
- if (door_1.width < 0 || door_1.width > DXSIZE)
- door_1.width = DXSIZE;
- if (door_1.height < 0 || door_1.height > DYSIZE)
- door_1.height = DYSIZE;
- if (door_2.width < 0 || door_2.width > VXSIZE)
- door_2.width = VXSIZE;
- if (door_2.height < 0 || door_2.height > VYSIZE)
- door_2.height = VYSIZE;
-
if (door_state == DOOR_GET_STATE)
return (door1 | door2);
int max_move_delay = 0; // delay for complete animations of all doors
int max_step_delay = 0; // delay (ms) between two animation frames
int num_move_steps = 0; // number of animation steps for all doors
+ int max_move_delay_doors_only = 0; // delay for doors only (no panel)
+ int num_move_steps_doors_only = 0; // steps for doors only (no panel)
int current_move_delay = 0;
+ int start = 0;
int k;
for (i = 0; i < NUM_DOORS; i++)
if (door_part_skip[nr])
continue;
- if (!is_panel)
- panel_has_doors[door_index] = TRUE;
-
max_move_delay = MAX(max_move_delay, move_delay);
max_step_delay = (max_step_delay == 0 ? step_delay :
euclid(max_step_delay, step_delay));
num_steps[nr] = move_steps;
+
+ if (!is_panel)
+ {
+ max_move_delay_doors_only = MAX(max_move_delay_doors_only, move_delay);
+
+ panel_has_doors[door_index] = TRUE;
+ }
}
+ max_step_delay = MAX(1, max_step_delay); // prevent division by zero
+
num_move_steps = max_move_delay / max_step_delay;
+ num_move_steps_doors_only = max_move_delay_doors_only / max_step_delay;
door_delay_value = max_step_delay;
- for (k = 0; k < num_move_steps; k++)
+ if ((door_state & DOOR_NO_DELAY) || setup.quick_doors)
{
+ start = num_move_steps - 1;
+ }
+ else
+ {
+ /* opening door sound has priority over simultaneously closing door */
+ if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
+ PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
+ else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
+ PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
+ }
+
+ for (k = start; k < num_move_steps; k++)
+ {
+ int last_frame = num_move_steps - 1; // last frame of this "for" loop
+
door_part_done_all = TRUE;
for (i = 0; i < NUM_DOORS; i++)
int door_token = dpc->door_token;
int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
boolean is_panel = DOOR_PART_IS_PANEL(nr);
+ boolean is_panel_and_door_has_closed = FALSE;
struct Rect *door_rect = &door_rect_list[door_index];
Bitmap *bitmap_db_door = (door_token == DOOR_1 ? bitmap_db_door_1 :
bitmap_db_door_2);
int step_factor = step_delay / max_step_delay;
int k1 = (step_factor ? k / step_factor + 1 : k);
int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
- int kk = (k2 < 0 ? 0 : k2);
+ int kk = MAX(0, k2);
+ int g_src_x = 0;
+ int g_src_y = 0;
int src_x, src_y, src_xx, src_yy;
int dst_x, dst_y, dst_xx, dst_yy;
int width, height;
if (!g->bitmap)
continue;
+ if (!is_panel)
+ {
+ int k2_door = (door_opening ? k : num_move_steps_doors_only - k - 1);
+ int kk_door = MAX(0, k2_door);
+ int sync_frame = kk_door * door_delay_value;
+ int frame = getGraphicAnimationFrame(dpc->graphic, sync_frame);
+
+ getGraphicSource(dpc->graphic, frame, &bitmap, &g_src_x, &g_src_y);
+ }
+
// draw door panel
if (!door_panel_drawn[door_index])
width = g->width - src_xx;
+ if (width > door_rect->width)
+ width = door_rect->width;
+
// printf("::: k == %d [%d] \n", k, start_step);
}
height = g->height - src_yy;
}
- if (is_panel)
- {
- src_x = src_xx;
- src_y = src_yy;
- }
- else
- {
- src_x = g->src_x + src_xx;
- src_y = g->src_y + src_yy;
- }
+ src_x = g_src_x + src_xx;
+ src_y = g_src_y + src_yy;
dst_x = door_rect->x + dst_xx;
dst_y = door_rect->y + dst_yy;
+ is_panel_and_door_has_closed =
+ (is_panel &&
+ door_closing &&
+ panel_has_doors[door_index] &&
+ k >= num_move_steps_doors_only - 1);
+
if (width >= 0 && width <= g->width &&
- height >= 0 && height <= g->height)
+ height >= 0 && height <= g->height &&
+ !is_panel_and_door_has_closed)
{
if (is_panel || !pos->draw_masked)
BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
door_part_done[nr] = TRUE;
// continue door part animations, but not panel after door has closed
- if (!door_part_done[nr] &&
- !(is_panel && door_closing && panel_has_doors[door_index]))
+ if (!door_part_done[nr] && !is_panel_and_door_has_closed)
door_part_done_all = FALSE;
}
if (game_status == GAME_MODE_MAIN)
DoAnimation();
- WaitUntilDelayReached(&door_delay, door_delay_value);
+ SkipUntilDelayReached(&door_delay, door_delay_value, &k, last_frame);
current_move_delay += max_step_delay;
}
return (door1 | door2);
}
+static boolean useSpecialEditorDoor()
+{
+ int graphic = IMG_GLOBAL_BORDER_EDITOR;
+ boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
+
+ // do not draw special editor door if editor border defined or redefined
+ if (graphic_info[graphic].bitmap != NULL || redefined)
+ return FALSE;
+
+ // do not draw special editor door if global border defined to be empty
+ if (graphic_info[IMG_GLOBAL_BORDER].bitmap == NULL)
+ return FALSE;
+
+ // do not draw special editor door if viewport definitions do not match
+ if (EX != VX ||
+ EY >= VY ||
+ EXSIZE != VXSIZE ||
+ EY + EYSIZE != VY + VYSIZE)
+ return FALSE;
+
+ return TRUE;
+}
+
void DrawSpecialEditorDoor()
{
struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
int vy = VY - outer_border;
int exsize = EXSIZE + 2 * outer_border;
- CloseDoor(DOOR_CLOSE_2);
+ if (!useSpecialEditorDoor())
+ return;
/* draw bigger level editor toolbox window */
BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
int exsize = EXSIZE + 2 * outer_border;
int eysize = EYSIZE + 2 * outer_border;
+ if (!useSpecialEditorDoor())
+ return;
+
/* draw normal tape recorder window */
if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
{
},
{
Xalpha_copyr, TRUE, FALSE,
- EL_CHAR('©'), -1, -1
+ EL_CHAR(CHAR_BYTE_COPYRIGHT), -1, -1
},
{
#endif
}
+void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame,
+ boolean any_player_moving,
+ boolean any_player_snapping,
+ boolean any_player_dropping)
+{
+ static boolean player_was_waiting = TRUE;
+
+ if (frame == 0 && !any_player_dropping)
+ {
+ if (!player_was_waiting)
+ {
+ if (!SaveEngineSnapshotToList())
+ return;
+
+ player_was_waiting = TRUE;
+ }
+ }
+ else if (any_player_moving || any_player_snapping || any_player_dropping)
+ {
+ player_was_waiting = FALSE;
+ }
+}
+
+void CheckSaveEngineSnapshot_SP(boolean murphy_is_waiting,
+ boolean murphy_is_dropping)
+{
+ static boolean player_was_waiting = TRUE;
+
+ if (murphy_is_waiting)
+ {
+ if (!player_was_waiting)
+ {
+ if (!SaveEngineSnapshotToList())
+ return;
+
+ player_was_waiting = TRUE;
+ }
+ }
+ else
+ {
+ player_was_waiting = FALSE;
+ }
+}
+
void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
boolean any_player_moving,
- boolean player_is_dropping)
+ boolean any_player_snapping,
+ boolean any_player_dropping)
{
if (tape.single_step && tape.recording && !tape.pausing)
- if (frame == 0 && !player_is_dropping)
+ if (frame == 0 && !any_player_dropping)
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+
+ CheckSaveEngineSnapshot_EM(action, frame, any_player_moving,
+ any_player_snapping, any_player_dropping);
}
void CheckSingleStepMode_SP(boolean murphy_is_waiting,
if (tape.single_step && tape.recording && !tape.pausing)
if (murphy_is_waiting)
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+
+ CheckSaveEngineSnapshot_SP(murphy_is_waiting, murphy_is_dropping);
}
void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
}
}
+void JoinRectangles(int *x, int *y, int *width, int *height,
+ int x2, int y2, int width2, int height2)
+{
+ // do not join with "off-screen" rectangle
+ if (x2 == -1 || y2 == -1)
+ return;
+
+ *x = MIN(*x, x2);
+ *y = MIN(*y, y2);
+ *width = MAX(*width, width2);
+ *height = MAX(*height, height2);
+}
+
void ChangeViewportPropertiesIfNeeded()
{
int gfx_game_mode = game_status;
new_tilesize_var != TILESIZE_VAR
)
{
+ // ------------------------------------------------------------------------
+ // determine next fading area for changed viewport definitions
+ // ------------------------------------------------------------------------
+
+ // start with current playfield area (default fading area)
+ FADE_SX = REAL_SX;
+ FADE_SY = REAL_SY;
+ FADE_SXSIZE = FULL_SXSIZE;
+ FADE_SYSIZE = FULL_SYSIZE;
+
+ // add new playfield area if position or size has changed
+ if (new_real_sx != REAL_SX || new_real_sy != REAL_SY ||
+ new_full_sxsize != FULL_SXSIZE || new_full_sysize != FULL_SYSIZE)
+ {
+ JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+ new_real_sx, new_real_sy, new_full_sxsize,new_full_sysize);
+ }
+
+ // add current and new door 1 area if position or size has changed
+ if (new_dx != DX || new_dy != DY ||
+ new_dxsize != DXSIZE || new_dysize != DYSIZE)
+ {
+ JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+ DX, DY, DXSIZE, DYSIZE);
+ JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+ new_dx, new_dy, new_dxsize, new_dysize);
+ }
+
+ // add current and new door 2 area if position or size has changed
+ if (new_dx != VX || new_dy != VY ||
+ new_dxsize != VXSIZE || new_dysize != VYSIZE)
+ {
+ JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+ VX, VY, VXSIZE, VYSIZE);
+ JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
+ new_vx, new_vy, new_vxsize, new_vysize);
+ }
+
+ // ------------------------------------------------------------------------
+ // handle changed tile size
+ // ------------------------------------------------------------------------
+
if (new_tilesize_var != TILESIZE_VAR)
{
// printf("::: new_tilesize_var != TILESIZE_VAR\n");
// changing tile size invalidates scroll values of engine snapshots
- FreeEngineSnapshot();
+ FreeEngineSnapshotSingle();
// changing tile size requires update of graphic mapping for EM engine
init_em_graphics = TRUE;
SCR_FIELDX = new_scr_fieldx;
SCR_FIELDY = new_scr_fieldy;
+
+ SetDrawDeactivationMask(REDRAW_NONE);
+ SetDrawBackgroundMask(REDRAW_FIELD);
}
if (init_video_buffer)
// printf("::: init_video_buffer\n");
InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
-
- SetDrawDeactivationMask(REDRAW_NONE);
- SetDrawBackgroundMask(REDRAW_FIELD);
}
if (init_gadgets_and_toons)