检查形状之间的碰撞设计模式 [英] Design pattern for checking collision between shapes

查看:157
本文介绍了检查形状之间的碰撞设计模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的碰撞检测各种形状(长方形圆形戒指等),所有这些形状是从抽象基图形类派生的。我的游戏对象有型形状的财产。

 类游戏物体
{
(...)
公共形状CollisionShape {搞定;组; }
}

和在初始化过程中,我决定将使用什么形状的每个对象,这样的:

 游戏对象的人=新游戏物体(); 
person.CollisionShape =新圈(100); // 100是半径

当我要检查,如果两个物体相交,我用下面的类

现在:

 公共类IntersectionChecker 
{
公共BOOL相交(形状A,b形)
{
型ATYPE = a.GetType();
型B型= b.GetType();

如果(atype的== typeof运算(矩形)及和放大器; BTYPE == typeof运算(矩形))
返回相交(一个为矩形,B为矩形);

如果(atype的== typeof运算(矩形)及和放大器; BTYPE == typeof运算(圆))
返回相交(一个为矩形,B为圆);

//等等,等等所有组合
}

私人布尔相交(矩形中,矩形B)
{
//检查长方形
}
}

所以我的代码看起来像之间的交集:

  IntersectionChecker IC =新IntersectionCHecker(); 
布尔isIntersection =
is.Intersect(personA.CollisionShape,personB.CollisionShape);



有没有更好的方式来实现我的目标,没有几十个IntersectionChecker如果检查和类型检查?类



编辑:



请采取记住,检查方法形状A和B之间的交集可用于B和A之间的藏汉检查交集。在许多答案(感谢所有你的想法!)路口检查建议从形状本身,而不是IntersectionChecker对象调用。我认为它会迫使我复制代码。现在,我可以做如下:

 如果(atype的== typeof运算(矩形)及和放大器; BTYPE == typeof运算(圆))
返回相交(一个为矩形,b为矩形);

如果(atype的== typeof运算(圆)及和放大器; BTYPE == typeof运算(矩形))
返回相交(B为矩形,圆形为) //上面同样的方法


解决方案

您可以使用< A HREF =htt​​p://en.wikipedia.org/wiki/Visitor_pattern>访问者模式,这里是一个C#示例



这将使你根本就Shape.Intersect(矩形),Shape.Intersect(圆),......方法每个派生塑造工具。它会阻止您不必支付额外的方法调用的开销上做类型的反射



修改 - 这是一个示例实现,它很可能是更清洁的,如果没有共享的功能可能会包含在形状使用接口IShape的,但我只是停留在一个抽象基类。

 公共类游戏物体
{
私人形状_collisionShape;

公共游戏物体(形状collisionShape)
{
_collisionShape = collisionShape;
}

公共BOOL相交(游戏物体等)
{
返回_collisionShape.IntersectVisit(other._collisionShape);
}
}

公共抽象类外形
{
公共抽象BOOL IntersectVisit(其它形状);
公共抽象布尔相交(圈圈)
公共抽象布尔相交(矩形圈);
}

公共类圆:外形
{
公众覆盖布尔IntersectVisit(形状等)
{
返回other.Intersect(这);
}

公众覆盖布尔相交(圈圈)
{
Console.WriteLine(圆相交的圆);
返回FALSE; //实现圆圈的碰撞检测
}

公众覆盖布尔相交(矩形RECT)
{
Console.WriteLine(圆相交矩形);
返回FALSE; //实现圆矩形碰撞检测
}
}

公共类矩形:外形
{
公众覆盖布尔IntersectVisit(形状等)
{
返回other.Intersect(本);
}

公众覆盖布尔相交(圈圈)
{
Console.WriteLine(矩形相交圆);
返回真; //实现矩形圈的碰撞检测
}

公众覆盖布尔相交(矩形RECT)
{
Console.WriteLine(矩形相交矩形);
返回真; //实现矩形矩形碰撞检测
}
}

和示例代码调用它:

 游戏物体objectCircle =新游戏物体(新圈()); 
游戏物体objectRect =新游戏物体(新的Rectangle());

objectCircle.Intersects(objectCircle);
objectCircle.Intersects(objectRect);
objectRect.Intersects(objectCircle);
objectRect.Intersects(objectRect);



生成的输出:

 圆相交的圆
矩形相交的圆
圆相交的矩形
矩形相交的矩形


I use various shapes for collision detection ( Rectangle, Circle, Cone, Ring etc.) All those shapes are derived from base abstract Shape class. My game objects have property of type Shape.

class GameObject
{
    (...)
    public Shape CollisionShape { get; set; }
}

and during initialize process I decide what shape will be used for each object, like:

GameObject person = new GameObject();
person.CollisionShape = new Circle(100); // 100 is radius

Now when I want to check if two objects intersects I use following class:

public class IntersectionChecker
{
   public bool Intersect(Shape a, Shape b)
   {
      Type aType = a.GetType();
      Type bType = b.GetType();

      if( aType == typeof(Rectangle) && bType == typeof(Rectangle))
          return Intersect(a as Rectangle, b as Rectangle);

      if( aType == typeof(Rectangle) && bType == typeof(Circle))
          return Intersect(a as Rectangle, b as Circle);

      // etc. etc. All combinations      
   }

   private bool Intersect(Rectangle a, Rectangle b)
   {
      // check intersection between rectangles
   }
}

so my code looks like:

IntersectionChecker ic = new IntersectionCHecker();
bool isIntersection = 
    is.Intersect(personA.CollisionShape, personB.CollisionShape);

Is there better way to achieve my goal, without dozens of 'if' checks and type checks in IntersectionChecker class?

EDIT:

Please take in mind, that method that check intersection between shape A and B can be used to check intersection between B and A aswell. In many answers ( thanks for all yours thoughts!) intersection check is proposed to be invoked from shape itself rather than IntersectionChecker object. I think it will force me to duplicate code. Now i can do as follow:

  if( aType == typeof(Rectangle) && bType == typeof(Circle))
      return Intersect(a as Rectangle, b as Rectangle);

  if( aType == typeof(Circle) && bType == typeof(Rectangle))
      return Intersect(b as Rectangle, a as Circle); // same method as above

解决方案

You could use the Visitor Pattern, here is a C# example

That would allow you to simply have Shape.Intersect(Rectangle), Shape.Intersect(Circle), ... methods that each derived shape implements. It would prevent you from having to do any reflection on types at the cost of an extra method call.

EDIT - Here is a sample implementation, it would probably be cleaner to use an interface IShape if there is no shared functionality that would go in Shape, but I just stuck in an abstract base class.

public class GameObject
{
    private Shape _collisionShape;

    public GameObject(Shape collisionShape)
    {
        _collisionShape = collisionShape;
    }

    public bool Intersects(GameObject other)
    {
        return _collisionShape.IntersectVisit(other._collisionShape);
    }
}

public abstract class Shape
{
    public abstract bool IntersectVisit(Shape other);
    public abstract bool Intersect(Circle circle);
    public abstract bool Intersect(Rectangle circle);
}

public class Circle : Shape
{
    public override bool IntersectVisit(Shape other)
    {
        return other.Intersect(this);
    }

    public override bool Intersect(Circle circle)
    {
        Console.WriteLine("Circle intersecting Circle");
        return false; //implement circle to circle collision detection
    }

    public override bool Intersect(Rectangle rect)
    {
        Console.WriteLine("Circle intersecting Rectangle");
        return false; //implement circle to rectangle collision detection
    }
}

public class Rectangle : Shape
{
    public override bool IntersectVisit(Shape other)
    {
        return other.Intersect(this);
    }

    public override bool Intersect(Circle circle)
    {
        Console.WriteLine("Rectangle intersecting Circle");
        return true; //implement rectangle to circle collision detection
    }

    public override bool Intersect(Rectangle rect)
    {
        Console.WriteLine("Rectangle intersecting Rectangle");
        return true; //implement rectangle to rectangle collision detection
    }
}

And example code calling it:

GameObject objectCircle = new GameObject(new Circle());
GameObject objectRect = new GameObject(new Rectangle());

objectCircle.Intersects(objectCircle);
objectCircle.Intersects(objectRect);
objectRect.Intersects(objectCircle);
objectRect.Intersects(objectRect);

Produces the output:

Circle intersecting Circle
Rectangle intersecting Circle
Circle intersecting Rectangle
Rectangle intersecting Rectangle

这篇关于检查形状之间的碰撞设计模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆