I’ve already posted a few times on handling input for Monogame. This one’s a little bit different though, and came from the fact that I had a game trying to get through certification that was repeatedly failing. What I was doing was detecting touch capabilities and, where I found them, using them; otherwise, using keyboard or mouse.
What I ended up doing was handling both. At the time this was just to get the game through certification in the Windows Store; but the more I think about it, the better I think the solution is.
Instead of maintaining a single input contoller, and assigning to it via a factory method, I maintain a list of controllers:
List<IInputController> _inputControllers;
Then, instead of an if / else statement to assign to the controllers, I simply add what’s available:
// Determine how the user will interface with the game private void HandleInput() { // Instantiate the controllers collection if (_inputControllers == null) _inputControllers = new List<IInputController>(); if (_inputControllers.Count == 0) { // Can we handle touch? If so, add a new controller to handle touch Windows.Devices.Input.TouchCapabilities tc = new Windows.Devices.Input.TouchCapabilities(); if (tc.TouchPresent == 1) { _inputControllers.Add(new TouchController()); } // Can we handle Mouse? If so, add a new controller to handle mouse Windows.Devices.Input.MouseCapabilities mc = new Windows.Devices.Input.MouseCapabilities(); if (mc.MousePresent == 1) { _inputControllers.Add(new MouseController()); } }
So, now we’ve got a list (and it doesn’t have to be restricted to 2 elements if, for example, you suddenly decide to support a thought-power interface http://en.wikipedia.org/wiki/Emotiv_Systems).
On the update method of your game, you now simply iterate through them:
foreach (IInputController inputController in _inputControllers) { inputController.HandleInput(); }
Isn’t it a bit messy having the (potentially) giant conditional statement above
Yes. So, how about this.
// Determine how the user will interface with the game if (_inputControllers == null) _inputControllers = new List<IInputController>(); if (_inputControllers.Count == 0) { TouchController.AddController(_inputControllers); KeyboardController.AddController(_inputControllers); }
And then add the AddController function as a static method; like so:
internal static void AddController(List<IInputController> controllers) { Windows.Devices.Input.MouseCapabilities mc = new Windows.Devices.Input.MouseCapabilities(); if (mc.MousePresent == 1) { controllers.Add(new KeyboardController()); } }
I’m unsure if this qualifies as a “Factory” method as such, although effectively that is what it is.
Conclusion
I’m now quite happy with this approach. I can foresee future uses for the logic, so at some point, if I get time, I might transfer it all to a PCL and publish on Codeplex… assuming I can work out how to get the Windows.Devices namespace to work in a PCL.
Nice example but you go in to a bit more depth on your setup, detailing the sample interface or better yet, provide a simple example project with the implementation?
I might revisit this soon for Windows 10, as I’m playing around with that quite a bit now.