static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
static int request_gadget_id = -1;
+static int preview_tilesize = TILEX / 4;
+
static char *print_if_not_empty(int element)
{
static char *s = NULL;
void FadeIn(int fade_delay)
{
+ if (fade_delay == 0)
+ {
+ BackToFront();
+
+ return;
+ }
+
FadeScreen(NULL, FADE_MODE_FADE_IN, fade_delay, 0);
redraw_mask = REDRAW_NONE;
void FadeOut(int fade_delay, int post_delay)
{
+ if (fade_delay == 0)
+ {
+ ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
+ BackToFront();
+
+ return;
+ }
+
FadeScreen(NULL, FADE_MODE_FADE_OUT, fade_delay, post_delay);
redraw_mask = REDRAW_NONE;
}
-void FadeCross(Bitmap *bitmap, int fade_delay)
+void FadeCross(int fade_delay)
{
- FadeScreen(bitmap, FADE_MODE_CROSSFADE, fade_delay, 0);
+ if (fade_delay == 0)
+ {
+ BlitBitmap(bitmap_db_title, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ BackToFront();
+
+ return;
+ }
+
+ FadeScreen(bitmap_db_title, FADE_MODE_CROSSFADE, fade_delay, 0);
redraw_mask = REDRAW_NONE;
}
int font_nr = FONT_ENVELOPE_1 + envelope_nr;
int font_width = getFontWidth(font_nr);
int font_height = getFontHeight(font_nr);
- int max_xsize = level.envelope_xsize[envelope_nr];
- int max_ysize = level.envelope_ysize[envelope_nr];
+ int max_xsize = level.envelope[envelope_nr].xsize;
+ int max_ysize = level.envelope[envelope_nr].ysize;
int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
int xend = max_xsize;
DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
- level.envelope_text[envelope_nr], font_nr, max_xsize,
+ level.envelope[envelope_nr].text, font_nr, max_xsize,
xsize - 2, ysize - 2, mask_mode);
redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
- PlaySoundStereo(sound_opening, SOUND_MIDDLE);
+ PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
if (anim_mode == ANIM_DEFAULT)
AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
else
WaitForEventToContinue();
- PlaySoundStereo(sound_closing, SOUND_MIDDLE);
+ PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
if (anim_mode != ANIM_NONE)
AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
*y = src_y;
}
+void getPreviewGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y,
+ int tilesize)
+{
+ struct
+ {
+ int width_mult, width_div;
+ int height_mult, height_div;
+ } offset_calc[4] =
+ {
+ { 0, 1, 0, 1 },
+ { 0, 1, 2, 3 },
+ { 1, 2, 2, 3 },
+ { 3, 4, 2, 3 },
+ };
+ int offset_calc_pos = (tilesize < MICRO_TILESIZE || tilesize > TILESIZE ? 3 :
+ 5 - log_2(tilesize));
+ Bitmap *src_bitmap = graphic_info[graphic].bitmap;
+ 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 mini_startx = src_bitmap->width * width_mult / width_div;
+ int mini_starty = src_bitmap->height * height_mult / height_div;
+ int src_x = mini_startx + graphic_info[graphic].src_x * tilesize / TILESIZE;
+ int src_y = mini_starty + graphic_info[graphic].src_y * tilesize / TILESIZE;
+
+ *bitmap = src_bitmap;
+ *x = src_x;
+ *y = src_y;
+}
+
void DrawMicroElement(int xpos, int ypos, int element)
{
Bitmap *src_bitmap;
xpos, ypos);
}
+void DrawPreviewElement(int xpos, int ypos, int element, int tilesize)
+{
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int graphic = el2preimg(element);
+
+ getPreviewGraphicSource(graphic, &src_bitmap, &src_x, &src_y, tilesize);
+ BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, xpos, ypos);
+}
+
void DrawLevel()
{
int x,y;
static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
{
+ boolean show_level_border = (BorderElement != EL_EMPTY);
+ int level_size_x = lev_fieldx + (show_level_border ? 2 : 0);
+ int level_size_y = lev_fieldy + (show_level_border ? 2 : 0);
+ int preview_size_x = MICROLEVEL_XSIZE / preview_tilesize;
+ int preview_size_y = MICROLEVEL_YSIZE / preview_tilesize;
+ int real_preview_size_x = MIN(level_size_x, preview_size_x);
+ int real_preview_size_y = MIN(level_size_y, preview_size_y);
int x, y;
DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
- if (lev_fieldx < STD_LEV_FIELDX)
- xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
- if (lev_fieldy < STD_LEV_FIELDY)
- ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
+ xpos += (MICROLEVEL_XSIZE - real_preview_size_x * preview_tilesize) / 2;
+ ypos += (MICROLEVEL_YSIZE - real_preview_size_y * preview_tilesize) / 2;
- xpos += MICRO_TILEX;
- ypos += MICRO_TILEY;
-
- for (x = -1; x <= STD_LEV_FIELDX; x++)
+ for (x = 0; x < real_preview_size_x; x++)
{
- for (y = -1; y <= STD_LEV_FIELDY; y++)
+ for (y = 0; y < real_preview_size_y; y++)
{
- int lx = from_x + x, ly = from_y + y;
-
- if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
- DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
- level.field[lx][ly]);
- else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
- && BorderElement != EL_EMPTY)
- DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
- getBorderElement(lx, ly));
+ int lx = from_x + x + (show_level_border ? -1 : 0);
+ int ly = from_y + y + (show_level_border ? -1 : 0);
+ int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
+ getBorderElement(lx, ly));
+
+ DrawPreviewElement(xpos + x * preview_tilesize,
+ ypos + y * preview_tilesize,
+ element, preview_tilesize);
}
}
static unsigned long label_delay = 0;
static int from_x, from_y, scroll_direction;
static int label_state, label_counter;
+ int delay_factor = preview_tilesize / MICRO_TILESIZE;
+ unsigned long scroll_delay_value = MICROLEVEL_SCROLL_DELAY * delay_factor;
+ boolean show_level_border = (BorderElement != EL_EMPTY);
+ int level_size_x = lev_fieldx + (show_level_border ? 2 : 0);
+ int level_size_y = lev_fieldy + (show_level_border ? 2 : 0);
+ int preview_size_x = MICROLEVEL_XSIZE / preview_tilesize;
+ int preview_size_y = MICROLEVEL_YSIZE / preview_tilesize;
int last_game_status = game_status; /* save current game status */
/* force PREVIEW font on preview level */
}
/* scroll micro level, if needed */
- if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
- DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
+ if ((level_size_x > preview_size_x || level_size_y > preview_size_y) &&
+ DelayReached(&scroll_delay, scroll_delay_value))
{
switch (scroll_direction)
{
break;
case MV_RIGHT:
- if (from_x < lev_fieldx - STD_LEV_FIELDX)
+ if (from_x < level_size_x - preview_size_x)
from_x++;
else
scroll_direction = MV_DOWN;
break;
case MV_DOWN:
- if (from_y < lev_fieldy - STD_LEV_FIELDY)
+ if (from_y < level_size_y - preview_size_y)
from_y++;
else
scroll_direction = MV_LEFT;
last_element == EL_EM_DYNAMITE_ACTIVE ||
last_element == EL_SP_DISK_RED_ACTIVE)
DrawDynamite(last_jx, last_jy);
+#if 0
+ /* !!! this is not enough to prevent flickering of players which are
+ moving next to each others without a free tile between them -- this
+ can only be solved by drawing all players layer by layer (first the
+ background, then the foreground etc.) !!! => TODO */
+ else if (!IS_PLAYER(last_jx, last_jy))
+ DrawLevelField(last_jx, last_jy);
+#else
else
DrawLevelField(last_jx, last_jy);
+#endif
if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
DrawLevelElement(next_jx, next_jy, EL_EMPTY);
#if 1
int end = door_size;
#else
- int end = (door_state & DOOR_ACTION_1 &&
- door_1.anim_mode & ANIM_VERTICAL ? DYSIZE : DXSIZE);
+ int end = (door_state & DOOR_ACTION_1 && door_1.anim_mode & ANIM_VERTICAL ?
+ DYSIZE : DXSIZE);
#endif
#if 1
int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
{
/* opening door sound has priority over simultaneously closing door */
if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
- PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
+ PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
- PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
+ PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
}
for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
if (door_state & DOOR_ACTION_2)
{
+#if 1
+ int a = MIN(x * door_2.step_offset, door_size);
+ int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
+ int i = p + door_skip;
+#else
int a = MIN(x * door_2.step_offset, door_size_2);
int p = (door_state & DOOR_OPEN_2 ? door_size_2 - a : a);
int i = p + door_skip;
+#endif
if (door_2.anim_mode & ANIM_STATIC_PANEL)
{
exit(0);
#endif
}
+
+void PlayMenuSound()
+{
+ int sound = menu.sound[game_status];
+
+ if (sound == SND_UNDEFINED)
+ return;
+
+ if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
+ (!setup.sound_loops && IS_LOOP_SOUND(sound)))
+ return;
+
+ if (IS_LOOP_SOUND(sound))
+ PlaySoundLoop(sound);
+ else
+ PlaySound(sound);
+}
+
+void PlayMenuSoundStereo(int sound, int stereo_position)
+{
+ if (sound == SND_UNDEFINED)
+ return;
+
+ if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
+ (!setup.sound_loops && IS_LOOP_SOUND(sound)))
+ return;
+
+ if (IS_LOOP_SOUND(sound))
+ PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
+ else
+ PlaySoundStereo(sound, stereo_position);
+}
+
+void PlayMenuSoundIfLoop()
+{
+ int sound = menu.sound[game_status];
+
+ if (sound == SND_UNDEFINED)
+ return;
+
+ if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
+ (!setup.sound_loops && IS_LOOP_SOUND(sound)))
+ return;
+
+ if (IS_LOOP_SOUND(sound))
+ PlaySoundLoop(sound);
+}
+
+void PlayMenuMusic()
+{
+ int music = menu.music[game_status];
+
+ if (music == MUS_UNDEFINED)
+ return;
+
+ PlayMusic(music);
+}
+
+void ToggleFullscreenIfNeeded()
+{
+ if (setup.fullscreen != video.fullscreen_enabled ||
+ setup.fullscreen_mode != video.fullscreen_mode_current)
+ {
+ Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
+
+ /* save backbuffer content which gets lost when toggling fullscreen mode */
+ BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+ if (setup.fullscreen && video.fullscreen_enabled)
+ {
+ /* keep fullscreen mode, but change screen mode */
+ video.fullscreen_mode_current = setup.fullscreen_mode;
+ video.fullscreen_enabled = FALSE;
+ }
+
+ /* toggle fullscreen */
+ ChangeVideoModeIfNeeded(setup.fullscreen);
+ setup.fullscreen = video.fullscreen_enabled;
+
+ /* restore backbuffer content from temporary backbuffer backup bitmap */
+ BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+ FreeBitmap(tmp_backbuffer);
+
+ redraw_mask = REDRAW_ALL;
+ }
+}