我对矢量非常环保,这是我第一次真正使用它们进行碰撞检查。这是我的项目,我对如何实现碰撞感到困惑。我目前的碰撞检查和响应代码似乎是......糟糕的设计。
这是我的代码:
for(auto it = ArrayofEntities.begin(); it != ArrayofEntities.end(); it++)
{
CEntity * go = (*it);
for(auto i = ArrayofEntities.begin(); i != ArrayofEntities.end();)
{
//Collision for entities. Collision Event returns the iterator after an element is erased.
CEntity * other = (*i);
if (go != other)
{
if (!theCollision.CheckCollision(go, other, false, false, false, false)) //Checks if it has collided go with other
{
i = go->CollisionEvent(*other, ArrayofEntities); //Run collision code, setting i to the iterator which is returned.
//break;
}
else
{
i++;
}
}
else
{
i++;
}
}
}
CEntity是所有实体的基类。
我的CheckCollision只会在碰撞时返回true或false,我的碰撞事件会运行碰撞并返回一个迭代器(因为我可能需要销毁向量中的东西)。
我的碰撞事件在
之下vector<CEntity*>::iterator bullet::CollisionEvent(CEntity &other, vector<CEntity*> & theArray)
{
case ZOMBIE:
{
other.hp -= power * 0.01;//Effect
int Counter, index, bulletindex;
auto it = theArray.begin();
//Find the bullet and the other in the array.
for (it = theArray.begin(), Counter = 0; it != theArray.end();it++, Counter++)
{
CEntity *go = NULL;
go = (*it);
if (go == &other)
{
index = Counter;
}
if(go->ID == BULLET && go->GetX() == GetX() && go->GetY() == GetY())
{
bulletindex = Counter;
}
}
this->~bullet();//Delete the bullet
theArray.erase(theArray.begin() + bulletindex);
if(other.hp <= 0)
{
other.~CEntity();
it = theArray.erase(theArray.begin() + index); //delete from array.
return it;
}
it = theArray.begin() + index;
return it;
}
}
我基本上已经完成了这个,就像我将如何做一个数组。只是检查它自己。在碰撞事件运行后的第一个for循环中,它给出的错误是“Vector Iterator not Incrementable”。
所以我的问题:1)我做错了什么? 2)我的想法就像检查数组错误一样吗?
这是我的学校项目,所以我完全控制了这些代码。
我更希望快速修复所有碰撞代码的完整重写,但如果真的归结为它,我会重写我的代码。
答案 0 :(得分:2)
如果你看一下std::remove_if
的实现,你会发现他们以另一种方式解决了迭代器失效的问题。而不是擦除元素,他们将它们移动到数组的末尾。
这对您来说可能是最简单的解决方案。保持一个迭代器,它指向最后一个“实时”状态。它从.end
开始,但是当子弹击中时,你将实体交换到你的范围的后面并减少最后一个迭代器。
然后,当您完成对阵列的循环时,只需调用.erase
即可清理。
是的,您应该在集合中使用std::unique_ptr<CEntity>
或std::shared_ptr<CEntity>
。这样,.erase
不仅会擦除指针,还会擦除指向的对象。