X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=9ff9bf2ec840da5c4088caaec32c265cf2a4df0c;hb=9ec014a4e4a6a2332bb45c6cea8cccc46c64c6ae;hp=7fd229444b19f2cbf55bfa2b9b51347a5c63f1ce;hpb=fa9c72bb286c8e5e5095e666dbf85981ad3a8ea2;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 7fd22944..9ff9bf2e 100644 --- a/src/game.c +++ b/src/game.c @@ -89,6 +89,8 @@ #define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value)) #define HALVE_PLAYER_SPEED(p) (DOUBLE_MOVE_DELAY((p)->move_delay_value)) +#define INIT_GFX_RANDOM() (SimpleRND(1000000)) + /* game button identifiers */ #define GAME_CTRL_ID_STOP 0 #define GAME_CTRL_ID_PAUSE 1 @@ -99,7 +101,9 @@ #define NUM_GAME_BUTTONS 6 + /* forward declaration for internal use */ + static void InitBeltMovement(void); static void CloseAllOpenTimegates(void); static void CheckGravityMovement(struct PlayerInfo *); @@ -115,9 +119,6 @@ static void HandleGameButtons(struct GadgetInfo *); static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS]; -#define IS_ANIMATED(g) (graphic_info[g].anim_frames > 1) -#define IS_LOOP_SOUND(s) (sound_info[s].loop) - /* ------------------------------------------------------------------------- */ /* definition of elements that automatically change to other elements after */ @@ -161,6 +162,9 @@ static struct ChangingElementInfo changing_element_list[] = { EL_TIMEGATE_OPENING, EL_TIMEGATE_OPEN, 29, NULL, NULL, NULL }, { EL_TIMEGATE_CLOSING, EL_TIMEGATE_CLOSED, 29, NULL, NULL, NULL }, + { EL_ACID_SPLASH_LEFT, EL_EMPTY, 8, NULL, NULL, NULL }, + { EL_ACID_SPLASH_RIGHT, EL_EMPTY, 8, NULL, NULL, NULL }, + { EL_SP_BUGGY_BASE, EL_SP_BUGGY_BASE_ACTIVATING, 0, InitBuggyBase, NULL, NULL }, { EL_SP_BUGGY_BASE_ACTIVATING,EL_SP_BUGGY_BASE_ACTIVE, 0, @@ -187,60 +191,6 @@ static struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS]; #define IS_AUTO_CHANGING(e) (changing_element[e].base_element != EL_UNDEFINED) - -#ifdef DEBUG -#if 0 -static unsigned int getStateCheckSum(int counter) -{ - int x, y; - unsigned int mult = 1; - unsigned int checksum = 0; - /* - static short lastFeld[MAX_LEV_FIELDX][MAX_LEV_FIELDY]; - */ - static boolean first_game = TRUE; - - for (y=0; ygems_still_needed, 3), FS_SMALL, FC_YELLOW); + int2str(local_player->gems_still_needed, 3), FONT_DEFAULT_SMALL); DrawText(DX + XX_DYNAMITE, DY + YY_DYNAMITE, - int2str(local_player->dynamite, 3), FS_SMALL, FC_YELLOW); + int2str(local_player->dynamite, 3), FONT_DEFAULT_SMALL); DrawText(DX + XX_SCORE, DY + YY_SCORE, - int2str(local_player->score, 5), FS_SMALL, FC_YELLOW); + int2str(local_player->score, 5), FONT_DEFAULT_SMALL); DrawText(DX + XX_TIME, DY + YY_TIME, - int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); + int2str(TimeLeft, 3), FONT_DEFAULT_SMALL); } @@ -689,13 +643,18 @@ void InitGame() player->GfxPos = 0; player->Frame = 0; - player->actual_frame_counter = 0; + player->GfxAction = ACTION_DEFAULT; - player->frame_reset_delay = 0; + player->use_murphy_graphic = FALSE; + + player->actual_frame_counter = 0; player->last_move_dir = MV_NO_MOVING; player->is_moving = FALSE; + player->is_moving = FALSE; + player->is_waiting = FALSE; + player->move_delay = game.initial_move_delay; player->move_delay_value = game.initial_move_delay_value; @@ -773,6 +732,7 @@ void InitGame() GfxFrame[x][y] = 0; GfxAction[x][y] = ACTION_DEFAULT; + GfxRandom[x][y] = INIT_GFX_RANDOM(); } } @@ -949,14 +909,15 @@ void InitGame() if (level_nr < 100) DrawText(DX + XX_LEVEL, DY + YY_LEVEL, - int2str(level_nr, 2), FS_SMALL, FC_YELLOW); + int2str(level_nr, 2), FONT_DEFAULT_SMALL); else { DrawTextExt(drawto, DX + XX_EMERALDS, DY + YY_EMERALDS, - int2str(level_nr, 3), FS_SMALL, FC_SPECIAL3, FONT_OPAQUE); + int2str(level_nr, 3), FONT_SPECIAL_NARROW, FONT_OPAQUE); BlitBitmap(drawto, drawto, DX + XX_EMERALDS, DY + YY_EMERALDS + 1, - FONT5_XSIZE * 3, FONT5_YSIZE - 1, + getFontWidth(FONT_SPECIAL_NARROW) * 3, + getFontHeight(FONT_SPECIAL_NARROW) - 1, DX + XX_LEVEL - 1, DY + YY_LEVEL + 1); } @@ -1150,7 +1111,7 @@ void GameWon() TimeLeft -= 10; else TimeLeft--; - DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); + DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL); BackToFront(); if (!tape.playing) @@ -1176,7 +1137,7 @@ void GameWon() TimePlayed += 10; else TimePlayed++; - DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FS_SMALL, FC_YELLOW); + DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_DEFAULT_SMALL); BackToFront(); if (!tape.playing) @@ -1187,10 +1148,6 @@ void GameWon() StopSound(SND_GAME_LEVELTIME_BONUS); } -#if 0 - FadeSounds(); -#endif - /* Hero disappears */ DrawLevelField(ExitX, ExitY); BackToFront(); @@ -1301,6 +1258,26 @@ int NewHiScore() return position; } +static void InitPlayerGfxAnimation(struct PlayerInfo *player, int action) +{ + if (player->GfxAction != action) + { + player->GfxAction = action; + player->Frame = 0; + } +} + +static void ResetRandomAnimationValue(int x, int y) +{ + GfxRandom[x][y] = INIT_GFX_RANDOM(); +} + +static void ResetGfxAnimation(int x, int y) +{ + GfxFrame[x][y] = 0; + GfxAction[x][y] = ACTION_DEFAULT; +} + void InitMovingField(int x, int y, int direction) { int element = Feld[x][y]; @@ -1308,10 +1285,9 @@ void InitMovingField(int x, int y, int direction) int newy = y + (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0); if (!JustStopped[x][y] || direction != MovDir[x][y]) - GfxFrame[x][y] = 0; + ResetGfxAnimation(x, y); - MovDir[x][y] = direction; - MovDir[newx][newy] = direction; + MovDir[newx][newy] = MovDir[x][y] = direction; if (Feld[newx][newy] == EL_EMPTY) Feld[newx][newy] = EL_BLOCKED; @@ -1320,6 +1296,10 @@ void InitMovingField(int x, int y, int direction) GfxAction[x][y] = ACTION_FALLING; else GfxAction[x][y] = ACTION_MOVING; + + GfxFrame[newx][newy] = GfxFrame[x][y]; + GfxAction[newx][newy] = GfxAction[x][y]; + GfxRandom[newx][newy] = GfxRandom[x][y]; } void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y) @@ -1460,17 +1440,15 @@ void DrawDynamite(int x, int y) void CheckDynamite(int x, int y) { - int element = Feld[x][y]; - if (MovDelay[x][y] != 0) /* dynamite is still waiting to explode */ { MovDelay[x][y]--; if (MovDelay[x][y] != 0) { - if (checkDrawLevelGraphicAnimation(x, y, el2img(element))) - DrawDynamite(x, y); + DrawDynamite(x, y); + /* !!! correct: "PlaySoundLevelActionIfLoop" etc. !!! */ PlaySoundLevelAction(x, y, ACTION_ACTIVE); return; @@ -1529,7 +1507,7 @@ void Explode(int ex, int ey, int phase, int mode) RemoveMovingField(x, y); } - if (IS_MASSIVE(element) || element == EL_FLAMES) + if (IS_INDESTRUCTIBLE(element) || element == EL_FLAMES) continue; if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y))) @@ -1731,7 +1709,7 @@ void DynaExplode(int ex, int ey) int y = ey + j * xy[i % 4][1]; int element; - if (!IN_LEV_FIELD(x, y) || IS_MASSIVE(Feld[x][y])) + if (!IN_LEV_FIELD(x, y) || IS_INDESTRUCTIBLE(Feld[x][y])) break; element = Feld[x][y]; @@ -1802,52 +1780,24 @@ void Bang(int x, int y) } } -void Blurb(int x, int y) +void SplashAcid(int x, int y) { int element = Feld[x][y]; if (element != EL_ACID_SPLASH_LEFT && - element != EL_ACID_SPLASH_RIGHT) /* start */ + element != EL_ACID_SPLASH_RIGHT) { PlaySoundLevel(x, y, SND_ACID_SPLASHING); + if (IN_LEV_FIELD(x-1, y) && IS_FREE(x-1, y) && (!IN_LEV_FIELD(x-1, y-1) || !CAN_FALL(MovingOrBlocked2Element(x-1, y-1)))) - { Feld[x-1][y] = EL_ACID_SPLASH_LEFT; - } + if (IN_LEV_FIELD(x+1, y) && IS_FREE(x+1, y) && (!IN_LEV_FIELD(x+1, y-1) || !CAN_FALL(MovingOrBlocked2Element(x+1, y-1)))) - { Feld[x+1][y] = EL_ACID_SPLASH_RIGHT; - } - } - else /* go on */ - { - int graphic = (element == EL_ACID_SPLASH_LEFT ? - IMG_ACID_SPLASH_LEFT : - IMG_ACID_SPLASH_RIGHT); - - if (!MovDelay[x][y]) /* initialize animation counter */ - MovDelay[x][y] = 9; - - if (MovDelay[x][y]) /* continue animation */ - { - MovDelay[x][y]--; - if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(graphic, 8 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame); - } - - if (!MovDelay[x][y]) - { - Feld[x][y] = EL_EMPTY; - DrawLevelField(x, y); - } - } } } @@ -2163,18 +2113,24 @@ void Impact(int x, int y) return; object_hit = (!IS_FREE(x, y+1) && (!IS_MOVING(x, y+1) || - MovDir[x][y+1]!=MV_DOWN || - MovPos[x][y+1]<=TILEY/2)); + MovDir[x][y+1] != MV_DOWN || + MovPos[x][y+1] <= TILEY / 2)); if (object_hit) smashed = MovingOrBlocked2Element(x, y+1); } if (!lastline && smashed == EL_ACID) /* element falls into acid */ { - Blurb(x, y); + SplashAcid(x, y); return; } + if (lastline || object_hit) + { + ResetGfxAnimation(x, y); + DrawLevelField(x, y); + } + if ((element == EL_BOMB || element == EL_SP_DISK_ORANGE || element == EL_DX_SUPABOMB) && @@ -2200,6 +2156,8 @@ void Impact(int x, int y) { Feld[x][y] = EL_AMOEBA_CREATING; Store[x][y] = EL_AMOEBA_WET; + + ResetRandomAnimationValue(x, y); } return; } @@ -2903,14 +2861,22 @@ void StartMoving(int x, int y) EL_BD_MAGIC_WALL_FILLING); Store[x][y] = element; } +#if 0 else if (CAN_SMASH(element) && Feld[x][y+1] == EL_ACID) +#else + else if (CAN_FALL(element) && Feld[x][y+1] == EL_ACID) +#endif { - Blurb(x, y); + SplashAcid(x, y); InitMovingField(x, y, MV_DOWN); started_moving = TRUE; Store[x][y] = EL_ACID; +#if 0 + /* !!! TEST !!! better use "_FALLING" etc. !!! */ + GfxAction[x][y+1] = ACTION_ACTIVE; +#endif } else if (CAN_SMASH(element) && Feld[x][y+1] == EL_BLOCKED && JustStopped[x][y]) @@ -2927,6 +2893,9 @@ void StartMoving(int x, int y) } else if (IS_FREE(x, y+1)) { + if (JustStopped[x][y]) /* prevent animation from being restarted */ + MovDir[x][y] = MV_DOWN; + InitMovingField(x, y, MV_DOWN); started_moving = TRUE; } @@ -3021,15 +2990,8 @@ void StartMoving(int x, int y) element != EL_DARK_YAMYAM && element != EL_PACMAN) { -#if 0 - if (element == EL_SPRING) - printf("1--> %d\n", MovDir[x][y]); -#endif TurnRound(x, y); -#if 0 - if (element == EL_SPRING) - printf("2--> %d\n", MovDir[x][y]); -#endif + if (MovDelay[x][y] && (element == EL_BUG || element == EL_SPACESHIP || element == EL_SP_SNIKSNAK || @@ -3044,36 +3006,24 @@ void StartMoving(int x, int y) MovDelay[x][y]--; if (element == EL_ROBOT || - element == EL_YAMYAM || element == EL_DARK_YAMYAM) + element == EL_YAMYAM || + element == EL_DARK_YAMYAM) { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int graphic = el2img(element); - int frame = getGraphicAnimationFrame(graphic, MovDelay[x][y] % 8); - - DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame); - } - - if (MovDelay[x][y] % 4 == 3) - { - if (element == EL_YAMYAM) - PlaySoundLevel(x, y, SND_YAMYAM_WAITING); - else if (element == EL_DARK_YAMYAM) - PlaySoundLevel(x, y, SND_DARK_YAMYAM_WAITING); - } + DrawLevelElementAnimationIfNeeded(x, y, element); + PlaySoundLevelAction(x, y, ACTION_WAITING); } else if (element == EL_SP_ELECTRON) - DrawLevelElementAnimation(x, y, element); + DrawLevelElementAnimationIfNeeded(x, y, element); else if (element == EL_DRAGON) { int i; int dir = MovDir[x][y]; int dx = (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0); int dy = (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0); - int graphic = (dir == MV_LEFT ? IMG_FLAMES_LEFT1 : - dir == MV_RIGHT ? IMG_FLAMES_RIGHT1 : - dir == MV_UP ? IMG_FLAMES_UP1 : - dir == MV_DOWN ? IMG_FLAMES_DOWN1 : IMG_EMPTY); + int graphic = (dir == MV_LEFT ? IMG_FLAMES1_LEFT : + dir == MV_RIGHT ? IMG_FLAMES1_RIGHT : + dir == MV_UP ? IMG_FLAMES1_UP : + dir == MV_DOWN ? IMG_FLAMES1_DOWN : IMG_EMPTY); int frame = getGraphicAnimationFrame(graphic, -1); for (i=1; i<=3; i++) @@ -3140,7 +3090,7 @@ void StartMoving(int x, int y) IN_LEV_FIELD(newx, newy) && MovDir[x][y] == MV_DOWN && Feld[newx][newy] == EL_ACID) { - Blurb(x, y); + SplashAcid(x, y); Store[x][y] = EL_ACID; } else if (element == EL_PENGUIN && IN_LEV_FIELD(newx, newy)) @@ -3321,11 +3271,11 @@ void StartMoving(int x, int y) element == EL_SP_SNIKSNAK || element == EL_MOLE) DrawLevelField(x, y); else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY) - DrawLevelElementAnimation(x, y, element); + DrawLevelElementAnimationIfNeeded(x, y, element); else if (element == EL_SATELLITE) - DrawLevelElementAnimation(x, y, element); + DrawLevelElementAnimationIfNeeded(x, y, element); else if (element == EL_SP_ELECTRON) - DrawLevelElementAnimation(x, y, element); + DrawLevelElementAnimationIfNeeded(x, y, element); if (DONT_TOUCH(element)) TestIfBadThingTouchesHero(x, y); @@ -3460,9 +3410,14 @@ void ContinueMoving(int x, int y) MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0; MovDelay[newx][newy] = 0; + /* copy animation control values to new field */ + GfxFrame[newx][newy] = GfxFrame[x][y]; GfxAction[newx][newy] = GfxAction[x][y]; /* keep action one frame */ - GfxAction[x][y] = ACTION_DEFAULT; + GfxRandom[newx][newy] = GfxRandom[x][y]; /* keep same random value */ + + ResetGfxAnimation(x, y); /* reset animation values for old field */ +#if 1 #if 0 if (!CAN_MOVE(element)) MovDir[newx][newy] = 0; @@ -3475,6 +3430,7 @@ void ContinueMoving(int x, int y) if (!CAN_MOVE(element) || (element == EL_SPRING && MovDir[newx][newy] == MV_DOWN)) MovDir[newx][newy] = 0; +#endif #endif DrawLevelField(x, y); @@ -3498,15 +3454,6 @@ void ContinueMoving(int x, int y) } else /* still moving on */ { -#if 0 - if (GfxAction[x][y] == ACTION_DEFAULT) - { - printf("reset GfxAction...\n"); - - GfxAction[x][y] = ACTION_MOVING; - } -#endif - DrawLevelField(x, y); } } @@ -3999,38 +3946,6 @@ static void StopRobotWheel(int x, int y) ZX = ZY = -1; } -#if 1 -void RobotWheel(int x, int y) -{ - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - if (MovDelay[x][y]) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_ROBOT_WHEEL_ACTIVE, -1); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_ROBOT_WHEEL_ACTIVE, frame); - } - - PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVE); - - return; - } - } - - Feld[x][y] = EL_ROBOT_WHEEL; - DrawLevelField(x, y); - - if (ZX == x && ZY == y) - ZX = ZY = -1; -} -#endif - static void InitTimegateWheel(int x, int y) { MovDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND; @@ -4041,106 +3956,6 @@ static void RunTimegateWheel(int x, int y) PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVE); } -#if 1 -void TimegateWheel(int x, int y) -{ - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - if (MovDelay[x][y]) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_TIMEGATE_SWITCH_ACTIVE, -1); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_TIMEGATE_SWITCH_ACTIVE, frame); - } - - PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVE); - - return; - } - } - - Feld[x][y] = EL_TIMEGATE_SWITCH; - DrawLevelField(x, y); - - /* THIS HAS NO EFFECT AT ALL! */ -#if 1 - /* !!! THIS LOOKS WRONG !!! */ - if (ZX == x && ZY == y) - ZX = ZY = -1; -#endif - -} -#endif - -#if 1 -void NussKnacken(int x, int y) -{ - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 7; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - if (MovDelay[x][y]) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_NUT_CRACKING, - 6 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_NUT_CRACKING, frame); - } - - return; - } - } - - Feld[x][y] = EL_EMERALD; - DrawLevelField(x, y); -} -#endif - -#if 1 -void BreakingPearl(int x, int y) -{ - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 9; - - if (MovDelay[x][y]) /* wait some time before next frame */ - { - MovDelay[x][y]--; - if (MovDelay[x][y]) - { - if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - int frame = getGraphicAnimationFrame(IMG_PEARL_BREAKING, - 8 - MovDelay[x][y]); - - DrawGraphic(SCREENX(x), SCREENY(y), IMG_PEARL_BREAKING, frame); - } - - return; - } - } - - Feld[x][y] = EL_EMPTY; - DrawLevelField(x, y); -} -#endif - -void SiebAktivieren(int x, int y, int type) -{ - int graphic = (type == 1 ? IMG_MAGIC_WALL_FULL : IMG_BD_MAGIC_WALL_FULL); - - DrawLevelGraphicAnimation(x, y, graphic); -} - void CheckExit(int x, int y) { if (local_player->gems_still_needed > 0 || @@ -4163,246 +3978,73 @@ void CheckExitSP(int x, int y) PlaySoundLevelNearest(x, y, SND_SP_EXIT_OPENING); } -#if 1 -void AusgangstuerOeffnen(int x, int y) +static void CloseAllOpenTimegates() { - int delay = 6; - - if (!MovDelay[x][y]) /* next animation frame */ - MovDelay[x][y] = 5 * delay; + int x, y; - if (MovDelay[x][y]) /* wait some time before next frame */ + for (y=0; yframe_reset_delay = 0; - if (button1) snapped = SnapField(player, dx, dy); else @@ -4875,20 +4374,7 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action) } } -#if 0 - if (tape.recording && (moved || snapped || bombed)) - { - if (bombed && !moved) - player_action &= JOY_BUTTON; - - stored_player_action[player->index_nr] = player_action; - save_tape_entry = TRUE; - } - else if (tape.playing && snapped) - SnapField(player, 0, 0); /* stop snapping */ -#else stored_player_action[player->index_nr] = player_action; -#endif } else { @@ -4898,81 +4384,24 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action) SnapField(player, 0, 0); CheckGravityMovement(player); -#if 1 + InitPlayerGfxAnimation(player, ACTION_DEFAULT); + if (player->MovPos == 0) /* needed for tape.playing */ player->is_moving = FALSE; -#endif -#if 0 - if (player->MovPos == 0) /* needed for tape.playing */ - player->last_move_dir = MV_NO_MOVING; - - /* !!! CHECK THIS AGAIN !!! - (Seems to be needed for some EL_ROBOT stuff, but breaks - tapes when walking through pipes!) - */ - - /* it seems that "player->last_move_dir" is misused as some sort of - "player->is_just_moving_in_this_moment", which is needed for the - robot stuff (robots don't kill players when they are moving) - */ -#endif - - /* if the player does not move for some time, reset animation to start */ - if (++player->frame_reset_delay > player->move_delay_value) - player->Frame = 0; } -#if 0 - if (tape.recording && num_stored_actions >= MAX_PLAYERS && save_tape_entry) - { - TapeRecordAction(stored_player_action); - num_stored_actions = 0; - save_tape_entry = FALSE; - } -#else if (tape.recording && num_stored_actions >= MAX_PLAYERS) { TapeRecordAction(stored_player_action); num_stored_actions = 0; } -#endif - -#if 0 - if (tape.playing && !tape.pausing && !player_action && - tape.counter < tape.length) - { - int jx = player->jx, jy = player->jy; - int next_joy = - tape.pos[tape.counter].action[player->index_nr] & (JOY_LEFT|JOY_RIGHT); - - if ((next_joy == JOY_LEFT || next_joy == JOY_RIGHT) && - (player->MovDir != JOY_UP && player->MovDir != JOY_DOWN)) - { - int dx = (next_joy == JOY_LEFT ? -1 : +1); - - if (IN_LEV_FIELD(jx+dx, jy) && IS_PUSHABLE(Feld[jx+dx][jy])) - { - int el = Feld[jx+dx][jy]; - int push_delay = (IS_SB_ELEMENT(el) || el == EL_SATELLITE ? 2 : - (el == EL_BALLOON || el == EL_SPRING) ? 0 : 10); - - if (tape.delay_played + push_delay >= tape.pos[tape.counter].delay) - { - player->MovDir = next_joy; - player->Frame = FrameCounter % 4; - player->Pushing = TRUE; - } - } - } - } -#endif } void GameActions() { static unsigned long action_delay = 0; unsigned long action_delay_value; - int sieb_x = 0, sieb_y = 0; + int magic_wall_x = 0, magic_wall_y = 0; int i, x, y, element, graphic; byte *recorded_player_action; byte summarized_player_action = 0; @@ -5056,30 +4485,12 @@ void GameActions() ScrollScreen(NULL, SCROLL_GO_ON); - - -#ifdef DEBUG -#if 0 - if (TimeFrames == 0 && local_player->active) - { - extern unsigned int last_RND(); - - printf("DEBUG: %03d last RND was %d \t [state checksum is %d]\n", - TimePlayed, last_RND(), getStateCheckSum(TimePlayed)); - } -#endif -#endif - -#ifdef DEBUG -#if 0 - if (GameFrameDelay >= 500) - printf("FrameCounter == %d\n", FrameCounter); -#endif -#endif - FrameCounter++; TimeFrames++; + for (i=0; ijx, jy = local_player->jy; - if (element == EL_MAGIC_WALL_FULL || - element == EL_MAGIC_WALL_ACTIVE || - element == EL_MAGIC_WALL_EMPTYING) - { - SiebAktivieren(x, y, 1); - sieb = TRUE; - } - else if (element == EL_BD_MAGIC_WALL_FULL || - element == EL_BD_MAGIC_WALL_ACTIVE || - element == EL_BD_MAGIC_WALL_EMPTYING) - { - SiebAktivieren(x, y, 2); - sieb = TRUE; - } - /* play the element sound at the position nearest to the player */ - if (sieb && ABS(x-jx)+ABS(y-jy) < ABS(sieb_x-jx)+ABS(sieb_y-jy)) + if ((element == EL_MAGIC_WALL_FULL || + element == EL_MAGIC_WALL_ACTIVE || + element == EL_MAGIC_WALL_EMPTYING || + element == EL_BD_MAGIC_WALL_FULL || + element == EL_BD_MAGIC_WALL_ACTIVE || + element == EL_BD_MAGIC_WALL_EMPTYING) && + ABS(x-jx) + ABS(y-jy) < ABS(magic_wall_x-jx) + ABS(magic_wall_y-jy)) { - sieb_x = x; - sieb_y = y; + magic_wall_x = x; + magic_wall_y = y; } } } @@ -5332,14 +4738,14 @@ void GameActions() { if (!(game.magic_wall_time_left % 4)) { - int element = Feld[sieb_x][sieb_y]; + int element = Feld[magic_wall_x][magic_wall_y]; if (element == EL_BD_MAGIC_WALL_FULL || element == EL_BD_MAGIC_WALL_ACTIVE || element == EL_BD_MAGIC_WALL_EMPTYING) - PlaySoundLevel(sieb_x, sieb_y, SND_BD_MAGIC_WALL_ACTIVE); + PlaySoundLevel(magic_wall_x, magic_wall_y, SND_BD_MAGIC_WALL_ACTIVE); else - PlaySoundLevel(sieb_x, sieb_y, SND_MAGIC_WALL_ACTIVE); + PlaySoundLevel(magic_wall_x, magic_wall_y, SND_MAGIC_WALL_ACTIVE); } if (game.magic_wall_time_left > 0) @@ -5427,14 +4833,14 @@ void GameActions() if (TimeLeft <= 10 && setup.time_limit) PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MAX_RIGHT); - DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); + DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL); if (!TimeLeft && setup.time_limit) for (i=0; iPushing) - player->Frame = 0; - else #if 0 - player->Frame = (player->Frame + 1) % 4; +#if 1 + InitPlayerGfxAnimation(player, ACTION_DEFAULT); #else - player->Frame += 1 * 0; + if (!(moved & MF_MOVING) && !player->Pushing) + player->Frame = 0; +#endif #endif if (moved & MF_MOVING) @@ -5804,8 +5210,6 @@ void ScrollFigure(struct PlayerInfo *player, int mode) { player->actual_frame_counter = FrameCounter; player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); - if (player->Frame) - player->Frame += 1; if (Feld[last_jx][last_jy] == EL_EMPTY) Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING; @@ -5818,7 +5222,6 @@ void ScrollFigure(struct PlayerInfo *player, int mode) player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize; player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); - player->Frame += 1; if (Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING) Feld[last_jx][last_jy] = EL_EMPTY; @@ -6183,6 +5586,8 @@ int DigField(struct PlayerInfo *player, dy == +1 ? MV_DOWN : MV_NO_MOVING); int element; + player->is_digging = FALSE; + if (player->MovPos == 0) player->Pushing = FALSE; @@ -6260,7 +5665,7 @@ int DigField(struct PlayerInfo *player, RaiseScoreElement(element); DrawText(DX_EMERALDS, DY_EMERALDS, int2str(local_player->gems_still_needed, 3), - FS_SMALL, FC_YELLOW); + FONT_DEFAULT_SMALL); PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); break; @@ -6280,7 +5685,7 @@ int DigField(struct PlayerInfo *player, if (level.time > 0) { TimeLeft += 10; - DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); + DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL); } PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MAX_RIGHT); break; @@ -6304,8 +5709,7 @@ int DigField(struct PlayerInfo *player, player->dynamite++; RaiseScoreElement(EL_DYNAMITE); DrawText(DX_DYNAMITE, DY_DYNAMITE, - int2str(local_player->dynamite, 3), - FS_SMALL, FC_YELLOW); + int2str(local_player->dynamite, 3), FONT_DEFAULT_SMALL); PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); break; @@ -6337,14 +5741,15 @@ int DigField(struct PlayerInfo *player, case EL_KEY4: { int key_nr = element - EL_KEY1; + int graphic = el2edimg(element); RemoveField(x, y); player->key[key_nr] = TRUE; RaiseScoreElement(element); DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - IMG_KEY1 + key_nr); + graphic); DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - IMG_KEY1 + key_nr); + graphic); PlaySoundLevel(x, y, SND_KEY_COLLECTING); break; } @@ -6355,14 +5760,15 @@ int DigField(struct PlayerInfo *player, case EL_EM_KEY4: { int key_nr = element - EL_EM_KEY1; + int graphic = el2edimg(EL_KEY1 + key_nr); RemoveField(x, y); player->key[key_nr] = TRUE; RaiseScoreElement(element); DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - IMG_KEY1 + key_nr); + graphic); DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - IMG_KEY1 + key_nr); + graphic); PlaySoundLevel(x, y, SND_KEY_COLLECTING); break; } @@ -6478,7 +5884,9 @@ int DigField(struct PlayerInfo *player, case EL_SPRING: if (mode == DF_SNAP) return MF_NO_ACTION; + /* no "break" -- fall through to next case */ + /* the following elements can be pushed by "snapping" */ case EL_BD_ROCK: if (dy) @@ -6499,7 +5907,8 @@ int DigField(struct PlayerInfo *player, player->push_delay = FrameCounter; #if 0 if (!FrameReached(&player->push_delay, player->push_delay_value) && - !tape.playing && element != EL_SPRING) + !tape.playing && + element != EL_SPRING) return MF_NO_ACTION; #else if (!FrameReached(&player->push_delay, player->push_delay_value) && @@ -6705,7 +6114,7 @@ int DigField(struct PlayerInfo *player, case EL_TIME_ORB_FULL: Feld[x][y] = EL_TIME_ORB_EMPTY; TimeLeft += 10; - DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); + DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL); DrawLevelField(x, y); PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MAX_RIGHT); return MF_ACTION; @@ -6810,11 +6219,56 @@ int DigField(struct PlayerInfo *player, break; default: + if (IS_PUSHABLE(element)) + { + if (mode == DF_SNAP) + return MF_NO_ACTION; + + if (CAN_FALL(element) && dy) + return MF_NO_ACTION; + + player->Pushing = TRUE; + + if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy)) + return MF_NO_ACTION; + + if (dx && real_dy) + { + if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy])) + return MF_NO_ACTION; + } + else if (dy && real_dx) + { + if (IN_LEV_FIELD(jx+real_dx, jy) && !IS_SOLID(Feld[jx+real_dx][jy])) + return MF_NO_ACTION; + } + + if (player->push_delay == 0) + player->push_delay = FrameCounter; + + if (!FrameReached(&player->push_delay, player->push_delay_value) && + !(tape.playing && tape.file_version < FILE_VERSION_2_0)) + return MF_NO_ACTION; + + RemoveField(x, y); + Feld[x + dx][y + dy] = element; + + player->push_delay_value = 2 + RND(8); + + DrawLevelField(x + dx, y + dy); + PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING); + + break; + } + return MF_NO_ACTION; } player->push_delay = 0; + if (Feld[x][y] != element) /* really digged something */ + player->is_digging = TRUE; + return MF_MOVING; } @@ -6835,6 +6289,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) player->Pushing = FALSE; player->snapped = FALSE; + player->is_digging = FALSE; return FALSE; } @@ -6850,6 +6305,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) return FALSE; player->snapped = TRUE; + player->is_digging = FALSE; DrawLevelField(x, y); BackToFront(); @@ -6874,7 +6330,9 @@ boolean PlaceBomb(struct PlayerInfo *player) Store[jx][jy] = element; MovDelay[jx][jy] = 96; - GfxFrame[jx][jy] = 0; + + ResetGfxAnimation(jx, jy); + ResetRandomAnimationValue(jx, jy); if (player->dynamite) { @@ -6882,7 +6340,7 @@ boolean PlaceBomb(struct PlayerInfo *player) player->dynamite--; DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3), - FS_SMALL, FC_YELLOW); + FONT_DEFAULT_SMALL); if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy))) { if (game.emulation == EMU_SUPAPLEX) @@ -7001,7 +6459,7 @@ void RaiseScore(int value) { local_player->score += value; DrawText(DX_SCORE, DY_SCORE, int2str(local_player->score, 5), - FS_SMALL, FC_YELLOW); + FONT_DEFAULT_SMALL); } void RaiseScoreElement(int element)