游戏开发中用于碰撞检测的良好面向对象类设计

20

我想学习如何在游戏开发中为两个物体碰撞的情况创建良好的面向对象(OO)设计实践。

假设我有一个SpaceShip类和一个Meteor类。 当Meteor与SpaceShip相撞时,SpaceShip将被摧毁。

问题:应该将检查是否发生Meteor与SpaceShip碰撞以及碰撞解决方法(摧毁SpaceShip)的方法放在哪个类中? 是在SpaceShip类还是Meteor类中? 或者我应该将其放在另一个类中,例如GameArea或GameController类中?

注意:为简单起见,假设Meteor和SpaceShip以图像资源的形式存在。 我习惯使用Java语言,但其他语言也可以。


我会投票支持在GameController(或者任何管理游戏区域的类)中实现碰撞检测,并在MeteorSpaceShip(以及任何可能与物体发生碰撞的其他对象)上添加一个collidedWithObject(GameObject theObject)方法,用于通知对象发生了碰撞。 - aroth
谢谢您的投票。您是否知道有关面向对象游戏设计的好教程或书籍? - null
4个回答

15

更自然的想法是,碰撞检测不应该是Spaceship或Meteor类的职责,尤其是在不同方向存在多个碰撞可能性时。如果将此逻辑放在这两个类中,它们将需要引用许多周围的其他对象,这是不合适的。

您可以在一个单独的类中拥有此功能,例如CollisionDetector,它跟踪游戏空间中所有对象的坐标并检测碰撞。在我看来,碰撞预防也是一项不同的职责,应该由另一个类负责。您可以为此创建一个单独的类CollisionResolver。根据要求,CollisionDetector可以与CollisionResolver交互。

CollisionResolver可能需要能够与Spaceships交互,以便建议它们改变方向或向Meteor发射导弹。

CollisionDetectorCollisionResolver可以位于GameSpace/*GameController*等内部。

这将促进单一职责原则,因此每个组件只会执行一个专注的任务。


3

在我看来,碰撞检测不应该是对象的一部分...它应该被定义为其他东西 - 例如物理管理器等。这样你的对象将不依赖于碰撞算法。

另一件事是,在游戏中通常物体由几个层(组件)组成:图形层、物理层、逻辑层。这样物理管理器只管理给定对象的物理组件。

class GameObject 
{
    RenderComponent  m_renderComponent;
    LogicComponent   m_aiComponent;
    PhysicsComponent m_physicsComponent;
};

那么你的意思是碰撞逻辑应该驻留在PhysicsComponent类中吗? - null
1
是的... 碰撞组件(例如某些边界框)可以在物理组件内部。 - fen

1

嗯,我通常会创建一个(有时是通用的)GameObject类或接口,其中包含一个collides方法。例如:

template< typename T = int > class GameObject
{
public:
    bool collides(const GameObject& obj);
};

// usage
GameObject<int> my_obj, your_obj;
if(my_obj.collides(your_obj)) { ... };

我有时(但很少)会创建一个单独的GamePhysics类:

template< typename T > class GamePhysics
{
public:
    /* you may make this static or the class a singleton */
    void detect_collision(const T& obj, const T& obj2);
};

谢谢。你会把 "if(my_obj.collides(your_obj)) { ... };" 代码放在哪里?GameController? - null
1
无论在哪里需要检测碰撞,比如主循环、游戏控制器、瓦片渲染器等。 - ApprenticeHacker

1
在Java(或其他面向对象的语言)中,我会在您游戏中所有移动对象的共同祖先类中放置一个CollisionDetected回调/事件。
这是关于游戏的简化说明:
- 在游戏中,通常有一个游戏循环。 游戏循环类似于连续运行的while(true)循环(有点像应用程序的主UI线程),并在每一步检查对象的变化,更新内容以及应该调用哪些事件(等等...)。 - 为了响应灵敏,此循环每秒应循环多次。 - 在此循环内,物理引擎对象应持续更新其状态。 这将是独立类的实例对象。 就是这个引擎应该检测对象之间的碰撞,并在所有已发生碰撞的对象上调用CollisionDetected事件。
这只是一个想法,而非最终解决方案...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接