Entwickler-Ecke
Multimedia / Grafik - Zwei Tasten werden gleichzeitig gedrückt
Karlson - Mi 22.06.05 16:20
Titel: Zwei Tasten werden gleichzeitig gedrückt
Moin,
In jedem über die Tastatur gesteuertem Spiel, sollte es möglich sein z.B. gleichzeitig nach vorne zu laufen und dabei nach links zu strafen.
Wie kann man das denn abfragen, ob zwei Tasten gedrückt sind mein ich.
Meine Ansätze:
1.) KeyDown Event - solang ich nur eine Taste abfrage klappt es, wenn ich eine zweite Taste dazu drücke wird die erste als losgelassen angezeigt und nur die zweite als gedrückt.
2.) KeyPress Event - gleiches Spiel
3.) GetAsyncKeyState - gleiches Spiel
4.) GetKeyState - gleiches Spiel
Hinzukommt folgendes Problem wenn man mit einer der oben geannten Methode arbeitet.
Ich zeige das mal anhand einer logdatei. Diese hat mittels GetAsyncKeyState abgefragt ob die Taste vk_left gedrückt ist, und zwar in einem Intervall von 50 ms. Wenn sie gedrückt war, wurde 1 vermerkt, wenn nicht 0:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| 0 0 0 0 0 0 0 0 1 /// Jetzt Habe ich vk_left gedrückt, und lies es auch gedrückt 1 0 // Das sieht evt. unwichtig aus, in einem Spiel stört es aber enorm! 0 0 1 1 1 1 1 1 1 1 |
Die Taste wird für ~300 ms nach dem Drücken als nicht gedrückt angezeigt.
retnyg - Mi 22.06.05 16:33
mit directinput sollte das auf jeden fall gehen
DIRECTINPUT DELPHI
gibt aber sicher auch nen anderen weg, den ich aber nicht kenne ;)
Lossy eX - Do 23.06.05 09:16
Also ich kann das Verhalten mit GetAsyncKeyState absolut nicht bestätigen. Normal funktioniert das 100%tig richtig. Und GetAsyncKeyState greift auch nur auf die Tastatur zu. Ich denke mal da würde dann auch Directinput nicht ändern.
Delphi-Quelltext
1: 2: 3: 4:
| if GetAsyncKeyState(VK_LEFT) <> 0 then Memo1.Lines.Add('gedrückt') else Memo1.Lines.Add('nicht gedrückt'); |
Du könntest das Verhalten von GetAsyncKeyState auch mit Hilfe von einem Array[0..255] of Boolean und KeyDown und KeyUp simulieren. Jedes mal wenn du ein KeyDown bekommst setzt du das entsprechende Bool auf True und wenn du ein KeyUp bekommst dann löscht du es wieder. Um abzufragen ob eine Taste gedrückt ist überprüfst du dann nur noch die entsprechde Stelle im Array.
Aber wie gesagt. Normal sollte es 100%tig mit GetAsyncKeyState funktionieren. Anderenfalls würde ich mal testen ob deine Hardware und Windows richtig funktionieren. Also eine Testanwednung auf anderen Rechnern ausprobieren. Evtl auch mal ne andere Tastatur ausprobieren etc. Veilleicht hat die ja nen Wackelkontakt der sich so äußerst.
Phobeus - Do 23.06.05 10:01
Ja, man muss nicht DirectInput verwenden um so etwas zu lösen. Der häufigste Codierungsfehler in diesem Zusammenhang besteht meistens darinne, dass die Tasten in der Event-Loop verarbeitet werden. Ich erinnere mich da an einen Fehler im Zusammenhang mit SDL als jemand nur innerhalb der Event-Schleife die Tasten verarbeitete (mit der Absicht dies nach dem Tastensignal zu tun). Spätestens ab dem zweiten Durchgang gab es dann meist weniger Signale als Tasten und Signale gingen verloren. Versuche daher genausten nachzuvollziehen wie dies bei Dir geschieht.
Generell bietet es sich gerade bei Spielen der Weg an den SDL geht. Beim Drücken und loslassen der Tasten werden die Signale in ein Array of Boolean geschrieben. Wird eine Taste gedrückt wird dessen Index auf True gesetzt, und beim Release wieder auf false. Die Verarbeitung erfolgt dann bei jedem Zeichengang. Man erhält so die volle Kontrolle über den Datenfluss und kann sogar Tastensignale auf diese Weise leicht "rücksetzen" (z.B. beim Feuern mit der Rakete, darf kein Laser mehr abgefeuert werden). Nur ein Gedankengang, der mir beim lesen deines Problems in den Sinn kam.
Pansenen - Di 28.06.05 09:55
Titel: yo, ich hatte das problem auch
hab das aber anders ( und wie ich sagen muss ganz gut) geregelt. Die Tasten werden im Variablenarray keys abgespeichert und bei procedure keyup wieder gelöscht. Ich habs bei 2 Playern probiert und man kann ohne Probleme bis zu Acht Tasten gleichzeitig drücken. P[1] ist die Spielfigur des ersten Spielers und pmove ist ein Timer der alle 30 Millisekunden den Player bewegt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = vk_up) then keys[1]:= 1; if (key = vk_down) then keys[2]:=1; if (key = vk_left) then keys[3]:=1; if (key = vk_right) then keys[4]:=1; end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = vk_up) then keys[1]:= 0; if (key = vk_down) then keys[2]:=0; if (key = vk_left) then keys[3]:=0; if (key = vk_right) then keys[4]:=0; end;
procedure TForm1.pmoveTimer(Sender: TObject); begin if (keys[1] = 1) and (P[1].top>speed[1]+21) then P[1].Top := P[1].top-speed[1]; if (keys[2] = 1) and (P[1].top<form1.ClientHeight-65-speed[1]) then P[1].Top := P[1].top+speed[1]; if (keys[3] = 1) and (P[1].left>0) then P[1].left := P[1].left-speed[1]; if (keys[4] = 1) and (P[1].left<form1.Width-65-speed[1]) then P[1].left := P[1].left+speed[1]; end; |
Moderiert von
UGrohne: Code- durch Delphi-Tags ersetzt.
Heiko - Di 28.06.05 10:57
Lossy eX hat folgendes geschrieben: |
Du könntest das Verhalten von GetAsyncKeyState auch mit Hilfe von einem Array[0..255] of Boolean und KeyDown und KeyUp simulieren. Jedes mal wenn du ein KeyDown bekommst setzt du das entsprechende Bool auf True und wenn du ein KeyUp bekommst dann löscht du es wieder. Um abzufragen ob eine Taste gedrückt ist überprüfst du dann nur noch die entsprechde Stelle im Array. |
Mit diesem Verfahren arbeite ich, allerdings hat es einen Nachteil: Es kann dir passieren, dass das loslassen/drücken einer Taste nicht registriert wird. Dieser Fall war bisher allerdings ein Einzelfall, der bisher nur bei einem Freund von mir passiert ist.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| var Keys: array[0..255] of Boolean;
procedure TForm1.WMKeyDown(var Msg: TWMKeyDown); begin Keys[Msg.CharCode]:=true; end;
procedure TForm1.WMKeyUp(var Msg: TWMKeyUp); begin Keys[Msg.CharCode]:=false; end; |
Und dann kannst du Tastenkombinationen abfragen, so wie du die willst ;).
BwK - Di 09.08.05 23:32
kann mir einer sagen, warum TForm1.FormKeyDown bei mir nich geht ?? TForm1.FormKeyUp geht, das andere nich ... Form1.KeyPreview is auf true ... da müsste das doch gehn oder ??
Speedmaster - Mi 10.08.05 00:52
Gibt es nicht normal ein Softwareinterrupt wenn eine Taste gedrückt wird? So hatte ich das glaube ich mal irgendwo gehört!
Logikmensch - Mi 10.08.05 06:20
Titel: Nicht funktionierendes KeyUp-Ereignis...
Hallo,
BwK hat folgendes geschrieben: |
kann mir einer sagen, warum TForm1.FormKeyDown bei mir nich geht ?? TForm1.FormKeyUp geht, das andere nich ... Form1.KeyPreview is auf true ... da müsste das doch gehn oder ?? |
Grundsätzlich tritt nach dem Drücken einer Taste ein entsprechender KeyDown (und im Falle von 'normalen' Tasten KeyPress) ein. Beim Loslassen wird ein zuvor erreichtes KeyDown durch ein KeyUp-Ereignis wieder aufgehoben. Es muss eigentlich funktionieren. Zeig mal Deine betreffenden Event-Prozeduren, vielleicht kann man dort den Fehler erkennen.
Liebe Grüße,
Claus.
Lossy eX - Mi 10.08.05 08:38
Es wird nicht immer bei allen Tasten aufgerufen. Ich meine bei Tab wird es nicht von Hause aus aufgerufen. Bei einem Panel glaube ich werden die Cursortasten auch nicht aufgerufen.
Mit folgendem Code kannst du Windows sagen, dass du sie dennoch gerne hättest.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| type TForm1 = class(TForm) protected procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE; end;
implementation
procedure TForm1.WMGetDlgCode(var Message: TWMGetDlgCode); begin Message.Result := DLGC_WANTALLKEYS or DLGC_WANTTAB or DLGC_WANTARROWS; end; |
PS: Wenn du es bei einem Panel ermöglichen möchtest musst du das Panel ableiten und den Codeschnipsel auch dort einfügen.
BwK - Mi 10.08.05 11:30
so ... ich habs hinbekommen ... ich hab anstatt der pfeiltasten buchstaben genommen (wollte ich sowieso, ich dachte nur die coursortasten gehen erst mal einfacher :D ) ...
also so gehts:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = Ord('U')) then keys[0]:= 1; if (key = Ord('J')) then keys[1]:=1; if (key = Ord('H')) then keys[2]:=1; if (key = Ord('K')) then keys[3]:=1; end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = Ord('U')) then keys[0]:= 0; if (key = Ord('J')) then keys[1]:=0; if (key = Ord('H')) then keys[2]:=0; if (key = Ord('K')) then keys[3]:=0; end; |
mfg BwK
Joachim Knutson - Mi 17.05.06 16:22
BwK hat folgendes geschrieben: |
so ... ich habs hinbekommen ... ich hab anstatt der pfeiltasten buchstaben genommen (wollte ich sowieso, ich dachte nur die coursortasten gehen erst mal einfacher :D ) ...
also so gehts:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = Ord('U')) then keys[0]:= 1; if (key = Ord('J')) then keys[1]:=1; if (key = Ord('H')) then keys[2]:=1; if (key = Ord('K')) then keys[3]:=1; end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = Ord('U')) then keys[0]:= 0; if (key = Ord('J')) then keys[1]:=0; if (key = Ord('H')) then keys[2]:=0; if (key = Ord('K')) then keys[3]:=0; end; |
mfg BwK |
mich würde jetz ma noch interessieren, wie du das array deklariert hast.
kann mir das ma einer erklähren? arrays sind immer so ne sache, hab bei mir nich immer so gute erfahrungen damit gemacht :roll: .(versuche die eigendlich wo's geht zu vermeiden)
0xCC - Mi 17.05.06 19:27
Delphi-Quelltext
1:
| var keys : array[0..3] of byte; |
markier mal array in delphi und drück F1 ^^
Joachim Knutson - Do 18.05.06 21:10
boa da seh ich echt nich durch. sitz jetz seit ner 3/4 stunde und weiß noch nich mehr. ;-)
@0xCC danke
also hab noch ne frage dazu:
ich woltts eigendlich wie Pansenen machen (schien mir einfach zu sein), doch
follgendes versteh ich nich
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure TForm1.pmoveTimer(Sender: TObject); begin if (keys[1] = 1) and (P[1].top>speed[1]+21) then P[1].Top := P[1].top-speed[1]; if (keys[2] = 1) and (P[1].top<form1.ClientHeight-65-speed[1]) then P[1].Top := P[1].top+speed[1]; if (keys[3] = 1) and (P[1].left>0) then P[1].left := P[1].left-speed[1]; if (keys[4] = 1) and (P[1].left<form1.Width-65-speed[1]) then P[1].left := P[1].left+speed[1]; end; |
und zwar das mit speed. wie definiere ich das? oder am besten wie mach ichs das ich kein speed drin hab? will ja eigendlich nur zwei tasten und ein ereignis haben.
oder soll ich lieber doch ne andere variante nehmen????
NeoInDerMATRIX - Do 18.05.06 22:10
Hallo,
also mit einem Time (POLLING) solte man solche sachen in zeiten von Windows und Co. nicht mehr machen. So hab ich das noch unter DOS gemacht. Damit ist dann die CPU aber mehr damit beschäftigt das Polling zu erledigen als wie alles andere. Und wenn du das mit einem Timer machst kannst du nicht jeder Zeit den aktuellen status der Tasten erfahren!
Ich habe mal einen etwas älteren Code raus gesucht, ohne den overhead von Omorphia. Der sollte dir denke ich etwas mehr helfen. Und wenn nicht dann frag mich bei den sachen die du nicht verstehst.
Eigentlich ist es recht simpel:
1. Im Form wo du den KeyMapper nutzen möchtest must du ihn via InitMapper(Self) Initzialisieren.
2. Und dann natürlich auch noch die Tasten, via BindKey, mit Commandos Binden.
3. In der Form Class die Procedure WndProc überschreiben.
In der Unit Main.pas siehst du recht gut wie man das anwenden kann.
Ich hoffe das es so etwas Informativer ist.
Cu
Neo
0xCC - Fr 19.05.06 15:48
Joachim Knutson hat folgendes geschrieben: |
ich woltts eigendlich wie Pansenen machen (schien mir einfach zu sein) |
lass die finger von code, den du nicht verstehst, sondern schreib deinen eigenen.
das kommt natürlich darauf an, was du machen willst.
ich nehme mal an, es geht um ein objekt, dass sich auf cursordruck rumbewegen soll
am besten liest du dir hierzu folgendes tutorial durch
http://www.delphi-library.de/viewtopic.php?t=44374&highlight=delphix
Joachim Knutson - Fr 19.05.06 18:05
0xCC hat folgendes geschrieben: |
Joachim Knutson hat folgendes geschrieben: |
ich woltts eigendlich wie Pansenen machen (schien mir einfach zu sein) |
lass die finger von code, den du nicht verstehst, sondern schreib deinen eigenen.
das kommt natürlich darauf an, was du machen willst.
ich nehme mal an, es geht um ein objekt, dass sich auf cursordruck rumbewegen soll
am besten liest du dir hierzu folgendes tutorial durch
http://www.delphi-library.de/viewtopic.php?t=44374&highlight=delphix |
nur das problem is ich habe nur delphi6 personal zur verfügung und KANN auch nichts anderes nehmen. (hat so seine gründe)
kann mir trotzdem einer helfen?? bitte
NeoInDerMATRIX - Fr 19.05.06 18:20
Hallo,
ich verstehe nicht wo das problem ist! Du hast jetzt zwei mögliche ansätze, sogar mit Source. Du must für dich selber entscheiden welcher weg für dich einfacher zu verstehen ist und welcher besser für dein program ist. Und wenn du dich entschieden hast, dann probiere den source zu verstehen. Wenn dann fragen aufkommen können / werden wir dir helfen. Im moment vestehe ich halt nicht wobei du hilfe brauchst!
Cu
Neo
Joachim Knutson - Fr 19.05.06 18:29
NeoInDerMATRIX hat folgendes geschrieben: |
Hallo,
ich verstehe nicht wo das problem ist! Du hast jetzt zwei mögliche ansätze, sogar mit Source. Du must für dich selber entscheiden welcher weg für dich einfacher zu verstehen ist und welcher besser für dein program ist. Und wenn du dich entschieden hast, dann probiere den source zu verstehen. Wenn dann fragen aufkommen können / werden wir dir helfen. Im moment vestehe ich halt nicht wobei du hilfe brauchst!
Cu
Neo |
also ich wollte ursprünglich wissen, wie man nach Pansenen's variante diese variable 'speed' dekariert.
eigenlich weiß ich gar nich wie ich die dritte prozedur in mein progri bringe.
0xCC - Fr 19.05.06 19:02
Joachim Knutson hat folgendes geschrieben: |
also ich wollte ursprünglich wissen, wie man nach Pansenen's variante diese variable 'speed' dekariert.
eigenlich weiß ich gar nich wie ich die dritte prozedur in mein progri bringe. |
was willst du mit der dritten prozedur wenn du nicht mal weisst was sie macht ?
was willst du denn nun eigentlich machen ?
Joachim Knutson - Sa 20.05.06 15:15
0xCC hat folgendes geschrieben: |
Joachim Knutson hat folgendes geschrieben: | also ich wollte ursprünglich wissen, wie man nach Pansenen's variante diese variable 'speed' dekariert.
eigenlich weiß ich gar nich wie ich die dritte prozedur in mein progri bringe. |
was willst du mit der dritten prozedur wenn du nicht mal weisst was sie macht ?
was willst du denn nun eigentlich machen ? |
also ich habe ein timage, welches ich schon nach allen seiten steuern kann.
doch ich will auch, dass man es in 2 richtungen zugleich gehen kann. also z.b. nach oben-rechts.
und dazu brauch ich ja noch 2 extra prozeduren. ich habe schon bei onkeydown und onkeyup reingeschrieben:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = Ord('U')) then keys[0]:= 1; if (key = Ord('J')) then keys[1]:=1; if (key = Ord('H')) then keys[2]:=1; if (key = Ord('K')) then keys[3]:=1; end; procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (key = Ord('U')) then keys[0]:= 0; if (key = Ord('J')) then keys[1]:=0; if (key = Ord('H')) then keys[2]:=0; if (key = Ord('K')) then keys[3]:=0; end; |
und nun muss ich doch noch sagen was ich machen soll wenn nun 2 tasten gedrückt werden oder?
und dazu hab ich für jeweils eine taste das hier:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm4.FormKeyPress(Sender: TObject; var Key: Char); begin if key = 'd' then Image1.Left:=Image1.Left+10; if key = 'a' then Image1.left:=Image1.left-10; if key = 'w' then Image1.top:=Image1.top-10; if key = 's' then Image1.top:=Image1.top+10; end; |
und jetz brauch ich halt noch das für 2 tasten, weiß aber nich wie ichs machen soll.
Pansenen hatte ja in seiner porzedur das:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure TForm1.pmoveTimer(Sender: TObject); begin if (keys[1] = 1) and (P[1].top>speed[1]+21) then P[1].Top := P[1].top-speed[1]; if (keys[2] = 1) and (P[1].top<form1.ClientHeight-65-speed[1]) then P[1].Top := P[1].top+speed[1]; if (keys[3] = 1) and (P[1].left>0) then P[1].left := P[1].left-speed[1]; if (keys[4] = 1) and (P[1].left<form1.Width-65-speed[1]) then P[1].left := P[1].left+speed[1]; end; |
nur da weiß ich nich wie ich speed deklariere.
villeicht hast du ja ne idee?
0xCC - Sa 20.05.06 15:33
benötigt ein timer mit interval 10:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TForm1.Timer1Timer(Sender: TObject); begin if GetForeGroundWindow = handle then begin if GetKeyState(byte('W'))and $8000 >0 then image1.Top:=image1.Top-10; if GetKeyState(byte('S'))and $8000 >0 then image1.Top:=image1.Top+10; if GetKeyState(byte('A'))and $8000 >0 then image1.Left:=image1.Left-10; if GetKeyState(byte('D'))and $8000 >0 then image1.Left:=image1.Left+10; end; end; |
NeoInDerMATRIX - Sa 20.05.06 18:52
Hallo,
dann brauchst du garkeine onKeyPress mehr!
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm4.CalcMovement; begin if key[1] then Image1.Left:=Image1.Left+10; if key[2] then Image1.left:=Image1.left-10; if key[3] then Image1.top:=Image1.top-10; if key[4] then Image1.top:=Image1.top+10; End; |
Und das rufst du for dem Rendern auf! Kann sein das du die Key Var sachen anpassen must! Weis leider nicht genau wie die deklariert sind.
Und wenn du das noch mit Movement Speed machen willst, dann machste noch ne var die nen durchlauf Timer beinhaltet.
Cu
Neo
P.S.: Habe mich mal eben hingesetzt und sowas in der art zusammen gebastelt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; StaticText1: TStaticText; procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormCreate(Sender: TObject); private KeyState: Array[0..255]of Boolean; KeyTime: Array[0..255]of Integer; Procedure onIdle(Sender: TObject; var Done: Boolean); Procedure CalcMovement; Procedure CheckPlace; public end;
var Form1: TForm1;
implementation
{$R *.dfm} Const km_BackSlash = 8; km_TAB = 9; km_Return = 13; km_Shift = 16; km_Ctrl = 17; km_Alt = 18; km_Break = 19; km_ESC = 27; km_Lehrtaste = 32; km_ScreenUp = 33; km_ScreenDown = 34; km_End = 35; km_Home = 36; km_Left = 37; km_Up = 38; km_Rigth = 39; km_Down = 40; km_Print = 44; km_Ins = 45; km_Del = 46; km_0 = 47; km_1 = 48; km_2 = 49; km_3 = 50; km_4 = 51; km_5 = 52; km_6 = 53; km_7 = 54; km_8 = 55; km_9 = 56; km_A = 65; km_B = 66; km_C = 67; km_D = 68; km_E = 69; km_F = 70; km_G = 71; km_H = 72; km_I = 73; km_J = 74; km_K = 75; km_L = 76; km_M = 77; km_N = 78; km_O = 79; km_P = 80; km_Q = 81; km_R = 82; km_S = 83; km_T = 84; km_U = 85; km_V = 86; km_W = 87; km_X = 88; km_Y = 89; km_Z = 90; km_WinLeft = 91; km_WinRigth = 92; km_WinKontect =93; km_NUM0 = 96; km_NUM1 = 97; km_NUM2 = 98; km_NUM3 = 99; km_NUM4 = 100; km_NUM5 = 101; km_NUM6 = 102; km_NUM7 = 103; km_NUM8 = 104; km_NUM9 = 105; km_NUMMul = 106; km_NUMPlus = 107; km_NUMMinus = 109; km_NUMKomma = 110; km_NUMDiv = 111; km_F1 = 112; km_F2 = 113; km_F3 = 114; km_F4 = 115; km_F5 = 116; km_F6 = 117; km_F7 = 118; km_F8 = 119; km_F9 = 120; km_F10 = 121; km_F11 = 122; km_F12 = 123; km_NUMLook = 144; km_Roll = 145; km_Plus = 187; km_Komma = 188; km_Minus = 189; km_Punkt = 190; km_Raute = 191; km_Fragezeichen = 219; km_Dead0 = 220; km_Dead2 = 221; km_Dead1 = 226;
km_MouseLeft = 246; km_MouseRigth = 247; km_MouseUp = 248; km_MouseDown = 249; km_MouseButtonLeft = 250; km_MouseButtonRigth = 251; km_MouseButtonMiddle = 252; km_MouseWheelUp = 253; km_MouseWheelDown = 254; km_MouseWheelPressed = 255;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin If KeyState[Key] Then KeyTime[Key]:=KeyTime[Key] + 1 Else Begin KeyState[Key]:=TRUE; KeyTime[Key]:=1; End; end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin KeyState[Key]:=FALSE; KeyTime[Key]:=0; end;
procedure TForm1.FormCreate(Sender: TObject); begin KeyPreview:=TRUE; Application.onIdle:=onIdle; end;
Procedure tForm1.CalcMovement; Begin If KeyState[km_S] Then Button1.Top:=Button1.Top + KeyTime[km_S]; If KeyState[km_W] Then Button1.Top:=Button1.Top - KeyTime[km_W]; If KeyState[km_A] Then Button1.Left:=Button1.Left - KeyTime[km_A]; If KeyState[km_D] Then Button1.Left:=Button1.Left + KeyTime[km_D]; End;
Procedure tForm1.CheckPlace; Begin If Button1.Left<5 Then Button1.Left:=5; If Button1.Left+Button1.Width>Width - 10 Then Button1.Left:=Width - Button1.Left - 10; If Button1.Top<5 Then Button1.Top:=5; If Button1.Top + Button1.Height>Height - 10 Then Button1.Top:=Height - Button1.Height - 10; End;
Procedure tForm1.onIdle(Sender: TObject; var Done: Boolean); Begin CalcMovement; CheckPlace; StaticText1.Caption:='X = ' + IntToStr(Button1.Left) + ' | Y = ' + IntToStr(Button1.Top); End;
end. |
Das geht bei mir bis auf die Kollision rechts und unten! Aber darn solltest du sehen wie du das recht simpel machen kannst! Ohne Polling.
Joachim Knutson - Sa 20.05.06 20:52
NeoInDerMATRIX hat folgendes geschrieben: |
Hallo,
P.S.: Habe mich mal eben hingesetzt und sowas in der art zusammen gebastelt.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; StaticText1: TStaticText; procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormCreate(Sender: TObject); private KeyState: Array[0..255]of Boolean; KeyTime: Array[0..255]of Integer; Procedure onIdle(Sender: TObject; var Done: Boolean); Procedure CalcMovement; Procedure CheckPlace; public end;
var Form1: TForm1;
implementation
{$R *.dfm} Const [...]
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin If KeyState[Key] Then KeyTime[Key]:=KeyTime[Key] + 1 Else Begin KeyState[Key]:=TRUE; KeyTime[Key]:=1; End; end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin KeyState[Key]:=FALSE; KeyTime[Key]:=0; end;
procedure TForm1.FormCreate(Sender: TObject); begin KeyPreview:=TRUE; Application.onIdle:=onIdle; end;
Procedure tForm1.CalcMovement; Begin If KeyState[km_S] Then Button1.Top:=Button1.Top + KeyTime[km_S]; If KeyState[km_W] Then Button1.Top:=Button1.Top - KeyTime[km_W]; If KeyState[km_A] Then Button1.Left:=Button1.Left - KeyTime[km_A]; If KeyState[km_D] Then Button1.Left:=Button1.Left + KeyTime[km_D]; End;
Procedure tForm1.CheckPlace; Begin If Button1.Left<5 Then Button1.Left:=5; If Button1.Left+Button1.Width>Width - 10 Then Button1.Left:=Width - Button1.Left - 10; If Button1.Top<5 Then Button1.Top:=5; If Button1.Top + Button1.Height>Height - 10 Then Button1.Top:=Height - Button1.Height - 10; End;
Procedure tForm1.onIdle(Sender: TObject; var Done: Boolean); Begin CalcMovement; CheckPlace; StaticText1.Caption:='X = ' + IntToStr(Button1.Left) + ' | Y = ' + IntToStr(Button1.Top); End;
end. |
Das geht bei mir bis auf die Kollision rechts und unten! Aber darn solltest du sehen wie du das recht simpel machen kannst! Ohne Polling. |
cool thx, jetz hab ich hinbekommen. das leuchtet soweit ein.
(lustige sache mit dem StaticText1. :wink: )
also weißt du nich genau woran das liegt, dass er ganz rechts dann auf einmal wieder links erscheint?
NeoInDerMATRIX - Sa 20.05.06 21:09
Ist nur nen rechen oder prüf fehler den ich so auf die schnelle nicht seh! Aber ich denke das bekommst du mit ein wenig testen hin! Ach übrigens das ist so ungefair der source denn ich dir auch schon am anfang gezeigt habe. Nur das hier noch kein Mappen der Tasten gemacht wird. Und vergess nicht das du sicher auch noch etwas in der Time sache anpassen must!
Joachim Knutson - Sa 20.05.06 21:40
NeoInDerMATRIX hat folgendes geschrieben: |
Ist nur nen rechen oder prüf fehler den ich so auf die schnelle nicht seh! Aber ich denke das bekommst du mit ein wenig testen hin! Ach übrigens das ist so ungefair der source denn ich dir auch schon am anfang gezeigt habe. Nur das hier noch kein Mappen der Tasten gemacht wird. Und vergess nicht das du sicher auch noch etwas in der Time sache anpassen must! |
ja das werd ich machen. nichts geht übers testen... :D
danke dafür.
Joachim Knutson - Mo 22.05.06 17:16
ich habe zwar nun schon sehr sehr (sehr) lange getestet, aber das nicht meinen bedürfnissen anpassen können.
also das größte problem ist:
je länger man auf eine taste drückt, desto schneller wird er. (d.h. irgendwann ist er so schnell, dass man ihn kaun noch sieht.)
sieht da jemand ne lösung? bin echt am ende, kann nich mehr.
ich denke ja, dass es an folgender prozedur liegt (bzw. die makierte zeile):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| Procedure tForm4.CalcMovement; Begin If KeyState[km_S] Then -------> Image1.Top:=Image1.Top + KeyTime[km_S]; <------- If KeyState[km_W] Then -------> Image1.Top:=Image1.Top - KeyTime[km_W];<------- If KeyState[km_A] Then -------> Image1.Left:=Image1.Left - KeyTime[km_A];<------- If KeyState[km_D] Then -------> Image1.Left:=Image1.Left + KeyTime[km_D];<------- End; |
NeoInDerMATRIX - Mo 22.05.06 18:03
Hallo,
Du must dazu den KeyTime ein maximal wert zuordnen und dies vor jedem Verwenden Prüfen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| Procedure tForm4.CalcMovement; Var Lauf: Integer; Begin For Lauf:=0 to 255 do If KeyTime[Lauf]>10 Then KeyTime[Lauf]:=10; If KeyState[km_S] Then -------> Image1.Top:=Image1.Top + KeyTime[km_S]; <------- If KeyState[km_W] Then -------> Image1.Top:=Image1.Top - KeyTime[km_W];<------- If KeyState[km_A] Then -------> Image1.Left:=Image1.Left - KeyTime[km_A];<------- If KeyState[km_D] Then -------> Image1.Left:=Image1.Left + KeyTime[km_D];<------- End; |
Cu
Neo
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!