Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 面向对象设计和镜像/复制方法_Oop_Collision Detection - Fatal编程技术网

Oop 面向对象设计和镜像/复制方法

Oop 面向对象设计和镜像/复制方法,oop,collision-detection,Oop,Collision Detection,我在OO设计中遇到了一个问题,我在两个不同的类中得到了重复的代码。下面是发生的事情: 在这个例子中,我想检测游戏对象之间的碰撞 我有一个基本CollisionObject,它包含常用方法(如checkForCollisionWith)和扩展基类的CollisionObjectBox、CollisionObjectCircle、CollisionObjectPolygon 设计的这一部分似乎还可以,但让我烦恼的是:打电话 aCircle checkForCollisionWith: aBox 将

我在OO设计中遇到了一个问题,我在两个不同的类中得到了重复的代码。下面是发生的事情:

在这个例子中,我想检测游戏对象之间的碰撞

我有一个基本CollisionObject,它包含常用方法(如checkForCollisionWith)和扩展基类的CollisionObjectBox、CollisionObjectCircle、CollisionObjectPolygon

设计的这一部分似乎还可以,但让我烦恼的是:打电话

aCircle checkForCollisionWith: aBox
将在circle子类内执行圆与长方体碰撞检查。反过来说

aBox checkForCollisionWith: aCircle
将在box子类内执行box vs circle碰撞检查


这里的问题是圆与框的冲突代码是重复的,因为它同时存在于Box和Circle类中。有没有办法避免这种情况,或者我处理这个问题的方式不对?现在,我倾向于使用一个包含所有重复代码的helper类,并从aCircle和aBox对象调用它以避免重复。不过,我很好奇是否有更优雅的面向对象解决方案。

也许您可以拥有一个碰撞对象,其中包含测试不同类型碰撞的方法。这些方法可以返回包含碰撞点和其他必要信息的其他对象。

所需的内容称为

多分派或多方法是某些面向对象编程语言的特性,在这些语言中,函数或方法可以基于其多个参数的运行时(动态)类型进行动态分派

这可以在主线OOP语言中进行模拟,如果使用Common Lisp,也可以直接使用它

Wikipedia文章中的Java示例甚至处理了您的确切问题,即冲突检测

以下是我们“现代”语言中的假象:

abstract class CollisionObject {
    public abstract Collision CheckForCollisionWith(CollisionObject other);
}

class Box : CollisionObject {
    public override Collision CheckForCollisionWith(CollisionObject other) {
        if (other is Sphere) { 
            return Collision.BetweenBoxSphere(this, (Sphere)other);
        }
    }
}

class Sphere : CollisionObject {
    public override Collision CheckForCollisionWith(CollisionObject other) {
        if (other is Box) { 
            return Collision.BetweenBoxSphere((Box)other, this);
        }
    }
}

class Collision {
    public static Collision BetweenBoxSphere(Box b, Sphere s) { ... }
}
以下是Common Lisp中的示例:

(defmethod check-for-collision-with ((x box) (y sphere))
   (box-sphere-collision x y))

(defmethod check-for-collision-with ((x sphere) (y box))
   (box-sphere-collision y x))

(defun box-sphere-collision (box sphere)
    ...)

您应该使用checkForCollisionWith:aCollisionObject,因为您的所有对象都在扩展CollisionObject,所以您可以将所有公共逻辑放在那里


或者,您可以使用在不同的类之间共享公共逻辑。

您没有说明您使用的是什么语言,因此我假定它类似于Java或C

在这种情况下,多方法是理想的解决方案,但大多数语言不支持它们。模仿它们的通常方法是使用访问者模式的一些变体——请参阅任何关于设计模式的好书


或者,使用一个单独的CollisionDetection类来检查对象对之间的碰撞,如果两个对象发生碰撞,则会调用对象上的相应方法,例如bomb.explode()和player.die()。该类可以有一个大的查找表,其中每一行和每一列都有一个对象类型,并且条目提供了调用这两个对象的方法。

这是OO开发中的一个典型陷阱。我也曾试图以这种方式解决碰撞问题,结果惨败

这是一个所有权问题。Box类真的拥有与circle的冲突逻辑吗?为什么不反过来呢?结果是代码重复或将冲突代码从圆圈委派到方框。两者都不干净。双重分派不能解决这个问题-所有权的问题是一样的


因此,您是对的-您需要解决特定冲突的第三方函数/方法,以及为两个发生冲突的对象选择正确函数的机制(这里可以使用双重分派,但如果冲突原语的数量有限,则可能2D函子数组是更快的解决方案,代码更少)

第一个选项:使碰撞具有方向性。例如,如果长方体是静止的,它不会检查自身与任何其他对象的碰撞;但移动的圆检查与长方体(和其他静止对象)的碰撞。这是不直观的,因为我们一生都被教导“平等和相反的反应”。陷阱:移动对象会复制与其他移动对象的碰撞


第二个选项:给每个对象一个唯一的ID号。在碰撞检查方法中,仅当第一个参数/对象的ID低于第二个参数时,才检查碰撞

假设框的id=2,圆的id=5。然后执行“box与圆圈碰撞”,因为box.id我也有同样的问题(在目标C中工作),我找到了一个解决方法,当我已经知道两个对象的类型时,定义一个外部函数来解决冲突

例如,如果我有矩形和圆形,它们都实现了协议(这种语言的接口)形状

而且

-(BOOL) intersectsWithRectangle:(Rectangle*) aRectangle
{
    return CircleAndRectangleCollision(self, aRectangle);
}

当然,它不会攻击双重分派的耦合问题,但至少它避免了代码重复

这似乎很难维护,对于从碰撞对象派生的每个类,您必须在所有其他派生类中添加一个新的
checkForCollisionWithX
。这绝对很难维护。我从来没有说过这是用于碰撞检测的正确技术。实际上,代码应该自动构造冲突分派矩阵。然后,应通过该矩阵处理冲突操作。你编写一次矩阵生成器,它使用反射,之后一切都运行得又好又快。Objective-C。不过,我假设Java或C#的问题是一样的。哦,嗯。也许我解决了一个与你所说的不同的问题。为了解决您的问题,我想我应该使用泛型(java)或模板方法(c++)。
-(BOOL) intersectsWithCircle:(Circle*) aCircle
{
    return CircleAndRectangleCollision(aCircle, self);
}
-(BOOL) intersectsWithRectangle:(Rectangle*) aRectangle
{
    return CircleAndRectangleCollision(self, aRectangle);
}