我目前正在开发一款小型游戏引擎,而且我有点想找到合适的模式。 首先是一些代码片段,以了解我想要实现的目标:
单位:能力施法者/目标(投掷能力或接受能力)
public class Unit
{
public string Name { get; set; } // Unit name
public List<BaseAbility> MyAbilities{get; set;} // abilities that an unit has.
}
能力:
public abstract class BaseAbility
{
public string Name {get; set;} // ability name
public Unit Caster { get; set; } // ability caster (owner)
public List<BaseEffect> EffectList {get; set;} // effects that an ability possess
// apply all effects that this ability has on the selected target
public virtual void DoAbility(Unit target)
{
foreach (BaseEffect eff in this.EffectList)
{
eff.CalculateEffect(target);
}
}
// here we gonna subscribe to some events
public abstract void initListeners();
}
效果:
public abstract class BaseEffect
{
public BaseAbility Owner { get; set; } // each effect belong to an ability
protected string Name { get; set; } // effect name
public EventDispatcher Event { get; set; } // the event to dispatched when this effect is called or used
//apply effect on target
public virtual void CalculateEffect(Unit target)
{
// Do Stuffs here like damage and poison etc etc
this.Event.DispatchMyEvent();
}
}
事件调度程序:
public class EventDispatcher
{
private object mySender;
private EffectEventArgs myArgument;
public delegate void EventHandler(object sender, EffectEventArgs argument);
public event EventHandler OnMyEvent;
public EventDispatcher(object sender, EffectEventArgs argument)
{
this.mySender = sender;
this.myArgument = argument;
}
public void DispatchMyEvent()
{
if (OnMyEvent != null)
{
OnMyEvent(this.mySender, this.myArgument);
Debug.WriteLine("event has been raised");
}
}
}
效果事件参数:
public class EffectEventArgs : EventArgs
{
private Unit target; // target affected by effect
// not sure if we even need this EffectEventArgs ?!
public EffectEventArgs(Unit unit)
{
this.target = unit;
}
}
现在我将为模拟创建2个效果和2个技能以及2个单位:
火焰效果:
public class FireEffect : BaseEffect
{
public FireEffect(BaseAbility effectOwner)
{
this.Owner = effectOwner;
this.Name = "Fire";
}
public override void CalculateEffect(Unit target)
{
// set the event here (to get the target as argument for the event)
this.Event = new EventDispatcher(this.Owner, new EffectEventArgs(target));
base.CalculateEffect(target);
}
}
风效果:与火焰效果相同,但名称和事件不同,也适用不同的效果。
火球能力:
public class FireBall : BaseAbility
{
public FireBall(Unit caster)
{
this.Name = "FireBall";
this.Caster = caster;
this.EffectList = new List<BaseEffect>();
this.EffectList.Add(new FireEffect(this)); // fire ball ability has "FireEffect" as effect
}
public override void DoEffect(Unit target)
{
base.DoEffect(target);
}
}
两个单位,让我们说: “龙”作为单位=&gt;有FireBall(能力)并且会击中=&gt; “少林风之师”作为单位有一个被称为“WindFury”的被动行为
WindFury:
public class PassiveAbility : BaseAbility
{
public PassiveAbility(Unit caster)
{
this.Name = "WindFury";
this.Caster = caster;
this.EffectList = new List<BaseEffect>();
this.EffectList.Add(new WindEffect(this));
this.initListeners(); // subscribe to events (aka add listeners)
}
public override void DoEffect(Unit target)
{
base.DoEffect(target);
}
// THE MAIN PROBLEM :
public override void initListeners()
{
// here i need to subscribe to an event fired from any Instance/Object of type FireEffect so that the targeted Unit
// can react to the Unit caster (kind of counter attack)
// to resume this , it should follows this logic :
// if any Ability has The effect(FireEffect => FireBall for example) was casted
// on this Unit thats possess this passive, react to it and counter with (WindEffect)
// otherwise put : when our dragon or Ryu or even Sasuke throw an ability with
// a FireEffect on our friend "Shaolin" ,he should react to it
// and send the attacker flying with a powerfull WindEffect
}
public void CallBack(object sender, EffectEventArgs e)
{
BaseAbility ab = (BaseAbility)sender;
this.DoEffect(ab.UnitCaster); // hit the unit caster back (revenge)
}
}
请注意,我们可以在这个游戏或模拟中拥有这么多龙和Shaolins,任何被动持有者(单位)都应该只对攻击者(单位)等作出反应。
编辑:(回顾主要问题)
如何订阅通过 PassiveAbility.initListeners()从事件从任何类型的FireEffect 触发事件 (使用fireEffect的能力)???
非常感谢您的支持和贡献。
Youness
答案 0 :(得分:0)
将静态EventDispatcher添加到FireEffect
并订阅。
public class FireEffect : BaseEffect
{
public static EventDispatcher FireEffectEventDispatcher = new EventDispatcher(null,null);
public FireEffect(BaseAbility effectOwner)
{
this.Owner = effectOwner;
this.Name = "Fire";
}
public override void CalculateEffect(Unit target)
{
// set the event here (to get the target as argument for the event)
FireEffectEventDispatcher.mySender = Owner;
FireEffectEventDispatcher.myArgument = new EffectEventArgs(target);
// Fire the event
FireEffectEventDispatcher.DispatchMyEvent();
//If you still want the base effect firing.
base.CalculateEffect(target);
}
}
为了完成这项工作,您还需要更改EventDispatcher
,以便在构建后设置发件人/参数(无论如何都无法理解 - 它&# 39;无用的限制)。
但我建议您重做(或删除)EventDispatcher
实施。在事件触发期间更合理地设置事件参数时,在构造函数中设置事件参数是没有意义的。