From b8a4b4dfe7c1b923b10b8babdd9b037fe34ce8b9 Mon Sep 17 00:00:00 2001 From: Misa Date: Fri, 9 Oct 2020 20:58:58 -0700 Subject: [PATCH] Restore previous oldxp/oldyp variables in favor of lerpoldxp/lerpoldyp I was investigating a desync in my Nova TAS, and it turns out that the gravity line collision functions check for the `oldxp` and `oldyp` of the player, i.e. their position on the previous frame, along with their position on the current frame. So, if the player either collided with the gravity line last frame or this frame, then the player collided with the gravity line this frame. Except, that's not actually true. It turns out that `oldxp` and `oldyp` don't necessarily always correspond to the `xp` and `yp` of the player on the previous frame. It turns out that your `oldyp` will be updated if you stand on a vertically moving platform, before the gravity line collision function gets ran. So, if you were colliding with a gravity line on the previous frame, but you got moved out of there by a vertically moving platform, then you just don't collide with the gravity line at all. However, this behavior changed in 2.3 after my over-30-FPS patch got merged (#220). That patch took advantage of the existing `oldxp` and `oldyp` entity attributes, and uses them to interpolate their positions during rendering to make everything look real smooth. Previously, `oldxp` and `oldyp` would both be updated in `entityclass::updateentitylogic()`. However, I moved it in that patch to update right before `gameinput()` in `main.cpp`. As a result, `oldyp` no longer gets updated whenever the player stands on a vertically moving platform. This ends up desyncing my TAS. As expected, updating `oldyp` in `entityclass::movingplatformfix()` (the function responsible for moving the player whenever they stand on a vertically moving platform) makes it so that my TAS syncs, but the visuals are glitchy when standing on a vertically moving platform. And as much as I'd like to get rid of gravity lines checking for whether you've collided with them on the previous frame, doing that desyncs my TAS, too. In the end, it seems like I should just leave `oldxp` and `oldyp` alone, and switch to using dedicated variables that are never used in the physics of the game. So I'm introducing `lerpoldxp` and `lerpoldyp`, and replacing all instances of using `oldxp` and `oldyp` that my over-30-FPS patch added, with `lerpoldxp` and `lerpoldyp` instead. After doing this, and applying #503 as well, my Nova TAS syncs after some minor but acceptable fixes with Viridian's walkingframe. --- desktop_version/src/Ent.cpp | 2 ++ desktop_version/src/Ent.h | 1 + desktop_version/src/Entity.cpp | 21 ++++++++++------- desktop_version/src/Game.cpp | 40 ++++++++++++++++---------------- desktop_version/src/Graphics.cpp | 4 ++-- desktop_version/src/Logic.cpp | 20 ++++++++-------- desktop_version/src/Map.cpp | 8 +++---- desktop_version/src/Script.cpp | 4 ++-- desktop_version/src/main.cpp | 6 ++--- 9 files changed, 56 insertions(+), 50 deletions(-) diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index b6e126af..77f655c6 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -56,6 +56,8 @@ entclass::entclass() actionframe = 0; realcol = 0; + lerpoldxp = 0; + lerpoldyp = 0; } bool entclass::outside() diff --git a/desktop_version/src/Ent.h b/desktop_version/src/Ent.h index 96c7ee87..6b66c5f4 100644 --- a/desktop_version/src/Ent.h +++ b/desktop_version/src/Ent.h @@ -49,6 +49,7 @@ public: int yp;int xp; Uint32 realcol; + int lerpoldxp, lerpoldyp; }; #endif /* ENT_H */ diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index b63f219c..510bd7e3 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -1213,8 +1213,8 @@ void entityclass::createentity( float xp, float yp, int t, float vx /*= 0*/, flo entclass entity; entity.xp = xp; entity.yp = yp; - entity.oldxp = xp; - entity.oldyp = yp; + entity.lerpoldxp = xp; + entity.lerpoldyp = yp; entity.type = t; switch(t) { @@ -1783,7 +1783,7 @@ void entityclass::createentity( float xp, float yp, int t, float vx /*= 0*/, flo entity.tile = 188 + vx; entity.colour = 37; entity.h += 3; - entity.oldyp -= 3; + entity.lerpoldyp -= 3; entity.yp -= 3; } break; @@ -2440,20 +2440,20 @@ bool entityclass::updateentities( int i ) { entities[i].tile = 120; entities[i].yp = (28*8)-62; - entities[i].oldyp = (28*8)-62; + entities[i].lerpoldyp = (28*8)-62; } else { entities[i].tile = 96; entities[i].yp = 24; - entities[i].oldyp = 24; + entities[i].lerpoldyp = 24; } //now, x position if (INBOUNDS_VEC(player, entities) && entities[player].xp > 20 * 8) { //approach from the left entities[i].xp = -64; - entities[i].oldxp = -64; + entities[i].lerpoldxp = -64; entities[i].state = 2; bool entitygone = updateentities(i); //right if (entitygone) return true; @@ -2462,7 +2462,7 @@ bool entityclass::updateentities( int i ) { //approach from the left entities[i].xp = 320; - entities[i].oldxp = 320; + entities[i].lerpoldxp = 320; entities[i].state = 3; bool entitygone = updateentities(i); //left if (entitygone) return true; @@ -2491,7 +2491,7 @@ bool entityclass::updateentities( int i ) { entities[i].statedelay = 6; entities[i].xp -= int(entities[i].para); - entities[i].oldxp -= int(entities[i].para); + entities[i].lerpoldxp -= int(entities[i].para); } break; case 18: //Special for ASCII Snake (right) @@ -2499,7 +2499,7 @@ bool entityclass::updateentities( int i ) { entities[i].statedelay = 6; entities[i].xp += int(entities[i].para); - entities[i].oldxp += int(entities[i].para); + entities[i].lerpoldxp += int(entities[i].para); } break; } @@ -4422,6 +4422,9 @@ void entityclass::updateentitylogic( int t ) return; } + entities[t].oldxp = entities[t].xp; + entities[t].oldyp = entities[t].yp; + entities[t].vx = entities[t].vx + entities[t].ax; entities[t].vy = entities[t].vy + entities[t].ay; entities[t].ax = 0; diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index ec31f8cb..1b67acae 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -1987,8 +1987,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; } obj.entities[i].ay = -6; obj.entities[i].ax = 6; @@ -3361,8 +3361,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; obj.entities[j].colour = 101; } @@ -3492,8 +3492,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; obj.entities[j].colour = 101; } @@ -3605,8 +3605,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; obj.entities[j].colour = 101; } @@ -3718,8 +3718,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; obj.entities[j].colour = 101; } @@ -3836,8 +3836,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; obj.entities[j].colour = 101; } @@ -3954,8 +3954,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; obj.entities[j].colour = 101; } @@ -4070,8 +4070,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; obj.entities[j].colour = 101; } @@ -4183,8 +4183,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; obj.entities[j].colour = 101; } @@ -4296,8 +4296,8 @@ void Game::updatestate() { obj.entities[i].xp = obj.entities[j].xp+44; obj.entities[i].yp = obj.entities[j].yp+44; - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; obj.entities[j].tile = 2; obj.entities[j].colour = 101; } diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index f6d9000d..20ebc2f3 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -1633,8 +1633,8 @@ void Graphics::drawentities() continue; } - int xp = lerp(obj.entities[i].oldxp, obj.entities[i].xp); - int yp = lerp(obj.entities[i].oldyp, obj.entities[i].yp); + int xp = lerp(obj.entities[i].lerpoldxp, obj.entities[i].xp); + int yp = lerp(obj.entities[i].lerpoldyp, obj.entities[i].yp); switch (obj.entities[i].size) { diff --git a/desktop_version/src/Logic.cpp b/desktop_version/src/Logic.cpp index 3b5984db..8622c88e 100644 --- a/desktop_version/src/Logic.cpp +++ b/desktop_version/src/Logic.cpp @@ -1070,7 +1070,7 @@ void gamelogic() obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp + 400, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h); } obj.entities[i].xp += 400; - obj.entities[i].oldxp += 400; + obj.entities[i].lerpoldxp += 400; } else if (obj.entities[i].xp > 320) { @@ -1079,7 +1079,7 @@ void gamelogic() obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp - 400, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h); } obj.entities[i].xp -= 400; - obj.entities[i].oldxp -= 400; + obj.entities[i].lerpoldxp -= 400; } } else @@ -1091,7 +1091,7 @@ void gamelogic() obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp + 320, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h); } obj.entities[i].xp += 320; - obj.entities[i].oldxp += 320; + obj.entities[i].lerpoldxp += 320; } else if (obj.entities[i].xp > 310) { @@ -1100,7 +1100,7 @@ void gamelogic() obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp - 320, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h); } obj.entities[i].xp -= 320; - obj.entities[i].oldxp -= 320; + obj.entities[i].lerpoldxp -= 320; } } } @@ -1119,7 +1119,7 @@ void gamelogic() obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp, obj.entities[i].yp + 232, obj.entities[i].w, obj.entities[i].h); } obj.entities[i].yp += 232; - obj.entities[i].oldyp += 232; + obj.entities[i].lerpoldyp += 232; } else if (obj.entities[i].yp > 226) { @@ -1128,7 +1128,7 @@ void gamelogic() obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp, obj.entities[i].yp - 232, obj.entities[i].w, obj.entities[i].h); } obj.entities[i].yp -= 232; - obj.entities[i].oldyp -= 232; + obj.entities[i].lerpoldyp -= 232; } } } @@ -1149,7 +1149,7 @@ void gamelogic() obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp + 350, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h); } obj.entities[i].xp += 350; - obj.entities[i].oldxp += 350; + obj.entities[i].lerpoldxp += 350; } else if (obj.entities[i].xp > 320) { @@ -1158,7 +1158,7 @@ void gamelogic() obj.moveblockto(obj.entities[i].xp, obj.entities[i].yp, obj.entities[i].xp - 350, obj.entities[i].yp, obj.entities[i].w, obj.entities[i].h); } obj.entities[i].xp -= 350; - obj.entities[i].oldxp -= 350; + obj.entities[i].lerpoldxp -= 350; } } } @@ -1256,12 +1256,12 @@ void gamelogic() if (obj.entities[i].xp <= -10) { obj.entities[i].xp += 320; - obj.entities[i].oldxp += 320; + obj.entities[i].lerpoldxp += 320; } else if (obj.entities[i].xp > 310) { obj.entities[i].xp -= 320; - obj.entities[i].oldxp -= 320; + obj.entities[i].lerpoldxp -= 320; } } } diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index 007621a5..118d6646 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -894,8 +894,8 @@ void mapclass::warpto(int rx, int ry , int t, int tx, int ty) { obj.entities[t].xp = tx * 8; obj.entities[t].yp = (ty * 8) - obj.entities[t].h; - obj.entities[t].oldxp = obj.entities[t].xp; - obj.entities[t].oldyp = obj.entities[t].yp; + obj.entities[t].lerpoldxp = obj.entities[t].xp; + obj.entities[t].lerpoldyp = obj.entities[t].yp; } game.gravitycontrol = 0; } @@ -1100,8 +1100,8 @@ void mapclass::gotoroom(int rx, int ry) temp = obj.getplayer(); if(INBOUNDS_VEC(temp, obj.entities)) { - obj.entities[temp].oldxp = obj.entities[temp].xp - int(obj.entities[temp].vx); - obj.entities[temp].oldyp = obj.entities[temp].yp - int(obj.entities[temp].vy); + obj.entities[temp].lerpoldxp = obj.entities[temp].xp - int(obj.entities[temp].vx); + obj.entities[temp].lerpoldyp = obj.entities[temp].yp - int(obj.entities[temp].vy); } for (size_t i = 0; i < obj.entities.size(); i++) diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index c9bbaab2..1bc9be8b 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -3447,8 +3447,8 @@ void scriptclass::teleport() obj.entities[i].xp = 150; obj.entities[i].yp = 110; if(game.teleport_to_x==17 && game.teleport_to_y==17) obj.entities[i].xp = 88; //prevent falling! - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; } if (game.teleportscript == "levelonecomplete") diff --git a/desktop_version/src/main.cpp b/desktop_version/src/main.cpp index d9410981..b50e8c81 100644 --- a/desktop_version/src/main.cpp +++ b/desktop_version/src/main.cpp @@ -542,11 +542,11 @@ void inline fixedloop() script.run(); } - //Update old positions of entities - has to be done BEFORE gameinput! + //Update old lerp positions of entities - has to be done BEFORE gameinput! for (size_t i = 0; i < obj.entities.size(); i++) { - obj.entities[i].oldxp = obj.entities[i].xp; - obj.entities[i].oldyp = obj.entities[i].yp; + obj.entities[i].lerpoldxp = obj.entities[i].xp; + obj.entities[i].lerpoldyp = obj.entities[i].yp; } gameinput();