C++ 游戏碰撞处理
C++ 游戏碰撞处理,c++,collision-detection,C++,Collision Detection,给出的代码仅供示例使用,而不是从我的代码库中复制 我在C++中用Booost和SDL编写一个原始的跨平台的蛇形游戏,我想知道实现冲突处理的最佳方法是什么(不是冲突检测)。到目前为止,我一直在使用一个单一的分派想法,带有难看的意大利面代码,如下所示: void Snake::CollisionHandler(const WorldObject& obj) { // collided with self if(obj.GetObjectType() == snake)
给出的代码仅供示例使用,而不是从我的代码库中复制
我在C++中用Booost和SDL编写一个原始的跨平台的蛇形游戏,我想知道实现冲突处理的最佳方法是什么(不是冲突检测)。到目前为止,我一直在使用一个单一的分派想法,带有难看的意大利面代码,如下所示:
void Snake::CollisionHandler(const WorldObject& obj)
{
// collided with self
if(obj.GetObjectType() == snake)
Die();
...
...
}
void GameWorld::CollisionHandler(WorldObject& obj1, WorldObject& obj2)
{
// snake collided with self
if(obj1.GetObjectType() == snake && obj2.GetObjectType() == snake)
{
obj1.Die();
obj2.Die();
PlayDeathSound();
}
...
...
}
此外,我还有一个“全局”冲突处理程序,它处理冲突中涉及的事情,这些事情独立于每个对象,例如:
void GameWorld::CollisionHandler(WorldObject& obj1, WorldObject& obj2)
{
if(obj1.GetObjectType() == snake && obj2.GetObjectType() == snake)
PlayDeathSound();
...
...
}
避免碰撞时两次播放声音之类的事情
我也考虑过双重派遣,比如:
void Snake::CollisionHandler(WorldObject& obj) const
{
// invoke obj's collision handler with a const Snake& parameter
obj.CollisionHandler(*this);
}
// collided with self
void Snake::CollisionHandler(const Snake& obj)
{
Die();
}
我有没有遗漏什么策略?其中哪一个是最好的?它们似乎都涉及到一些丑陋的代码,单调度和双调度的代码都涉及多态性,我个人试图避开多态性。在我看来,让游戏类完全处理冲突和其他全局事件的最后一种方法是最明智、可能也是最“正确”的方法
例如,以国际象棋程序为例。很明显,游戏类应该处理一个玩家的输赢,而不是玩家类
它在实践中也更有效。考虑一种情况,您希望添加更多类(例如另一种类型的snake),而不是复制代码或重写CollisionHandler,您可以让游戏类轻松地处理它。
但是如果您的唯一目的是一个简单的蛇游戏,那么您选择如何实现它可能并不重要。冲突处理是一个C++/Java风格的面向对象(单一分派)不够灵活的领域。碰撞的结果取决于两个碰撞对象的类型,因此需要多个分派来处理它。(维基百科文章中激发灵感的例子是冲突处理,这绝非巧合!)
我认为,一个全局冲突处理程序,然后发送到单独的对象方法,是解决C++中不足的最好办法。
如果我添加另一种Snake类,使用双调度方法不是更简单吗?不需要代码复制,而且它被很好地分割成模块。单行通用CollisionHandler(WorldObject&)函数存在少量代码重复。如果要从WorldObject继承,则需要复制代码。另外,作为一条经验法则,在不需要的时候最好不要使用函数重载。这就是我现在所拥有的。实际上,在C++中,有几种方法可以在C++中获得双调度。其中一个在我的原始帖子(第三段代码)中显示了是的,但我认为这是本例中较弱的解决方法。如果您在类A中有代码用于与类B冲突,在类B中有单独的代码用于与类A冲突,那么您可能会无意中使它们不一致。(也许在你的游戏中,只有蛇才能与物体碰撞,所以这在实践中不会发生,但在更一般的情况下,这是一个值得考虑的风险。)我不明白你的意思;任何事物都会处理自身与其他事物的碰撞。A只在与B发生冲突时处理其自身的结束,B只在与A发生冲突时处理其结束。我不确定我是否理解你所说的“不一致”的意思。如果你犯了错误,它将是不一致的(例如,你决定更改A/B冲突的某些方面,而你在类A中更改它,而不是在类B中更改它)。显然,如果你从未犯过错误,那么你如何组织你的代码并不重要,但对于像我这样容易犯错的凡人来说,将相关代码放在一起会有帮助。在你的上一个示例中,注释是“snake与self冲突”,然后你调用Die()
两次。我怀疑那是件坏事。PS:不需要“交友”任何东西,只需将它需要的函数公开即可。PPS:为了避免重复代码,我倾向于只将该对象的效果放在它的“我与一个Foo冲突”函数中。当一艘船与子弹相撞时,它会受到一些伤害。当子弹与船相撞时,它就会消失。