@@ -773,6 +773,10 @@ static bool registerEndlessHighscore = false;
773773static bool registerTTHighscorePlayer1 = false ;
774774static bool registerTTHighscorePlayer2 = false ;
775775static bool saveReplay = false ;
776+ static std::deque<BlockGameAction> replayQueue;
777+ static size_t replayActionIndex = 0 ;
778+ static bool isReplayMode = false ;
779+ static unsigned int replayTimeOffset = 0 ; // Offset between original game time and replay time
776780
777781/* *
778782 * startSpeed is a value from 0 to 4
@@ -1463,6 +1467,10 @@ int runGame(Gametype gametype, int level) {
14631467 registerEndlessHighscore = false ;
14641468 registerTTHighscorePlayer1 = false ;
14651469 registerTTHighscorePlayer2 = false ;
1470+ isReplayMode = false ;
1471+ replayQueue.clear ();
1472+ replayActionIndex = 0 ;
1473+ replayTimeOffset = 0 ;
14661474 switch (gametype) {
14671475 case Gametype::SinglePlayerTimeTrial:
14681476 StartSinglePlayerTimeTrial ();
@@ -1515,6 +1523,35 @@ int runGame(Gametype gametype, int level) {
15151523 case Gametype::TwoPlayerVs:
15161524 StartTwoPlayerVs ();
15171525 break ;
1526+ case Gametype::Replay: {
1527+ BlockGameInfo replayInfo;
1528+ if (!LoadLatestSinglePlayerReplay (replayInfo)) {
1529+ // No replay available, exit
1530+ return 1 ;
1531+ }
1532+ // Calculate time offset: current time - original start time
1533+ unsigned int currentStartTime = SDL_GetTicks ();
1534+ unsigned int originalStartTime = replayInfo.startInfo .ticks ;
1535+ replayTimeOffset = currentStartTime - originalStartTime;
1536+
1537+ // Adjust startInfo ticks to current time
1538+ replayInfo.startInfo .ticks = currentStartTime;
1539+ theGame.NewGame (replayInfo.startInfo );
1540+ twoPlayers = false ;
1541+ BlockGameAction a;
1542+ a.action = BlockGameAction::Action::SET_GAME_OVER;
1543+ theGame2.DoAction (a);
1544+ theGame.name = replayInfo.extra .name ;
1545+ theGame2.name = globalData.player2name ;
1546+ // Set up replay queue and adjust all action timestamps
1547+ replayQueue = replayInfo.actions ;
1548+ for (BlockGameAction& action : replayQueue) {
1549+ action.tick += replayTimeOffset;
1550+ }
1551+ replayActionIndex = 0 ;
1552+ isReplayMode = true ;
1553+ }
1554+ break ;
15181555 case Gametype::SinglePlayerEndless:
15191556 default :
15201557 StartSinglePlayerEndless (level);
@@ -1606,7 +1643,7 @@ int runGame(Gametype gametype, int level) {
16061643 done=1 ;
16071644 DrawBackground (globalData.screen );
16081645 }
1609- if (!theGame.GetAIenabled ()) {
1646+ if (!theGame.GetAIenabled () && !isReplayMode ) {
16101647 // player1:
16111648 if ( event.key .keysym .sym == keySettings[player1keys].up ) {
16121649 a.action = BlockGameAction::Action::MOVE;
@@ -1923,9 +1960,34 @@ int runGame(Gametype gametype, int level) {
19231960
19241961 // set bNearDeath to false theGame*.Update() will change to true as needed
19251962 bNearDeath = theGame.IsNearDeath () || theGame2.IsNearDeath ();
1926- // Updates the objects
1963+
1964+ // Process replay actions if in replay mode
1965+ if (isReplayMode) {
1966+ unsigned int currentTick = SDL_GetTicks ();
1967+ while (replayActionIndex < replayQueue.size ()) {
1968+ const BlockGameAction& replayAction = replayQueue[replayActionIndex];
1969+ // Process all actions up to the current tick
1970+ if (replayAction.action == BlockGameAction::Action::UPDATE) {
1971+ if (replayAction.tick > currentTick) {
1972+ break ; // Wait for the right time
1973+ }
1974+ theGame.DoAction (replayAction);
1975+ replayActionIndex++;
1976+ break ; // Only process one UPDATE per frame
1977+ } else {
1978+ // Non-UPDATE actions can be processed immediately
1979+ theGame.DoAction (replayAction);
1980+ replayActionIndex++;
1981+ }
1982+ }
1983+ } else {
1984+ // Updates the objects (only when not in replay mode)
1985+ a.action = BlockGameAction::Action::UPDATE;
1986+ theGame.DoAction (a);
1987+ }
1988+
1989+ // Always update player 2
19271990 a.action = BlockGameAction::Action::UPDATE;
1928- theGame.DoAction (a);
19291991 theGame2.DoAction (a);
19301992
19311993// see if anyone has won (two players only)
@@ -2021,6 +2083,10 @@ int runGame(Gametype gametype, int level) {
20212083 }
20222084 }
20232085#endif
2086+ // Save latest single player replay for replay feature
2087+ if (theGame.isGameOver () && !twoPlayers && !theGame.GetAIenabled ()) {
2088+ SaveLatestSinglePlayerReplay (theGame.GetBlockGameInfo ());
2089+ }
20242090
20252091 // Once evrything has been checked, update graphics
20262092 MoveBlockGameSdls (theGame, theGame2);
0 commit comments