X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ftools.c;h=f1fd599ead465894a43b1044ab6219e7466d6da6;hb=8cea50fbd1b74a2bc164a79cbd26bdbb3abd6689;hp=b6e9f10ad881393db27c0bd77980af36f9e15760;hpb=44051f2e9b98cc3cf5e065616ef0c7569262dd06;p=rocksndiamonds.git diff --git a/src/tools.c b/src/tools.c index b6e9f10a..f1fd599e 100644 --- a/src/tools.c +++ b/src/tools.c @@ -44,6 +44,8 @@ static int el_act2crm(int, int); static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS]; static int request_gadget_id = -1; +static int preview_tilesize = 4; + static char *print_if_not_empty(int element) { static char *s = NULL; @@ -241,7 +243,8 @@ void BackToFront() if (redraw_mask & REDRAW_ALL) { BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); - redraw_mask = 0; + + redraw_mask = REDRAW_NONE; } if (redraw_mask & REDRAW_FIELD) @@ -413,6 +416,50 @@ void FadeToFront() BackToFront(); } +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(int fade_delay) +{ + 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; +} + void SetMainBackgroundImageIfDefined(int graphic) { if (graphic_info[graphic].bitmap) @@ -1353,8 +1400,8 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) 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; @@ -1381,7 +1428,7 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) 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; @@ -1407,7 +1454,7 @@ void ShowEnvelope(int envelope_nr) 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); @@ -1419,7 +1466,7 @@ void ShowEnvelope(int envelope_nr) 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); @@ -1448,6 +1495,37 @@ void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y) *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; @@ -1459,6 +1537,16 @@ void DrawMicroElement(int xpos, int ypos, int element) 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; @@ -1484,33 +1572,37 @@ void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y) redraw_mask |= REDRAW_FIELD; } -static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y) +static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y, + int preview_size_x, int 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; + if (lev_fieldx < preview_size_x) + xpos += (preview_size_x - lev_fieldx) / 2 * preview_tilesize; + if (lev_fieldy < preview_size_y) + ypos += (preview_size_y - lev_fieldy) / 2 * preview_tilesize; - xpos += MICRO_TILEX; - ypos += MICRO_TILEY; + xpos += preview_tilesize; + ypos += preview_tilesize; - for (x = -1; x <= STD_LEV_FIELDX; x++) + for (x = -1; x <= preview_size_x; x++) { - for (y = -1; y <= STD_LEV_FIELDY; y++) + for (y = -1; y <= 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)); + if (lx >= 0 && lx < lev_fieldx && + ly >= 0 && ly < lev_fieldy) + DrawPreviewElement(xpos + x * preview_tilesize, + ypos + y * preview_tilesize, + level.field[lx][ly], preview_tilesize); + else if (lx >= -1 && lx < lev_fieldx+1 && + ly >= -1 && ly < lev_fieldy+1 && BorderElement != EL_EMPTY) + DrawPreviewElement(xpos + x * preview_tilesize, + ypos + y * preview_tilesize, + getBorderElement(lx, ly), preview_tilesize); } } @@ -1580,6 +1672,8 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) static unsigned long label_delay = 0; static int from_x, from_y, scroll_direction; static int label_state, label_counter; + int preview_size_x = STD_LEV_FIELDX * MICRO_TILESIZE / preview_tilesize; + int preview_size_y = STD_LEV_FIELDY * MICRO_TILESIZE / preview_tilesize; int last_game_status = game_status; /* save current game status */ /* force PREVIEW font on preview level */ @@ -1592,7 +1686,8 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) label_state = 1; label_counter = 0; - DrawMicroLevelExt(xpos, ypos, from_x, from_y); + DrawMicroLevelExt(xpos, ypos, from_x, from_y, + preview_size_x, preview_size_y); DrawMicroLevelLabelExt(label_state); /* initialize delay counters */ @@ -1621,7 +1716,7 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) } /* scroll micro level, if needed */ - if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) && + if ((lev_fieldx > preview_size_x || lev_fieldy > preview_size_y) && DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY)) { switch (scroll_direction) @@ -1634,7 +1729,7 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) break; case MV_RIGHT: - if (from_x < lev_fieldx - STD_LEV_FIELDX) + if (from_x < lev_fieldx - preview_size_x) from_x++; else scroll_direction = MV_DOWN; @@ -1648,7 +1743,7 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) break; case MV_DOWN: - if (from_y < lev_fieldy - STD_LEV_FIELDY) + if (from_y < lev_fieldy - preview_size_y) from_y++; else scroll_direction = MV_LEFT; @@ -1658,7 +1753,8 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) break; } - DrawMicroLevelExt(xpos, ypos, from_x, from_y); + DrawMicroLevelExt(xpos, ypos, from_x, from_y, + preview_size_x, preview_size_y); } /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */ @@ -1915,8 +2011,17 @@ void DrawPlayer(struct PlayerInfo *player) 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); @@ -2513,7 +2618,7 @@ unsigned int MoveDoor(unsigned int door_state) door_2.height = VYSIZE; if (door_state == DOOR_GET_STATE) - return(door1 | door2); + return (door1 | door2); if (door_state & DOOR_SET_STATE) { @@ -2522,17 +2627,20 @@ unsigned int MoveDoor(unsigned int door_state) if (door_state & DOOR_ACTION_2) door2 = door_state & DOOR_ACTION_2; - return(door1 | door2); + return (door1 | door2); } - if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1) - door_state &= ~DOOR_OPEN_1; - else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1) - door_state &= ~DOOR_CLOSE_1; - if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2) - door_state &= ~DOOR_OPEN_2; - else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2) - door_state &= ~DOOR_CLOSE_2; + if (!(door_state & DOOR_FORCE_REDRAW)) + { + if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1) + door_state &= ~DOOR_OPEN_1; + else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1) + door_state &= ~DOOR_CLOSE_1; + if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2) + door_state &= ~DOOR_OPEN_2; + else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2) + door_state &= ~DOOR_CLOSE_2; + } door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay : door_2.step_delay); @@ -2567,8 +2675,8 @@ unsigned int MoveDoor(unsigned int door_state) #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); @@ -2581,9 +2689,9 @@ unsigned int MoveDoor(unsigned int door_state) { /* 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) @@ -2686,9 +2794,15 @@ unsigned int MoveDoor(unsigned int door_state) 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) { @@ -2765,13 +2879,15 @@ unsigned int MoveDoor(unsigned int door_state) door_2_done = (a == VXSIZE); } - BackToFront(); + if (!(door_state & DOOR_NO_DELAY)) + { + BackToFront(); - if (game_status == GAME_MODE_MAIN) - DoAnimation(); + if (game_status == GAME_MODE_MAIN) + DoAnimation(); - if (!(door_state & DOOR_NO_DELAY)) WaitUntilDelayReached(&door_delay, door_delay_value); + } } } @@ -5864,3 +5980,60 @@ void InitGraphicInfo_EM(void) 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); +}