X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_mm%2Fmm_game.c;h=c9712c9b2639521de4f612d63795cd249aaefc3a;hb=75a80bb5e95a67ae6343e15e8b835056b6862615;hp=d001df011b9c3bcc5e3ffe9294122ca767746e5d;hpb=e4ab53e36bb4fe4ccf5aa82b2279dcaebc3df624;p=rocksndiamonds.git diff --git a/src/game_mm/mm_game.c b/src/game_mm/mm_game.c index d001df01..c9712c9b 100644 --- a/src/game_mm/mm_game.c +++ b/src/game_mm/mm_game.c @@ -25,9 +25,8 @@ // values for Explode_MM() #define EX_PHASE_START 0 -#define EX_NORMAL 0 -#define EX_KETTLE 1 -#define EX_SHORT 2 +#define EX_TYPE_NONE 0 +#define EX_TYPE_NORMAL (1 << 0) // special positions in the game control window (relative to control window) #define XX_LEVEL 36 @@ -116,8 +115,22 @@ static DelayCounter pacman_delay = { PACMAN_MOVE_DELAY }; static DelayCounter energy_delay = { ENERGY_DELAY }; static DelayCounter overload_delay = { 0 }; +// element mask positions for scanning pixels of MM elements +#define MM_MASK_MCDUFFIN_RIGHT 0 +#define MM_MASK_MCDUFFIN_UP 1 +#define MM_MASK_MCDUFFIN_LEFT 2 +#define MM_MASK_MCDUFFIN_DOWN 3 +#define MM_MASK_GRID_1 4 +#define MM_MASK_GRID_2 5 +#define MM_MASK_GRID_3 6 +#define MM_MASK_GRID_4 7 +#define MM_MASK_RECTANGLE 8 +#define MM_MASK_CIRCLE 9 + +#define NUM_MM_MASKS 10 + // element masks for scanning pixels of MM elements -static const char mm_masks[10][16][16 + 1] = +static const char mm_masks[NUM_MM_MASKS][16][16 + 1] = { { " ", @@ -612,6 +625,7 @@ void InitGameEngine_MM(void) (native_mm_level.auto_count_kettles ? 0 : native_mm_level.kettles_needed); game_mm.lights_still_needed = 0; game_mm.num_keys = 0; + game_mm.ball_choice_pos = 0; game_mm.level_solved = FALSE; game_mm.game_over = FALSE; @@ -634,6 +648,9 @@ void InitGameEngine_MM(void) laser.fuse_x = laser.fuse_y = -1; laser.dest_element = EL_EMPTY; + laser.dest_element_last = EL_EMPTY; + laser.dest_element_last_x = -1; + laser.dest_element_last_y = -1; laser.wall_mask = 0; last_LX = 0; @@ -663,7 +680,6 @@ void InitGameEngine_MM(void) Angle[x][y] = 0; MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0; Store[x][y] = Store2[x][y] = 0; - Frame[x][y] = 0; Stop[x][y] = FALSE; InitField(x, y); @@ -814,13 +830,13 @@ static boolean StepBehind(void) static int getMaskFromElement(int element) { if (IS_GRID(element)) - return IMG_MM_MASK_GRID_1 + get_element_phase(element); + return MM_MASK_GRID_1 + get_element_phase(element); else if (IS_MCDUFFIN(element)) - return IMG_MM_MASK_MCDUFFIN_RIGHT + get_element_phase(element); + return MM_MASK_MCDUFFIN_RIGHT + get_element_phase(element); else if (IS_RECTANGLE(element) || IS_DF_GRID(element)) - return IMG_MM_MASK_RECTANGLE; + return MM_MASK_RECTANGLE; else - return IMG_MM_MASK_CIRCLE; + return MM_MASK_CIRCLE; } static int ScanPixel(void) @@ -874,7 +890,7 @@ static int ScanPixel(void) } else { - int pos = getMaskFromElement(element) - IMG_MM_MASK_MCDUFFIN_RIGHT; + int pos = getMaskFromElement(element); pixel = (mm_masks[pos][dy / 2][dx / 2] == 'X' ? 1 : 0); } @@ -900,6 +916,29 @@ static int ScanPixel(void) return hit_mask; } +static void DeactivateLaserTargetElement(void) +{ + if (laser.dest_element_last == EL_BOMB_ACTIVE || + laser.dest_element_last == EL_MINE_ACTIVE || + laser.dest_element_last == EL_GRAY_BALL_OPENING) + { + int x = laser.dest_element_last_x; + int y = laser.dest_element_last_y; + int element = laser.dest_element_last; + + if (Tile[x][y] == element) + Tile[x][y] = (element == EL_BOMB_ACTIVE ? EL_BOMB : + element == EL_MINE_ACTIVE ? EL_MINE : EL_BALL_GRAY); + + if (Tile[x][y] == EL_BALL_GRAY) + MovDelay[x][y] = 0; + + laser.dest_element_last = EL_EMPTY; + laser.dest_element_last_x = -1; + laser.dest_element_last_y = -1; + } +} + void ScanLaser(void) { int element; @@ -909,6 +948,8 @@ void ScanLaser(void) if (game_mm.game_over) return; + DeactivateLaserTargetElement(); + laser.overloaded = FALSE; laser.stops_inside_element = FALSE; @@ -1547,6 +1588,12 @@ boolean HitElement(int element, int hit_mask) { PlayLevelSound_MM(ELX, ELY, element, MM_ACTION_HITTING); + Tile[ELX][ELY] = (element == EL_BOMB ? EL_BOMB_ACTIVE : EL_MINE_ACTIVE); + + laser.dest_element_last = Tile[ELX][ELY]; + laser.dest_element_last_x = ELX; + laser.dest_element_last_y = ELY; + if (element == EL_MINE) laser.overloaded = TRUE; } @@ -2366,7 +2413,8 @@ static void OpenSurpriseBall(int x, int y) if (!MovDelay[x][y]) { Tile[x][y] = Store[x][y]; - Store[x][y] = 0; + Store[x][y] = Store2[x][y] = 0; + DrawField_MM(x, y); ScanLaser(); @@ -2506,20 +2554,27 @@ static void Explode_MM(int x, int y, int phase, int mode) Tile[x][y] = center_element; } - if (center_element == EL_BOMB || IS_MCDUFFIN(center_element)) + if (center_element == EL_BOMB_ACTIVE || IS_MCDUFFIN(center_element)) Store[x][y] = center_element; else Store[x][y] = EL_EMPTY; Store2[x][y] = mode; + Tile[x][y] = EL_EXPLODING_OPAQUE; + GfxElement[x][y] = center_element; + MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0; - Frame[x][y] = 1; + + ExplodePhase[x][y] = 1; return; } - Frame[x][y] = (phase < last_phase ? phase + 1 : 0); + if (phase == 1) + GfxFrame[x][y] = 0; // restart explosion animation + + ExplodePhase[x][y] = (phase < last_phase ? phase + 1 : 0); if (phase == half_phase) { @@ -2531,7 +2586,7 @@ static void Explode_MM(int x, int y, int phase, int mode) if (phase == last_phase) { - if (Store[x][y] == EL_BOMB) + if (Store[x][y] == EL_BOMB_ACTIVE) { DrawLaser(0, DL_LASER_DISABLED); InitLaser(); @@ -2559,44 +2614,10 @@ static void Explode_MM(int x, int y, int phase, int mode) } else if (!(phase % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) { - int graphic = IMG_MM_DEFAULT_EXPLODING; - int graphic_phase = (phase / delay - 1); - Bitmap *bitmap; - int src_x, src_y; + int graphic = el_act2gfx(GfxElement[x][y], MM_ACTION_EXPLODING); + int frame = getGraphicAnimationFrameXY(graphic, x, y); - if (Store2[x][y] == EX_KETTLE) - { - if (graphic_phase < 3) - { - graphic = IMG_MM_KETTLE_EXPLODING; - } - else if (graphic_phase < 5) - { - graphic_phase += 3; - } - else - { - graphic = IMG_EMPTY; - graphic_phase = 0; - } - } - else if (Store2[x][y] == EX_SHORT) - { - if (graphic_phase < 4) - { - graphic_phase += 4; - } - else - { - graphic = IMG_EMPTY; - graphic_phase = 0; - } - } - - getGraphicSource(graphic, graphic_phase, &bitmap, &src_x, &src_y); - - BlitBitmap(bitmap, drawto_field, src_x, src_y, TILEX, TILEY, - cFX + x * TILEX, cFY + y * TILEY); + DrawGraphicAnimation_MM(x, y, graphic, frame); MarkTileDirty(x, y); } @@ -2605,38 +2626,21 @@ static void Explode_MM(int x, int y, int phase, int mode) static void Bang_MM(int x, int y) { int element = Tile[x][y]; - int mode = EX_NORMAL; #if 0 DrawLaser(0, DL_LASER_ENABLED); #endif - switch (element) - { - case EL_KETTLE: - mode = EX_KETTLE; - break; - - case EL_GATE_STONE: - case EL_GATE_WOOD: - mode = EX_SHORT; - break; - - default: - mode = EX_NORMAL; - break; - } - if (IS_PACMAN(element)) PlayLevelSound_MM(x, y, element, MM_ACTION_EXPLODING); - else if (element == EL_BOMB || IS_MCDUFFIN(element)) + else if (element == EL_BOMB_ACTIVE || IS_MCDUFFIN(element)) PlayLevelSound_MM(x, y, element, MM_ACTION_EXPLODING); else if (element == EL_KEY) PlayLevelSound_MM(x, y, element, MM_ACTION_EXPLODING); else PlayLevelSound_MM(x, y, element, MM_ACTION_EXPLODING); - Explode_MM(x, y, EX_PHASE_START, mode); + Explode_MM(x, y, EX_PHASE_START, EX_TYPE_NORMAL); } void TurnRound(int x, int y) @@ -3161,7 +3165,7 @@ static void GameActions_MM_Ext(void) else if (IS_MOVING(x, y)) ContinueMoving_MM(x, y); else if (IS_EXPLODING(element)) - Explode_MM(x, y, Frame[x][y], EX_NORMAL); + Explode_MM(x, y, ExplodePhase[x][y], EX_TYPE_NORMAL); else if (element == EL_EXIT_OPENING) OpenExit(x, y); else if (element == EL_GRAY_BALL_OPENING) @@ -3231,7 +3235,9 @@ static void GameActions_MM_Ext(void) if (!laser.overloaded && laser.overload_value == 0 && element != EL_BOMB && + element != EL_BOMB_ACTIVE && element != EL_MINE && + element != EL_MINE_ACTIVE && element != EL_BALL_GRAY && element != EL_BLOCK_STONE && element != EL_BLOCK_WOOD && @@ -3339,26 +3345,38 @@ static void GameActions_MM_Ext(void) if (element == EL_BALL_GRAY && CT > native_mm_level.time_ball) { - static int new_elements[] = + if (!Store2[ELX][ELY]) // check if content element not yet determined { - EL_MIRROR_START, - EL_MIRROR_FIXED_START, - EL_POLAR_START, - EL_POLAR_CROSS_START, - EL_PACMAN_START, - EL_KETTLE, - EL_BOMB, - EL_PRISM - }; - int num_new_elements = sizeof(new_elements) / sizeof(int); - int new_element = new_elements[RND(num_new_elements)]; - - Store[ELX][ELY] = new_element + RND(get_num_elements(new_element)); + int last_anim_random_frame = gfx.anim_random_frame; + int element_pos; + + if (native_mm_level.ball_choice_mode == ANIM_RANDOM) + gfx.anim_random_frame = RND(native_mm_level.num_ball_contents); + + element_pos = getAnimationFrame(native_mm_level.num_ball_contents, 1, + native_mm_level.ball_choice_mode, 0, + game_mm.ball_choice_pos); + + if (native_mm_level.ball_choice_mode == ANIM_RANDOM) + gfx.anim_random_frame = last_anim_random_frame; + + game_mm.ball_choice_pos++; + + int new_element = native_mm_level.ball_content[element_pos]; + + Store[ELX][ELY] = new_element + RND(get_num_elements(new_element)); + Store2[ELX][ELY] = TRUE; + } + Tile[ELX][ELY] = EL_GRAY_BALL_OPENING; // !!! CHECK AGAIN: Laser on Polarizer !!! ScanLaser(); + laser.dest_element_last = Tile[ELX][ELY]; + laser.dest_element_last_x = ELX; + laser.dest_element_last_y = ELY; + return; #if 0 @@ -3679,24 +3697,27 @@ static void GameActions_MM_Ext(void) if (element == EL_FUEL_FULL && CT > 10) { - for (i = game_mm.energy_left; i <= MAX_LASER_ENERGY; i+=2) + int num_init_game_frames = INIT_GAME_ACTIONS_DELAY; + int start = num_init_game_frames * game_mm.energy_left / native_mm_level.time; + + for (i = start; i <= num_init_game_frames; i++) { -#if 0 - BlitBitmap(pix[PIX_DOOR], drawto, - DOOR_GFX_PAGEX4 + XX_ENERGY, - DOOR_GFX_PAGEY1 + YY_ENERGY + ENERGY_YSIZE - i, - ENERGY_XSIZE, i, DX_ENERGY, - DY_ENERGY + ENERGY_YSIZE - i); -#endif + if (i == num_init_game_frames) + StopSound_MM(SND_MM_GAME_LEVELTIME_CHARGING); + else if (setup.sound_loops) + PlaySoundLoop_MM(SND_MM_GAME_LEVELTIME_CHARGING); + else + PlaySound_MM(SND_MM_GAME_LEVELTIME_CHARGING); - redraw_mask |= REDRAW_DOOR_1; - BackToFront(); + game_mm.energy_left = native_mm_level.time * i / num_init_game_frames; - Delay_WithScreenUpdates(20); + UpdateAndDisplayGameControlValues(); + + BackToFront(); } - game_mm.energy_left = MAX_LASER_ENERGY; - Tile[ELX][ELY] = EL_FUEL_EMPTY; + Tile[ELX][ELY] = laser.dest_element = EL_FUEL_EMPTY; + DrawField_MM(ELX, ELY); DrawLaser(0, DL_LASER_ENABLED); @@ -4011,7 +4032,6 @@ void SaveEngineSnapshotValues_MM(void) engine_snapshot_mm.Hit[x][y] = Hit[x][y]; engine_snapshot_mm.Box[x][y] = Box[x][y]; engine_snapshot_mm.Angle[x][y] = Angle[x][y]; - engine_snapshot_mm.Frame[x][y] = Frame[x][y]; } } @@ -4054,7 +4074,6 @@ void LoadEngineSnapshotValues_MM(void) Hit[x][y] = engine_snapshot_mm.Hit[x][y]; Box[x][y] = engine_snapshot_mm.Box[x][y]; Angle[x][y] = engine_snapshot_mm.Angle[x][y]; - Frame[x][y] = engine_snapshot_mm.Frame[x][y]; } }