zgo*_*ski 12 c# design-patterns
我使用各种形状碰撞检测(Rectangle,Circle,Cone,Ring等)所有这些形状都从基抽象派生Shape类.我的游戏对象具有Shape类型的属性.
class GameObject
{
(...)
public Shape CollisionShape { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在初始化过程中,我决定将为每个对象使用什么形状,例如:
GameObject person = new GameObject();
person.CollisionShape = new Circle(100); // 100 is radius
Run Code Online (Sandbox Code Playgroud)
现在,当我想检查两个对象是否相交时,我使用以下类:
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
}
}
Run Code Online (Sandbox Code Playgroud)
所以我的代码看起来像:
IntersectionChecker ic = new IntersectionCHecker();
bool isIntersection =
is.Intersect(personA.CollisionShape, personB.CollisionShape);
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来实现我的目标,没有在IntersectionChecker类中进行数十次'if'检查和类型检查?
编辑:
请注意,检查形状A和B之间的交点的方法可用于检查B和A之间的交点.在许多答案中(感谢您的所有想法!)建议从形状本身而不是IntersectionChecker对象调用交叉检查.我认为它会迫使我重复代码.现在我可以这样做:
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
Run Code Online (Sandbox Code Playgroud)
Bra*_*AGr 13
这将允许您简单地使用Shape.Intersect(Rectangle),Shape.Intersect(Circle),...每个派生形状实现的方法.它会阻止您以额外的方法调用为代价对类型进行任何反射.
编辑 - 这是一个示例实现,如果没有可以在Shape中使用的共享功能,那么使用接口IShape可能会更清晰,但我只是停留在一个抽象基类中.
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
}
}
Run Code Online (Sandbox Code Playgroud)
并调用它的示例代码:
GameObject objectCircle = new GameObject(new Circle());
GameObject objectRect = new GameObject(new Rectangle());
objectCircle.Intersects(objectCircle);
objectCircle.Intersects(objectRect);
objectRect.Intersects(objectCircle);
objectRect.Intersects(objectRect);
Run Code Online (Sandbox Code Playgroud)
产生输出:
Circle intersecting Circle
Rectangle intersecting Circle
Circle intersecting Rectangle
Rectangle intersecting Rectangle
Run Code Online (Sandbox Code Playgroud)
您可以按照Shape类执行碰撞检查,向IntersectsWith(Shape other)Shape 添加方法.我也建议添加IntersectsWith(GameObject other)到您GameObject,让您保持您的CollisionShape私人.