X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_mm%2Fmm_game.c;h=8f61572d9c26a69da2b14f0704949c1ad049ca15;hb=46f998cb9e98f77911bbfa8a24f80d062af8acaa;hp=0403795fcf48c21e334e4368807ce6180626b4c0;hpb=e89a21e95b3cb84d1515c0fb3378ce902a48c1c8;p=rocksndiamonds.git diff --git a/src/game_mm/mm_game.c b/src/game_mm/mm_game.c index 0403795f..8f61572d 100644 --- a/src/game_mm/mm_game.c +++ b/src/game_mm/mm_game.c @@ -411,6 +411,20 @@ static void CheckExitMM(void) PlayLevelSound_MM(exit_x, exit_y, exit_element, MM_ACTION_OPENING); } +static void SetLaserColor(int brightness) +{ + int color_min = 0x00; + int color_max = brightness; // (0x00 <= brightness <= 0xFF) + int color_up = color_max * laser.overload_value / MAX_LASER_OVERLOAD; + int color_down = color_max - color_up; + + pen_ray = + GetPixelFromRGB(window, + (native_mm_level.laser_red ? color_max : color_up), + (native_mm_level.laser_green ? color_down : color_min), + (native_mm_level.laser_blue ? color_down : color_min)); +} + static void InitMovDir_MM(int x, int y) { int element = Tile[x][y]; @@ -436,7 +450,7 @@ static void InitMovDir_MM(int x, int y) } } -static void InitField(int x, int y, boolean init_game) +static void InitField(int x, int y) { int element = Tile[x][y]; @@ -537,7 +551,6 @@ static void InitCycleElements_RotateSingleStep(void) Tile[x][y] = next_element; - DrawField_MM(x, y); game_mm.cycle[i].steps -= step; } } @@ -574,10 +587,7 @@ static void InitLaser(void) AddLaserEdge(LX, LY); // set laser starting edge - pen_ray = GetPixelFromRGB(window, - native_mm_level.laser_red * 0xFF, - native_mm_level.laser_green * 0xFF, - native_mm_level.laser_blue * 0xFF); + SetLaserColor(0xFF); } void InitGameEngine_MM(void) @@ -656,7 +666,7 @@ void InitGameEngine_MM(void) Frame[x][y] = 0; Stop[x][y] = FALSE; - InitField(x, y, TRUE); + InitField(x, y); } } @@ -691,6 +701,11 @@ void InitGameActions_MM(void) cycle_steps_done++; } + AdvanceFrameCounter(); + AdvanceGfxFrame(); + + DrawLevel_MM(); + BackToFront(); ColorCycling(); @@ -710,6 +725,46 @@ void InitGameActions_MM(void) SetTileCursorActive(TRUE); } +static void FadeOutLaser(void) +{ + int i; + + for (i = 15; i >= 0; i--) + { + SetLaserColor(0x11 * i); + + DrawLaser(0, DL_LASER_ENABLED); + + BackToFront(); + Delay_WithScreenUpdates(50); + } + + DrawLaser(0, DL_LASER_DISABLED); + + StopSound_MM(SND_MM_GAME_HEALTH_CHARGING); +} + +static void GameOver_MM(int game_over_cause) +{ + // do not handle game over if request dialog is already active + if (game.request_active) + return; + + game_mm.game_over = TRUE; + game_mm.game_over_cause = game_over_cause; + + if (setup.ask_on_game_over) + game.restart_game_message = (game_over_cause == GAME_OVER_BOMB ? + "Bomb killed Mc Duffin! Play it again?" : + game_over_cause == GAME_OVER_NO_ENERGY ? + "Out of magic energy! Play it again?" : + game_over_cause == GAME_OVER_OVERLOADED ? + "Magic spell hit Mc Duffin! Play it again?" : + NULL); + + SetTileCursorActive(FALSE); +} + void AddLaserEdge(int lx, int ly) { int clx = dSX + lx; @@ -945,7 +1000,7 @@ void ScanLaser(void) if (element == EL_EMPTY) { - if (!HitOnlyAnEdge(element, hit_mask)) + if (!HitOnlyAnEdge(hit_mask)) break; } else if (element == EL_FUSE_ON) @@ -1315,7 +1370,7 @@ void DrawLaser_MM(void) boolean HitElement(int element, int hit_mask) { - if (HitOnlyAnEdge(element, hit_mask)) + if (HitOnlyAnEdge(hit_mask)) return FALSE; if (IS_MOVING(ELX, ELY) || IS_BLOCKED(ELX, ELY)) @@ -1459,14 +1514,14 @@ boolean HitElement(int element, int hit_mask) LX += step_size * XS; LY += step_size * YS; -#if 0 // draw sparkles on mirror - if ((IS_MIRROR(element) || IS_MIRROR_FIXED(element)) && + if ((IS_MIRROR(element) || + IS_MIRROR_FIXED(element) || + element == EL_PRISM) && current_angle != laser.current_angle) { - MoveSprite(vp, &Pfeil[2], 4 + 16 * ELX, 5 + 16 * ELY + 1); + MovDelay[ELX][ELY] = 11; // start animation } -#endif if ((!IS_POLAR(element) && !IS_POLAR_CROSS(element)) && current_angle != laser.current_angle) @@ -1638,7 +1693,7 @@ boolean HitElement(int element, int hit_mask) return TRUE; } -boolean HitOnlyAnEdge(int element, int hit_mask) +boolean HitOnlyAnEdge(int hit_mask) { // check if the laser hit only the edge of an element and, if so, go on @@ -1697,7 +1752,7 @@ boolean HitOnlyAnEdge(int element, int hit_mask) boolean HitPolarizer(int element, int hit_mask) { - if (HitOnlyAnEdge(element, hit_mask)) + if (HitOnlyAnEdge(hit_mask)) return FALSE; if (IS_DF_GRID(element)) @@ -1895,7 +1950,7 @@ boolean HitBlock(int element, int hit_mask) boolean HitLaserSource(int element, int hit_mask) { - if (HitOnlyAnEdge(element, hit_mask)) + if (HitOnlyAnEdge(hit_mask)) return FALSE; PlayLevelSound_MM(ELX, ELY, element, MM_ACTION_HITTING); @@ -1907,7 +1962,7 @@ boolean HitLaserSource(int element, int hit_mask) boolean HitLaserDestination(int element, int hit_mask) { - if (HitOnlyAnEdge(element, hit_mask)) + if (HitOnlyAnEdge(hit_mask)) return FALSE; if (element != EL_EXIT_OPEN && @@ -2143,7 +2198,7 @@ boolean HitReflectingWalls(int element, int hit_mask) } } - if (!HitOnlyAnEdge(element, hit_mask)) + if (!HitOnlyAnEdge(hit_mask)) { laser.overloaded = TRUE; @@ -2155,7 +2210,7 @@ boolean HitReflectingWalls(int element, int hit_mask) boolean HitAbsorbingWalls(int element, int hit_mask) { - if (HitOnlyAnEdge(element, hit_mask)) + if (HitOnlyAnEdge(hit_mask)) return FALSE; if (ABS(XS) == 4 && @@ -2398,6 +2453,36 @@ static void GrowAmoeba(int x, int y) } } +static void DrawFieldAnimated_MM(int x, int y) +{ + int element = Tile[x][y]; + + if (IS_BLOCKED(x, y)) + return; + + DrawField_MM(x, y); + + if (IS_MIRROR(element) || + IS_MIRROR_FIXED(element) || + element == EL_PRISM) + { + if (MovDelay[x][y] != 0) // wait some time before next frame + { + MovDelay[x][y]--; + + if (MovDelay[x][y] != 0) + { + int graphic = IMG_TWINKLE_WHITE; + int frame = getGraphicAnimationFrame(graphic, 10 - MovDelay[x][y]); + + DrawGraphicThruMask_MM(SCREENX(x), SCREENY(y), graphic, frame); + } + } + } + + laser.redraw = TRUE; +} + static void Explode_MM(int x, int y, int phase, int mode) { int num_phase = 9, delay = 2; @@ -2452,10 +2537,7 @@ static void Explode_MM(int x, int y, int phase, int mode) Bang_MM(laser.start_edge.x, laser.start_edge.y); Store[x][y] = EL_EMPTY; - game_mm.game_over = TRUE; - game_mm.game_over_cause = GAME_OVER_BOMB; - - SetTileCursorActive(FALSE); + GameOver_MM(GAME_OVER_DELAYED); laser.overloaded = FALSE; } @@ -2463,14 +2545,14 @@ static void Explode_MM(int x, int y, int phase, int mode) { Store[x][y] = EL_EMPTY; - game.restart_game_message = "Bomb killed Mc Duffin! Play it again?"; + GameOver_MM(GAME_OVER_BOMB); } Tile[x][y] = Store[x][y]; Store[x][y] = Store2[x][y] = 0; MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0; - InitField(x, y, FALSE); + InitField(x, y); DrawField_MM(x, y); } else if (!(phase % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) @@ -2916,7 +2998,9 @@ void RotateMirror(int x, int y, int button) LX, LY, laser.beamer_edge, laser.beamer[1].num); #endif +#if 0 laser.num_edges--; +#endif } ScanLaser(); @@ -3056,7 +3140,7 @@ void ColorCycling(void) } } -static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) +static void GameActions_MM_Ext(void) { int element; int x, y, i; @@ -3084,6 +3168,8 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) MeltIce(x, y); else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_AMOEBA) GrowAmoeba(x, y); + else + DrawFieldAnimated_MM(x, y); } AutoRotateMirrors(); @@ -3110,6 +3196,10 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) } } + // skip all following game actions if game is over + if (game_mm.game_over) + return; + if (FrameReached(&energy_delay)) { if (game_mm.energy_left > 0) @@ -3120,35 +3210,9 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) } else if (game.time_limit && !game_mm.game_over) { - int i; + FadeOutLaser(); - for (i = 15; i >= 0; i--) - { -#if 0 - SetRGB(pen_ray, 0x0000, 0x0000, i * color_scale); -#endif - pen_ray = GetPixelFromRGB(window, - native_mm_level.laser_red * 0x11 * i, - native_mm_level.laser_green * 0x11 * i, - native_mm_level.laser_blue * 0x11 * i); - - DrawLaser(0, DL_LASER_ENABLED); - BackToFront(); - Delay_WithScreenUpdates(50); - } - - StopSound_MM(SND_MM_GAME_HEALTH_CHARGING); -#if 0 - FadeMusic(); -#endif - - DrawLaser(0, DL_LASER_DISABLED); - game_mm.game_over = TRUE; - game_mm.game_over_cause = GAME_OVER_NO_ENERGY; - - SetTileCursorActive(FALSE); - - game.restart_game_message = "Out of magic energy! Play it again?"; + GameOver_MM(GAME_OVER_NO_ENERGY); return; } @@ -3197,18 +3261,7 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) if (laser.overload_value < MAX_LASER_OVERLOAD - 8) { - int color_up = 0xFF * laser.overload_value / MAX_LASER_OVERLOAD; - int color_down = 0xFF - color_up; - -#if 0 - SetRGB(pen_ray, (laser.overload_value / 6) * color_scale, 0x0000, - (15 - (laser.overload_value / 6)) * color_scale); -#endif - pen_ray = - GetPixelFromRGB(window, - (native_mm_level.laser_red ? 0xFF : color_up), - (native_mm_level.laser_green ? color_down : 0x00), - (native_mm_level.laser_blue ? color_down : 0x00)); + SetLaserColor(0xFF); DrawLaser(0, DL_LASER_ENABLED); } @@ -3246,31 +3299,11 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) if (laser.overload_value == MAX_LASER_OVERLOAD) { - int i; - UpdateAndDisplayGameControlValues(); - for (i = 15; i >= 0; i--) - { -#if 0 - SetRGB(pen_ray, i * color_scale, 0x0000, 0x0000); -#endif - - pen_ray = GetPixelFromRGB(window, 0x11 * i, 0x00, 0x00); - - DrawLaser(0, DL_LASER_ENABLED); - BackToFront(); - Delay_WithScreenUpdates(50); - } - - DrawLaser(0, DL_LASER_DISABLED); - - game_mm.game_over = TRUE; - game_mm.game_over_cause = GAME_OVER_OVERLOADED; - - SetTileCursorActive(FALSE); + FadeOutLaser(); - game.restart_game_message = "Magic spell hit Mc Duffin! Play it again?"; + GameOver_MM(GAME_OVER_OVERLOADED); return; } @@ -3673,12 +3706,12 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) return; } -void GameActions_MM(struct MouseActionInfo action, boolean warp_mode) +void GameActions_MM(struct MouseActionInfo action) { boolean element_clicked = ClickElement(action.lx, action.ly, action.button); boolean button_released = (action.button == MB_RELEASED); - GameActions_MM_Ext(action, warp_mode); + GameActions_MM_Ext(); CheckSingleStepMode_MM(element_clicked, button_released); } @@ -3962,7 +3995,7 @@ void RaiseScoreElement_MM(int element) // Mirror Magic game engine snapshot handling functions // ---------------------------------------------------------------------------- -void SaveEngineSnapshotValues_MM(ListNode **buffers) +void SaveEngineSnapshotValues_MM(void) { int x, y;