|
Antwort |
In diesem Tutorial werde ich erklären, wie man einen Snakeklon in Delphi programmiert. Am Ende dieses Tutorials kann ein Beispielcode heruntergeladen werden.
Die Grundlagen Zuerst muss geklärt werden, wie das ganze funktionieren wird. Das Spielfeld besteht aus einzelnen Feldern. Jedes Feld kann leer sein, oder einen Teil der Schlange, bzw. ein Stück Futter enthalten. Zum Speichern der einzelnen Felder wird ein zwei dimensionales Array genommen. Jedes Feld hat einen Index und kann folgende Werte beinhalten:
Code:
Alle Werte, die größer als 0 sind stellen einen Teil der Schlange da, wobei das Feld mit der höchsten Zahl (immer die Länge der Schlange) den Kopf darstellt. Dazu gleich mehr. Die folgende Abbildung zeigt die einzelnen Indizes der Felder, so wie sie später auch im Programm genutzt werden:
-1 -> Futter
0 -> ein leeres Feld >0 -> einen Teil der Schlange Die Schlange Nun müssen wir uns überlegen, wie die Position der einzelnen Schlangenteile am besten gespeichert wird. Ich will euch nun ein System erläutern, welches wir in diesem Tutorial nutzen werden und welches ich sehr gut finde. Gehen wir mal davon aus, dass die Schlange beim Start eine Länge von 5 hat, im Feld mit dem Index (0/0) startet und die aktuelle Laufrichtung (auch dazu gleich mehr) nach unten führt. Also wird zuerst in das Feld (0/0) die Länge der Schlange, also der Wert 5 gespeichert. Nun folgt eine Routine, die bei jeder Bewegung ausgeführt wird. Diese geht alle Felder durch und verringert jeden Wert, der höher als 0 ist um 1. In Feld (0/0) ist nun also der Wert 4 gespeichert. Da unsere Schlange nach unten geht müssen wir noch die neue Position für den Kopf setzen. Dies wäre das Feld (0/1), welches nun den Wert 5 erhält. Wenn wir nun die Routine von eben wieder durchlaufen lassen, dann wäre im Feld (0/0) der Wert 3, im Feld (0/1) der Wert 4 gespeichert und der neue Kopf würde (falls die Laufrichtung nicht geändert wird) im Feld (0/2) wieder mit dem Wert 5 gespeichert werden. Nach einiger Zeit wäre der Wert im Feld (0/0) bei 0 angekommen, also die Schlänge wäre nicht mehr auf diesem Feld. Bei einer Länge von 5 hätte wir dann 5 Felder mit Werten höher als 0. Das Feld mit dem Kopf hat den Wert 5, die dahinterliegenden Felder die Werte 4 bis 1. Da das Feld mit dem Wert 1 nach der Routine immer wegfällt und der Kopf neu gesetzt wird kommt eine Bewegung zustande. Die Laufrichtung Die Laufrichtung, sowohl auf der X als auch auf der Y Achse werden wir in eine Variable vom Typ "TPoint" speichern. Die Variable heißt "richtung" und kann folgende Wertkombinationen enthalten. Der erste Wert steht in "richtung.X", der zweite in "richtung.Y":
Code:
Die Bewegung
( 0 / -1) -> nach oben
( 1 / 0) -> nach rechts ( 0 / 1) -> nach unten (-1 / 0) -> nach links Mit Hilfe der Laufrichtung können wir die neue Position des Kopfs berechnen. Dazu benötigen wir aber auch noch die alte, bzw. aktuelle Position des Kopfs. Diese könnte man natürlich jedes Mal aus dem Array heraussuchen, jedoch ist es leichter und schneller, wenn man diese auch in einer Variable vom Typ "TPoint" speichern würde. Nennen wir die Variable mal "kopf". Ist der Kopf der Schlange auf Feld (1/2), so hat "kopf.X" den Wert 1 und "kopf.Y" den Wert 2. Nun werden die Werte aus "richtung" zu den Werten aus Kopf addiert. Dazu ein Beispiele für einen Schritt nach oben, die anderen Richtung laufen gleich ab, ausgehend von dem Feld (1/2):
Delphi-Quellcode:
Der Kopf hat nun die Position (1/1), also ein Feld höher als vorher.
// "richtung" -> (0/-1)
kopf.X = kopf.X + richtung.X kopf.Y = kopf.Y + richtung.Y kopf.X = 1 + 0 kopf.Y = 2 + (-1) kopf.X = 1 kopf.Y = 2 - 1 kopf.X = 1 kopf.Y = 1 Die Ausgabe Um das Spiel auch sehen zu können, brauchen wir eine Fläche, wo wir drauf zeichnen können. Dazu nehmen wir eine "TPaintBox". Für jedes Feld zeichnen wir ein Kästchen. Würden wir für die leeren Felder die Farbe Schwarz (auf dem Bild Grau), für die Schlange Grün und für das Futter Rot nehmen, so könnte die Ausgabe im Spiel folgendermaßen aussehen (die Zaheln werden im Spiel natürlich nicht zu sehen sein, sollen jedoch nun auf der Abbildung die Werte verdeutlichen): Der Code Nun aber genug Theorie, kommen wir zum Code. Startet Delphi oder erstellt ein neues Projekt. Plaziert nun eine "TPaintBox" (Komponentenregister "System") mit einer Breite und Höhe von jeweils 250 auf der Form. Setzt nun einen "TTimer" auf die Form und setzt bei "Interval" den Wert 100 und bei "Enabled" den Wert "False". Nun brauchen wir noch 5 "TButtons". Der erste wird zum Starten des Spiels genutzt, die anderen sind für den Wechsel der Laufrichtung zuständig. Legt nun am Anfang des Codes folgende Konstanten an:
Delphi-Quellcode:
In der Konstante "farben" werden die Farben zum späteren Darstellen der leeren Felder, der Schlange und des Futters gespeichert. In "raster" steht, wie viele Pixel ein Feld breit und hoch ist. In "breite" und "hoehe" wird angegeben, wie viele Felder es gibt. Wir nehmen ein Fläche von 25x25 Feldern. Nun zu den Variablen. Diese werden kommen in den "private" Abschnitt:
...
uses... const farben: Array [0..2] of TColor = (clBlack, clLime, clRed); raster = 10; breite = 24; //0 bis 24 -> 25 hoehe = 24; type TForm1 = class(TForm) ...
Delphi-Quellcode:
"map" ist unser Spielfeld, wie vorhin besprochen. Darin werden die verschiedenen Werte der einzelnen Felder gespeichert. In "kopf" und "futter" wird die aktuelle Position des Kopfes der Schlange und des Futters gespeichert. In "richtung" die Laufrichtung, wie oben besprochen. In "laenge" wird die die aktuelle Länge der Schlange gespeichert und in "ende", ob das Spiel noch läuft oder nicht. Nun definieren wir mehrere Prozeduren, die gleich jeweils erläutert werden, auch in den "private" Abschnitt unter die Variablen:
...
private { Private-Deklarationen } map: Array [0..breite] of Array [0..hoehe] of Integer; kopf, richtung, futter: TPoint; laenge, punkte: Integer; ende: Boolean; bmp: TBitmap; public { Public-Deklarationen } end; ...
Delphi-Quellcode:
Die Prozedur "enable_buttons" sorgt dafür, dass die Richtungswechsel-Buttons bspw. nur aktiv sind, wenn das Spiel auch läuft, als Parameter wird angegeben, ob die Buttons aktiv ("True") oder nicht aktiv ("False") sein sollen. Die Prozeduren werden unter dem Implementationsteil geschrieben:
...
procedure enable_buttons(status: Boolean); procedure spiel_ende; procedure neues_futter; procedure paint_map; procedure calc_snake; public { Public-Deklarationen } end; ...
Delphi-Quellcode:
Unter "enable_buttons" kommt die Prozedur "spiel_ende". Diese wird beim Ende des Spiels aufgerufen. Die einzelnenen Schritte in der Prozedur sollten (später jedenfalls) klar sein:
...
implementation {$R *.dfm} procedure TForm1.enable_buttons(status: Boolean); begin Button2.Enabled := status; Button3.Enabled := status; Button4.Enabled := status; Button5.Enabled := status; end; ...
Delphi-Quellcode:
Nun kommt die Prozedur "neues_futter". Diese berechnet so lange eine neue zufällige Futterposition, bis ein freies Feld gefunden wurde. Danach enthält dieses Feld den Wert "-1":
...
procedure TForm1.spiel_ende; begin ende := True; Timer1.Enabled := False; enable_buttons(False); Button1.Enabled := True; end; ...
Delphi-Quellcode:
Die nächste Prozedur, "paint_map", ist für die Ausgabe zuständig. Mit zwei Schleifen wird die gesammte "map" durchgegangen und für jedes Feld die passende Farbe aus dem Array "farben" herausgesucht. "-1" war das Futter, "0" ein leeres Feld und alles andere ein Teil der Schlange. Dann wird an der entsprechenden Position ein Kästchen mit der zuvor ermittelten und in "col" gespeicherten Farbe geszeichnet:
...
procedure TForm1.neues_futter; begin futter := Point(Random(breite), Random(hoehe)); while map[futter.X, futter.Y]<>0 do futter := Point(Random(breite), Random(hoehe)); map[futter.X,futter.Y] := -1; end; ...
Delphi-Quellcode:
Die letzte (selbsgeschriebene) Prozedur, "calc_snake", ist für das Berechnen der neuen Kopfposition und das verringern aller Werte in "map" um eins zuständig. Eine genauere Erklärung kommt nach dem Code:
...
procedure TForm1.paint_map; var i, j: Integer; col: TColor; begin for i := 0 to breite do for j := 0 to hoehe do begin case map[i, j] of -1: col := farben[1]; 0: col := farben[0]; else col := farben[2]; end; PaintBox1.Canvas.Brush.Color:=col; PaintBox1.Canvas.FillRect(Rect(i*raster, j*raster, (i+1)*raster, (j+1)*raster)); end; end; ...
Delphi-Quellcode:
Zuerst wird mit zwei Schleifen jedes Feld, welches einen Wert höher als 0 enthält um eins verringert. "Dec(a)" ist eine kürzere Schreibweise für "a := a-1". Diese Routine wurde vorhin schon im Abschnitt "Die Schlange" erläutert. Nun werden, wie in "Die Laufrichtung" beschrieben, die Werte aus "richtung" zu den aktuellen Werten aus "kopf" addiert. Die Funktion "inc(a, b)" ist eine kürzere Schreibweise für "a := a+b;". Danach wird geprüft, ob der Kopf den Rand oder einen Teil der Schlange berührt hat und gegebenenfalls das Spiel beendet und eine entsprechende Meldung ausgegeben. Dann wird geprüft, ob der Kopf auf dem Feld mit dem Futter steht. Wenn ja, dann wird die Länge der Schlange um eins erhöht und eine neue Futterposition errechnet. Zum Schluss wird der Kopf an die neue Position gesetzt. Gebt nun dem "Button1" die Caption "Start" und klickt doppelt drauf um in das "OnClick"-Ereignis zu gelangen. Dort schreibt ihr folgenden Code rein:
...
procedure TForm1.calc_snake; var i, j: Integer; begin for i := 0 to breite do for j := 0 to hoehe do if map[i, j]>0 then Dec(map[i, j]); Inc(kopf.X, richtung.X); Inc(kopf.Y, richtung.Y); if (kopf.X<0) or (kopf.X>breite) or (kopf.Y<0) or (kopf.Y>hoehe) then begin spiel_ende; ShowMessage('Sie haben den Rand berührt!'); end; if (map[kopf.X, kopf.Y]>0) and (not ende) then begin spiel_ende; ShowMessage('Sie haben sich selbst gebissen!'); end; if (kopf.X=futter.X) and (kopf.Y=futter.Y) then begin Inc(laenge); neues_futter; end; map[kopf.X, kopf.Y] := laenge; end; ...
Delphi-Quellcode:
Nun eine Erklärung des Codes. Der Startbutton wird deaktiviert, dann wird mit einer Schleife die gesamte "map" auf den Wert "0" gesetzt. Als nächstes wird die Startposition des Kopfes angegeben. "kopf := Point(x, y);" ist dabei eine kürzere Schreibweise für "kopf.X := x; kopf.Y := y". Die Länge der Schlange wird auf 5 und die Laufrichtung "nach unten" gesetzt. Nun wird die erste Position des Kopfs in "map" eingetragen, dann eine neue Futterposition berechnet und das Spiel wird ausgegeben. Zum Schluss werden die Richtungswechsel-Buttons aktiviert und der Timer für das Spiel gestartet. Nun kommt der Code für den Timer. Klickt doppelt auf "Timner1" und fügt folgenden Code in dessen "OnTimer"-Ereignis ein:
...
procedure TForm1.Button1Click(Sender: TObject); var i, j: Integer; begin Button1.Enabled := False; for i:=0 to breite do for j:=0 to hoehe do map[i, j] := 0; kopf := Point(1, 1); laenge := 5; richtung := Point(0, 1); map[kopf.X, kopf.Y] := laenge; neues_futter; paint_map; enable_buttons(True); ende := False; Timer1.Enabled := True; end; ...
Delphi-Quellcode:
Bei jedem Timeraufruf wird die Prozedur "calc_snake" aufgerufen. Ist das Spiel noch nicht zu Ende, so wird die Ausgabe gezeichnet. Diese Abfrage ist trotz deaktivieren des Timers bei Spielende notwendig, da sonst nach Ende noch ein Schritt gezeicht wird. Nun kommen die Richtungswechsel-Buttons. Gebt "Button2" die Caption "oben" und fügt folgenden Code in dessen "OnClick"-Ereignis ein:
...
procedure TForm1.Timer1Timer(Sender: TObject); begin calc_snake; if not ende then paint_map; end; ...
Delphi-Quellcode:
Die "If"-Abfrage vor dem Setzen der neuen Richtung ist dazu da um einen direkten Richtungswechsel zu verhindern. So ist es bspw. nicht Möglich während man nach unten läuft die Richtung nach oben zu ändern. "Button3" bekommt die Caption "links" und folgenden Code:
...
procedure TForm1.Button2Click(Sender: TObject); begin if richtung.Y=0 then richtung := Point(0, -1); end; ...
Delphi-Quellcode:
"Button4" die Caption "rechts" und folgenden Code:
...
procedure TForm1.Button3Click(Sender: TObject); begin if richtung.X=0 then richtung := Point(-1, 0); end; ...
Delphi-Quellcode:
Und "Button5" die Caption "unten" und folgenden Code:
...
procedure TForm1.Button4Click(Sender: TObject); begin if richtung.X=0 then richtung := Point(1, 0); end; ...
Delphi-Quellcode:
Zu guter Letzt klickt ihr noch doppelt auf die "Form1" und schreibt in das "OnCreate"-Ereignis folgenden Code:
...
procedure TForm1.Button5Click(Sender: TObject); begin if richtung.Y=0 then richtung := Point(0, 1); end; ...
Delphi-Quellcode:
Der Befehl "Randomize" sorgt dafür, dass die Zufallszahlen (bei der Futterposition) auch wirklich Zufällig sind und sich nicht bei jedem Start wiederholen.
...
procedure TForm1.FormCreate(Sender: TObject); begin Randomize; end; ... Ende Wenn ihr alles richtig gemacht habt, sollte sich das Spiel nun kompilieren lassen. Falls ihr noch einen Punktezähler einbauen wollt, so definiert am Anfang eine Integervariable, die er dann beim Start "Button2" auf 0 setzt. Immer wenn nun in "calc_snake" sie Länge der Schlange um eins erhöht wird, könnt ihr auch euren Punktezähler um einen beliebigen Wert erhöhen und diesen dann bspw. in einem Label ausgeben. Zu Beginn habe ich Konstanten gewählt um die Rater und Spielfeldgröße anzugeben. Dadurch ist es Problemlos möglich die Spielfeldgröße zu ändern. Tragt dazu einfach neue Werte in "breite", "hoehe" und "raster" ein und passt die Größe der Paintbox an. Die könnt ihr folgendermaßen errechnen: "(breite+1)*raster" und die Höhe entsprechend auch. Download des Beispielcodes: snake_src.zip (1.99Kb) MfG Pr0g |
|
#51
habs erstmal hinbekommen....aber diese procedure wählt ja nur die buitton an...kann man die damit auch gleich , quasi "direkt" bedienen?
|
Zitat |
FreePascal / Lazarus |
#52
Du kannst natürlich den Code in den Buttonevents auslagern und die ausgelagerten Prozeduren dann "direkt" aufrufen.
|
Zitat |
|
#53
um da nen punktezähler einzubauen muss ich ja theoretisch einfach nur die anzahl ausummieren die die schlange mit den futterpunkten übereinstimmt
Delphi-Quellcode:
oder ist das so abwägig?... i wie kommen da höchst dumme punktzahlen raus...
if (kopf.X=futter.X) and (kopf.Y=futter.Y) then
begin edit1.text:=inttostr(punkte); Inc(laenge); neues_futter; [b]punkte:=punkte+1;[/b] end; |
Zitat |
|
#54
i packs net wenn ich des ganze einfach beim futter erschaffen mit rein packe dann gehts trotzdem ent, aber eig muss i ja nur zählen wieoft futter erschaffen wird-1... hmm
|
Zitat |
|
#55
ich bin neu hier und auch beim Programmieren mit Delphi.
Ich benutze Lazarus Für Einsteiger ist richtig gut erklärt und nachvollziehbar. Am Anfang konnte ich kein Bild kriegen, aber nach copy/paste von source code, ging das. Allerdings kann ich die Schlange nicht steuern, weder mit den Buttons noch mit den Pfeiltasten Kann mir jemand dabei helfen? Vielen Dank! |
Zitat |
Delphi 12 Athens |
#56
Du musst die Eigenschaft Keypreview
im Formular aktivieren! Dann kannst du dir im KeyDownEvent vom Formular die letzten Gedrückte Pfeiltaste merken.
Andreas
|
Zitat |
|
#57
Danke für die schnelle Antwort, allerdings hat sich nichts geändert. Ich kann leider nicht finden, wo der Fehler sein kann.
object Form1: TForm1 Left = 361 Height = 335 Top = 139 Width = 484 Caption = 'Form1' ClientHeight = 335 ClientWidth = 484 KeyPreview = True OnCreate = FormCreate OnKeyDown = FormKeyDown LCLVersion = '1.8.0.6' Wie Du es beschrieben hast, habe ich in den Eigenschaften der Form das geändert und auch die Methode FormKeyDown verknüpft. Das ist die Implementation der Buttons und von FormKeyDown: procedure TForm1.Button2Click(Sender: TObject); begin if richtung.Y=0 then richtung :=Point(0,-1); end; procedure TForm1.Button3Click(Sender: TObject); begin if richtung.X=0 then richtung:=Point(1, 0); end; procedure TForm1.Button4Click(Sender: TObject); begin if richtung.X=0 then richtung:=Point(1,0); end; procedure TForm1.Button5Click(Sender: TObject); begin if richtung.Y=0 then richtung:= Point(0,1); end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin case Key of VK_UP: Button2.Click; VK_DOWN: Button5.Click; VK_RIGHT: Button4.Click; VK_LEFT: Button3.Click; end; end; Danke nochmal für Deine Hilfe! |
Zitat |
|
#58
Hallo QuickAndDirty,
Hier ist der Code ohne die Anwendungsdatei, sonst war zu gross zum Hochladen. Danke! |
Zitat |
Delphi 12 Athens |
#59
Ich hab nicht alles gefixt
nur 2 Zeilen oder so von hier aus müsstest es selbst können. 1. SpielEnde oder der startbutton initialisieren das Spiel nicht komplett! Das muss du dir mal ansehen 2. Der Quelltext ist komisch formatiert! 3. Das malen habe ich in das Paint Ereignis gelegt, so wie Gott es gewollt hat. Grundsätzliches zu spielen: Jedes spiel hat eine Gameloop das ist eine schleife die den status des Spiels iteriert.(OK heute baut keiner mehr solche Spiele, aber irgendwo in der eingekauften Engine ist sicher auch irgendeine mainloop) In deinem Fall ist Timer1 deine "Gameloop für Arme". Hier muss die komplette spiellogik stattfinden. Damit das möglich ist muss der timer auch laufen, bei start! 4. Hab im Startbutton den timer aktiviert. 5. als letzten aufruf im timer die darstellung von Paintbox für ungültig(invalide) erklärt. Paintbox rendert das Canvas dann neue sobald es geht. 6. Dein VK_LEFT war nicht in ordnung es lenkte nach rechts. Habs gerade gebogen 7. Else if in Calc Snake. Weil da kann immer nur eine von den sachen passieren.
Delphi-Quellcode:
unit unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; const farben: Array [0..2] of TColor = (clBlack, clLime, clRed); raster: integer = 10; breite: integer = 24; hoehe: integer = 24; type { TForm1 } TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; Timer1: TTimer; PaintBox1: TPaintBox; procedure Button1Click(Sender: TObject); procedure PaintBox1Paint(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); private { Private declarations } map: Array [0..24] of Array [0..24] of Integer; kopf, richtung, futter: TPoint; laenge, punkte: Integer; ende: Boolean; bmp: TBitmap; procedure enable_buttons(status: Boolean); procedure spiel_ende; procedure neues_futter; procedure paint_map; procedure calc_snake; public { Public declarations } end; var Form1: TForm1; implementation {$R *.lfm} procedure TForm1.enable_buttons(status: Boolean); begin Button2.Enabled := status; Button3.Enabled := status; Button4.Enabled := status; Button5.Enabled := status; end; procedure TForm1.spiel_ende; Begin ende:= True; Timer1.Enabled := False; enable_buttons(False); Button1.Enabled := True; end; procedure TForm1.neues_futter; begin futter := Point(Random(breite), Random(hoehe)); while map[futter.X, futter.Y]<>0 do futter:= Point(Random(breite), Random(hoehe)); map[futter.X,futter.Y] := -1; end; procedure TForm1.paint_map; var i,j: integer; col:TColor; begin for i := 0 to breite do for j := 0 to hoehe do begin case map[i, j] of -1: col := farben[1]; 0: col := farben[0]; else col := farben[2]; end; PaintBox1.Canvas.Brush.Color:=col; PaintBox1.Canvas.FillRect(Rect(i*raster, j*raster, (i+1)*raster, (j+1)*raster)); end; end; procedure TForm1.calc_snake; var i,j: Integer; begin for i := 0 to breite do for j := 0 to hoehe do if map[i,j]>0 then Dec(map[i,j]); Inc(kopf.X, richtung.X); Inc(kopf.Y, richtung.Y); if (kopf.X<0) or (kopf.X>breite) or (kopf.Y<0) or (kopf.Y>hoehe) then begin spiel_ende; ShowMessage('Sie haben den Rand berührt!'); end else if (map[kopf.X, kopf.Y]>0) and (not ende) then begin spiel_ende; ShowMessage('Sie haben sich selbst gebissen!'); end else if (kopf.X=futter.X) and (kopf.Y=futter.Y) then begin Inc(laenge); neues_futter; end; map[kopf.X, kopf.Y] := laenge; end; procedure TForm1.Button1Click(Sender: TObject); var i,j: Integer; begin Button1.Enabled := False; for i:=0 to breite do for j:=0 to hoehe do map[i,j] := 0; kopf:= Point(1,1); laenge:= 5; richtung:= Point(0,1); map[kopf.X,kopf.Y] := laenge; neues_futter; enable_buttons(True); Timer1.enabled := true; end; procedure TForm1.PaintBox1Paint(Sender: TObject); begin paint_map; end; procedure TForm1.Timer1Timer(Sender: TObject); begin calc_snake; Paintbox1.invalidate; if ende then Timer1.enabled := false; end; procedure TForm1.Button2Click(Sender: TObject); begin if richtung.Y=0 then richtung :=Point(0,-1); end; procedure TForm1.Button3Click(Sender: TObject); begin if richtung.X=0 then richtung:=Point(-1, 0); end; procedure TForm1.Button4Click(Sender: TObject); begin if richtung.X=0 then richtung:=Point(1,0); end; procedure TForm1.Button5Click(Sender: TObject); begin if richtung.Y=0 then richtung:= Point(0,1); end; procedure TForm1.FormCreate(Sender: TObject); begin randomize; end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin case Key of VK_UP: Button2.Click; VK_DOWN: Button5.Click; VK_RIGHT: Button4.Click; VK_LEFT: Button3.Click; end; end; end.
Andreas
Geändert von QuickAndDirty ( 8. Mai 2018 um 10:00 Uhr) |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |