flopoloco's picture

OpenTK Keyboard Input Example

3 different ways of getting key input, each with his benefits.

using System;
using OpenTK;
using OpenTK.Input;
namespace OpenTKKey
{
	class MainClass : GameWindow
	{
		// 1. Exit using keyboard event handler
		// 2. Exit by using method of OpenTK GameWindow
		// 3. By using the Keyboard property
 
		protected override void OnLoad (EventArgs e)
		{
			// 1
			Keyboard.KeyDown += HandleKeyDown;
		}
 
		// 1
		void HandleKeyDown (object sender, KeyboardKeyEventArgs e)
		{
			if (e.Key == Key.Escape) Exit ();
		}
 
		// 2
		protected override void OnKeyPress (OpenTK.KeyPressEventArgs e)
		{
			// This brings this Exact string "Escape"
			// If you don not want to use Windows.Forms assembly then
			// check against plain charachters else you do it like this
			// for type value safety: System.Windows.Forms.Keys.Q
			if (e.KeyChar == 'q' || e.KeyChar == 'Q')
				Exit ();
		}
 
		// 3
		protected override void OnUpdateFrame (FrameEventArgs e)
		{
			if (Keyboard[Key.Space])
				Exit ();
 
			base.OnUpdateFrame (e);
		}
 
		public static void Main (string[] args)
		{
			using (var m = new MainClass()) {
				m.Run ();
			}
		}
	}
}

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
flopoloco's picture

I am searching how to get the Keyboard device without the GameWindow.
Must be a keyboard instantiation with event handler... Any ideas?

rvIceBreaker's picture

Getting Input while bypassing the 'GameWindow' requires a couple of things...

Firstly, to get input in general, you need to have the respective 'Device' class, so you'll need something like this...

MouseDevice mouse; //Mouse Device ( for mouse input )
KeyboardDevice keyboard; //Keyboard Device ( for keyboard input )

In order to instantiate this class, you have to have access to the 'IInputDriver' from the NativeWindow your project is using. I made a singleton reference to my NativeWindow and grabbed the IInputDriver when i needed it.

NativeWindow nativeWindow = new NativeWindow( ... );
 
...
 
IInputDriver inputDriver = nativeWindow.InputDriver;
 
MouseDevice mouse = inputDriver.Mouse[0]; //'inputDriver.Mouse' is a collection of available MouseDevice classes; we want the first device
KeyboardDevice keyboard = inputDriver.Keyboard[0]; //'inputDriver.Keyboard' is a collection of available KeyboardDevice classes; we want the first device

After you have all of this, you can add new EventHandlers to the ButtonUp/Down and KeyUp/Down events.

mouse.ButtonDown += new EventHandler<MouseButtonEventArgs>(mouse_ButtonDown);
mouse.ButtonUp += new EventHandler<MouseButtonEventArgs>(mouse_ButtonUp);
 
keyboard.KeyDown += new EventHandler<KeyboardKeyEventArgs>(keyboard_KeyDown);
keyboard.KeyUp += new EventHandler<KeyboardKeyEventArgs>(keyboard_KeyUp);

You can also access things like the mouse position and the wheel position from the MouseDevice class.

The main thing to keep in mind is that you'll need to keep a reference to your NativeWindow instance for many reasons (depending on your desired features), so be sure to do so to save yourself a headache.

Eackz's picture

nativeWindow.InputDriver is deprecated. Whats the alternative?

the Fiddler's picture

For event-based input:

INativeWindow.KeyDown
INativeWindow.KeyUp
INativeWindow.KeyPress // for text input

and for polling:

OpenTK.Input.Keyboard.GetState()
publicENEMY's picture
the Fiddler wrote:

For event-based input:

INativeWindow.KeyDown
INativeWindow.KeyUp
INativeWindow.KeyPress // for text input

and for polling:

OpenTK.Input.Keyboard.GetState()

Is this the recommended way to get input? If not, what is the recommended way of getting input?

Thanks.

winterhell's picture

They are both valid ways to get keyboard input, it depends on what you want to do.
If you are in 'press any key to continue' or get text input type of state, use events for KeyDown and KeyPress.

If you want input for a game and looking at specific keys (for example the ones you use for character move and jump / fire)
then use

KeyboardState keyboard = Keyboard.GetState();
if(keyboard[Key.Left]) { move character left};
if(keyboard[Key.Right]) { move character right};

You want to do this once every frame, and it'll tell you during that frame if the user is pressing/holding left or right.
For fire and jump you'd still check every frame, but you probably dont want to perform the action every frame. For that you'd have either an action cooldown timer after a fire before you can fire again, and/ or keep track if the previous frame the button was released and just this frame you pressed it.