return s;
}
-void DumpTile(int x, int y)
+int correctLevelPosX_EM(int lx)
{
- int sx = SCREENX(x);
- int sy = SCREENY(y);
+ lx -= 1;
+ lx -= (BorderElement != EL_EMPTY ? 1 : 0);
- if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ return lx;
+}
+
+int correctLevelPosY_EM(int ly)
+{
+ ly -= 1;
+ ly -= (BorderElement != EL_EMPTY ? 1 : 0);
+
+ return ly;
+}
+
+static int getFieldbufferOffsetX_RND()
+{
+ int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
+ int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
+ int dx_var = dx * TILESIZE_VAR / TILESIZE;
+ int fx = FX;
+
+ if (EVEN(SCR_FIELDX))
+ {
+ int ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
+
+ if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
+ fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
+ else
+ fx += (dx_var > 0 ? TILEX_VAR : 0);
+ }
+ else
{
- x--;
- y--;
+ fx += dx_var;
}
+ if (full_lev_fieldx <= SCR_FIELDX)
+ {
+ if (EVEN(SCR_FIELDX))
+ fx = 2 * TILEX_VAR - (ODD(lev_fieldx) ? TILEX_VAR / 2 : 0);
+ else
+ fx = 2 * TILEX_VAR - (EVEN(lev_fieldx) ? TILEX_VAR / 2 : 0);
+ }
+
+ return fx;
+}
+
+static int getFieldbufferOffsetY_RND()
+{
+ int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
+ int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
+ int dy_var = dy * TILESIZE_VAR / TILESIZE;
+ int fy = FY;
+
+ if (EVEN(SCR_FIELDY))
+ {
+ int ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
+
+ if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
+ fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
+ else
+ fy += (dy_var > 0 ? TILEY_VAR : 0);
+ }
+ else
+ {
+ fy += dy_var;
+ }
+
+ if (full_lev_fieldy <= SCR_FIELDY)
+ {
+ if (EVEN(SCR_FIELDY))
+ fy = 2 * TILEY_VAR - (ODD(lev_fieldy) ? TILEY_VAR / 2 : 0);
+ else
+ fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0);
+ }
+
+ return fy;
+}
+
+static int getLevelFromScreenX_RND(int sx)
+{
+ int fx = getFieldbufferOffsetX_RND();
+ int dx = fx - FX;
+ int px = sx - SX;
+ int lx = LEVELX((px + dx) / TILESIZE_VAR);
+
+ return lx;
+}
+
+static int getLevelFromScreenY_RND(int sy)
+{
+ int fy = getFieldbufferOffsetY_RND();
+ int dy = fy - FY;
+ int py = sy - SY;
+ int ly = LEVELY((py + dy) / TILESIZE_VAR);
+
+ return ly;
+}
+
+static int getLevelFromScreenX_EM(int sx)
+{
+ int level_xsize = level.native_em_level->lev->width;
+ int full_xsize = level_xsize * TILESIZE_VAR;
+
+ sx -= (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
+
+ int fx = getFieldbufferOffsetX_EM();
+ int dx = fx;
+ int px = sx - SX;
+ int lx = LEVELX((px + dx) / TILESIZE_VAR);
+
+ lx = correctLevelPosX_EM(lx);
+
+ return lx;
+}
+
+static int getLevelFromScreenY_EM(int sy)
+{
+ int level_ysize = level.native_em_level->lev->height;
+ int full_ysize = level_ysize * TILESIZE_VAR;
+
+ sy -= (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
+
+ int fy = getFieldbufferOffsetY_EM();
+ int dy = fy;
+ int py = sy - SY;
+ int ly = LEVELY((py + dy) / TILESIZE_VAR);
+
+ ly = correctLevelPosY_EM(ly);
+
+ return ly;
+}
+
+static int getLevelFromScreenX_SP(int sx)
+{
+ int menBorder = setup.sp_show_border_elements;
+ int level_xsize = level.native_sp_level->width;
+ int full_xsize = (level_xsize - (menBorder ? 0 : 1)) * TILESIZE_VAR;
+
+ sx += (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
+
+ int fx = getFieldbufferOffsetX_SP();
+ int dx = fx - FX;
+ int px = sx - SX;
+ int lx = LEVELX((px + dx) / TILESIZE_VAR);
+
+ return lx;
+}
+
+static int getLevelFromScreenY_SP(int sy)
+{
+ int menBorder = setup.sp_show_border_elements;
+ int level_ysize = level.native_sp_level->height;
+ int full_ysize = (level_ysize - (menBorder ? 0 : 1)) * TILESIZE_VAR;
+
+ sy += (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
+
+ int fy = getFieldbufferOffsetY_SP();
+ int dy = fy - FY;
+ int py = sy - SY;
+ int ly = LEVELY((py + dy) / TILESIZE_VAR);
+
+ return ly;
+}
+
+static int getLevelFromScreenX_MM(int sx)
+{
+ int level_xsize = level.native_mm_level->fieldx;
+ int full_xsize = level_xsize * TILESIZE_VAR;
+
+ sx -= (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
+
+ int px = sx - SX;
+ int lx = (px + TILESIZE_VAR) / TILESIZE_VAR - 1;
+
+ return lx;
+}
+
+static int getLevelFromScreenY_MM(int sy)
+{
+ int level_ysize = level.native_mm_level->fieldy;
+ int full_ysize = level_ysize * TILESIZE_VAR;
+
+ sy -= (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
+
+ int py = sy - SY;
+ int ly = (py + TILESIZE_VAR) / TILESIZE_VAR - 1;
+
+ return ly;
+}
+
+int getLevelFromScreenX(int x)
+{
+ if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ return getLevelFromScreenX_EM(x);
+ if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ return getLevelFromScreenX_SP(x);
+ if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ return getLevelFromScreenX_MM(x);
+ else
+ return getLevelFromScreenX_RND(x);
+}
+
+int getLevelFromScreenY(int y)
+{
+ if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ return getLevelFromScreenY_EM(y);
+ if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ return getLevelFromScreenY_SP(y);
+ if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ return getLevelFromScreenY_MM(y);
+ else
+ return getLevelFromScreenY_RND(y);
+}
+
+void DumpTile(int x, int y)
+{
+ int sx = SCREENX(x);
+ int sy = SCREENY(y);
+ char *token_name;
+
printf_line("-", 79);
printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
printf_line("-", 79);
return;
}
- printf(" Feld: %d\t['%s']\n", Feld[x][y],
- element_info[Feld[x][y]].token_name);
+ token_name = element_info[Feld[x][y]].token_name;
+
+ printf(" Feld: %d\t['%s']\n", Feld[x][y], token_name);
printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
printf(" GfxElement: %d\n", GfxElement[x][y]);
printf(" GfxAction: %d\n", GfxAction[x][y]);
printf(" GfxFrame: %d [%d]\n", GfxFrame[x][y], FrameCounter);
+ printf(" Player x/y: %d, %d\n", local_player->jx, local_player->jy);
printf("\n");
}
+void DumpTileFromScreen(int sx, int sy)
+{
+ int lx = getLevelFromScreenX(sx);
+ int ly = getLevelFromScreenY(sy);
+
+ DumpTile(lx, ly);
+}
+
void SetDrawtoField(int mode)
{
if (mode == DRAW_TO_FIELDBUFFER)
RedrawPlayfield_EM(TRUE);
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
RedrawPlayfield_SP(TRUE);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ RedrawPlayfield_MM();
else if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
RedrawPlayfield_RND();
}
}
-void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
+void DrawTileCursor(int draw_target)
{
- 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);
+ Bitmap *fade_bitmap;
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int dst_x, dst_y;
+ int graphic = IMG_GLOBAL_TILE_CURSOR;
+ int frame = 0;
+ int tilesize = TILESIZE_VAR;
+ int width = tilesize;
+ int height = tilesize;
- int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
- int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
- int dx_var = dx * TILESIZE_VAR / TILESIZE;
- int dy_var = dy * TILESIZE_VAR / TILESIZE;
- int ffx, ffy;
+ if (game_status != GAME_MODE_PLAYING)
+ return;
- ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
- ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
+ if (!tile_cursor.enabled ||
+ !tile_cursor.active)
+ return;
- 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;
- else
- fx += (dx_var > 0 ? TILEX_VAR : 0);
- }
- else
+ if (tile_cursor.moving)
{
- fx += dx_var;
- }
+ int step = TILESIZE_VAR / 4;
+ int dx = tile_cursor.target_x - tile_cursor.x;
+ int dy = tile_cursor.target_y - tile_cursor.y;
- 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 (ABS(dx) < step)
+ tile_cursor.x = tile_cursor.target_x;
else
- fy += (dy_var > 0 ? TILEY_VAR : 0);
- }
- else
- {
- fy += dy_var;
- }
+ tile_cursor.x += SIGN(dx) * step;
- if (full_lev_fieldx <= SCR_FIELDX)
- {
- if (EVEN(SCR_FIELDX))
- fx = 2 * TILEX_VAR - (ODD(lev_fieldx) ? TILEX_VAR / 2 : 0);
+ if (ABS(dy) < step)
+ tile_cursor.y = tile_cursor.target_y;
else
- fx = 2 * TILEX_VAR - (EVEN(lev_fieldx) ? TILEX_VAR / 2 : 0);
- }
+ tile_cursor.y += SIGN(dy) * step;
- if (full_lev_fieldy <= SCR_FIELDY)
- {
- if (EVEN(SCR_FIELDY))
- fy = 2 * TILEY_VAR - (ODD(lev_fieldy) ? TILEY_VAR / 2 : 0);
- else
- fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0);
+ if (tile_cursor.x == tile_cursor.target_x &&
+ tile_cursor.y == tile_cursor.target_y)
+ tile_cursor.moving = FALSE;
}
+ dst_x = tile_cursor.x;
+ dst_y = tile_cursor.y;
+
+ frame = getGraphicAnimationFrame(graphic, -1);
+
+ getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
+
+ fade_bitmap =
+ (draw_target == DRAW_TO_FADE_SOURCE ? gfx.fade_bitmap_source :
+ draw_target == DRAW_TO_FADE_TARGET ? gfx.fade_bitmap_target : NULL);
+
+ if (draw_target == DRAW_TO_SCREEN)
+ BlitToScreenMasked(src_bitmap, src_x, src_y, width, height, dst_x, dst_y);
+ else
+ BlitBitmapMasked(src_bitmap, fade_bitmap, src_x, src_y, width, height,
+ dst_x, dst_y);
+}
+
+void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
+{
+ int fx = getFieldbufferOffsetX_RND();
+ int fy = getFieldbufferOffsetY_RND();
+
BlitBitmap(drawto_field, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
}
BlitScreenToBitmap_EM(target_bitmap);
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
BlitScreenToBitmap_SP(target_bitmap);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ BlitScreenToBitmap_MM(target_bitmap);
else if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
BlitScreenToBitmap_RND(target_bitmap);
char text[100];
int font_nr = FONT_TEXT_2;
int font_width = getFontWidth(font_nr);
+ int draw_deactivation_mask = GetDrawDeactivationMask();
+ boolean draw_masked = (draw_deactivation_mask == REDRAW_NONE);
- sprintf(text, "%04.1f fps", global.frames_per_second);
+ /* draw FPS with leading space (needed if field buffer deactivated) */
+ sprintf(text, " %04.1f fps", global.frames_per_second);
- DrawTextExt(backbuffer, WIN_XSIZE - font_width * strlen(text), 0, text,
- font_nr, BLIT_OPAQUE);
+ /* override draw deactivation mask (required for invisible warp mode) */
+ SetDrawDeactivationMask(REDRAW_NONE);
+
+ /* draw opaque FPS if field buffer deactivated, else draw masked FPS */
+ DrawTextExt(backbuffer, SX + SXSIZE - font_width * strlen(text), SY, text,
+ font_nr, (draw_masked ? BLIT_MASKED : BLIT_OPAQUE));
+
+ /* set draw deactivation mask to previous value */
+ SetDrawDeactivationMask(draw_deactivation_mask);
+
+ /* force full-screen redraw in this frame */
+ redraw_mask = REDRAW_ALL;
}
#if DEBUG_FRAME_TIME
}
#endif
+static int unifiedRedrawMask(int mask)
+{
+ if (mask & REDRAW_ALL)
+ return REDRAW_ALL;
+
+ if (mask & REDRAW_FIELD && mask & REDRAW_DOORS)
+ return REDRAW_ALL;
+
+ return mask;
+}
+
+static boolean equalRedrawMasks(int mask_1, int mask_2)
+{
+ return unifiedRedrawMask(mask_1) == unifiedRedrawMask(mask_2);
+}
+
void BackToFront()
{
static int last_redraw_mask = REDRAW_NONE;
if (redraw_mask & REDRAW_FPS)
DrawFramesPerSecond();
+ // remove playfield redraw before potentially merging with doors redraw
+ if (DrawingDeactivated(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE))
+ redraw_mask &= ~REDRAW_FIELD;
+
// redraw complete window if both playfield and (some) doors need redraw
if (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS)
redraw_mask = REDRAW_ALL;
}
else if (redraw_mask & REDRAW_DOORS)
{
+ // merge door areas to prevent calling screen redraw more than once
+ int x1 = WIN_XSIZE;
+ int y1 = WIN_YSIZE;
+ int x2 = 0;
+ int y2 = 0;
+
if (redraw_mask & REDRAW_DOOR_1)
- BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
+ {
+ x1 = MIN(x1, DX);
+ y1 = MIN(y1, DY);
+ x2 = MAX(x2, DX + DXSIZE);
+ y2 = MAX(y2, DY + DYSIZE);
+ }
if (redraw_mask & REDRAW_DOOR_2)
- BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
+ {
+ x1 = MIN(x1, VX);
+ y1 = MIN(y1, VY);
+ x2 = MAX(x2, VX + VXSIZE);
+ y2 = MAX(y2, VY + VYSIZE);
+ }
if (redraw_mask & REDRAW_DOOR_3)
- BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
+ {
+ x1 = MIN(x1, EX);
+ y1 = MIN(y1, EY);
+ x2 = MAX(x2, EX + EXSIZE);
+ y2 = MAX(y2, EY + EYSIZE);
+ }
+
+ // make sure that at least one pixel is blitted, and inside the screen
+ // (else nothing is blitted, causing the animations not to be updated)
+ x1 = MIN(MAX(0, x1), WIN_XSIZE - 1);
+ y1 = MIN(MAX(0, y1), WIN_YSIZE - 1);
+ x2 = MIN(MAX(1, x2), WIN_XSIZE);
+ y2 = MIN(MAX(1, y2), WIN_YSIZE);
+
+ BlitBitmap(backbuffer, window, x1, y1, x2 - x1, y2 - y1, x1, y1);
}
redraw_mask = REDRAW_NONE;
SetVideoFrameDelay(frame_delay_value_old);
}
-static void FadeCrossSaveBackbuffer()
-{
- 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 int fade_type_skip = FADE_TYPE_NONE;
static void FadeExt(int fade_mask, int fade_mode, int fade_type)
{
- static int fade_type_skip = FADE_TYPE_NONE;
void (*draw_border_function)(void) = NULL;
- Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
int x, y, width, height;
int fade_delay, post_delay;
return;
}
-#if 1
- FadeCrossSaveBackbuffer();
-#endif
-
if (fading.fade_mode & FADE_TYPE_TRANSFORM)
- {
-#if 0
- FadeCrossSaveBackbuffer();
-#endif
-
return;
- }
}
redraw_mask |= fade_mask;
return;
}
- FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
+ FadeRectangle(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;
+
+ ClearEventQueue();
}
static void SetScreenStates_BeforeFadingIn()
global.anim_status = global.anim_status_next;
// store backbuffer with all animations that will be started after fading in
- PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
+ if (fade_type_skip != FADE_MODE_SKIP_FADE_IN)
+ PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
// set screen mode for animations back to fading
global.anim_status = GAME_MODE_PSEUDO_FADING;
gfx.fade_border_source_status = global.border_status;
global.anim_status = global.anim_status_next;
-
- // force update of global animation status in case of rapid screen changes
- redraw_mask = REDRAW_ALL;
- BackToFront();
}
static void SetScreenStates_BeforeFadingOut()
global.anim_status = GAME_MODE_PSEUDO_FADING;
// store backbuffer with all animations that will be stopped for fading out
- PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
+ if (fade_type_skip != FADE_MODE_SKIP_FADE_OUT)
+ PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
}
static void SetScreenStates_AfterFadingOut()
FADE_SXSIZE = FULL_SXSIZE;
FADE_SYSIZE = FULL_SYSIZE;
+ if (game_status == GAME_MODE_PLAYING &&
+ strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS))
+ SetOverlayActive(TRUE);
+
SetScreenStates_AfterFadingIn();
+
+ // force update of global animation status in case of rapid screen changes
+ redraw_mask = REDRAW_ALL;
+ BackToFront();
}
void FadeOut(int fade_mask)
{
+ // update screen if areas covered by "fade_mask" and "redraw_mask" differ
+ if (!equalRedrawMasks(fade_mask, redraw_mask))
+ BackToFront();
+
SetScreenStates_BeforeFadingOut();
+ SetTileCursorActive(FALSE);
+ SetOverlayActive(FALSE);
+
#if 0
DrawMaskedBorder(REDRAW_ALL);
#endif
static int dxsize_last = -1, dysize_last = -1;
static int vx_last = -1, vy_last = -1;
static int vxsize_last = -1, vysize_last = -1;
+static int ex_last = -1, ey_last = -1;
+static int exsize_last = -1, eysize_last = -1;
boolean CheckIfGlobalBorderHasChanged()
{
vxsize_last != VXSIZE || vysize_last != VYSIZE)
return TRUE;
+ // redraw if position or size of editor area has changed
+ if (ex_last != EX || ey_last != EY ||
+ exsize_last != EXSIZE || eysize_last != EYSIZE)
+ return TRUE;
+
return FALSE;
}
redraw_mask = REDRAW_ALL;
}
+#define ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED 0
+
static void RedrawGlobalBorderIfNeeded()
{
+#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
if (game_status == game_status_last)
return;
+#endif
// copy current draw buffer to later copy back areas that have not changed
if (game_status_last != GAME_MODE_TITLE)
- BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ BlitBitmap(backbuffer, bitmap_db_store_1, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
if (CheckIfGlobalBorderRedrawIsNeeded())
+#endif
{
// redraw global screen border (or clear, if defined to be empty)
RedrawGlobalBorderFromBitmap(global_border_bitmap);
+ if (game_status == GAME_MODE_EDITOR)
+ DrawSpecialEditorDoor();
+
// 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,
+ BlitBitmap(bitmap_db_store_1, 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,
+ BlitBitmap(bitmap_db_store_1, 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);
+ if (game_status != GAME_MODE_EDITOR)
+ {
+ if (vx_last != -1 && vy_last != -1 &&
+ VX != -1 && VY != -1 &&
+ vxsize_last == VXSIZE && vysize_last == VYSIZE)
+ BlitBitmap(bitmap_db_store_1, backbuffer,
+ vx_last, vy_last, VXSIZE, VYSIZE, VX, VY);
+ }
+ else
+ {
+ if (ex_last != -1 && ey_last != -1 &&
+ EX != -1 && EY != -1 &&
+ exsize_last == EXSIZE && eysize_last == EYSIZE)
+ BlitBitmap(bitmap_db_store_1, backbuffer,
+ ex_last, ey_last, EXSIZE, EYSIZE, EX, EY);
+ }
redraw_mask = REDRAW_ALL;
}
vy_last = VY;
vxsize_last = VXSIZE;
vysize_last = VYSIZE;
+ ex_last = EX;
+ ey_last = EY;
+ exsize_last = EXSIZE;
+ eysize_last = EYSIZE;
}
void ClearField()
BorderElement = EL_EMPTY;
+ /* the MM game engine does not use a visible border element */
+ if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ return;
+
for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
{
for (x = 0; x < lev_fieldx; x++)
}
}
-void FloodFillLevel(int from_x, int from_y, int fill_element,
- short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
- int max_fieldx, int max_fieldy)
+void FloodFillLevelExt(int from_x, int from_y, int fill_element,
+ int max_array_fieldx, int max_array_fieldy,
+ short field[max_array_fieldx][max_array_fieldy],
+ int max_fieldx, int max_fieldy)
{
int i,x,y;
int old_element;
y = from_y + check[i][1];
if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
- FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
+ FloodFillLevelExt(x, y, fill_element, max_array_fieldx, max_array_fieldy,
+ field, max_fieldx, max_fieldy);
}
safety--;
}
+void FloodFillLevel(int from_x, int from_y, int fill_element,
+ short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
+ int max_fieldx, int max_fieldy)
+{
+ FloodFillLevelExt(from_x, from_y, fill_element,
+ MAX_LEV_FIELDX, MAX_LEV_FIELDY, field,
+ max_fieldx, max_fieldy);
+}
+
void SetRandomAnimationValue(int x, int y)
{
gfx.anim_random_frame = GfxRandom[x][y];
sync_frame);
}
-void getSizedGraphicSourceExt(int graphic, int frame, int tilesize,
- Bitmap **bitmap, int *x, int *y,
- boolean get_backside)
+void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap)
{
struct GraphicInfo *g = &graphic_info[graphic];
- Bitmap *src_bitmap = g->bitmap;
- 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 no in-game graphics defined, always use standard graphic size
- if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
- tilesize = TILESIZE;
-
if (tilesize == gfx.standard_tile_size)
- src_bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
+ *bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
else if (tilesize == game.tile_size)
- src_bitmap = g->bitmaps[IMG_BITMAP_GAME];
+ *bitmap = g->bitmaps[IMG_BITMAP_GAME];
else
- src_bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
+ *bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
+}
+
+void getGraphicSourceXY(int graphic, int frame, 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);
+ int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
if (g->offset_y == 0) /* frames are ordered horizontally */
{
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 % g->height + pos / max_width * g->height;
+ *x = pos % max_width;
+ *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 * g->height;
int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
- src_x = src_x % g->width + pos / max_height * g->width;
- src_y = pos % max_height;
+ *x = src_x % g->width + pos / max_height * g->width;
+ *y = pos % max_height;
}
else /* frames are ordered diagonally */
{
- src_x = src_x + frame * g->offset_x;
- src_y = src_y + frame * g->offset_y;
+ *x = src_x + frame * g->offset_x;
+ *y = src_y + frame * g->offset_y;
}
-
- *bitmap = src_bitmap;
- *x = src_x * tilesize / g->tile_size;
- *y = src_y * tilesize / g->tile_size;
}
-void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
- int *x, int *y, boolean get_backside)
+void getSizedGraphicSourceExt(int graphic, int frame, int tilesize,
+ Bitmap **bitmap, int *x, int *y,
+ boolean get_backside)
{
- getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
- get_backside);
+ struct GraphicInfo *g = &graphic_info[graphic];
+
+ // if no graphics defined at all, use fallback graphics
+ if (g->bitmaps == NULL)
+ *g = graphic_info[IMG_CHAR_EXCLAM];
+
+ // if no in-game graphics defined, always use standard graphic size
+ if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
+ tilesize = TILESIZE;
+
+ getGraphicSourceBitmap(graphic, tilesize, bitmap);
+ getGraphicSourceXY(graphic, frame, x, y, get_backside);
+
+ *x = *x * tilesize / g->tile_size;
+ *y = *y * tilesize / g->tile_size;
}
void getSizedGraphicSource(int graphic, int frame, int tilesize,
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);
- int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
-
- if (TILESIZE_VAR != TILESIZE)
- return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
- get_backside);
-
- *bitmap = g->bitmap;
-
- if (g->offset_y == 0) /* frames are ordered horizontally */
- {
- int max_width = g->anim_frames_per_line * g->width;
- int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
-
- *x = pos % max_width;
- *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 * g->height;
- int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
-
- *x = src_x % g->width + pos / max_height * g->width;
- *y = pos % max_height;
- }
- else /* frames are ordered diagonally */
- {
- *x = src_x + frame * g->offset_x;
- *y = src_y + frame * g->offset_y;
- }
-
- *x = *x * TILESIZE_VAR / g->tile_size;
- *y = *y * TILESIZE_VAR / g->tile_size;
+ getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
+ get_backside);
}
void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
MarkTileDirty(x / tilesize, y / tilesize);
}
+void DrawSizedGraphicThruMask(int x, int y, int graphic, int frame,
+ int tilesize)
+{
+ DrawSizedGraphicThruMaskExt(drawto, SX + x * tilesize, SY + y * tilesize,
+ graphic, frame, tilesize);
+ MarkTileDirty(x / tilesize, y / tilesize);
+}
+
void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
int tilesize)
{
BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
}
+void DrawSizedGraphicThruMaskExt(DrawBuffer *d, int x, int y, int graphic,
+ int frame, int tilesize)
+{
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+
+ getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
+ BlitBitmapMasked(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
+}
+
void DrawMiniGraphic(int x, int y, int graphic)
{
DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
int width, height, cx, cy;
int sx = SCREENX(x), sy = SCREENY(y);
int crumbled_border_size = graphic_info[graphic].border_size;
+ int crumbled_tile_size = graphic_info[graphic].tile_size;
+ int crumbled_border_size_var =
+ crumbled_border_size * TILESIZE_VAR / crumbled_tile_size;
int i;
getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
- width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
- height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
+ width = crumbled_border_size_var;
+ height = crumbled_border_size_var;
cx = (dx > 0 ? TILESIZE_VAR - width : 0);
cy = (dy > 0 ? TILESIZE_VAR - height : 0);
int width, height, bx, by, cx, cy;
int sx = SCREENX(x), sy = SCREENY(y);
int crumbled_border_size = graphic_info[graphic].border_size;
- int crumbled_border_size_var = crumbled_border_size * TILESIZE_VAR / TILESIZE;
+ int crumbled_tile_size = graphic_info[graphic].tile_size;
+ int crumbled_border_size_var =
+ crumbled_border_size * TILESIZE_VAR / crumbled_tile_size;
int crumbled_border_pos_var = TILESIZE_VAR - crumbled_border_size_var;
int i;
/* (remaining middle border part must be at least as big as corner part) */
if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
- crumbled_border_size >= TILESIZE / 3)
+ crumbled_border_size_var >= TILESIZE_VAR / 3)
return;
/* correct corners of crumbled border, if needed */
element = TILE_GFX_ELEMENT(x, y);
- /* crumble field itself */
- if (IS_CRUMBLED_TILE(x, y, element))
+ if (IS_CRUMBLED_TILE(x, y, element)) /* crumble field itself */
{
if (!IN_SCR_FIELD(sx, sy))
return;
+ /* crumble field borders towards direct neighbour fields */
for (i = 0; i < 4; i++)
{
int xx = x + xy[i][0];
DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
}
+ /* crumble inner field corners towards corner neighbour fields */
if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
graphic_info[graphic].anim_frames == 2)
{
MarkTileDirty(sx, sy);
}
- else /* center field not crumbled -- crumble neighbour fields */
+ else /* center field is not crumbled -- crumble neighbour fields */
{
+ /* crumble field borders of direct neighbour fields */
for (i = 0; i < 4; i++)
{
int xx = x + xy[i][0];
MarkTileDirty(sxx, syy);
}
+
+ /* crumble inner field corners of corner neighbour fields */
+ for (i = 0; i < 4; i++)
+ {
+ int dx = (i & 1 ? +1 : -1);
+ int dy = (i & 2 ? +1 : -1);
+ int xx = x + dx;
+ int yy = y + dy;
+ int sxx = sx + dx;
+ int syy = sy + dy;
+
+ if (!IN_LEV_FIELD(xx, yy) ||
+ !IN_SCR_FIELD(sxx, syy))
+ continue;
+
+ if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
+ continue;
+
+ element = TILE_GFX_ELEMENT(xx, yy);
+
+ if (!IS_CRUMBLED_TILE(xx, yy, element))
+ continue;
+
+ graphic = el_act2crm(element, ACTION_DEFAULT);
+
+ if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
+ graphic_info[graphic].anim_frames == 2)
+ DrawLevelFieldCrumbledInnerCorners(xx, yy, -dx, -dy, graphic);
+
+ MarkTileDirty(sxx, syy);
+ }
}
}
};
int i;
+ /* crumble direct neighbour fields (required for field borders) */
for (i = 0; i < 4; i++)
{
int xx = x + xy[i][0];
DrawLevelField(xx, yy);
}
+
+ /* crumble corner neighbour fields (required for inner field corners) */
+ for (i = 0; i < 4; i++)
+ {
+ int dx = (i & 1 ? +1 : -1);
+ int dy = (i & 2 ? +1 : -1);
+ int xx = x + dx;
+ int yy = y + dy;
+ int sxx = sx + dx;
+ int syy = sy + dy;
+
+ if (!IN_LEV_FIELD(xx, yy) ||
+ !IN_SCR_FIELD(sxx, syy) ||
+ !GFX_CRUMBLED(Feld[xx][yy]) ||
+ IS_MOVING(xx, yy))
+ continue;
+
+ int element = TILE_GFX_ELEMENT(xx, yy);
+ int graphic = el_act2crm(element, ACTION_DEFAULT);
+
+ if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
+ graphic_info[graphic].anim_frames == 2)
+ DrawLevelField(xx, yy);
+ }
}
static int getBorderElement(int x, int y)
int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
DrawLevelElementThruMask(newlx, newly, EL_ACID);
+
+ // prevent target field from being drawn again (but without masking)
+ // (this would happen if target field is scanned after moving element)
+ Stop[newlx][newly] = TRUE;
}
}
else if (IS_BLOCKED(lx, ly))
}
}
+static void DrawSizedWallExt_MM(int dst_x, int dst_y, int element, int tilesize,
+ int (*el2img_function)(int), boolean masked,
+ int element_bits_draw)
+{
+ int element_base = map_mm_wall_element(element);
+ int element_bits = (IS_DF_WALL(element) ?
+ element - EL_DF_WALL_START :
+ IS_MM_WALL(element) ?
+ element - EL_MM_WALL_START : EL_EMPTY) & 0x000f;
+ int graphic = el2img_function(element_base);
+ int tilesize_draw = tilesize / 2;
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int i;
+
+ getSizedGraphicSource(graphic, 0, tilesize_draw, &src_bitmap, &src_x, &src_y);
+
+ for (i = 0; i < 4; i++)
+ {
+ int dst_draw_x = dst_x + (i % 2) * tilesize_draw;
+ int dst_draw_y = dst_y + (i / 2) * tilesize_draw;
+
+ if (!(element_bits_draw & (1 << i)))
+ continue;
+
+ if (element_bits & (1 << i))
+ {
+ if (masked)
+ BlitBitmapMasked(src_bitmap, drawto, src_x, src_y,
+ tilesize_draw, tilesize_draw, dst_draw_x, dst_draw_y);
+ else
+ BlitBitmap(src_bitmap, drawto, src_x, src_y,
+ tilesize_draw, tilesize_draw, dst_draw_x, dst_draw_y);
+ }
+ else
+ {
+ if (!masked)
+ ClearRectangle(drawto, dst_draw_x, dst_draw_y,
+ tilesize_draw, tilesize_draw);
+ }
+ }
+}
+
+void DrawSizedWallParts_MM(int x, int y, int element, int tilesize,
+ boolean masked, int element_bits_draw)
+{
+ DrawSizedWallExt_MM(SX + x * tilesize, SY + y * tilesize,
+ element, tilesize, el2edimg, masked, element_bits_draw);
+}
+
+void DrawSizedWall_MM(int dst_x, int dst_y, int element, int tilesize,
+ int (*el2img_function)(int))
+{
+ DrawSizedWallExt_MM(dst_x, dst_y, element, tilesize, el2img_function, FALSE,
+ 0x000f);
+}
+
+void DrawSizedElementExt(int x, int y, int element, int tilesize,
+ boolean masked)
+{
+ if (IS_MM_WALL(element))
+ {
+ DrawSizedWallExt_MM(SX + x * tilesize, SY + y * tilesize,
+ element, tilesize, el2edimg, masked, 0x000f);
+ }
+ else
+ {
+ int graphic = el2edimg(element);
+
+ if (masked)
+ DrawSizedGraphicThruMask(x, y, graphic, 0, tilesize);
+ else
+ DrawSizedGraphic(x, y, graphic, 0, tilesize);
+ }
+}
+
void DrawSizedElement(int x, int y, int element, int tilesize)
{
- int graphic;
+ DrawSizedElementExt(x, y, element, tilesize, FALSE);
+}
- graphic = el2edimg(element);
- DrawSizedGraphic(x, y, graphic, 0, tilesize);
+void DrawSizedElementThruMask(int x, int y, int element, int tilesize)
+{
+ DrawSizedElementExt(x, y, element, tilesize, TRUE);
}
void DrawMiniElement(int x, int y, int element)
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) / 2;
+ int anim_delay_value = MAX(1, (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);
SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
}
+
+ ClearEventQueue();
}
void ShowEnvelope(int envelope_nr)
RedrawGadget(tool_gadget[i]);
// store readily prepared envelope request for later use when animating
- BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ BlitBitmap(backbuffer, bitmap_db_store_2, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
if (text_door_style)
free(text_door_style);
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) / 2;
+ int anim_delay_value = MAX(1, (no_delay ? 0 : delay_value + 500 * 0) / 2);
unsigned int anim_delay = 0;
int tile_size = MAX(request.step_offset, 1);
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);
+ BlitBitmap(bitmap_db_store_1, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
for (yy = 0; yy < 2; yy++)
{
int yy_size = (yy ? tile_size : ysize_size_top);
if (draw_masked)
- BlitBitmapMasked(bitmap_db_cross, backbuffer,
+ BlitBitmapMasked(bitmap_db_store_2, backbuffer,
src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
else
- BlitBitmap(bitmap_db_cross, backbuffer,
+ BlitBitmap(bitmap_db_store_2, backbuffer,
src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
}
}
SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
}
+
+ ClearEventQueue();
}
void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
if (action == ACTION_OPENING)
{
- BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ BlitBitmap(backbuffer, bitmap_db_store_1, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
if (req_state & REQ_ASK)
{
game.envelope_active = FALSE;
if (action == ACTION_CLOSING)
- BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ BlitBitmap(bitmap_db_store_1, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
// SetDrawBackgroundMask(last_draw_background_mask);
void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
{
- Bitmap *src_bitmap;
- int src_x, src_y;
- int graphic = el2preimg(element);
+ if (IS_MM_WALL(element))
+ {
+ DrawSizedWall_MM(dst_x, dst_y, element, tilesize, el2preimg);
+ }
+ else
+ {
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int graphic = el2preimg(element);
- getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
- BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
+ getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
+ BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize,
+ dst_x, dst_y);
+ }
}
void DrawLevel(int draw_background_mask)
redraw_mask |= REDRAW_FIELD;
}
-static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
+static void DrawPreviewLevelPlayfield(int from_x, int from_y)
{
boolean show_level_border = (BorderElement != EL_EMPTY);
int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
return max_text_width / font_width;
}
-static void DrawPreviewLevelLabelExt(int mode)
+static void DrawPreviewLevelLabelExt(int mode, struct TextPosInfo *pos)
{
- struct TextPosInfo *pos = &menu.main.text.level_info_2;
char label_text[MAX_OUTPUT_LINESIZE + 1];
int max_len_label_text;
int font_nr = pos->font;
redraw_mask |= REDRAW_FIELD;
}
+static void DrawPreviewLevelLabel(int mode)
+{
+ DrawPreviewLevelLabelExt(mode, &menu.main.text.level_info_2);
+}
+
+static void DrawPreviewLevelInfo(int mode)
+{
+ if (mode == MICROLABEL_LEVEL_NAME)
+ DrawPreviewLevelLabelExt(mode, &menu.main.text.level_name);
+ else if (mode == MICROLABEL_LEVEL_AUTHOR)
+ DrawPreviewLevelLabelExt(mode, &menu.main.text.level_author);
+}
+
static void DrawPreviewLevelExt(boolean restart)
{
static unsigned int scroll_delay = 0;
label_state = 1;
label_counter = 0;
- DrawPreviewLevelPlayfieldExt(from_x, from_y);
- DrawPreviewLevelLabelExt(label_state);
+ DrawPreviewLevelPlayfield(from_x, from_y);
+ DrawPreviewLevelLabel(label_state);
+
+ DrawPreviewLevelInfo(MICROLABEL_LEVEL_NAME);
+ DrawPreviewLevelInfo(MICROLABEL_LEVEL_AUTHOR);
/* initialize delay counters */
DelayReached(&scroll_delay, 0);
scroll_direction = MV_LEFT;
break;
- default:
- break;
- }
+ default:
+ break;
+ }
+
+ DrawPreviewLevelPlayfield(from_x, from_y);
+ }
+
+ /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
+ /* redraw micro level label, if needed */
+ 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;
+
+ if (leveldir_current->imported_from != NULL &&
+ strlen(leveldir_current->imported_from) > 0)
+ max_label_counter += 14;
+ if (leveldir_current->imported_by != NULL &&
+ strlen(leveldir_current->imported_by) > 0)
+ max_label_counter += 14;
+
+ label_counter = (label_counter + 1) % max_label_counter;
+ label_state = (label_counter >= 0 && label_counter <= 7 ?
+ MICROLABEL_LEVEL_NAME :
+ label_counter >= 9 && label_counter <= 12 ?
+ MICROLABEL_LEVEL_AUTHOR_HEAD :
+ label_counter >= 14 && label_counter <= 21 ?
+ MICROLABEL_LEVEL_AUTHOR :
+ label_counter >= 23 && label_counter <= 26 ?
+ MICROLABEL_IMPORTED_FROM_HEAD :
+ label_counter >= 28 && label_counter <= 35 ?
+ MICROLABEL_IMPORTED_FROM :
+ label_counter >= 37 && label_counter <= 40 ?
+ MICROLABEL_IMPORTED_BY_HEAD :
+ label_counter >= 42 && label_counter <= 49 ?
+ MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
+
+ if (leveldir_current->imported_from == NULL &&
+ (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
+ label_state == MICROLABEL_IMPORTED_FROM))
+ label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
+ MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
+
+ DrawPreviewLevelLabel(label_state);
+ }
+}
+
+void DrawPreviewPlayers()
+{
+ if (game_status != GAME_MODE_MAIN)
+ return;
+
+ if (!network.enabled && !setup.team_mode)
+ return;
+
+ boolean player_found[MAX_PLAYERS];
+ int num_players = 0;
+ int i, x, y;
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ player_found[i] = FALSE;
+
+ /* check which players can be found in the level (simple approach) */
+ for (x = 0; x < lev_fieldx; x++)
+ {
+ for (y = 0; y < lev_fieldy; y++)
+ {
+ int element = level.field[x][y];
+
+ if (ELEM_IS_PLAYER(element))
+ {
+ int player_nr = GET_PLAYER_NR(element);
+
+ player_nr = MIN(MAX(0, player_nr), MAX_PLAYERS - 1);
+
+ if (!player_found[player_nr])
+ num_players++;
+
+ player_found[player_nr] = TRUE;
+ }
+ }
+ }
+
+ struct TextPosInfo *pos = &menu.main.preview_players;
+ int tile_size = pos->tile_size;
+ int border_size = pos->border_size;
+ int player_xoffset_raw = (pos->vertical ? 0 : tile_size + border_size);
+ int player_yoffset_raw = (pos->vertical ? tile_size + border_size : 0);
+ int player_xoffset = (pos->xoffset != -1 ? pos->xoffset : player_xoffset_raw);
+ int player_yoffset = (pos->yoffset != -1 ? pos->yoffset : player_yoffset_raw);
+ int max_players_width = (MAX_PLAYERS - 1) * player_xoffset + tile_size;
+ int max_players_height = (MAX_PLAYERS - 1) * player_yoffset + tile_size;
+ int all_players_width = (num_players - 1) * player_xoffset + tile_size;
+ int all_players_height = (num_players - 1) * player_yoffset + tile_size;
+ int max_xpos = SX + ALIGNED_XPOS(pos->x, max_players_width, pos->align);
+ int max_ypos = SY + ALIGNED_YPOS(pos->y, max_players_height, pos->valign);
+ int xpos = SX + ALIGNED_XPOS(pos->x, all_players_width, pos->align);
+ int ypos = SY + ALIGNED_YPOS(pos->y, all_players_height, pos->valign);
+
+ /* clear area in which the players will be drawn */
+ ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
+ max_players_width, max_players_height);
+
+ /* only draw players if level is suited for team mode */
+ if (num_players < 2)
+ return;
+
+ /* draw all players that were found in the level */
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (player_found[i])
+ {
+ int graphic = el2img(EL_PLAYER_1 + i);
+
+ DrawSizedGraphicThruMaskExt(drawto, xpos, ypos, graphic, 0, tile_size);
+
+ xpos += player_xoffset;
+ ypos += player_yoffset;
+ }
+ }
+}
+
+void DrawPreviewLevelInitial()
+{
+ DrawPreviewLevelExt(TRUE);
+ DrawPreviewPlayers();
+}
+
+void DrawPreviewLevelAnimation()
+{
+ DrawPreviewLevelExt(FALSE);
+}
+
+static void DrawNetworkPlayer(int x, int y, int player_nr, int tile_size,
+ int border_size, int font_nr)
+{
+ int graphic = el2img(EL_PLAYER_1 + player_nr);
+ int font_height = getFontHeight(font_nr);
+ int player_height = MAX(tile_size, font_height);
+ int xoffset_text = tile_size + border_size;
+ int yoffset_text = (player_height - font_height) / 2;
+ int yoffset_graphic = (player_height - tile_size) / 2;
+ char *player_name = getNetworkPlayerName(player_nr + 1);
+
+ DrawSizedGraphicThruMaskExt(drawto, x, y + yoffset_graphic, graphic, 0,
+ tile_size);
+ DrawText(x + xoffset_text, y + yoffset_text, player_name, font_nr);
+}
- DrawPreviewLevelPlayfieldExt(from_x, from_y);
- }
+void DrawNetworkPlayersExt(boolean force)
+{
+ if (game_status != GAME_MODE_MAIN)
+ return;
- /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
- /* redraw micro level label, if needed */
- if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
- !strEqual(level.author, ANONYMOUS_NAME) &&
- !strEqual(level.author, leveldir_current->name) &&
- DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
+ if (!network.connected && !force)
+ return;
+
+ int num_players = 0;
+ int i;
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ if (stored_player[i].connected_network)
+ num_players++;
+
+ struct TextPosInfo *pos = &menu.main.network_players;
+ int tile_size = pos->tile_size;
+ int border_size = pos->border_size;
+ int xoffset_text = tile_size + border_size;
+ int font_nr = pos->font;
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ int player_height = MAX(tile_size, font_height);
+ int player_yoffset = player_height + border_size;
+ int max_players_width = xoffset_text + MAX_PLAYER_NAME_LEN * font_width;
+ int max_players_height = MAX_PLAYERS * player_yoffset - border_size;
+ int all_players_height = num_players * player_yoffset - border_size;
+ int max_xpos = SX + ALIGNED_XPOS(pos->x, max_players_width, pos->align);
+ int max_ypos = SY + ALIGNED_YPOS(pos->y, max_players_height, pos->valign);
+ int ypos = SY + ALIGNED_YPOS(pos->y, all_players_height, pos->valign);
+
+ ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
+ max_players_width, max_players_height);
+
+ /* first draw local network player ... */
+ for (i = 0; i < MAX_PLAYERS; i++)
{
- int max_label_counter = 23;
+ if (stored_player[i].connected_network &&
+ stored_player[i].connected_locally)
+ {
+ char *player_name = getNetworkPlayerName(i + 1);
+ int player_width = xoffset_text + getTextWidth(player_name, font_nr);
+ int xpos = SX + ALIGNED_XPOS(pos->x, player_width, pos->align);
- if (leveldir_current->imported_from != NULL &&
- strlen(leveldir_current->imported_from) > 0)
- max_label_counter += 14;
- if (leveldir_current->imported_by != NULL &&
- strlen(leveldir_current->imported_by) > 0)
- max_label_counter += 14;
+ DrawNetworkPlayer(xpos, ypos, i, tile_size, border_size, font_nr);
- label_counter = (label_counter + 1) % max_label_counter;
- label_state = (label_counter >= 0 && label_counter <= 7 ?
- MICROLABEL_LEVEL_NAME :
- label_counter >= 9 && label_counter <= 12 ?
- MICROLABEL_LEVEL_AUTHOR_HEAD :
- label_counter >= 14 && label_counter <= 21 ?
- MICROLABEL_LEVEL_AUTHOR :
- label_counter >= 23 && label_counter <= 26 ?
- MICROLABEL_IMPORTED_FROM_HEAD :
- label_counter >= 28 && label_counter <= 35 ?
- MICROLABEL_IMPORTED_FROM :
- label_counter >= 37 && label_counter <= 40 ?
- MICROLABEL_IMPORTED_BY_HEAD :
- label_counter >= 42 && label_counter <= 49 ?
- MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
+ ypos += player_yoffset;
+ }
+ }
- if (leveldir_current->imported_from == NULL &&
- (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
- label_state == MICROLABEL_IMPORTED_FROM))
- label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
- MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
+ /* ... then draw all other network players */
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (stored_player[i].connected_network &&
+ !stored_player[i].connected_locally)
+ {
+ char *player_name = getNetworkPlayerName(i + 1);
+ int player_width = xoffset_text + getTextWidth(player_name, font_nr);
+ int xpos = SX + ALIGNED_XPOS(pos->x, player_width, pos->align);
- DrawPreviewLevelLabelExt(label_state);
+ DrawNetworkPlayer(xpos, ypos, i, tile_size, border_size, font_nr);
+
+ ypos += player_yoffset;
+ }
}
}
-void DrawPreviewLevelInitial()
+void DrawNetworkPlayers()
{
- DrawPreviewLevelExt(TRUE);
+ DrawNetworkPlayersExt(FALSE);
}
-void DrawPreviewLevelAnimation()
+void ClearNetworkPlayers()
{
- DrawPreviewLevelExt(FALSE);
+ DrawNetworkPlayersExt(TRUE);
}
inline static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
{
boolean still_wait = TRUE;
+ if (program.headless)
+ return;
+
/* simulate releasing mouse button over last gadget, if still pressed */
if (button_status)
HandleGadgets(-1, -1, 0);
while (still_wait)
{
- if (PendingEvent())
- {
- Event event;
-
- NextEvent(&event);
+ Event event;
+ if (NextValidEvent(&event))
+ {
switch (event.type)
{
case EVENT_BUTTONPRESS:
case EVENT_KEYPRESS:
+#if defined(TARGET_SDL2)
+ case SDL_CONTROLLERBUTTONDOWN:
+#endif
+ case SDL_JOYBUTTONDOWN:
still_wait = FALSE;
break;
{
if (level_solved)
{
- SetDrawtoField(DRAW_TO_FIELDBUFFER);
+ /* the MM game engine does not use a special (scrollable) field buffer */
+ if (level.game_engine_type != GAME_ENGINE_TYPE_MM)
+ SetDrawtoField(DRAW_TO_FIELDBUFFER);
HandleGameActions();
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);
+ BlitBitmap(bitmap_db_store_2, drawto, sx, sy, width, height, sx, sy);
}
}
break;
}
+#if defined(TARGET_SDL2)
+ case SDL_WINDOWEVENT:
+ HandleWindowEvent((WindowEvent *) &event);
+ break;
+
+ case SDL_APP_WILLENTERBACKGROUND:
+ case SDL_APP_DIDENTERBACKGROUND:
+ case SDL_APP_WILLENTERFOREGROUND:
+ case SDL_APP_DIDENTERFOREGROUND:
+ HandlePauseResumeEvent((PauseResumeEvent *) &event);
+ break;
+#endif
+
case EVENT_KEYPRESS:
- switch (GetEventKey((KeyEvent *)&event, TRUE))
+ {
+ Key key = GetEventKey((KeyEvent *)&event, TRUE);
+
+ switch (key)
{
case KSYM_space:
if (req_state & REQ_CONFIRM)
break;
case KSYM_Return:
+ case KSYM_y:
#if defined(TARGET_SDL2)
+ case KSYM_Y:
+ case KSYM_Select:
case KSYM_Menu:
+#if defined(KSYM_Rewind)
+ case KSYM_Rewind: /* for Amazon Fire TV remote */
+#endif
#endif
result = 1;
break;
case KSYM_Escape:
+ case KSYM_n:
#if defined(TARGET_SDL2)
+ case KSYM_N:
case KSYM_Back:
+#if defined(KSYM_FastForward)
+ case KSYM_FastForward: /* for Amazon Fire TV remote */
+#endif
#endif
result = 0;
break;
default:
+ HandleKeysDebug(key);
break;
}
if (req_state & REQ_PLAYER)
- result = 0;
+ {
+ int old_player_nr = setup.network_player_nr;
+
+ if (result != -1)
+ result = old_player_nr + 1;
+
+ switch (key)
+ {
+ case KSYM_space:
+ result = old_player_nr + 1;
+ break;
+
+ case KSYM_Up:
+ case KSYM_1:
+ result = 1;
+ break;
+
+ case KSYM_Right:
+ case KSYM_2:
+ result = 2;
+ break;
+
+ case KSYM_Down:
+ case KSYM_3:
+ result = 3;
+ break;
+
+ case KSYM_Left:
+ case KSYM_4:
+ result = 4;
+ break;
+
+ default:
+ break;
+ }
+ }
+
break;
+ }
case EVENT_KEYRELEASE:
ClearPlayerAction();
break;
+#if defined(TARGET_SDL2)
+ case SDL_CONTROLLERBUTTONDOWN:
+ switch (event.cbutton.button)
+ {
+ case SDL_CONTROLLER_BUTTON_A:
+ case SDL_CONTROLLER_BUTTON_X:
+ case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
+ case SDL_CONTROLLER_BUTTON_LEFTSTICK:
+ result = 1;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_B:
+ case SDL_CONTROLLER_BUTTON_Y:
+ case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
+ case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
+ case SDL_CONTROLLER_BUTTON_BACK:
+ result = 0;
+ break;
+ }
+
+ if (req_state & REQ_PLAYER)
+ {
+ int old_player_nr = setup.network_player_nr;
+
+ if (result != -1)
+ result = old_player_nr + 1;
+
+ switch (event.cbutton.button)
+ {
+ case SDL_CONTROLLER_BUTTON_DPAD_UP:
+ case SDL_CONTROLLER_BUTTON_Y:
+ result = 1;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
+ case SDL_CONTROLLER_BUTTON_B:
+ result = 2;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
+ case SDL_CONTROLLER_BUTTON_A:
+ result = 3;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
+ case SDL_CONTROLLER_BUTTON_X:
+ result = 4;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ break;
+
+ case SDL_CONTROLLERBUTTONUP:
+ HandleJoystickEvent(&event);
+ ClearPlayerAction();
+ break;
+#endif
+
default:
HandleOtherEvents(&event);
break;
else if (joy & JOY_BUTTON_2)
result = 0;
}
+ else if (AnyJoystick())
+ {
+ int joy = AnyJoystick();
+
+ if (req_state & REQ_PLAYER)
+ {
+ if (joy & JOY_UP)
+ result = 1;
+ else if (joy & JOY_RIGHT)
+ result = 2;
+ else if (joy & JOY_DOWN)
+ result = 3;
+ else if (joy & JOY_LEFT)
+ result = 4;
+ }
+ }
if (level_solved)
{
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);
+ BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy);
}
}
SetMouseCursor(CURSOR_DEFAULT);
-#if defined(NETWORK_AVALIABLE)
/* pause network game while waiting for request to answer */
- if (options.network &&
+ if (network.enabled &&
game_status == GAME_MODE_PLAYING &&
+ !AllPlayersGone &&
req_state & REQUEST_WAIT_FOR_INPUT)
SendToServer_PausePlaying();
-#endif
old_door_state = GetDoorState();
SetDrawBackgroundMask(REDRAW_FIELD);
}
-#if defined(NETWORK_AVALIABLE)
/* continue network game after request */
- if (options.network &&
+ if (network.enabled &&
game_status == GAME_MODE_PLAYING &&
+ !AllPlayersGone &&
req_state & REQUEST_WAIT_FOR_INPUT)
SendToServer_ContinuePlaying();
-#endif
/* restore deactivated drawing when quick-loading level tape recording */
if (tape.playing && tape.deactivate_display)
SetMouseCursor(CURSOR_DEFAULT);
-#if defined(NETWORK_AVALIABLE)
/* pause network game while waiting for request to answer */
- if (options.network &&
+ if (network.enabled &&
game_status == GAME_MODE_PLAYING &&
+ !AllPlayersGone &&
req_state & REQUEST_WAIT_FOR_INPUT)
SendToServer_PausePlaying();
-#endif
/* simulate releasing mouse button over last gadget, if still pressed */
if (button_status)
SetDrawBackgroundMask(REDRAW_FIELD);
}
-#if defined(NETWORK_AVALIABLE)
/* continue network game after request */
- if (options.network &&
+ if (network.enabled &&
game_status == GAME_MODE_PLAYING &&
+ !AllPlayersGone &&
req_state & REQUEST_WAIT_FOR_INPUT)
SendToServer_ContinuePlaying();
-#endif
/* restore deactivated drawing when quick-loading level tape recording */
if (tape.playing && tape.deactivate_display)
boolean Request(char *text, unsigned int req_state)
{
+ boolean overlay_active = GetOverlayActive();
+ boolean result;
+
+ SetOverlayActive(FALSE);
+
if (global.use_envelope_request)
- return RequestEnvelope(text, req_state);
+ result = RequestEnvelope(text, req_state);
else
- return RequestDoor(text, req_state);
+ result = RequestDoor(text, req_state);
+
+ SetOverlayActive(overlay_active);
+
+ return result;
}
static int compareDoorPartOrderInfo(const void *object1, const void *object2)
door_state &= ~DOOR_CLOSE_ALL;
}
- if (game_status == GAME_MODE_EDITOR)
+ if (game_status == GAME_MODE_EDITOR && !(door_state & DOOR_FORCE_ANIM))
door_state |= DOOR_NO_DELAY;
if (door_state & DOOR_ACTION)
{
/* opening door sound has priority over simultaneously closing door */
if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
+ {
PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
+
+ if (door_state & DOOR_OPEN_1)
+ PlayMenuSoundStereo(SND_DOOR_1_OPENING, SOUND_MIDDLE);
+ if (door_state & DOOR_OPEN_2)
+ PlayMenuSoundStereo(SND_DOOR_2_OPENING, SOUND_MIDDLE);
+ }
else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
+ {
PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
+
+ if (door_state & DOOR_CLOSE_1)
+ PlayMenuSoundStereo(SND_DOOR_1_CLOSING, SOUND_MIDDLE);
+ if (door_state & DOOR_CLOSE_2)
+ PlayMenuSoundStereo(SND_DOOR_2_CLOSING, SOUND_MIDDLE);
+ }
}
for (k = start; k < num_move_steps; k++)
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);
+ getFixedGraphicSource(dpc->graphic, frame, &bitmap,
+ &g_src_x, &g_src_y);
}
// draw door panel
SkipUntilDelayReached(&door_delay, door_delay_value, &k, last_frame);
current_move_delay += max_step_delay;
+
+ /* prevent OS (Windows) from complaining about program not responding */
+ CheckQuitEvent();
}
if (door_part_done_all)
break;
}
+
+ if (!(door_state & DOOR_NO_DELAY))
+ {
+ /* wait for specified door action post delay */
+ if (door_state & DOOR_ACTION_1 && door_state & DOOR_ACTION_2)
+ door_delay_value = MAX(door_1.post_delay, door_2.post_delay);
+ else if (door_state & DOOR_ACTION_1)
+ door_delay_value = door_1.post_delay;
+ else if (door_state & DOOR_ACTION_2)
+ door_delay_value = door_2.post_delay;
+
+ while (!DelayReached(&door_delay, door_delay_value))
+ BackToFront();
+ }
}
if (door_state & DOOR_ACTION_1)
DrawMaskedBorder(REDRAW_DOOR_1);
DrawMaskedBorder(REDRAW_DOOR_2);
+ ClearEventQueue();
+
return (door1 | door2);
}
for (i = 0; i < NUM_TOOL_BUTTONS; i++)
{
- struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
+ int graphic = toolbutton_info[i].graphic;
+ struct GraphicInfo *gfx = &graphic_info[graphic];
struct TextPosInfo *pos = toolbutton_info[i].pos;
struct GadgetInfo *gi;
Bitmap *deco_bitmap = None;
int gd_y = gfx->src_y;
int gd_xp = gfx->src_x + gfx->pressed_xoffset;
int gd_yp = gfx->src_y + gfx->pressed_yoffset;
+ int x = pos->x;
+ int y = pos->y;
int id = i;
if (global.use_envelope_request)
+ {
setRequestPosition(&dx, &dy, TRUE);
+ // check if request buttons are outside of envelope and fix, if needed
+ if (x < 0 || x + gfx->width > request.width ||
+ y < 0 || y + gfx->height > request.height)
+ {
+ if (id == TOOL_CTRL_ID_YES)
+ {
+ x = 0;
+ y = request.height - 2 * request.border_size - gfx->height;
+ }
+ else if (id == TOOL_CTRL_ID_NO)
+ {
+ x = request.width - 2 * request.border_size - gfx->width;
+ y = request.height - 2 * request.border_size - gfx->height;
+ }
+ else if (id == TOOL_CTRL_ID_CONFIRM)
+ {
+ x = (request.width - 2 * request.border_size - gfx->width) / 2;
+ y = request.height - 2 * request.border_size - gfx->height;
+ }
+ else if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
+ {
+ int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
+
+ x = (request.width - 2 * request.border_size - gfx->width) / 2;
+ y = request.height - 2 * request.border_size - gfx->height * 2;
+
+ x += (player_nr == 3 ? -1 : player_nr == 1 ? +1 : 0) * gfx->width;
+ y += (player_nr == 0 ? -1 : player_nr == 2 ? +1 : 0) * gfx->height;
+ }
+ }
+ }
+
if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
{
int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
}
gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_IMAGE_ID, graphic,
GDI_INFO_TEXT, toolbutton_info[i].infotext,
- GDI_X, dx + GDI_ACTIVE_POS(pos->x),
- GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
+ GDI_X, dx + x,
+ GDI_Y, dy + y,
GDI_WIDTH, gfx->width,
GDI_HEIGHT, gfx->height,
GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
}
}
+int map_element_RND_to_MM(int element_rnd)
+{
+ return (element_rnd >= EL_MM_START_1 &&
+ element_rnd <= EL_MM_END_1 ?
+ EL_MM_START_1_NATIVE + element_rnd - EL_MM_START_1 :
+
+ element_rnd >= EL_MM_START_2 &&
+ element_rnd <= EL_MM_END_2 ?
+ EL_MM_START_2_NATIVE + element_rnd - EL_MM_START_2 :
+
+ element_rnd >= EL_CHAR_START &&
+ element_rnd <= EL_CHAR_END ?
+ EL_MM_CHAR_START_NATIVE + element_rnd - EL_CHAR_START :
+
+ element_rnd >= EL_MM_RUNTIME_START &&
+ element_rnd <= EL_MM_RUNTIME_END ?
+ EL_MM_RUNTIME_START_NATIVE + element_rnd - EL_MM_RUNTIME_START :
+
+ element_rnd >= EL_MM_DUMMY_START &&
+ element_rnd <= EL_MM_DUMMY_END ?
+ EL_MM_DUMMY_START_NATIVE + element_rnd - EL_MM_DUMMY_START :
+
+ EL_MM_EMPTY_NATIVE);
+}
+
+int map_element_MM_to_RND(int element_mm)
+{
+ return (element_mm == EL_MM_EMPTY_NATIVE ||
+ element_mm == EL_DF_EMPTY_NATIVE ?
+ EL_EMPTY :
+
+ element_mm >= EL_MM_START_1_NATIVE &&
+ element_mm <= EL_MM_END_1_NATIVE ?
+ EL_MM_START_1 + element_mm - EL_MM_START_1_NATIVE :
+
+ element_mm >= EL_MM_START_2_NATIVE &&
+ element_mm <= EL_MM_END_2_NATIVE ?
+ EL_MM_START_2 + element_mm - EL_MM_START_2_NATIVE :
+
+ element_mm >= EL_MM_CHAR_START_NATIVE &&
+ element_mm <= EL_MM_CHAR_END_NATIVE ?
+ EL_CHAR_START + element_mm - EL_MM_CHAR_START_NATIVE :
+
+ element_mm >= EL_MM_RUNTIME_START_NATIVE &&
+ element_mm <= EL_MM_RUNTIME_END_NATIVE ?
+ EL_MM_RUNTIME_START + element_mm - EL_MM_RUNTIME_START_NATIVE :
+
+ element_mm >= EL_MM_DUMMY_START_NATIVE &&
+ element_mm <= EL_MM_DUMMY_END_NATIVE ?
+ EL_MM_DUMMY_START + element_mm - EL_MM_DUMMY_START_NATIVE :
+
+ EL_EMPTY);
+}
+
+int map_action_MM_to_RND(int action_mm)
+{
+ /* all MM actions are defined to exactly match their RND counterparts */
+ return action_mm;
+}
+
+int map_sound_MM_to_RND(int sound_mm)
+{
+ switch (sound_mm)
+ {
+ case SND_MM_GAME_LEVELTIME_CHARGING:
+ return SND_GAME_LEVELTIME_CHARGING;
+
+ case SND_MM_GAME_HEALTH_CHARGING:
+ return SND_GAME_HEALTH_CHARGING;
+
+ default:
+ return SND_UNDEFINED;
+ }
+}
+
+int map_mm_wall_element(int element)
+{
+ return (element >= EL_MM_STEEL_WALL_START &&
+ element <= EL_MM_STEEL_WALL_END ?
+ EL_MM_STEEL_WALL :
+
+ element >= EL_MM_WOODEN_WALL_START &&
+ element <= EL_MM_WOODEN_WALL_END ?
+ EL_MM_WOODEN_WALL :
+
+ element >= EL_MM_ICE_WALL_START &&
+ element <= EL_MM_ICE_WALL_END ?
+ EL_MM_ICE_WALL :
+
+ element >= EL_MM_AMOEBA_WALL_START &&
+ element <= EL_MM_AMOEBA_WALL_END ?
+ EL_MM_AMOEBA_WALL :
+
+ element >= EL_DF_STEEL_WALL_START &&
+ element <= EL_DF_STEEL_WALL_END ?
+ EL_DF_STEEL_WALL :
+
+ element >= EL_DF_WOODEN_WALL_START &&
+ element <= EL_DF_WOODEN_WALL_END ?
+ EL_DF_WOODEN_WALL :
+
+ element);
+}
+
+int map_mm_wall_element_editor(int element)
+{
+ switch (element)
+ {
+ case EL_MM_STEEL_WALL: return EL_MM_STEEL_WALL_START;
+ case EL_MM_WOODEN_WALL: return EL_MM_WOODEN_WALL_START;
+ case EL_MM_ICE_WALL: return EL_MM_ICE_WALL_START;
+ case EL_MM_AMOEBA_WALL: return EL_MM_AMOEBA_WALL_START;
+ case EL_DF_STEEL_WALL: return EL_DF_STEEL_WALL_START;
+ case EL_DF_WOODEN_WALL: return EL_DF_WOODEN_WALL_START;
+
+ default: return element;
+ }
+}
+
int get_next_element(int element)
{
switch (element)
}
}
+int el2img_mm(int element_mm)
+{
+ return el2img(map_element_MM_to_RND(element_mm));
+}
+
int el_act_dir2img(int element, int action, int direction)
{
element = GFX_ELEMENT(element);
boolean getTeamMode_EM()
{
- return game.team_mode;
+ return game.team_mode || network_playing;
}
int getGameFrameDelay_EM(int native_em_game_frame_delay)
return InitEngineRandom_EM(seed);
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
return InitEngineRandom_SP(seed);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ return InitEngineRandom_MM(seed);
else
return InitEngineRandom_RND(seed);
}
&g_em->crumbled_src_x, &g_em->crumbled_src_y);
g_em->crumbled_border_size = graphic_info[crumbled].border_size;
+ g_em->crumbled_tile_size = graphic_info[crumbled].tile_size;
g_em->has_crumbled_graphics = TRUE;
}
g_em->crumbled_src_x = 0;
g_em->crumbled_src_y = 0;
g_em->crumbled_border_size = 0;
+ g_em->crumbled_tile_size = 0;
g_em->has_crumbled_graphics = FALSE;
}
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 (!local_player->was_waiting)
{
- if (!SaveEngineSnapshotToList())
+ if (!CheckSaveEngineSnapshotToList())
return;
- player_was_waiting = TRUE;
+ local_player->was_waiting = TRUE;
}
}
else if (any_player_moving || any_player_snapping || any_player_dropping)
{
- player_was_waiting = FALSE;
+ local_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 (!local_player->was_waiting)
{
- if (!SaveEngineSnapshotToList())
+ if (!CheckSaveEngineSnapshotToList())
return;
- player_was_waiting = TRUE;
+ local_player->was_waiting = TRUE;
}
}
else
{
- player_was_waiting = FALSE;
+ local_player->was_waiting = FALSE;
+ }
+}
+
+void CheckSaveEngineSnapshot_MM(boolean element_clicked,
+ boolean button_released)
+{
+ if (button_released)
+ {
+ if (game.snapshot.mode == SNAPSHOT_MODE_EVERY_MOVE)
+ CheckSaveEngineSnapshotToList();
+ }
+ else if (element_clicked)
+ {
+ if (game.snapshot.mode != SNAPSHOT_MODE_EVERY_MOVE)
+ CheckSaveEngineSnapshotToList();
+
+ game.snapshot.changed_action = TRUE;
}
}
void CheckSingleStepMode_SP(boolean murphy_is_waiting,
boolean murphy_is_dropping)
{
+ boolean murphy_starts_dropping = FALSE;
+ int i;
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ if (stored_player[i].force_dropping)
+ murphy_starts_dropping = TRUE;
+
if (tape.single_step && tape.recording && !tape.pausing)
- if (murphy_is_waiting)
+ if (murphy_is_waiting && !murphy_starts_dropping)
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
CheckSaveEngineSnapshot_SP(murphy_is_waiting, murphy_is_dropping);
}
+void CheckSingleStepMode_MM(boolean element_clicked,
+ boolean button_released)
+{
+ if (tape.single_step && tape.recording && !tape.pausing)
+ if (button_released)
+ TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+
+ CheckSaveEngineSnapshot_MM(element_clicked, button_released);
+}
+
void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
int graphic, int sync_frame, int x, int y)
{
void PlayMenuMusic()
{
- PlayMenuMusicExt(menu.music[game_status]);
+ char *curr_music = getCurrentlyPlayingMusicFilename();
+ char *next_music = getMusicInfoEntryFilename(menu.music[game_status]);
+
+ if (!strEqual(curr_music, next_music))
+ PlayMenuMusicExt(menu.music[game_status]);
+}
+
+void PlayMenuSoundsAndMusic()
+{
+ PlayMenuSound();
+ PlayMenuMusic();
+}
+
+static void FadeMenuSounds()
+{
+ FadeSounds();
+}
+
+static void FadeMenuMusic()
+{
+ char *curr_music = getCurrentlyPlayingMusicFilename();
+ char *next_music = getMusicInfoEntryFilename(menu.music[game_status]);
+
+ if (!strEqual(curr_music, next_music))
+ FadeMusic();
+}
+
+void FadeMenuSoundsAndMusic()
+{
+ FadeMenuSounds();
+ FadeMenuMusic();
}
void PlaySoundActivating()
{
if (anim_status_new == GAME_MODE_MAIN)
anim_status_new = GAME_MODE_PSEUDO_MAINONLY;
+ else if (anim_status_new == GAME_MODE_SCORES)
+ anim_status_new = GAME_MODE_PSEUDO_SCORESOLD;
global.anim_status_next = anim_status_new;
void SetGameStatus(int game_status_new)
{
+ if (game_status_new != game_status)
+ game_status_last_screen = game_status;
+
game_status = game_status_new;
SetAnimStatus(game_status_new);
SetFontStatus(-1);
}
+void SetLevelSetInfo(char *identifier, int level_nr)
+{
+ setString(&levelset.identifier, identifier);
+
+ levelset.level_nr = level_nr;
+}
+
+boolean CheckIfPlayfieldViewportHasChanged()
+{
+ // if game status has not changed, playfield viewport has not changed either
+ if (game_status == game_status_last)
+ return FALSE;
+
+ // check if playfield viewport has changed with current game status
+ struct RectWithBorder *vp_playfield = &viewport.playfield[game_status];
+ int new_real_sx = vp_playfield->x;
+ int new_real_sy = vp_playfield->y;
+ int new_full_sxsize = vp_playfield->width;
+ int new_full_sysize = vp_playfield->height;
+
+ return (new_real_sx != REAL_SX ||
+ new_real_sy != REAL_SY ||
+ new_full_sxsize != FULL_SXSIZE ||
+ new_full_sysize != FULL_SYSIZE);
+}
+
+boolean CheckIfGlobalBorderOrPlayfieldViewportHasChanged()
+{
+ return (CheckIfGlobalBorderHasChanged() ||
+ CheckIfPlayfieldViewportHasChanged());
+}
+
void ChangeViewportPropertiesIfNeeded()
{
+ boolean use_mini_tilesize = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
+ FALSE : setup.small_game_graphics);
int gfx_game_mode = game_status;
int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
game_status);
int new_ey = vp_door_3->y;
int new_exsize = vp_door_3->width;
int new_eysize = vp_door_3->height;
- int new_tilesize_var =
- (setup.small_game_graphics ? MINI_TILESIZE : game.tile_size);
-
+ int new_tilesize_var = (use_mini_tilesize ? MINI_TILESIZE : game.tile_size);
int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
int new_scr_fieldx = new_sxsize / tilesize;