Entwickler-Ecke
Delphi Tutorials - DelphiX einfache Bewegung einer Figur + PixelKollision
F34r0fTh3D4rk - Mo 27.06.05 12:01
Titel: DelphiX einfache Bewegung einer Figur + PixelKollision
DelphiX einfache Bewegung einer Figur + PixelKollision
So Leute, das ist mein 2. Tutorial, welches sich wiedermal um DelphiX dreht.
Jemand hat sich dieses Tutorial gewünscht und soll es auch bekommen :D
Fangen wir dann mal an.
(1). Komponenten platzieren und einstellen
- Platziert ein
DXDraw Objekt auf eurem Formular.
- Stellt dort
Align auf
alClient.
- Jetzt noch eine
DXImageList.
- Dort muss noch per doppelklick das
DXDraw ausgewählt werden (Bilder fügen wir später hinzu).
- Jetzt noch eine
DXSpriteEngine, dort das gleiche mit dem
DXDraw.
- Einen
DXTimer, mit
interval 0 (man kann auch andere Werte nehmen, um die FPS einzudämmen, aber so kommt man eben auf die höchste Framezahl und das ist für Kollisionen ganz nützlich).
- Als letztes noch ein
DXImput
(2). Die richtigen Animationen
- Für dieses Tutorial solltet ihr die beiligenden (Anhang) Animationen verwenden.
- Doppelklick auf das
DXImageList Objekt und wählt die Bilder aus dem anhang aus.
- Ordnet die Bilder in dieser Reihenfolge:
-das 2. Bild der Animation ist das Bild indem keine Bewegung stattfindet, also die Figur steht, von dem Bild gehen dann alle Bewegungen aus.
-
TransparentColor der Bilder muss auf
clFuchsia und
Transparent auf
true stehen
-
Patternwidthund
Patternheight stellen wir für unser Beispiel auf
19, das sind Breite un Höhe der einzelnen Bilder.
(2). Die Animation
- So, zu allererst eine neue Klasse:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| type TPlayer = class(TImageSprite) public procedure DoMove(MoveCount: Integer); override; procedure DoCollision(Sprite: TSprite; var Done: Boolean); override; end; |
-
DoMove wird unsere Bewegung.
-
DoCollision ist später für die Kollision wichtig.
- Nun zur eigentlichen Bewegung (sieht wilder aus, als es ist):
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:
| procedure TPlayer.DoMove(MoveCount: Integer); begin inherited DoMove(MoveCount); AnimStart := 1; AnimCount := 0; If (isup in GameForm.DXInput1.States) and not (isdown in GameForm.DXInput1.States) and not (isleft in GameForm.DXInput1.States) and not (isright in GameForm.DXInput1.States) then with Player1 do begin image := GameForm.DXImageList1.Items[0]; AnimStart := 0; AnimCount := image.patterncount; y := y - 1; end; If (isdown in GameForm.DXInput1.States) and not (isup in GameForm.DXInput1.States) and not (isleft in GameForm.DXInput1.States) and not (isright in GameForm.DXInput1.States) then with Player1 do begin image := GameForm.DXImageList1.Items[1]; AnimStart := 0; AnimCount := image.patterncount; y := y + 1; end; If (isleft in GameForm.DXInput1.States) and not (isright in GameForm.DXInput1.States) and not (isup in GameForm.DXInput1.States) and not (isdown in GameForm.DXInput1.States) then with Player1 do begin image := GameForm.DXImageList1.Items[2]; AnimStart := 0; AnimCount := image.patterncount; x := x - 1; end; If (isright in GameForm.DXInput1.States) and not (isleft in GameForm.DXInput1.States) and not (isup in GameForm.DXInput1.States) and not (isdown in GameForm.DXInput1.States) then with Player1 do begin image := GameForm.DXImageList1.Items[3]; AnimStart := 0; AnimCount := image.patterncount; x := x + 1; end; end; |
- Also nehmen wir das gewurschtel mal auseindander:
Delphi-Quelltext
1: 2: 3:
| inherited DoMove(MoveCount); AnimStart := 1; AnimCount := 0; |
- dann taucht 4 mal sowas hier auf,
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| If (isup in GameForm.DXInput1.States) and not (isdown in GameForm.DXInput1.States) and not (isleft in GameForm.DXInput1.States) and not (isright in GameForm.DXInput1.States) then with Player1 do begin image := GameForm.DXImageList1.Items[0]; AnimStart := 0; AnimCount := image.patterncount; y := y - 1; end; |
- erstmal wird abgefragt, ob nicht schon eine andere Richtungstaste gedrückt wurde, weil dann soll garnischt passieren, es soll nur eine gedrückt sein.
- Die Animation für die Bewegung nach Norden wird geladen (Bild nr 0).
- Dann wird das erste bild der aninmation auf 0 gesetzt.
- und die Animation auf ihre Maximale Länge.
- und das bild wird um die y achse verschoben (es bewegt sich nach oben).
- Aber wir haben noch etwas vergessen ! ja richtig, das Objekt zu erstellen.
- Wir brauchen also eine Globale Variable mit dem Namen
Player1, das Erstellen ist nicht so wild:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TGameForm.FormCreate(Sender: TObject); begin Player1 := TPlayer.Create(DXSpriteEngine1.Engine); with Player1 do begin image := dximagelist1.items[1]; AnimStart := 1; AnimCount := 0; AnimLooped := true; AnimSpeed := 1/150; width := image.width; height := image.height; x := GameForm.ClientWidth div 2 - width div 2; y := GameForm.ClientHeight div 2 - width div 2; z := 1; end; end; |
- Aber was hat das Z zu bedeuten, wir arbeiten doch nicht in 3d ?
- Nein, das Z zeigt an, in welcher reihenfolge die Bilder gezeichnet werden.
- Das mit dem kleinsten Z als erstes und das mit dem größten als letztes (befindet sich also oben).
- jetzt kommt unser Timer dran:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| procedure TGameForm.DXTimer1Timer(Sender: TObject; LagCount: Integer); begin DXInput1.Update; DXDraw1.Surface.Fill(clBlack); DXSpriteEngine1.Draw; DXSpriteEngine1.Move(20); DXDraw1.Flip; end; |
- Jetzt können wir unsere Figur schon wunderbar bewegen :D
(wenn man DoCollision auskommentiert oder die Prozedur schon hinzufügt)
(3). Kollisionsabfrage
- Jetzt kommt das schwerste von allem die KOLLISIONSABFRAGE
- Keine Angst, es ist einfacher als es klingt, denn es ist schon fast mit nur einem Befehl getan:
- Diese kommt ans Ende unserer
DoMove Procedure.
- Warum so wenig Code ?
- Weil DelphiX die Pixelkollision für uns erledigt.
- Nur Brauchen wir erstmal etwas zum Kollidieren:
Delphi-Quelltext
1: 2: 3: 4: 5:
| type TBall = class(TImageSprite) public procedure Contact; end; |
- Es reicht uns, wenn der Ball statisch ist, glaubt mir einfach, dass es auch funktioniert, wenn sich der Ball bewegt :D
- Als Bild könnt ihr euch schnell einen Ball malen, mit der hintergrundfarbe clfuchsia (R: 255, G: 0, B: 255);
- Der kommt dann in die ImageList an letzter Stelle, wird als Globale Variable Ball deklariert und wir erweitern unser
Form.Create:
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:
| procedure TGameForm.FormCreate(Sender: TObject); begin Player1 := TPlayer.Create(DXSpriteEngine1.Engine); with Player1 do begin image := dximagelist1.items[1]; AnimStart := 1; AnimCount := 0; AnimLooped := true; AnimSpeed := 1/150; width := image.width; height := image.height; x := GameForm.ClientWidth div 2 - width div 2; y := GameForm.ClientHeight div 2 - width div 2; z := 1; end; Ball := TBall.Create(DXSpriteEngine1.Engine); with Ball do begin image := dximagelist1.items[4]; x := 50; y := 50; width := image.width; height := image.height; end; end; |
- und nun zur Kollision:
Delphi-Quelltext
1: 2: 3: 4: 5:
| procedure TPlayer.DoCollision(Sprite: TSprite; var Done: Boolean); begin if Sprite is TBall then TBall(Sprite).Contact; end; |
- Das wars schon, es wird geprüft, ob das objekt ein Ball ist und dann die Kollision auf Seiten des Balls aufgerufen und zwar hier:
Delphi-Quelltext
1: 2: 3: 4:
| procedure TBall.Contact; begin beep; end; |
- Das
beep ist die Reaktion des Balls auf die Kollision.
- Natürlich können da jetzt alle möglichen sachen rein, zB der Ball stirbt, bzw er verschwindet, das sähe so aus:
Delphi-Quelltext
1: 2: 3: 4: 5:
| procedure TBall.Contact; begin beep; dead; end; |
- dazu müssen wir unseren Timer aber etwas erweitern:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TGameForm.DXTimer1Timer(Sender: TObject; LagCount: Integer); begin DXInput1.Update; DXDraw1.Surface.Fill(clBlack); DXSpriteEngine1.Dead; DXSpriteEngine1.Draw; DXSpriteEngine1.Move(20); DXDraw1.Flip; end; |
- Dead übernimmt das freigeben der gestorbenen Sprites
- so jetzt sind wir schon am ende angelangt, ich hoffe, es hat bei euch allen funktioniert, freue mich auf feedback, auch wenn manches etwas durcheinander geraten sein mag :lol:
Larus - Di 28.06.05 15:12
Thx erstmal das du ein Tut auf meine Bitte hin geschriebn hast 8)
retnyg - Di 28.06.05 15:24
hübsches progrämmlein, warum ist der source ned dabei ?
übrigens tritt keine kollision auf wenn man den rand des bildes überquert :twisted:
F34r0fTh3D4rk - Di 28.06.05 15:25
meinst du, das man nicht ausm bild rauslaufen darf ? das ist ja nun echt zu einfach :lol:
retnyg - Di 28.06.05 15:30
rück mal den source raus
F34r0fTh3D4rk - Di 28.06.05 15:31
den hab ich eben mal so dahin geschrieben steht auch hier im topic oben, aber wenn de willst dann schreib ich dir schnell nen neuen 8) (mit wandkollisionen)
F34r0fTh3D4rk - Di 28.06.05 15:56
so retnyg, hab jetzt ein SourceCode Beispiel hochgeladen :!:
Nochmal eine kleine Anmerkung:
wenn man auch diagonale Bewegungen haben will, dann muss man den Beweungsquellcode folgendermaßen abändern:
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:
| If (isup in MainForm.DXInput1.States) and not (isdown in MainForm.DXInput1.States) then with Player1 do begin image := MainForm.DXImageList1.Items[0]; AnimStart := 0; AnimCount := image.patterncount; y := y - 1; end; If (isdown in MainForm.DXInput1.States) and not (isup in MainForm.DXInput1.States) then with Player1 do begin image := MainForm.DXImageList1.Items[1]; AnimStart := 0; AnimCount := image.patterncount; y := y + 1; end; If (isleft in MainForm.DXInput1.States) and not (isright in MainForm.DXInput1.States) then with Player1 do begin image := MainForm.DXImageList1.Items[2]; AnimStart := 0; AnimCount := image.patterncount; x := x - 1; end; If (isright in MainForm.DXInput1.States) and not (isleft in MainForm.DXInput1.States) then with Player1 do begin image := MainForm.DXImageList1.Items[3]; AnimStart := 0; AnimCount := image.patterncount; x := x + 1; end; |
zwar fehlt uns dafür die animation, sieht aber trotzdem nicht alzu schlecht aus :D
retnyg - Mi 29.06.05 17:59
thx
wo kriege ich die komponenten, die ich brauche um den source zu verwenden ?
F34r0fTh3D4rk - Mi 29.06.05 18:16
welche delphi version hast du ?
retnyg - Mi 29.06.05 18:18
5 und 7, würd mir aber für die 7ner reichen
retnyg - Mi 29.06.05 18:22
ich meine diese Delphi-X units: DXSprite, DXInput, DXDraws, DXClass
F34r0fTh3D4rk - Mi 29.06.05 18:23
ja der link ist oben :D
(ist glaube ich sogar aktueller als meine version, sollte aber gehen :wink: )
retnyg - Mi 29.06.05 18:28
wahnsinn das zeuch ist ja uralt
, von anno 2000... gibts da nix neueres ?
F34r0fTh3D4rk - Mi 29.06.05 18:46
undelphix, musst du mal googlen, der erste link ist dann die unoffizielle delphix hp, da bekommst du undelphix auch für neue delphi versionen, ich weiß aber nicht ob mein tutorial damit 100% kompatibel ist, man kanns ja mal probieren :P
mimi - So 03.07.05 10:28
müste unDelphiX datet delphiX ja "nur" ab und bringt es von dx 7 auf 8
Darkscream - So 03.07.05 14:17
Also ich hab da mal ne frage undzwar, wenn ich das so mache wie im Tutorial steht (hmm oder wenn ich das so mache wie ich denke das es im Tutorial steht :D ) dann sieht das bei mir folgendermaßen aus
http://free.pages.at/warnant/Kollision.bmp xD und auch nur wenn ich mich bewege, denn wenn ich stehenbleibe ist das bomberman-mänchen komplett schwarz.
Ich verstehe halt nich wieso oO wäre für hilfe dankbar :)
MfG,
Darkscream
F34r0fTh3D4rk - So 03.07.05 14:57
du musst auf imagelist1 gehen dort die bilder auswählen und patternwidthund patternheight auf 19 stellen.
Hab ich das vergessen zu schreiben ? :lol:
Das ist die Breite und Höhe der einzelnen Bilder, die Anzahl der Bilder wird daraus automatisch berechnet :wink:
Darkscream - So 03.07.05 14:59
F34r0fTh3D4rk hat folgendes geschrieben: |
du musst auf imagelist1 gehen dort die bilder auswählen und patternwidthund patternheight auf 19 stellen.
Hab ich das vergessen zu schreiben ? :lol:
|
Sieht so aus ^_^ mal abgesehen davon das du vergessen hast zu sagen wo Collision; hingehört ^^
F34r0fTh3D4rk - So 03.07.05 15:15
danke für die hinweise, habs oben editiert :wink:
Maedhros - Do 21.07.05 08:51
Titel: höchst merkwürdig...
Hm.... komischerweise tut sich bewegungstechnisch gar nichts, wenn ich den Code so schreib wie oben im Tutorial. Ich hab es jetzt so weit nachgeschrieben, dass man die Figur bewegen kann, wenn man DoCollision auskommentiert. Fehlermeldungen bekomm ich keine.
Ich habe mir dann mal Deinen Sourcecode geladen, um mal zu vergleichen, ob da irgendwo Abweichungen sind, konnte aber nichts finden. Dein Source allerdings funktioniert bei mir.
Mit anderen Worten:
Der Source aus dem Totorial -> in neues Projekt kopiert -> keine Bewegung.
Der Source aus dem Totorial -> im eigenen Projekt ("as is") -> alles funktioniert
Woran kann das liegen, dass bei mir die Figur sich partout nicht bewegen will?
(Nachtrag: Mir fiel gerade auf, dass das Tutorial für DelphiX geschrieben ist. Ich habe bei mir UnDelphiX Version 6 installiert. Ist bei der Version etwas besonderes zu beachten?)
F34r0fTh3D4rk - Fr 22.07.05 13:38
wenn mein beispiel funktioniert, dann nein, ansonsten kA :wink:
vielleicht hast du eine einstellung bei den komponenten nicht übernommen ?
Maedhros - Sa 23.07.05 01:27
Die Komponenten auf dem Formular? Die sind exakt so eingestellt, wie es im Totorial geschrieben ist und auch in Deinem Sourcecode sind.
Vielleicht habe ich auch bei der Installation von UnDelphiX etwas verkehrt gemacht... gibt es da noch mehr zu tun, als nur die Packages zu installieren (sprich: Noch an anderen Stellen Einstellungen tätigen)?
Nachtrag:
Ich habe den Fehler jetzt gefunden: Der Code, der eigentlich dem Event "DXTimer1 OnTimer" hätte zugeordnet werden sollen, ist bei mir dem OnActivate zugewiesen gewesen. Klar dass es dann nicht funktioniert :oops:
Wie kam es zu dem Fehler? Aus Gewohnheit hab ich per Doppelclick auf die Komponente den Code für das Event hinzugefügt - bei einem normalen Timer haut das dann ja auch hin, nur der DXTimer weist dann automatisch "OnActivate" zu.
Nun hab ich schon eine Brille... :lol:
Noch mal ein Nachtrag:
Nun wo es funktioniert... bei der Animation fiel mir auf, dass die Figur doch tatsächlich flackert beim laufen. Ich habe dann die folgende Zeile auskommentiert (bei einer der vier Bewegungsrichtungen):
Quelltext
1: 2: 3: 4:
| procedure TPlayer.DoMove(MoveCount: Integer); ...
//AnimCount := image.patterncount; |
Man hat dann eine sich bewegende Figur ohne Animation, die aber dafür nicht flackert. Ich habe die Zeile dann mal modifiziert:
Quelltext
1:
| AnimCount := image.patterncount - 1; |
Kein Flackern mehr.
Also irgendwie scheint Delphi hier 5 Frames zu zählen statt der vier vorhandenen, wobei der fünfte dann einfach leer ist.
F34r0fTh3D4rk - Mo 25.07.05 12:56
das mit dem doppelklick kenne ich, das mit dem patterncount kann angehen, hab momentan kein delphi installiert wo ich delphix nutze, also kann ichs nicht testen, aber das flackern hatte ich auch, das -1 ist dann wohl richtig (vielleicht n rundungsfehler oder so)
mimi - Sa 30.07.05 17:10
eine ursache für das problem währe:
du setzt ständig den animation count bei jedem schritt, aber dies sollte nur bei der erstellung passieren damit ist es auch kein wunder das es bei deiner mod zeile kein fehler auftritt *G*
du solltes nur noch prüfen wenn -1 ereicht wurde sonst könnte es zu fehlern kommen !
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 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!