2013-05-05 137 views
1

我正在制作一款游戏,并且我正在尝试为对象处理彼此冲突的方法。我想要做的事,如:仿制药和事件

//Imaginary C# 

public SomethingThatCollides() 
{ 
    CollisionEvent<ObjectA> += CollisionWithObjA; 
    CollisionEvent<ObjectB> += CollisionWithObjB; 
} 

void CollisionWithObjA(ObjectA other) 
{ 
    //Do something 
} 
void CollisionWithObjB(ObjectB other) 
{ 
    //Do something else 
} 

时候,说,CollisionEvent<ObjectA>升高(可能由一些碰撞校验码),CollisionWithObjA应该被调用。相同的CollisionWithObjB;当检测到与ObjectB的碰撞时,它将引发CollisionEvent<ObjectB>事件,导致CollisionWithObjB被调用。

是这样的可能吗?

+0

它很难理解你正在尝试做什么。你是说当碰撞发生时,你会称之为'SomethingThatCollides'方法?请提供更多解释 – prashantsunkari 2013-05-05 01:02:18

+0

@Andrew:如果我有objA,objB和objC,它们都可以与它们全部相撞? AB,AC和BC会有碰撞方法吗? – 2013-05-05 01:28:59

+0

或者它是一个主人与其他人相互碰撞的对象,没有对他人之间的相互碰撞进行处理? – 2013-05-05 01:29:36

回答

0

你不能真的创建这样的通用事件。我建议你创建一个特殊的事件参数类也封装了碰撞对象,并检查其是否在事件处理方法类型:

public class CollisionEventArgs : EventArgs { 
    public object Object { 
    get; private set; 
    } 
    // ... 
} 

你需要一个特殊的调度方法来使用它:

class SomethingThatCollides { 

    public SomethingThatCollides(CollisionManager cm) { 
    cm.CollisionEvent += CollisionWithObj; 
    } 

    void CollisionWithObj(object sender, CollisionEventArgs args) { 
    if (args.Object is ObjectA) { 
     CollisionWithObjA((ObjectA)args.Object); 
    } 
    else if (args.Object is ObjectB) { 
     CollisionWithObjB((ObjectB)args.Object); 
    } 
    } 

    // ... 
} 

或者,您可以尝试使用双重调度解决此问题,而不使用C#事件。查看wikipedia查看碰撞示例。

+0

关键是创建一个单独的方法来处理每个碰撞,而不必进行不必要的装箱和类型检查。是否真的没有办法这样做? – 2013-05-05 01:21:29

+0

在维基百科上查看[double-dispatch](http://en.wikipedia.org/wiki/Double_dispatching)。 – 2013-05-05 01:32:48

0

这是uggly,但是......你可以按类型事件的dicionary:

Dictionary<Type, object> MyEventsByType; 

event Action<A> CollisionEventA; 
event Action<B> CollisionEventB; 
event Action<C> COllisionEventC; 

void Initialize() 
{ 
    MyEventsByType = new Dictionary<Type, object>(); 

    MyEventsByType.Add(typeof(A), CollisionEventA); 
    MyEventsByType.Add(typeof(B), CollisionEventB); 
    MyEventsByType.Add(typeof(C), CollisionEventC); 
} 

void RaiseCollision<T>(T Obj) 
{ 
    Action<T> Event = (Action<T>)MyEventsByType[typeof(T)]; 
    if (Event != null) Event(Obj); 
} 
1

这里是东西,如果类是通用的,它有静态字段,它可以工作像一本字典键是类型

public class Something { 
    public class EventsHolder<T> 
    { 
     static event Action<T> CollideEvent; 
    } 

    public void AddEvent<T>(Action<T> collisionEvent) 
    { 
     EventsHolder<T>.CollideEvent = collisionEvent; 
    } 

    public void RaiseCollision<T>(T Obj) 
    { 
     var Event = EventsHolder<T>.CollideEvent; 
     if (Event != null) Event(Obj); 
    } 
} 

缺点是它使用的静态字段可能不合适。 在这种情况下,您可以使用代码@Daniel发布。

+0

现在这是... – 2013-05-05 03:11:16

+0

嗯,听起来很有趣,但我不能从EventsHolder外部调用'EventsHolder .CollideEvent',我该如何解决这个问题? – 2013-05-05 04:15:12

+0

在EventsHolder中创建一个'CallEvent'静态方法来调用事件。现在在'RaiseCollision'中调用该方法。 (我编辑了答案,但必须等待某人的修改) – 2013-05-05 04:40:07