mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-22 17:49:43 +01:00
Optimize entity collision checking to O(n)
I noticed that if I have a large amount of entities in the room, the game starts to freeze and one frame would take a very long time. I identified an obvious cause of this, which is that the entity collision checking in entityclass::entitycollisioncheck() is O(n²), n being the number of entities in the room. But it doesn't need to be O(n²). The only entities you need to check against all other entities are the player and the supercrewmate. You don't need to "test entity to entity" if 99% of the pairs of entities you're checking don't involve the player or supercrewmate. How do we make it O(n)? Well, just hoist the rule 0 and type 14 checks out of the inner for-loop. That way, the inner for-loop won't be unconditionally ran, meaning that in most cases it will always be O(n). However, if you start having large amounts of duplicate player or supercrewmate entities (I don't know why you would), it would start approaching O(n²), but I feel like that's fair in that case. But most of the time, it will be O(n). So that's how collision checking is now O(n) instead.
This commit is contained in:
parent
d4336b9a33
commit
662a658cf6
1 changed files with 22 additions and 9 deletions
|
@ -4651,12 +4651,16 @@ void entityclass::entitycollisioncheck()
|
|||
|
||||
for (size_t i = 0; i < entities.size(); i++)
|
||||
{
|
||||
if (entities[i].rule != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//We test entity to entity
|
||||
for (size_t j = 0; j < entities.size(); j++)
|
||||
{
|
||||
if (i!=j)
|
||||
{
|
||||
if (entities[i].rule == 0 && entities[j].rule == 1 && entities[j].harmful)
|
||||
if (entities[j].rule == 1 && entities[j].harmful)
|
||||
{
|
||||
//player i hits enemy or enemy bullet j
|
||||
if (entitycollide(i, j) && !map.invincibility)
|
||||
|
@ -4685,18 +4689,18 @@ void entityclass::entitycollisioncheck()
|
|||
}
|
||||
}
|
||||
}
|
||||
if (entities[i].rule == 0 && entities[j].rule == 2) //Moving platforms
|
||||
if (entities[j].rule == 2) //Moving platforms
|
||||
{
|
||||
if (entitycollide(i, j)) removeblockat(entities[j].xp, entities[j].yp);
|
||||
}
|
||||
if (entities[i].rule == 0 && entities[j].rule == 3) //Entity to entity
|
||||
if (entities[j].rule == 3) //Entity to entity
|
||||
{
|
||||
if(entities[j].onentity>0)
|
||||
{
|
||||
if (entitycollide(i, j)) entities[j].state = entities[j].onentity;
|
||||
}
|
||||
}
|
||||
if (entities[i].rule == 0 && entities[j].rule == 4) //Player vs horizontal line!
|
||||
if (entities[j].rule == 4) //Player vs horizontal line!
|
||||
{
|
||||
if(game.deathseq==-1)
|
||||
{
|
||||
|
@ -4724,7 +4728,7 @@ void entityclass::entitycollisioncheck()
|
|||
}
|
||||
}
|
||||
}
|
||||
if (entities[i].rule == 0 && entities[j].rule == 5) //Player vs vertical line!
|
||||
if (entities[j].rule == 5) //Player vs vertical line!
|
||||
{
|
||||
if(game.deathseq==-1)
|
||||
{
|
||||
|
@ -4738,7 +4742,7 @@ void entityclass::entitycollisioncheck()
|
|||
}
|
||||
}
|
||||
}
|
||||
if (entities[i].rule == 0 && entities[j].rule == 6) //Player versus crumbly blocks! Special case
|
||||
if (entities[j].rule == 6) //Player versus crumbly blocks! Special case
|
||||
{
|
||||
if (entities[j].onentity > 0)
|
||||
{
|
||||
|
@ -4754,10 +4758,19 @@ void entityclass::entitycollisioncheck()
|
|||
}
|
||||
}
|
||||
}
|
||||
if (game.supercrewmate)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (game.supercrewmate)
|
||||
{
|
||||
for (size_t i = 0; i < entities.size(); i++)
|
||||
{
|
||||
//some extra collisions
|
||||
if (entities[i].type == 14) //i is the supercrewmate
|
||||
{
|
||||
for (size_t j = 0; j < entities.size(); j++)
|
||||
{
|
||||
//some extra collisions
|
||||
if (entities[i].type == 14) //i is the supercrewmate
|
||||
if (i != j)
|
||||
{
|
||||
if (entities[j].rule == 1 && entities[j].harmful) //j is a harmful enemy
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue