Taste gedrückt halten
-
Hey,
Ich habe ein Problem mit der KeyUp() und KeyDown() Funktion.
Ich habe schon viel im Internet rechachiert aber ich bekomms einfach nicht hin.Mein Ziel ist es, dass sich der Spieler auf der Form1 bewegt.
Dazu habe ich bis jetzt folgendes, dass leider auch nicht funktioniert.
Ich will auch noch schaffen, dass ich auf der Taste draufbleiben kann und der Spieler sich dauerhaft bewegt, bis man sie loslässt.private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.W ) { Spieler.Location = new Point(SpielerX, SpielerY - 20); } if (e.KeyData == Keys.S) { Spieler.Location = new Point(SpielerX, SpielerY + 20); } // ... }
Währe nett wenn mir das jemand genauer erklären könnte ( am besten mit einem Code Beispiel
)
Danke
-
Pseudocode:
// Merken, welche Tasten gedrückt sind: private Dictionary<Keys,bool> pressedKeys=new Dictionary<Keys,bool>(); private void Form1_KeyDown(object sender, KeyEventArgs e) { // Taste auf gedrückt setzen pressedKeys[e.KeyData]=true; } private void Form1_KeyUp(object sender, KeyEventArgs e) { // Taste auf nicht gedrückt setzen pressedKeys[e.KeyData]=false; } // Regelmässig z.B. via Timer: private void Timer_Callback() { if (pressedKeys[Keys.W]==true) { // Spieler bewegen... } }
-
Danke erstmal für deine Antwort. (:
Aber irgendwie funktioniert das nicht bei mir.
private void Form1_KeyDown(object sender, KeyEventArgs e) { // Taste auf gedrückt setzen pressedKeys[e.KeyData] = true; } private void Form1_KeyUp(object sender, KeyEventArgs e) { // Taste auf nicht gedrückt setzen pressedKeys[e.KeyData] = false; } private void timer1_Tick(object sender, EventArgs e) { if (pressedKeys[Keys.W] == true) { Spieler.Location = new Point(SpielerX, SpielerY - 10); } if (pressedKeys[Keys.S] == true) { Spieler.Location = new Point(SpielerX, SpielerY + 10); } if (pressedKeys[Keys.A] == true) { Spieler.Location = new Point(SpielerX + 10, SpielerY); } if (pressedKeys[Keys.D] == true) { Spieler.Location = new Point(SpielerX - 10, SpielerY); } } ________________________________________________________________________ Fehler : "Der angegebene Schlüssel war nicht im Wörterbuch angegeben."
-
Hallo D.J.,
verwende dafür die TryGetValue()-Methode (anstatt dem direkten Index-Zugriff).
-
verwende dafür die TryGetValue()-Methode (anstatt dem direkten Index-Zugriff).
Was mache ich nun falsch?
private void timer1_Tick(object sender, EventArgs e) { if (pressedKeys.TryGetValue("w", out value)) { Spieler.Location = new Point(SpielerX, SpielerY - 10); } if (pressedKeys[Keys.S] == true) { Spieler.Location = new Point(SpielerX, SpielerY + 10); } if (pressedKeys[Keys.A] == true) { Spieler.Location = new Point(SpielerX + 10, SpielerY); } if (pressedKeys[Keys.D] == true) { Spieler.Location = new Point(SpielerX - 10, SpielerY); } } ________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ Fehler 1 Die beste Übereinstimmung für die überladene System.Collections.Generic.Dictionary<System.Windows.Forms.Keys,bool>.TryGetValue(System.Windows.Forms.Keys, out bool)-Methode hat einige ungültige Argumente. Fehler 2 1-Argument: Kann nicht von "string" in "System.Windows.Forms.Keys" konvertiert werden. Fehler 3 2-Argument: Kann nicht von "out string" in "out bool" konvertiert werden. Danke :)
-
Bist du sicher das du ein Spiel machen willst wo du nicht mal die absoluten Basics beherrschst?
> "Der angegebene Schlüssel war nicht im Wörterbuch angegeben."
pressedKeys[Keys.W] (oder ein anderer Key) ist nicht im Dictionary sofern es nicht einmal gedrückt wurde.> Kann nicht von "string" in "System.Windows.Forms.Keys" konvertiert werden
> Kann nicht von "out string" in "out bool" konvertiert werden
Du willst uns doch nicht ernsthaft erzählen das du diese Fehlermeldungen nicht verstehst...selbst wenn du die Werte dann richtig hast, musst du "value" danach auch auswerten. Du hast "TryGetValue" so falsch wie nur möglich in Verwendung, nicht nur Syntaktisch sondern auch in der Position.
Ich finden den ganzen Ansatz ist für die Tonne. (Wenn du schon bei solchen Basics nach fragen musst, dann wird das nie was, lerne die Fehler selber zu lösen.)
Ich würde eher mit einer Liste statt eines Dictionaries arbeiten, der status false, also das die Taste los gelassen wurde ist doch völlig irrelevant, man muss ja nur wissen was gedrückt ist und nicht was man gedrückt war.private List<Keys> _pressedKeys = new List<Keys>(); private void Form1_KeyDown(object sender, KeyEventArgs e) { _pressedKeys.Add(e.KeyData); } private void Form1_KeyUp(object sender, KeyEventArgs e) { _pressedKeys.Remove(e.KeyData); } private void Timer_Callback() { if (pressedKeys.Contains(Keys.W")) { } }
(Sind gerade Ferien?)
-
Bist du sicher das du ein Spiel machen willst wo du nicht mal die absoluten Basics beherrschst?
Naja ich mache C# noch nicht so lange; besser gesagt erst so einen Monat.
In C++ ging das viel leichter; einfach mit _getch() + switch.Ich finden den ganzen Ansatz ist für die Tonne. (Wenn du schon bei solchen Basics nach fragen musst, dann wird das nie was, lerne die Fehler selber zu lösen.)
Ich habe schon so viel ausprobiert und gegooglet und es ging einfach nichts oder ich habe es nicht verstanden.
Deswegen habe ich ja diesen Forumseintrag gemacht.Ich würde eher mit einer Liste statt eines Dictionaries arbeiten, der status false, also das die Taste los gelassen wurde ist doch völlig irrelevant, man muss ja nur wissen was gedrückt ist und nicht was man gedrückt war.
Wie funktioniert das mit der Liste genau?
(Sind gerade Ferien?)
Ja Seit 2 Wochen sind Sommerferien
-
D.J. schrieb:
Ich würde eher mit einer Liste statt eines Dictionaries arbeiten, der status false, also das die Taste los gelassen wurde ist doch völlig irrelevant, man muss ja nur wissen was gedrückt ist und nicht was man gedrückt war.
Siehe mein Code, beim Drücken einer Taste wird diese in die Liste der gedrückten Tasten eingefügt, beim loslassen wieder entfernt.
Dann im 'Timertick' brauchst du nur schauen ob die Taste gedrückt ist (in der Liste vorhanden).
-
D.J. schrieb:
In C++ ging das viel leichter; einfach mit _getch() + switch.
Kleiner Hinweis: _getch() ist nicht Standrad C++
Und noch ein weiterer Hinweise an alle im Thread:
WinForms hat schon die Funktionalität für Key-Repeat drin. Heisst wenn man eine Taste gedrückt hält, werden entsprechend den Einstellungen in Windows dasKeyDown
-Event wiederholt aufgerufen.Bezogen auf den ersten Beitrag:
D.J. schrieb:
Ich habe schon viel im Internet rechachiert aber ich bekomms einfach nicht hin.
Was meinst du damit, dass du es nicht hinbekommst? Was passiert denn? Verschwindet womöglich der Spieler auf der Stelle, weil so viele
KeyDown
Events innert so kurzer Zeit ausgelöst werden, dass der Spieler in Nullkommanichts ganz wo anders steht?Grüssli
-
Vielen Dank!
Jetzt funktioniert das
-
Was meinst du damit, dass du es nicht hinbekommst? Was passiert denn? Verschwindet womöglich der Spieler auf der Stelle, weil so viele KeyDown Events innert so kurzer Zeit ausgelöst werden, dass der Spieler in Nullkommanichts ganz wo anders steht?
Nein. Allgemein hat sich mein Spieler einfach nicht bewegt.
-
Hm. Hab doch noch ein kleines Problem.
Wenn ich die Taste jetzt etwas länger gedrückt halte, dann hört der Spieler nicht mehr auf sie fortzubewegen.
-
D.J. schrieb:
Was meinst du damit, dass du es nicht hinbekommst? Was passiert denn? Verschwindet womöglich der Spieler auf der Stelle, weil so viele KeyDown Events innert so kurzer Zeit ausgelöst werden, dass der Spieler in Nullkommanichts ganz wo anders steht?
Nein. Allgemein hat sich mein Spieler einfach nicht bewegt.
Hast du vergessen ein
Invalidate
aufzurufen, damit dasOnPaint
Event erneut versendet wird?Grüssli
-
Hast du vergessen ein Invalidate aufzurufen, damit das OnPaint Event erneut versendet wird?
Nein. Ich wusste einfach nicht wirklich wie das in C# funktionier, das man einen Tastendruck einliest und auswertet. Hab das nur so halbrichtig gemacht indem ich mri google als HIlfestellung genommen habe.
Aber jetzt funktionierts ja.
Bis auf das Oben genannte Problem eben.Wenn ich die Taste jetzt etwas länger gedrückt halte, dann hört der Spieler nicht mehr auf sie fortzubewegen.
-
Wie hast du es denn jetzt gelöst? Mit der Variante von geeky oder meiner? Kannst du das Problem reproduzieren in einem einfachen Projekt (weniger als 100 Zeilen ;))?
Grüssli
-
So habe ich das jetzt gelöst.. Warum fragst du so dringlich?
private List<Keys> _pressedKeys = new List<Keys>(); private void Map_KeyDown(object sender, KeyEventArgs e) { _pressedKeys.Add(e.KeyData); } private void Map_KeyUp(object sender, KeyEventArgs e) { _pressedKeys.Clear(); } private void SpielerTimer_Tick(object sender, EventArgs e) { // Bewegungen Abhängig von Keys if (_pressedKeys.Contains(Keys.W)) { SpielerY -= 10; Spieler.Location = new Point(SpielerX, SpielerY); } if (_pressedKeys.Contains(Keys.S)) { SpielerY += 10; Spieler.Location = new Point(SpielerX, SpielerY); } if (_pressedKeys.Contains(Keys.A)) { SpielerX -= 10; Spieler.Location = new Point(SpielerX, SpielerY); } if (_pressedKeys.Contains(Keys.D)) { SpielerX += 10; Spieler.Location = new Point(SpielerX, SpielerY); } }
-
Wenn ich die Taste jetzt etwas länger gedrückt halte, dann hört der Spieler nicht mehr auf sie fortzubewegen.
Ist das nicht der Sinn darin? Also die Figur so lange bewegen wie die Taste gedrückt ist wird.
Hast du den Code den du da verwendest überhaupt komplett verstanden? Wenn ja dann findest du das Problem schon noch selber.
-
if(!pressedKeys.Contains(e.KeyData)) _pressedKeys.Add(e.KeyData);
-
Ich habs ja schon gelöst.
private void Map_KeyUp(object sender, KeyEventArgs e) { _pressedKeys.Clear(); }
War früher:
private void Form1_KeyUp(object sender, KeyEventArgs e) { _pressedKeys.Remove(e.KeyData); }
Und jetzt funktionierts.
Danke
-
Bedeutet aber auch, dass Du nur jeweils eine Taste zuverlässig nutzen kannst. Nix mit gleichzeitig laufen _und_ springen.
Denn beim Loslassen einer Taste löschst Du auch die Information über alle anderen gedrückten Tasten. Verwende lieber die OnKeyDown()-Variante von Jesus Christus (das ist ein Nick, oder?).