[.net] Is there a better way to present this interface?

Started by
4 comments, last by return0 13 years, 9 months ago
I'm currently split out my "engine" code from my recently completed project so that I can use it as a library for any future projects.

I'm having difficulty with providing the interface I want from my library however.

Currently my InputManager has a method that can be used to map an actions to a button(s) with the following header:

public void AddMapping(InputAction action, params Buttons[] buttons)


InputAction is an enum, which is currently defined as follows:

public enum InputAction{    Jump,    Use,    ...}


So for example the method could be used to map the A and B buttons to the Jump action:

InputManager.AddMapping(InputAction.Jump, Buttons.A, Buttons.B)


This all worked fine when the "engine" was part of the same project as the game, however now that I've seperated the two it causes problems.

I don't want InputAction to be predefined, I want this to be defined by the users (currently only me) of the library so they can have more flexibility.

The problem I'm having is that enums can't be inherited from though, so I can't define InputActions as an "abstract" enum and then have people inherit from it to add their own options.

One option would be to switch to the following, but it doesn't really sit well with me, as it's too generic and doesn't make the intention of the method clear.

public void AddMapping(Enum action, params Buttons[] buttons)


Defining InputActions as an abstract class and then expecting people to inherit use const int Value = 0 etc seems a complete mess to me and it's not obvious how it should be used.

The only other options I can think of is just to have InputAction to be completely generic:

public enum InputAction{    Action1,    Action2,    ...}


This approach seems to defeat the point of using an enum though, as if I'm going down this route I might as well just use an int to define my actions.

So, is there a better way to present this interface across a library boundary, or am I stuck with picking one of the solutions above?
Advertisement
I found the final example in the Effective Event Handling in C++ article's code can be easily converted to C# and delegates.

Then a solution I've found to mapping is the ability to map a key directly to an event by storing the event.
You could use a Dictionary and store KeyValue pairs with whatever key mappings you want.

Dictionary<string, int> keyMappings = new Dictionary<string, int>();keyMappings["jump"] = 13;keyMappings["fire"] = 11;keyMappings["walkForward"] = 5;...

I think I'll just go with using strings rather than an enum for now.

Doing string lookups each update doesn't seem the best way of doing things, but it's not like I'm trashing the CPU with enough that it's actually going to matter.
Quote:Original post by adt7
I think I'll just go with using strings rather than an enum for now.

Doing string lookups each update doesn't seem the best way of doing things, but it's not like I'm trashing the CPU with enough that it's actually going to matter.


Could you use objects instead of enums? That way you won't end up with 'typo' errors the compiler misses.

If you have an InputAction class, it just becomes a pointer/refernece compare. You can put a string in there for debugging:

InputAction Jump( "Jump" )
InputAction Punch( "Punch" )


AddMapping( Jump, Buttons.A, Buttons.B )
AddMapping( Punch, Buttons.A, Buttons.B )

InputAction action = Punch

Jump != action
Punch == action

Since they are all InputActions you can store them in lists, or arrays, or dictionaries. As long as they are classes, you get equality only if the pointer matches, unless you overload IsEqual().

Of course you cant switch on them, but you can load them into a dictionary with delegates just fine.

If you InputAction an interface only, the end user can do whatever he wants with the implementation, which might be useful for actions if you need to extend them for client reasons (is it currently valid, etc).



Why would this not work?

You are talking about actions... use an action. By that I mean a System.Action. The you don't need the user to implement an interface, just provide a void method with no args. If there are arguments use Action<T>, Action<T,U> etc.

public void AddMapping(Action action, params Buttons[] buttons)
{
//mapping code
}

AddMapping( ()=> Console.WriteLine ("I happen when A is pressed"), Buttons.A );


If you need to "jump", Jump() rather than InputAction.Jump

AddMapping( () => Jump(), Buttons.A ), or better yet...

AddMapping( Jump, Buttons.A )

This topic is closed to new replies.

Advertisement