gpt4 book ai didi

c++ - 如何编写优雅的碰撞处理机制?

转载 作者:可可西里 更新时间:2023-11-01 15:08:08 26 4
gpt4 key购买 nike

我有点困惑:假设我正在制作一款简单的 2D 类塞尔达传说游戏。当两个对象发生碰撞时,每个对象都应该有一个结果 Action 。然而,当主角与某物发生碰撞时,他的 react 完全取决于他所碰撞的物体的类型。如果是怪物,他应该反弹回来,如果是墙,什么都不应该发生,如果是带有丝带的神奇蓝色盒子,他应该治疗等等(这些只是例子)。

我还应该注意,这两者都是碰撞的一部分,也就是说,碰撞事件应该同时发生在角色和怪物身上,而不只是其中之一。

你会如何编写这样的代码?我可以想到许多令人难以置信的不优雅的方法,例如,在全局 WorldObject 类中使用虚函数来识别属性——例如,一个 GetObjectType() 函数(返回 ints、char*s,任何将对象标识为 Monster 的东西、Box 或 Wall),然后在具有更多属性的类中,比如 Monster,可能会有更多虚函数,比如 GetSpecies()。

但是,维护起来很烦人,并导致碰撞处理程序中出现大量级联开关(或 If)语句

MainCharacter::Handler(Object& obj)
{
switch(obj.GetType())
{
case MONSTER:
switch((*(Monster*)&obj)->GetSpecies())
{
case EVILSCARYDOG:
...
...
}
...
}

}

还有使用文件的选项,这些文件将包含以下内容:

Object=Monster
Species=EvilScaryDog
Subspecies=Boss

然后代码可以检索属性,而不需要虚函数把一切搞得一团糟。但是,这并不能解决级联 If 问题。

然后可以选择为每种情况设置一个函数,比如 CollideWall()、CollideMonster()、CollideHealingThingy()。这是我个人最不喜欢的(尽管它们都不讨人喜欢),因为它看起来维护起来最麻烦。

有人可以就这个问题的更优雅的解决方案提供一些见解吗?感谢您提供的所有帮助!

最佳答案

反之亦然——因为如果角色与物体发生碰撞,那么物体也会与角色发生碰撞。因此你可以有一个基类对象,像这样:

class Object  {
virtual void collideWithCharacter(MainCharacter&) = 0;
};

class Monster : public Object {
virtual void collideWithCharacter(MainCharacter&) { /* Monster collision handler */ }
};

// etc. for each object

通常在 OOP 设计中,虚函数是这种情况下唯一“正确”的解决方案:

switch (obj.getType())  {
case A: /* ... */ break;
case B: /* ... */ break;
}

编辑:
在你澄清之后,你需要稍微调整一下上面的内容。 MainCharacter 应该为它可能与之碰撞的每个对象提供重载方法:

class MainCharacter  {
void collideWith(Monster&) { /* ... */ }
void collideWith(EvilScaryDog&) { /* ... */ }
void collideWith(Boss&) { /* ... */ }
/* etc. for each object */
};

class Object {
virtual void collideWithCharacter(MainCharacter&) = 0;
};

class Monster : public Object {
virtual void collideWithCharacter(MainCharacter& c)
{
c.collideWith(*this); // Tell the main character it collided with us
/* ... */
}
};

/* So on for each object */

通过这种方式,您可以将碰撞通知给主角,它可以采取适当的行动。此外,如果您需要一个不应该通知主角有关碰撞的对象,您可以只删除该特定类中的通知调用。

这种方法称为 double dispatch .

我还会考虑将 MainCharacter 本身设为 Object,将重载移动到 Object 并使用 collideWith 而不是 collideWithCharacter .

关于c++ - 如何编写优雅的碰撞处理机制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3644065/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com