Alternative zur Abfrage von mehreren Keys

    • C#
    • .NET (FX) 4.5–4.8

    Es gibt 2 Antworten in diesem Thema. Der letzte Beitrag () ist von Radinator.

      Alternative zur Abfrage von mehreren Keys

      Hi Leute!

      Bin vor wenigen Tagen mal wieder durch die Alten Beiträge in diesem Forum gesurft und bin dann immer wieder auf Postings gestoßen, in denen neue User Probleme mit Tastaturabfragen einbringen[Objekt mit Tastatur bewegen]. Ebenso hatte ich einmal vor Jahren (in VB.NET) das Problem, dass ich mehrfache Tastatur Eingaben nicht verarbeiten konnte. Ich war nur in der Lage immer einen Tastendruck gleichzeitig zu prüfen. Das ist natürlich in einer Anwendung, in der man mit WASD sich bewegen kann und man diagonal gehen will, nicht unbedingt optimal ;/

      Jedenfalls hab ich mich mal hingesetzt und eine kleine Möglichkeit erschaffen *hust räusper* (kopiert von C Razor Sharp[crazorsharp.blogspot.de/search/label/GetKeyState])
      Dabei war es mir wichtig, dass die Lösung
      1.) Einfach zu verwenden ist
      2.) Der Code verständlich ist (Ok eine Stelle gibts, die is etwas komplizierter) und
      3.) Kurz zu halten ist

      Vorteil meiner Lösung:
      + Man braucht keine aufgeplusterten Select/Switch Case-Abfragen
      + Es können mehrer Tasten abgefrag werden (Im Gegensatz zu KeyDown und KeyPress-Events)

      Für GameLoop

      Wie in dem Blogeintrag schon beschrieben wurde, besteht so eine GameLoop aus 2 Bestanteile:
      1.) Die Update-Methode:
      ist dafür zuständig, dass Tastaturdrücke abgefragt werden und die Positionen der Entities neu setzen. Kurz: Die Game-Logik zu updaten
      2.)Die Draw-Methode:
      ist dafür zuständig, dass die ganzen Inhalte des UI neu gezeichnet werden

      In einer ganz normalen Window-Forms Anwendung braucht man für die Realisierung des Vorhabens einen einfachen Kreis mit den Pfeiltasten zu bewegen nur eine Klasse, die den Ball/den Kreis darstellt und einen Timer auf der MainForm.

      Bei besagter WinForms-Anwendung ist das Tick-Event des Timers die Update-Methode und OnPain()-Methode der MainForm die Draw-Methode
      In der OnPain wird jedes Element auf dem UI neu gezeichnet. Das erreicht man, indem jedes Element eine Draw-Methode implementiert, die in der OnPain aufgerufen wird.
      Bsp ist im Anhang enthalten


      Hier ist mal der Code zur KeyboardInfo-Klasse:
      KeyboardInfo-Klasse

      C#-Quellcode

      1. class KeyboardInfo
      2. {
      3. private KeyboardInfo() { }
      4. [DllImport("User32")]
      5. private static extern short GetKeyState(int vKey); //WinAPI-Funktion für den KeyState
      6. public static KeyStateInfo GetState(Keys key)
      7. {
      8. short keyState = GetKeyState((int)key); //Aufruf der WinAPI
      9. /*
      10. MSDN-Dokumentation zu GetKeyState() [https://msdn.microsoft.com/en-us/library/ms646301(VS.85).aspx]:
      11. If the high-order bit is 1, the key is down; otherwise, it is up.
      12. If the low-order bit is 1, the key is toggled.
      13. A key, such as the CAPS LOCK key, is toggled if it is turned on.
      14. The key is off and untoggled if the low-order bit is 0.
      15. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled.
      16. */
      17. int high = keyState > 0 ? //Wenn KeyState größer als 1 ist
      18. keyState >> 0x10 :
      19. (keyState >> 0x10) & 0x1;
      20. int low = keyState & 0xffff;
      21. bool toggled = low == 1;
      22. bool down = high == 1;
      23. bool up = high != 1;
      24. return new KeyStateInfo(up, down, toggled);
      25. }
      26. }
      27. public struct KeyStateInfo
      28. {
      29. private bool _isUp;
      30. private bool _isDown;
      31. private bool _isToggled;
      32. public KeyStateInfo(bool isUp, bool isDown, bool isToggled)
      33. {
      34. this._isUp = isUp;
      35. this._isDown = isDown;
      36. this._isToggled = isToggled;
      37. }
      38. public bool IsUp
      39. { get
      40. {
      41. return this._isUp == true;
      42. }
      43. }
      44. public bool IsDown
      45. {
      46. get
      47. {
      48. return this._isDown == true;
      49. }
      50. }
      51. public bool IsToggled
      52. {
      53. get
      54. {
      55. return this._isToggled == true;
      56. }
      57. }
      58. }



      Um jetzt Tasten abfzufragen, musst nur eine Referenzvariable vom Typen KeyStateInfo erzeugt werden und mit dem Ergebnis der Statischen Funktion GetState(), die als Parameter die gewünschten Taste enthält, befüllt werden. Hierbei können ALLE Tasten verwendet werden, die in der System.Windows.Forms.Keys-Enumeration erfasst sind.

      Zur Verwendung:

      C#-Quellcode

      1. KeyStateInfo arrowDown = KeyboardInfo.GetState(Keys.Down);
      2. if (arrowDown.IsDown)
      3. {
      4. }
      5. else if (arrowDown.IsUp)
      6. {
      7. }else
      8. {
      9. }
      10. //Gut man könnte hier für jeden Key eine Select/Switch Case-Abfrage machen, wenn man wollte ;D


      Wenn man nicht gerade eine Supermegaumfangreiche GameEngin, wie Sharpex2D[Sharpex2D 1.3.0 | 2D Game Framework] hernimmt, sondern sich in Grafikprogrammierung/spielentwicklung rantasten will, indem man eigene Projekt zuerst mal mit WinForms löst, hat man mit der Lösung einen einfachen Einstieg

      Lg Radinator
      Dateien
      In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
      Deine KeyStateInfo-Struct lässt sich erheblich kürzen:

      C#-Quellcode

      1. public struct KeyStateInfo
      2. {
      3. public KeyStateInfo(bool isUp, bool isDown, bool isToggled)
      4. {
      5. IsUp = isUp;
      6. IsDown = isDown;
      7. IsToggled = isToggled;
      8. }
      9. public bool IsUp { get; private set; }
      10. public bool IsDown { get; private set; }
      11. public bool IsToggled { get; private set; }
      12. }​
      »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
      @Plexian: dank dir für deinen Beitrag
      das mit dem private set der Property wusste ich gar ned

      Lg Radinator
      In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell