Saturday, November 19, 2016

c# - How to implement an event system


Im trying to implement an Event System for a game, where there are classes that can fire or handle an event wheter or not they implement these interfaces:


public interface IGameEvent where T : EventArgs
{

event EventHandler OnEvent;
}

public interface IGameHandler where T : EventArgs
{
void OnEvent(object sender, T e);
}

everything looked great until i realized that no class can implement more than 1 IGameEvent because it would cause duplicate declaration,


Here is an example:



public class Event
{
public KeyPressEvent OnKeyPress;
public UpdateEvent OnUpdate;

public void AddHadler(IGameEvent eEvent , IGameHandler eHandler) where T : EventArgs
{
eEvent.OnEvent += eHandler.OnEvent;
}


public void RemoveHandler(IGameEvent eEvent, IGameHandler eHandler) where T : EventArgs
{
eEvent.OnEvent -= eHandler.OnEvent;
}
}

KeyPressEvent:


public class KeyPressEvent : IGameEvent
{
public class KeyPressedEventArgs : EventArgs

{
public KeyPressedEventArgs(Keys key)
{
Key = key;
}

public Keys Key { get; private set; }
}

public event EventHandler OnEvent;


private void OnCheckForKeyPressed() //Example
{
if (OnEvent != null)
OnEvent(this, new KeyPressedEventArgs(Keys.Space));
}
}

Would be better to manually store the suscribers in a list in the EventSystem ?


How slower or faster than this approach that would be?



Thanks!



Answer



Although you can use the existing event model in C#, it might not always give you the flexibility that you require.


You can for instance not sort events based on their priority, clear events of a specific type or add a queued/delayed event.


Example)


EventManager


To signup for an event the object needs a method with the same signature as the CallbackMethod delegate. The call might look like this:


class SomeObject
{
private void OnDamageTaken(object sender, IGameEvent e)

{
...
}

... void Initialize()
{
...
EventManager.Subscribe("EVENT_PLAYERINJURED", this.OnDamageTaken);
...
}

}

//Somewhere in the application
EventManager.Notify("EVENT_PLAYERINJURED", new PlayerInjuredEvent(...));

If you don't like using hardcoded eventIds everywhere you could introduce a property on your game event classes.


public PlayerInjuredEvent : IGameEvent
{
public static string EventType
{

get
{
return "EVENT_PLAYERINJURED";
}
}
}

Now you can write:


EventManager.Notify(PlayerInjuredEvent.EventType, ...


I hope this gives you some ideas on how to solve your problem.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...