【问题标题】:Good Object Oriented Class Design for collision detection in game development良好的面向对象类设计,用于游戏开发中的碰撞检测
【发布时间】:2012-04-11 04:40:27
【问题描述】:

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

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

问题: 检查流星和飞船是否有碰撞的方法以及碰撞解决方法(摧毁飞船)应该放在什么类?是在 SpaceShip 类还是 Meteor 类?或者,也许我应该上另一堂课,即。 GameArea 还是 GameController 类?

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

【问题讨论】:

  • 我会投票支持在GameController(或管理您的游戏区域的任何类)中实现碰撞检测,在MeteorSpaceShip(以及任何其他对象)上使用collidedWithObject(GameObject theObject) 方法可能与事物发生碰撞)被调用以通知对象发生碰撞。
  • 感谢您的投票。您是否知道任何关于面向对象游戏设计的好教程或书籍?

标签: oop collision-detection


【解决方案1】:

更自然地认为碰撞检测是不属于 Spaceship 或 Meteor 类的职责。尤其是当这变得复杂时,在不同方向有多种碰撞可能性。如果你把这个逻辑放在这两个类中,它们将需要引用它们周围的许多其他对象,这是不合适的。

您可以将它放在一个单独的类中,例如 CollisionDetector,它会跟踪游戏空间中所有对象的坐标并检测碰撞。在我看来,防撞似乎也是一项单独的责任,应该属于不同的类别。您可以为此设置一个单独的类 CollisionResolver。根据要求,CollisionDetector 可以与 CollisionResolver 对话。

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

CollisionDetectorCollisionResolver 可以位于 GameSpace/*GameController* 中。等等。

这将促进 Single Responsibility Principle,因此每个组件将只执行一项重点任务。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 那么你的意思是碰撞逻辑应该驻留在 PhysicsComponent 类中?
    • 是的...碰撞组件(例如一些边界框)可以在物理组件内。
    【解决方案3】:

    嗯,我通常创建一个(有时是通用的)GameObject 类或接口,它有一个碰撞方法。例如:

    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)) { ... };”放在哪里代码?游戏控制器?
    • @suud 任何你需要检测碰撞的地方。主循环、GameController、tile-renderer 等。
    【解决方案4】:

    在 Java(或任何其他 OO 语言)中,我会将 CollisionDetected 回调/事件放置在游戏中所有移动对象的公共祖先类中。

    这是对游戏的简化描述:

    • 在游戏中,通常有一个游戏循环。游戏循环就像一个连续运行的 while(true) 循环(有点像应用程序的主 UI 线程),并且在每一步都检查对象发生了什么变化,应该更新什么以及应该调用哪些事件(以及更多...)。

    • 为了响应性,这个循环应该每秒循环很多次。

    • 在这个循环中,Physics Engine 对象应该不断更新它的状态。这将是一个独立类的实例对象。正是这个引擎应该检测对象之间的碰撞并对所有碰撞的对象调用 CollisionDetected 事件。

    这是一个想法,不是最终的解决方案......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      相关资源
      最近更新 更多