1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-22 20:48:29 +02:00

Prevent updating an entity if updateentities() removed it

Otherwise, this would result in the game updating an entity twice, which
isn't good. This is most noticeable in the Gravitron, where many
Gravitron squares are created and destroyed at a time, and it's
especially noticeable during the part near the end of the Gravitron
where the pattern is two Gravitron squares, one at the top and bottom,
and then two Gravitron squares in the middle afterwards. The timing is
just right such that the top one of the two middle ones would be
misaligned with the bottom one of the two when a Gravitron square gets
outside the screen.

To do this, I changed entityclass::updateentities() into a bool, and
made every single caller check its return value. I only needed to do
this for the ones preceding updateentitylogic() and
entitymapcollision(), but I wanted to play it safe and be defensive, so
I did it for the disappearing platform kludge, as well as the
updateentities() within the updateentities() function.
This commit is contained in:
Misa 2020-05-05 13:49:12 -07:00 committed by Ethan Lee
parent 3c80d136e4
commit ce1e212317
3 changed files with 91 additions and 25 deletions

View File

@ -2066,12 +2066,13 @@ void entityclass::createentity( float xp, float yp, int t, float vx /*= 0*/, flo
entities.push_back(entity);
}
void entityclass::updateentities( int i )
//Returns true if entity is removed
bool entityclass::updateentities( int i )
{
if (i < 0 || i >= (int) entities.size())
{
puts("updateentities() out-of-bounds!");
return;
return true;
}
if(entities[i].statedelay<=0)
@ -2088,7 +2089,8 @@ void entityclass::updateentities( int i )
if (entities[i].state == 0) //Init
{
entities[i].state = 3;
updateentities(i);
bool entitygone = updateentities(i);
if (entitygone) return true;
}
else if (entities[i].state == 1)
{
@ -2111,7 +2113,8 @@ void entityclass::updateentities( int i )
if (entities[i].state == 0) //Init
{
entities[i].state = 2;
updateentities(i);
bool entitygone = updateentities(i);
if (entitygone) return true;
}
else if (entities[i].state == 1)
{
@ -2134,7 +2137,8 @@ void entityclass::updateentities( int i )
if (entities[i].state == 0) //Init
{
entities[i].state = 3;
updateentities(i);
bool entitygone = updateentities(i);
if (entitygone) return true;
}
else if (entities[i].state == 1)
{
@ -2157,7 +2161,8 @@ void entityclass::updateentities( int i )
if (entities[i].state == 0) //Init
{
entities[i].state = 3;
updateentities(i);
bool entitygone = updateentities(i);
if (entitygone) return true;
}
else if (entities[i].state == 1)
{
@ -2252,10 +2257,18 @@ void entityclass::updateentities( int i )
}
else if (entities[i].state == 1)
{
if (entities[i].xp >= 335) removeentity(i);
if (entities[i].xp >= 335)
{
removeentity(i);
return true;
}
if (game.roomx == 117)
{
if (entities[i].xp >= (33*8)-32) removeentity(i);
if (entities[i].xp >= (33*8)-32)
{
removeentity(i);
return true;
}
//collector for LIES
}
}
@ -2281,10 +2294,18 @@ void entityclass::updateentities( int i )
}
else if (entities[i].state == 1)
{
if (entities[i].yp <= -60) removeentity(i);
if (entities[i].yp <= -60)
{
removeentity(i);
return true;
}
if (game.roomy == 108)
{
if (entities[i].yp <= 60) removeentity(i);
if (entities[i].yp <= 60)
{
removeentity(i);
return true;
}
//collector for factory
}
}
@ -2297,7 +2318,8 @@ void entityclass::updateentities( int i )
if (entities[j].type == 2 && entities[j].state== 3 && entities[j].xp == (entities[i].xp-32) )
{
entities[i].state = 3;
updateentities(i);
bool entitygone = updateentities(i);
if (entitygone) return true;
}
}
}
@ -2326,7 +2348,8 @@ void entityclass::updateentities( int i )
if (entities[j].type == 2 && entities[j].state==3 && entities[j].xp==entities[i].xp+32)
{
entities[i].state = 3;
updateentities(i);
bool entitygone = updateentities(i);
if (entitygone) return true;
}
}
}
@ -2367,14 +2390,16 @@ void entityclass::updateentities( int i )
//approach from the left
entities[i].xp = -64;
entities[i].state = 2;
updateentities(i); //right
bool entitygone = updateentities(i); //right
if (entitygone) return true;
}
else
{
//approach from the left
entities[i].xp = 320;
entities[i].state = 3;
updateentities(i); //left
bool entitygone = updateentities(i); //left
if (entitygone) return true;
}
}
@ -2475,6 +2500,7 @@ void entityclass::updateentities( int i )
{
removeblockat(entities[i].xp, entities[i].yp);
removeentity(i);
return true;
}
}
break;
@ -2484,6 +2510,7 @@ void entityclass::updateentities( int i )
{
removeentity(i);
game.gravitycontrol = (game.gravitycontrol + 1) % 2;
return true;
}
break;
@ -2491,7 +2518,11 @@ void entityclass::updateentities( int i )
if (entities[i].state == 0)
{
entities[i].life--;
if (entities[i].life < 0) removeentity(i);
if (entities[i].life < 0)
{
removeentity(i);
return true;
}
}
break;
case 6: //Small pickup
@ -2502,6 +2533,7 @@ void entityclass::updateentities( int i )
collect[entities[i].para] = true;
removeentity(i);
return true;
}
break;
case 7: //Found a trinket
@ -2526,6 +2558,7 @@ void entityclass::updateentities( int i )
}
removeentity(i);
return true;
}
break;
case 8: //Savepoints
@ -3022,6 +3055,7 @@ void entityclass::updateentities( int i )
{
game.scmprogress++;
removeentity(i);
return true;
}
}
break;
@ -3044,14 +3078,22 @@ void entityclass::updateentities( int i )
if (entities[i].state == 0) //Init
{
entities[i].vx = 7;
if (entities[i].xp > 320) removeentity(i);
if (entities[i].xp > 320)
{
removeentity(i);
return true;
}
}
break;
case 1:
if (entities[i].state == 0) //Init
{
entities[i].vx = -7;
if (entities[i].xp <-20) removeentity(i);
if (entities[i].xp <-20)
{
removeentity(i);
return true;
}
}
break;
}
@ -3143,6 +3185,7 @@ void entityclass::updateentities( int i )
}
removeentity(i);
return true;
}
break;
case 100: //The teleporter
@ -3217,6 +3260,8 @@ void entityclass::updateentities( int i )
entities[i].statedelay = 0;
}
}
return false;
}
void entityclass::animateentities( int _i )

View File

@ -76,7 +76,7 @@ public:
void createentity(float xp, float yp, int t, float vx = 0, float vy = 0,
int p1 = 0, int p2 = 0, int p3 = 320, int p4 = 240 );
void updateentities(int i);
bool updateentities(int i);
void animateentities(int i);

View File

@ -342,14 +342,32 @@ void gamelogic()
{
//ok, unfortunate case where the disappearing platform hasn't fully disappeared. Accept a little
//graphical uglyness to avoid breaking the room!
while (obj.entities[i].state == 2) obj.updateentities(i);
obj.entities[i].state = 4;
bool entitygone = false;
while (obj.entities[i].state == 2)
{
entitygone = obj.updateentities(i);
if (entitygone)
{
i--;
break;
}
}
if (!entitygone) obj.entities[i].state = 4;
}
else if (map.finalstretch && obj.entities[i].type == 2)
{
//for the final level. probably something 99% of players won't see.
while (obj.entities[i].state == 2) obj.updateentities(i);
obj.entities[i].state = 4;
bool entitygone = false;
while (obj.entities[i].state == 2)
{
entitygone = obj.updateentities(i);
if (entitygone)
{
i--;
break;
}
}
if (!entitygone) obj.entities[i].state = 4;
}
else if (obj.entities[i].type == 23 && game.swnmode && game.deathseq<15)
{
@ -699,7 +717,8 @@ void gamelogic()
{
obj.removeblockat(obj.entities[i].xp, obj.entities[i].yp);
obj.updateentities(i); // Behavioral logic
bool entitygone = obj.updateentities(i); // Behavioral logic
if (entitygone) continue;
obj.updateentitylogic(i); // Basic Physics
obj.entitymapcollision(i); // Collisions with walls
@ -728,7 +747,8 @@ void gamelogic()
{
obj.removeblockat(obj.entities[ie].xp, obj.entities[ie].yp);
obj.updateentities(ie); // Behavioral logic
bool entitygone = obj.updateentities(ie); // Behavioral logic
if (entitygone) continue;
obj.updateentitylogic(ie); // Basic Physics
obj.entitymapcollision(ie); // Collisions with walls
@ -759,7 +779,8 @@ void gamelogic()
{
if (!obj.entities[ie].isplatform)
{
obj.updateentities(ie); // Behavioral logic
bool entitygone = obj.updateentities(ie); // Behavioral logic
if (entitygone) continue;
obj.updateentitylogic(ie); // Basic Physics
obj.entitymapcollision(ie); // Collisions with walls
}