Jypeli  5
The simple game programming library
Keyboard.cs
Siirry tämän tiedoston dokumentaatioon.
1 #region MIT License
2 /*
3  * Copyright (c) 2009 University of Jyväskylä, Department of Mathematical
4  * Information Technology.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #endregion
25 
26 /*
27  * Authors: Tero Jäntti, Tomi Karppinen, Janne Nikkanen.
28  */
29 
30 using System;
31 using Microsoft.Xna.Framework.Input;
32 
33 using XnaKeyboard = Microsoft.Xna.Framework.Input.Keyboard;
34 using System.Collections.Generic;
35 
36 namespace Jypeli.Controls
37 {
41  public class Keyboard : Controller<KeyboardState>
42  {
43 #if WINDOWS
44  internal static KeyboardTextBuffer Buffer = new KeyboardTextBuffer();
45 #endif
46 
47  internal Keyboard()
48  {
49  oldState = XnaKeyboard.GetState();
50  }
51 
57  public static bool IsChar( Key k )
58  {
59  return ToMaybeChar( k ).HasValue;
60  }
61 
68  public static Key FromChar( char c )
69  {
70  Key result = Key.None;
71 #if WINDOWS
72  Enum.TryParse<Key>( c.ToString(), true, out result );
73 #endif
74  return result;
75  }
76 
83  public static char ToChar( Key k )
84  {
85  char? ch = ToMaybeChar( k );
86  if ( !ch.HasValue ) throw new ArgumentException( k.ToString() + " has no character attached to it." );
87  return ch.Value;
88  }
89 
90  private static char? ToMaybeChar( Key k )
91  {
92  if ( k == Key.Space ) return ' ';
93 
94  string keyStr = k.ToString();
95  if ( keyStr.Length == 1 ) return char.ToLower( keyStr[0] );
96  if ( keyStr.Length == 2 && keyStr[0] == 'D' ) return keyStr[1];
97  if ( keyStr.Length == 7 && keyStr.StartsWith( "NumPad" ) ) return keyStr[6];
98 
99  if ( k == Key.OemQuotes ) return 'ä';
100  if ( k == Key.OemTilde ) return 'ö';
101  if ( k == Key.OemPlus || k == Key.Add ) return '+';
102  if ( k == Key.Subtract ) return '-';
103  if ( k == Key.Multiply ) return '*';
104  if ( k == Key.Divide ) return '/';
105  if ( k == Key.Aring ) return 'Ã¥';
106  if ( k == Key.LessOrGreater ) return '<';
107 
108  return null;
109  }
110 
111  private static Keys ToXnaKeys( Key k )
112  {
113  return (Keys)k;
114  }
115 
116  protected override bool IsTriggered( Listener listener )
117  {
118  if ( listener.Type == ListeningType.KeyboardKey )
119  {
120  return KeyTriggered( listener );
121  }
122 
123  if ( listener.Type == ListeningType.KeyboardAll )
124  {
125  List<Key> keys = KeysTriggered( listener.State );
126  return keys.Count > 0;
127  }
128 
129  return base.IsTriggered( listener );
130  }
131 
132  private bool KeyTriggered( Listener listener )
133  {
134  Keys k = ToXnaKeys( listener.Key );
135 
136  switch ( listener.State )
137  {
138  case ButtonState.Irrelevant:
139  return true;
140 
141  case ButtonState.Released:
142  return ( oldState.IsKeyDown( k ) && newState.IsKeyUp( k ) );
143 
144  case ButtonState.Pressed:
145  return ( oldState.IsKeyUp( k ) && newState.IsKeyDown( k ) );
146 
147  case ButtonState.Up:
148  return ( newState.IsKeyUp( k ) );
149 
150  case ButtonState.Down:
151  return ( newState.IsKeyDown( k ) );
152  }
153 
154  return false;
155  }
156 
157  internal List<Key> KeysTriggered( ButtonState state )
158  {
159  List<Keys> pressedBefore = new List<Keys>( oldState.GetPressedKeys() );
160  List<Keys> pressedNow = new List<Keys>( newState.GetPressedKeys() );
161  List<Key> triggered = new List<Key>();
162 
163  switch ( state )
164  {
165  case ButtonState.Released:
166  for ( int i = 0; i < pressedBefore.Count; i++ )
167  {
168  if ( !pressedNow.Contains( pressedBefore[i] ) )
169  triggered.Add( (Key)pressedBefore[i] );
170  }
171  break;
172 
173  case ButtonState.Pressed:
174  for ( int i = 0; i < pressedNow.Count; i++ )
175  {
176  if ( !pressedBefore.Contains( pressedNow[i] ) )
177  triggered.Add( (Key)pressedNow[i] );
178  }
179  break;
180 
181  case ButtonState.Up:
182  throw new NotImplementedException( "Not implemented" );
183 
184  case ButtonState.Down:
185  for ( int i = 0; i < pressedNow.Count; i++ )
186  {
187  triggered.Add( (Key)pressedNow[i] );
188  }
189  break;
190  }
191 
192  return triggered;
193  }
194 
195  internal override bool IsBufferEmpty()
196  {
197  return ( newState.GetPressedKeys().Length == 0 );
198  }
199 
203  public void Enable( Key k )
204  {
205  base.Enable( listener => ( listener.Key == k ) );
206  }
207 
211  public void Disable( Key k )
212  {
213  base.Disable( listener => ( listener.Key == k ) );
214  }
215 
216  internal override KeyboardState GetCurrentState()
217  {
218  return XnaKeyboard.GetState();
219  }
220 
227  {
228  Keys key = ToXnaKeys( k );
229  bool down = newState.IsKeyDown( key );
230  bool lastdown = oldState.IsKeyDown( key );
231 
232  if ( lastdown && down )
233  return ButtonState.Down;
234  if ( !lastdown && down )
235  return ButtonState.Pressed;
236  if ( lastdown && !down )
237  return ButtonState.Released;
238 
239  return ButtonState.Up;
240  }
241 
248  public bool IsShiftDown()
249  {
250  return newState.IsKeyDown( Keys.LeftShift ) || newState.IsKeyDown( Keys.RightShift );
251  }
252 
259  public bool IsCtrlDown()
260  {
261  return newState.IsKeyDown( Keys.LeftControl ) || newState.IsKeyDown( Keys.RightControl );
262  }
263 
270  public bool IsAltDown()
271  {
272  return newState.IsKeyDown( Keys.LeftAlt ) || newState.IsKeyDown( Keys.RightAlt );
273  }
274 
275  internal override string GetControlText( Listener listener )
276  {
277  if ( listener.Key == Key.Add ) return "NumPad+";
278  if ( listener.Key == Key.Subtract ) return "NumPad-";
279  if ( listener.Key == Key.Multiply ) return "NumPad*";
280  if ( listener.Key == Key.Divide ) return "NumPad/";
281  if ( listener.Key == Key.OemQuotes ) return "Ä";
282  if ( listener.Key == Key.OemTilde ) return "Ö";
283  if ( listener.Key == Key.Left ) return "Left arrow";
284  if ( listener.Key == Key.Right ) return "Right arrow";
285  if ( listener.Key == Key.Up ) return "Up arrow";
286  if ( listener.Key == Key.Down ) return "Down arrow";
287 
288  return listener.Key.ToString();
289  }
290 
291  #region Listen
292  public Listener Listen( Key k, ButtonState state, Handler handler, String helpText )
293  {
294  Listener l = new SimpleListener( this, ListeningType.KeyboardKey, helpText, handler );
295  l.Key = k;
296  l.State = state;
297  Add( l );
298  return l;
299  }
300 
301  public Listener Listen<T1>( Key k, ButtonState state, Handler<T1> handler, String helpText, T1 p1 )
302  {
303  Listener l = new SimpleListener<T1>( this, ListeningType.KeyboardKey, helpText, handler, p1 );
304  l.Key = k;
305  l.State = state;
306  Add( l );
307  return l;
308  }
309 
310  public Listener Listen<T1, T2>( Key k, ButtonState state, Handler<T1, T2> handler, String helpText, T1 p1, T2 p2 )
311  {
312  Listener l = new SimpleListener<T1, T2>( this, ListeningType.KeyboardKey, helpText, handler, p1, p2 );
313  l.Key = k;
314  l.State = state;
315  Add( l );
316  return l;
317  }
318 
319  public Listener Listen<T1, T2, T3>( Key k, ButtonState state, Handler<T1, T2, T3> handler, String helpText, T1 p1, T2 p2, T3 p3 )
320  {
321  Listener l = new SimpleListener<T1, T2, T3>( this, ListeningType.KeyboardKey, helpText, handler, p1, p2, p3 );
322  l.Key = k;
323  l.State = state;
324  Add( l );
325  return l;
326  }
327 
328  public Listener Listen<T1, T2, T3, T4>( Key k, ButtonState state, Handler<T1, T2, T3, T4> handler, String helpText, T1 p1, T2 p2, T3 p3, T4 p4 )
329  {
330  Listener l = new SimpleListener<T1, T2, T3, T4>( this, ListeningType.KeyboardKey, helpText, handler, p1, p2, p3, p4 );
331  l.Key = k;
332  l.State = state;
333  Add( l );
334  return l;
335  }
336  #endregion
337 
338  #region ListenWSAD
339  public void ListenWSAD( ButtonState state, Handler<Vector> handler, String helpText )
346  {
347  Listen( Key.W, state, handler, helpText, Vector.UnitY );
348  Listen( Key.S, state, handler, helpText, -Vector.UnitY );
349  Listen( Key.A, state, handler, helpText, -Vector.UnitX );
350  Listen( Key.D, state, handler, helpText, Vector.UnitX );
351  }
352 
361  public void ListenWSAD<T1>( ButtonState state, Handler<Vector, T1> handler, String helpText, T1 p1 )
362  {
363  Listen( Key.W, state, handler, helpText, Vector.UnitY, p1 );
364  Listen( Key.S, state, handler, helpText, -Vector.UnitY, p1 );
365  Listen( Key.A, state, handler, helpText, -Vector.UnitX, p1 );
366  Listen( Key.D, state, handler, helpText, Vector.UnitX, p1 );
367  }
368 
379  public void ListenWSAD<T1, T2>( ButtonState state, Handler<Vector, T1, T2> handler, String helpText, T1 p1, T2 p2 )
380  {
381  Listen( Key.W, state, handler, helpText, Vector.UnitY, p1, p2 );
382  Listen( Key.S, state, handler, helpText, -Vector.UnitY, p1, p2 );
383  Listen( Key.A, state, handler, helpText, -Vector.UnitX, p1, p2 );
384  Listen( Key.D, state, handler, helpText, Vector.UnitX, p1, p2 );
385  }
386 
397  public void ListenWSAD<T1, T2, T3>( ButtonState state, Handler<Vector, T1, T2, T3> handler, String helpText, T1 p1, T2 p2, T3 p3 )
398  {
399  Listen( Key.W, state, handler, helpText, Vector.UnitY, p1, p2, p3 );
400  Listen( Key.S, state, handler, helpText, -Vector.UnitY, p1, p2, p3 );
401  Listen( Key.A, state, handler, helpText, -Vector.UnitX, p1, p2, p3 );
402  Listen( Key.D, state, handler, helpText, Vector.UnitX, p1, p2, p3 );
403  }
404  #endregion
405 
406  #region ListenArrows
407  public void ListenArrows( ButtonState state, Handler<Vector> handler, String helpText )
414  {
415  Listen( Key.Up, state, handler, helpText, Vector.UnitY );
416  Listen( Key.Down, state, handler, helpText, -Vector.UnitY );
417  Listen( Key.Left, state, handler, helpText, -Vector.UnitX );
418  Listen( Key.Right, state, handler, helpText, Vector.UnitX );
419  }
420 
429  public void ListenArrows<T1>( ButtonState state, Handler<Vector, T1> handler, String helpText, T1 p1 )
430  {
431  Listen( Key.Up, state, handler, helpText, Vector.UnitY, p1 );
432  Listen( Key.Down, state, handler, helpText, -Vector.UnitY, p1 );
433  Listen( Key.Left, state, handler, helpText, -Vector.UnitX, p1 );
434  Listen( Key.Right, state, handler, helpText, Vector.UnitX, p1 );
435  }
436 
447  public void ListenArrows<T1, T2>( ButtonState state, Handler<Vector, T1, T2> handler, String helpText, T1 p1, T2 p2 )
448  {
449  Listen( Key.Up, state, handler, helpText, Vector.UnitY, p1, p2 );
450  Listen( Key.Down, state, handler, helpText, -Vector.UnitY, p1, p2 );
451  Listen( Key.Left, state, handler, helpText, -Vector.UnitX, p1, p2 );
452  Listen( Key.Right, state, handler, helpText, Vector.UnitX, p1, p2 );
453  }
454 
465  public void ListenArrows<T1, T2, T3>( ButtonState state, Handler<Vector, T1, T2, T3> handler, String helpText, T1 p1, T2 p2, T3 p3 )
466  {
467  Listen( Key.Up, state, handler, helpText, Vector.UnitY, p1, p2, p3 );
468  Listen( Key.Down, state, handler, helpText, -Vector.UnitY, p1, p2, p3 );
469  Listen( Key.Left, state, handler, helpText, -Vector.UnitX, p1, p2, p3 );
470  Listen( Key.Right, state, handler, helpText, Vector.UnitX, p1, p2, p3 );
471  }
472  #endregion
473 
474  #region ListenAll
475  public Listener ListenAll( ButtonState state, MultiKeyHandler handler, String helpText )
476  {
477  Listener l = new MultiKeyListener( this, helpText, handler );
478  l.State = state;
479  Add( l );
480  return l;
481  }
482 
483  public Listener ListenAll<T1>( ButtonState state, MultiKeyHandler<T1> handler, String helpText, T1 p1 )
484  {
485  Listener l = new MultiKeyListener<T1>( this, helpText, handler, p1 );
486  l.State = state;
487  Add( l );
488  return l;
489  }
490 
491  public Listener ListenAll<T1, T2>( ButtonState state, MultiKeyHandler<T1, T2> handler, String helpText, T1 p1, T2 p2 )
492  {
493  Listener l = new MultiKeyListener<T1, T2>( this, helpText, handler, p1, p2 );
494  l.State = state;
495  Add( l );
496  return l;
497  }
498 
499  public Listener ListenAll<T1, T2, T3>( ButtonState state, MultiKeyHandler<T1, T2, T3> handler, String helpText, T1 p1, T2 p2, T3 p3 )
500  {
501  Listener l = new MultiKeyListener<T1, T2, T3>( this, helpText, handler, p1, p2, p3 );
502  l.State = state;
503  Add( l );
504  return l;
505  }
506 
507  public Listener ListenAll<T1, T2, T3, T4>( ButtonState state, MultiKeyHandler<T1, T2, T3, T4> handler, String helpText, T1 p1, T2 p2, T3 p3, T4 p4 )
508  {
509  Listener l = new MultiKeyListener<T1, T2, T3, T4>( this, helpText, handler, p1, p2, p3, p4 );
510  l.State = state;
511  Add( l );
512  return l;
513  }
514 
515  public Listener ListenAll( ButtonState state, Action<Key> handler )
516  {
517  Listener l = new MultiKeyListener( this, null, delegate( List<Key> keys ) { keys.ForEach( handler ); } );
518  l.State = state;
519  Add( l );
520  return l;
521  }
522 
523  public Listener ListenAll<T1>( ButtonState state, Action<Key, T1> handler, T1 p1 )
524  {
525  Listener l = new MultiKeyListener( this, null, delegate( List<Key> keys ) { foreach ( var k in keys ) handler( k, p1 ); } );
526  l.State = state;
527  Add( l );
528  return l;
529  }
530 
531  public Listener ListenAll<T1, T2>( ButtonState state, Action<Key, T1, T2> handler, T1 p1, T2 p2 )
532  {
533  Listener l = new MultiKeyListener( this, null, delegate( List<Key> keys ) { foreach ( var k in keys ) handler( k, p1, p2 ); } );
534  l.State = state;
535  Add( l );
536  return l;
537  }
538 
539  public Listener ListenAll<T1, T2, T3>( ButtonState state, Action<Key, T1, T2, T3> handler, T1 p1, T2 p2, T3 p3 )
540  {
541  Listener l = new MultiKeyListener( this, null, delegate( List<Key> keys ) { foreach ( var k in keys ) handler( k, p1, p2, p3 ); } );
542  l.State = state;
543  Add( l );
544  return l;
545  }
546  #endregion
547  }
548 }
delegate void MultiKeyHandler< T1 >(List< Key > keys, T1 p1)
Ohjaintapahtumankäsittelijä yhdellä parametrilla.
void Disable(Key k)
Poistaa napin k käytöstä.
Definition: Keyboard.cs:211
static readonly Vector UnitX
Vaakasuuntainen yksikkövektori (pituus 1, suunta oikealle).
Definition: Vector.cs:66
static Key FromChar(char c)
Palauttaa näppäimen merkille c. Jos merkille ei ole näppäintä, palautetaan Key.None.
Definition: Keyboard.cs:68
delegate void MultiKeyHandler< T1, T2, T3, T4 >(List< Key > keys, T1 p1, T2 p2, T3 p3, T4 p4)
Ohjaintapahtumankäsittelijä neljällä parametrilla.
ButtonState GetKeyState(Key k)
Palauttaa annetun näppäimen tilan (ks. ButtonState).
Definition: Keyboard.cs:226
static bool IsChar(Key k)
Tarkistaa, liittyykö näppäimeen k merkkiä.
Definition: Keyboard.cs:57
static char ToChar(Key k)
Palauttaa merkin, joka liittyy näppäimeen k. Jos näppäimeen ei liity merkkiä, tapahtuu poikkeus Argum...
Definition: Keyboard.cs:83
static readonly Vector UnitY
Pystysuuntainen yksikkövektori (pituus 1, suunta ylös).
Definition: Vector.cs:71
ButtonState
Napin (minkä tahansa) asento.
Definition: ButtonState.cs:37
delegate void MultiKeyHandler< T1, T2 >(List< Key > keys, T1 p1, T2 p2)
Ohjaintapahtumankäsittelijä kahdella parametrilla.
bool IsShiftDown()
Tarkistaa, onko kumpikaan shift-näppäimistä painettuna.
Definition: Keyboard.cs:248
Näppäimistö peliohjaimena.
Definition: Keyboard.cs:41
delegate void Handler< T1, T2, T3 >(T1 p1, T2 p2, T3 p3)
Ohjaintapahtumankäsittelijä kolmella parametrilla.
void Enable(Key k)
Ottaa käytöstä poistetun napin k takaisin käyttöön.
Definition: Keyboard.cs:203
delegate void Handler< T1 >(T1 p1)
Ohjaintapahtumankäsittelijä yhdellä parametrilla.
Listener ListenAll(ButtonState state, Action< Key > handler)
Definition: Keyboard.cs:515
delegate void MultiKeyHandler(List< Key > keys)
Ohjaintapahtumankäsittelijä ilman parametreja.
Listener Listen(Key k, ButtonState state, Handler handler, String helpText)
Definition: Keyboard.cs:292
delegate void MultiKeyHandler< T1, T2, T3 >(List< Key > keys, T1 p1, T2 p2, T3 p3)
Ohjaintapahtumankäsittelijä kolmella parametrilla.
delegate void Handler()
Ohjaintapahtumankäsittelijä ilman parametreja.
delegate void Handler< T1, T2 >(T1 p1, T2 p2)
Ohjaintapahtumankäsittelijä kahdella parametrilla.
Key
Näppäimistön näppäin.
Definition: Key.cs:37
Listener ListenAll(ButtonState state, MultiKeyHandler handler, String helpText)
Definition: Keyboard.cs:475
override bool IsTriggered(Listener listener)
Definition: Keyboard.cs:116
delegate void Handler< T1, T2, T3, T4 >(T1 p1, T2 p2, T3 p3, T4 p4)
Ohjaintapahtumankäsittelijä neljällä parametrilla.
2D-vektori.
Definition: Vector.cs:56
bool IsCtrlDown()
Tarkistaa, onko kumpikaan ctrl-näppäimistä painettuna.
Definition: Keyboard.cs:259
Yleinen peliohjainluokka.
Definition: Controller.cs:40
bool IsAltDown()
Tarkistaa, onko kumpikaan alt-näppäimistä painettuna.
Definition: Keyboard.cs:270