X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=a8389022119adf4edf8b101a8d74d59844df3d6b;hb=005e27dc77775cbda39afc1daabc8d5f6011f575;hp=6de0372ce71aba949569874c821db12d8707d7a9;hpb=784245c2e4dd32b84cff6c6044380c7801cb5513;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 6de0372c..a8389022 100644 --- a/src/game.c +++ b/src/game.c @@ -28,7 +28,10 @@ #define USE_NEW_AMOEBA_CODE FALSE /* EXPERIMENTAL STUFF */ -#define USE_NEW_MOVEMENT FALSE +#define USE_NEW_MOVE_STYLE TRUE *0 +#define USE_NEW_MOVE_DELAY TRUE *1 +#define USE_NEW_PUSH_DELAY TRUE *1 +#define USE_NEW_BLOCK_STYLE TRUE *1 /* for DigField() */ #define DF_NO_PUSH 0 @@ -295,6 +298,8 @@ /* forward declaration for internal use */ +static void AdvanceFrameAndPlayerCounters(int); + static boolean MovePlayerOneStep(struct PlayerInfo *, int, int, int, int); static boolean MovePlayer(struct PlayerInfo *, int, int); static void ScrollPlayer(struct PlayerInfo *, int); @@ -387,6 +392,18 @@ struct ChangingElementInfo static struct ChangingElementInfo change_delay_list[] = { +#if USE_NEW_BLOCK_STYLE +#if 0 + { + EL_PLAYER_IS_LEAVING, + EL_EMPTY, + -1, /* delay for blocking field left by player set at runtime */ + NULL, + NULL, + NULL + }, +#endif +#endif { EL_NUT_BREAKING, EL_EMERALD, @@ -757,6 +774,10 @@ static void InitPlayerField(int x, int y, int element, boolean init_game) { struct PlayerInfo *player = &stored_player[Feld[x][y] - EL_PLAYER_1]; int jx = player->jx, jy = player->jy; + int sp_block_delay = 7; + int em_block_delay = 7; + int sp_no_block_delay = 1; + int em_no_block_delay = 1; player->present = TRUE; @@ -764,6 +785,11 @@ static void InitPlayerField(int x, int y, int element, boolean init_game) level.sp_block_last_field : level.block_last_field); + player->block_delay_value = + (element == EL_SP_MURPHY ? + (player->block_last_field ? sp_block_delay : sp_no_block_delay) : + (player->block_last_field ? em_block_delay : em_no_block_delay)); + if (!options.network || player->connected) { player->active = TRUE; @@ -1153,7 +1179,7 @@ static void resolve_group_element(int group_element, int recursion_depth) /* ============================================================================= - InitGameEngine() + InitGameEngine() ----------------------------------------------------------------------------- initialize game engine due to level / tape version number ============================================================================= @@ -1189,6 +1215,15 @@ static void InitGameEngine() /* ---------- initialize player's initial move delay --------------------- */ +#if USE_NEW_MOVE_DELAY + /* dynamically adjust player properties according to level information */ + game.initial_move_delay_value = + (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED); + + /* dynamically adjust player properties according to game engine version */ + game.initial_move_delay = (game.engine_version <= VERSION_IDENT(2,0,1,0) ? + game.initial_move_delay_value : 0); +#else /* dynamically adjust player properties according to game engine version */ game.initial_move_delay = (game.engine_version <= VERSION_IDENT(2,0,1,0) ? INITIAL_MOVE_DELAY_ON : @@ -1197,6 +1232,7 @@ static void InitGameEngine() /* dynamically adjust player properties according to level information */ game.initial_move_delay_value = (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED); +#endif /* ---------- initialize player's initial push delay --------------------- */ @@ -1371,8 +1407,13 @@ static void InitGameEngine() { if (IS_SP_ELEMENT(i)) { +#if USE_NEW_MOVE_STYLE + element_info[i].push_delay_fixed = 7; /* just enough to escape ... */ + element_info[i].push_delay_random = 0; /* ... from falling zonk */ +#else element_info[i].push_delay_fixed = 6; /* just enough to escape ... */ element_info[i].push_delay_random = 0; /* ... from falling zonk */ +#endif } } } @@ -1497,7 +1538,10 @@ void InitGame() player->use_murphy_graphic = FALSE; - player->block_last_field = FALSE; + player->block_last_field = FALSE; /* initialized in InitPlayerField() */ + player->block_delay = 0; + player->block_delay_value = -1; /* initialized in InitPlayerField() */ + player->can_fall_into_acid = CAN_MOVE_INTO_ACID(player->element_nr); player->actual_frame_counter = 0; @@ -1573,8 +1617,13 @@ void InitGame() player->move_delay_reset_counter = 0; - player->push_delay = 0; +#if USE_NEW_PUSH_DELAY + player->push_delay = -1; /* initialized when pushing starts */ player->push_delay_value = game.initial_push_delay_value; +#else + player->push_delay = 0; + player->push_delay_value = game.initial_push_delay_value; +#endif player->drop_delay = 0; @@ -2890,7 +2939,12 @@ void RelocatePlayer(int jx, int jy, int el_player_raw) { ScrollPlayer(player, SCROLL_GO_ON); ScrollScreen(NULL, SCROLL_GO_ON); + +#if USE_NEW_MOVE_DELAY + AdvanceFrameAndPlayerCounters(player->index_nr); +#else FrameCounter++; +#endif DrawPlayer(player); @@ -6376,7 +6430,7 @@ void ContinueMoving(int x, int y) else if (element == EL_PENGUIN) TestIfFriendTouchesBadThing(newx, newy); -#if USE_NEW_MOVEMENT +#if USE_NEW_MOVE_STYLE #if 0 if (CAN_FALL(element) && direction == MV_DOWN && (newy == lev_fieldy - 1 || !IS_FREE(x, newy + 1)) && @@ -8323,6 +8377,45 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action) } #endif +void AdvanceFrameAndPlayerCounters(int player_nr) +{ + int i; + + /* advance frame counters (global frame counter and time frame counter) */ + FrameCounter++; + TimeFrames++; + + /* advance player counters (counters for move delay, move animation etc.) */ + for (i = 0; i < MAX_PLAYERS; i++) + { + boolean advance_player_counters = (player_nr == -1 || player_nr == i); + int move_frames = + MOVE_DELAY_NORMAL_SPEED / stored_player[i].move_delay_value; + + if (!advance_player_counters) /* not all players may be affected */ + continue; + + stored_player[i].Frame += move_frames; + + if (stored_player[i].MovPos != 0) + stored_player[i].StepFrame += move_frames; + +#if USE_NEW_MOVE_DELAY + if (stored_player[i].move_delay > 0) + stored_player[i].move_delay--; +#endif + +#if USE_NEW_PUSH_DELAY + /* due to bugs in previous versions, counter must count up, not down */ + if (stored_player[i].push_delay != -1) + stored_player[i].push_delay++; +#endif + + if (stored_player[i].drop_delay > 0) + stored_player[i].drop_delay--; + } +} + void GameActions() { static unsigned long action_delay = 0; @@ -8564,6 +8657,14 @@ void GameActions() Changed[x][y] = CE_BITMASK_DEFAULT; ChangeEvent[x][y] = CE_BITMASK_DEFAULT; + /* this must be handled before main playfield loop */ + if (Feld[x][y] == EL_PLAYER_IS_LEAVING) + { + MovDelay[x][y]--; + if (MovDelay[x][y] <= 0) + RemoveField(x, y); + } + #if DEBUG if (ChangePage[x][y] != -1 && ChangeDelay[x][y] != 1) { @@ -9014,7 +9115,9 @@ void GameActions() stored_player[0].StepFrame); #endif -#if 1 +#if USE_NEW_MOVE_DELAY + AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ +#else FrameCounter++; TimeFrames++; @@ -9028,6 +9131,11 @@ void GameActions() if (stored_player[i].MovPos != 0) stored_player[i].StepFrame += move_frames; +#if USE_NEW_MOVE_DELAY + if (stored_player[i].move_delay > 0) + stored_player[i].move_delay--; +#endif + if (stored_player[i].drop_delay > 0) stored_player[i].drop_delay--; } @@ -9513,7 +9621,11 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) player->move_delay + player->move_delay_value); #endif +#if USE_NEW_MOVE_DELAY + if (player->move_delay > 0) +#else if (!FrameReached(&player->move_delay, player->move_delay_value)) +#endif { #if 0 printf("::: can NOT move\n"); @@ -9533,6 +9645,10 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) printf("::: COULD move now\n"); #endif +#if USE_NEW_MOVE_DELAY + player->move_delay = -1; /* set to "uninitialized" value */ +#endif + /* store if player is automatically moved to next field */ player->is_auto_moving = (player->programmed_action != MV_NO_MOVING); @@ -9558,7 +9674,13 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) { ScrollPlayer(player, SCROLL_GO_ON); ScrollScreen(NULL, SCROLL_GO_ON); + +#if USE_NEW_MOVE_DELAY + AdvanceFrameAndPlayerCounters(player->index_nr); +#else FrameCounter++; +#endif + DrawAllPlayers(); BackToFront(); } @@ -9746,16 +9868,21 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) */ player->is_moving = FALSE; -#if USE_NEW_MOVEMENT +#if USE_NEW_MOVE_STYLE /* player is ALLOWED to move, but CANNOT move (something blocks his way) */ /* ensure that the player is also allowed to move in the next frame */ /* (currently, the player is forced to wait eight frames before he can try again!!!) */ - player->move_delay = -1; /* allow direct movement in the next frame */ + player->move_delay = 0; /* allow direct movement in the next frame */ #endif } +#if USE_NEW_MOVE_DELAY + if (player->move_delay == -1) /* not yet initialized by DigField() */ + player->move_delay = player->move_delay_value; +#endif + if (game.engine_version < VERSION_IDENT(3,0,7,0)) { TestIfHeroTouchesBadThing(jx, jy); @@ -9782,7 +9909,19 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) player->actual_frame_counter = FrameCounter; player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); -#if USE_NEW_MOVEMENT +#if USE_NEW_BLOCK_STYLE + if (player->block_delay_value > 0 && + Feld[last_jx][last_jy] == EL_EMPTY) + { + Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING; +#if 1 + MovDelay[last_jx][last_jy] = player->block_delay_value + 1; +#else + ChangeDelay[last_jx][last_jy] = player->block_last_field_delay; +#endif + } +#else +#if USE_NEW_MOVE_STYLE if (player->block_last_field && Feld[last_jx][last_jy] == EL_EMPTY) Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING; @@ -9790,6 +9929,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) if (Feld[last_jx][last_jy] == EL_EMPTY) Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING; #endif +#endif #if 0 DrawPlayer(player); @@ -9803,9 +9943,16 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize; player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); +#if USE_NEW_BLOCK_STYLE +#else if (!player->block_last_field && Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING) +#if 1 + RemoveField(last_jx, last_jy); +#else Feld[last_jx][last_jy] = EL_EMPTY; +#endif +#endif /* before DrawPlayer() to draw correct player graphic for this case */ if (player->MovPos == 0) @@ -9842,9 +9989,16 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) } #endif +#if USE_NEW_BLOCK_STYLE +#else if (player->block_last_field && Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING) +#if 1 + RemoveField(last_jx, last_jy); +#else Feld[last_jx][last_jy] = EL_EMPTY; +#endif +#endif player->last_jx = jx; player->last_jy = jy; @@ -10810,7 +10964,11 @@ int DigField(struct PlayerInfo *player, if (mode == DF_NO_PUSH) /* player just stopped pushing */ { player->is_switching = FALSE; +#if USE_NEW_PUSH_DELAY + player->push_delay = -1; +#else player->push_delay = 0; +#endif return MF_NO_ACTION; } @@ -11373,16 +11531,56 @@ int DigField(struct PlayerInfo *player, if (!checkDiagonalPushing(player, x, y, real_dx, real_dy)) return MF_NO_ACTION; +#if USE_NEW_PUSH_DELAY + +#if 0 + if ( (player->push_delay == -1) != (player->push_delay2 == 0) ) + printf("::: ALERT: %d, %d [%d / %d]\n", + player->push_delay, player->push_delay2, + FrameCounter, FrameCounter / 50); +#endif + + if (player->push_delay == -1) /* new pushing; restart delay */ + player->push_delay = 0; +#else if (player->push_delay == 0) /* new pushing; restart delay */ player->push_delay = FrameCounter; +#endif +#if USE_NEW_PUSH_DELAY +#if 0 + if ( (player->push_delay > 0) != (!xxx_fr) ) + printf("::: PUSH BUG! %d, (%d -> %d) %d [%d / %d]\n", + player->push_delay, + xxx_pdv2, player->push_delay2, player->push_delay_value, + FrameCounter, FrameCounter / 50); +#endif + +#if 0 + if (player->push_delay > 0 && + !(tape.playing && tape.file_version < FILE_VERSION_2_0) && + element != EL_SPRING && element != EL_BALLOON) +#else + /* !!! */ + if (player->push_delay < player->push_delay_value && + !(tape.playing && tape.file_version < FILE_VERSION_2_0) && + element != EL_SPRING && element != EL_BALLOON) +#endif + +#else if (!FrameReached(&player->push_delay, player->push_delay_value) && !(tape.playing && tape.file_version < FILE_VERSION_2_0) && element != EL_SPRING && element != EL_BALLOON) +#endif { /* make sure that there is no move delay before next try to push */ +#if USE_NEW_MOVE_DELAY + if (game.engine_version >= VERSION_IDENT(3,0,7,1)) + player->move_delay = 0; +#else if (game.engine_version >= VERSION_IDENT(3,0,7,1)) player->move_delay = INITIAL_MOVE_DELAY_OFF; +#endif return MF_NO_ACTION; } @@ -11608,7 +11806,11 @@ int DigField(struct PlayerInfo *player, return MF_NO_ACTION; } +#if USE_NEW_PUSH_DELAY + player->push_delay = -1; +#else player->push_delay = 0; +#endif if (Feld[x][y] != element) /* really digged/collected something */ player->is_collecting = !player->is_digging;