|
![]() |
![]() Andorra 2D Tutorials Teil 3 - Die Spriteengine Einleitung Einleitung der Einleitung Endlich ist es soweit: Das Tutorial (auf jeden Fall das erste), wie man die Spriteengine verwendet ist fertig. In diesem Tutorial bauen wir die Demo aus dem letzten Tutorial um. Sprites - Was sind das? Sprite kommt aus dem Englischen und bedeutet eigentlich soviel wie "Elfe" oder "Kobold". In der Computergrafik wird damit jedoch ein Objekt bezeichnet, welches sich (einfach ausgedrückt) unabhängig von anderen Objekten bewegen kann. (Nähere Informationen gibt es im ![]() Bei Andorra 2D handelt es sich bei einem Sprite um ein abstraktes Objekt, welches sich zeichenen, bewegen und kollidieren kann. Diese Handlungen werden von einem übergeordnetem Objekt, der SpriteEngine (bei der es sich eigentlich selbst um ein Sprite Handelt) kontrolliert. Die Sprites müssen auch nicht Zwangsläufig ein bewegtes Objekt in der Spielwelt darstellen, die Sprites werden auch durchaus dazu verwendet um z.B. den Hintergrund zu zeichnen. Und nicht nur so viel - Man kann ganze Spiele basierend auf der SpriteEngine schreiben. Erzeugen der SpriteEngine Bisher haben wir 4 Objekte der Andorra Bibliothek benutzt:
Deklarieren Sie also eine neue Variable "AdSpriteEngine" des Typs "TSpriteEngine". Mit den folgenden zwei Zeilen, die Sie am Besten nach der Erzeugung der ImageList einfügen, wird die SpriteEngine erzeugt: AdSpriteEngine := TSpriteEngine.Create(AdDraw); Natürlich sollten Sie nicht vergessen, das Objekt am Ende wieder frei zu geben. Die Familie der Sprites Achtung: Sollten Sie sich nicht mit objektorientierter Programmierung auskennen, dann empfehle ich Ihnen erstmal sich damit ein wenig außeinander zu setzen (z.B. hier: ![]() Wie schon oben geschrieben muss ein Sprite nicht unbedingt ein Bild zeichnen. Es kann auch (die Spriteengine selbst ist das beste Beispiel dafür) etwas ganz abstraktes verwalten. Daher stehen verschiedene Spriteklassen zur Verfügung. Sie alle haben jedoch eins gemeinsam: Sie sind von TSprite, der Basisspriteklasse, abgeleitet.
![]() Lauf, Sprite, Lauf Nun möchten wir unseren Kerl aus dem letzten Tutorial als Sprite über den Bildschirm rennen lassen. Kramen Sie also am Besten das Ergebnis des letzten Tutorials noch einmal hervor. Wir ergänzen die Initialisierungsroutine nun am das Erzeugen der SpriteEngine und das Erzeugen eines TImageSprites mit dem namen "Figur":
Delphi-Quellcode:
Bevor Sie jetzt - ordentlich wie Sie sind - "Figur" im Destruktor freigeben möchten, lassen Sie es lieber gleich. Die Spriteengine kümmert sich ganz automatisch darum, dass alle Sprites freigegeben werden. Sollten Sie dennoch (dazu kommen wir später noch) ein Sprite vorzeitig freigeben wollen, so tun Sie dies über die Methode "Dead". Rufen Sie dennoch "Free" auf, so werden Sie mit Fehlermeldungen überhäuft.
.
. AdImageList.Restore; //SpriteEngine erzeugen AdSpriteEngine := TSpriteEngine.Create(nil); AdSpriteEngine.Surface := AdDraw1; //Eine Instanz von TImageSprite erstellen Figur := TImageSprite.Create(AdSpriteEngine); with Figur do begin //Hier gehts gleich weiter end; Nun haben wir ein "nacktes" TImageSprite erstellt - ohne Bild und ohne Animation. Das ändert sich im nächsten Schritt:
Delphi-Quellcode:
Von unseren vorher definierten Variablen (Pattern,StartPt,EndPt,Y,X,XSpeed) brauchen wir eigentlich nur noch XSpeed, da alle anderen Variablen schon ein Teil von TImageSprite sind.
//Hier geht es jetzt weiter
//Dem ImageSprite ein Bild zuweisen Image := AdImageList.Find('figur'); //Die Animation aktiv schalten AnimActive := true; //Die Animation soll sich ständig wiederholen AnimLoop := true; //Die Animation soll mit 15 FPS abgespielt werden AnimSpeed := 15; Die Renderprozedur schreiben wir wiefolgt um:
Delphi-Quellcode:
Folgende Dinge haben sich verändert:
if AdDraw.CanDraw then
begin AdPerCounter.Calculate; Figur.X := Figur.X + XSpeed*AdPerCounter.TimeGap/1000; if ((Figur.X > ClientWidth) and (XSpeed > 0)) or ((Figur.X < -96) and (XSpeed < 0)) then begin SetLine; end; AdDraw.ClearSurface(clBlack); AdDraw.BeginScene; //Die Bewegunsroutine aller Sprites in der Engine aufrufen AdSpriteEngine.Move(AdPerCounter.TimeGap / 1000); //Die Zeichenroutine aller Sprites aufrufen AdSpriteEngine.Draw; //Alle als mit "Dead" als "tot" makierten Sprites löschen AdSpriteEngine.Dead; AdDraw1.EndScene; AdDraw1.Flip; Done := false; end;
Nun müssen wir nur noch die "SetLine" Prozedur ein wenig überarbeiten:
Delphi-Quellcode:
Die Änderungen, welche hier gemacht wurden, sollten eigentlich klar sein.
procedure TForm1.SetLine;
begin XSpeed := -XSpeed; if XSpeed > 0 then begin Figur.AnimStart := 0; Figur.AnimStop := 7; Figur.X := -96; end else begin Figur.AnimStart := 8; Figur.AnimStop := 15; Figur.X := ClientWidth+96; end; Figur.Y := Random(ClientHeight-96); end; Und nun rennt unsere Figur - munter wie eh un jeh - über den Bildschirm. Unsere eigene Spriteklasse Klasse! Wenn wir uns diese Lösung, welche wir bis hier hin erarbeitet haben so anschauen, so müssen wir leider zugeben, dass diese mehr oder weniger "suboptimal" ist. Wäre es nicht schöner eine eigene Spriteklasse zu haben, die sich automatisch um alle Bewegungen kümmert? Dann wäre es auch kein Problem mehr, mehrere Figuren unabhängig von einander über den Bildschirm zu bewegen. Dies ist natürlich ohne weitere möglich - denn dafür ist die Spriteengine schließlich gedacht. Also deklarieren wir erstmal eine neue Klasse, die wir von TImageSprite oder von TImageSpriteEx (je nach Geschmack) ableiten. Die Deklaration sollte am besten oberhalb von der Deklaration von TForm1 geschehen (oder in einer eigenen Unit).
Delphi-Quellcode:
DoMove, DoDraw...
type
TFigur = class(TImageSprite) private protected procedure DoMove(TimeGap:double);override; public XSpeed:integer; constructor Create(AParent:TSprite);override; procedure SetLine; end; Schauen wir uns einmal an, was wir bis hier Deklariert haben: Im "public"-Bereich befindet sich die Variable "XSpeed" - diese ist equivalent zu der "XSpeed"-Variable, die wir vorher global deklariert hatten (übrigens sollten Sie diese globale Deklaration löschen...). Außerdem scheint nun auch die Prozedur "SetLine" in den Aufgabenbereich des Sprites gewandert zu sein. Dann befindet sich noch ein überschriebener Konstruktor im Repertoire von TFigur. Nun haben wir so ziemlich alle Dinge, die zur Figur gehören dort Ausgelagert. Doch wohin soll nun der Code, der die Bewegungen steuert und bisher in der Renderschleife stand? Dafür haben wir die ererbte Methode "DoMove" überschrieben. Andorra 2D bietet eine ganze Reihe von "Do"-Methoden, mit welchen Verhalten und Aussehen der Sprites angepasst werden kann:
Delphi-Quellcode:
Nun haben wir also das Grundgerüst einer neuen Klasse mit dem Namen "TFigur" erstellt. Wir können also getrost die Varible "Figur" vom Typ TFigur sein lassen.
//Hier kommt all der Code rein, der mit Bewegungen zu tun hat
procedure DoMove(TimeGap:double); //Hier landet der Code, welcher ausgeführt wird, wenn eine Kollision stattfindet (später ;-)) procedure DoCollision(Sprite:TSprite; var Done:boolean); //Hier landet der Code, welcher das Sprite zeichnet (noch später...) procedure DoDraw; Es fehlt nur noch die Implementierung:
Delphi-Quellcode:
Achtung: Damit der Code ordnungsgemäß funktioniert ist es zwingend notwendig, dass die AdSprites.pas der Version 0.1.5 durch die neue Version aus dem CVS-Repository ausgetauscht wird:
{ TFigur }
constructor TFigur.Create(AParent: TSprite); begin inherited; //Am Punkt (0;0) starten. X := 0; Y := 0; //XSpeed auf -150 setzten XSpeed := -150; end; procedure TFigur.DoMove(TimeGap: double); begin inherited; //Der Teil aus der Renderprozedur, der sich um die Bewegungen kümmert X := X + XSpeed*TimeGap; if ((X > Engine.SurfaceRect.Right) and (XSpeed > 0)) or ((X < -96) and (XSpeed < 0)) then begin SetLine; end; end; procedure TFigur.SetLine; begin //Bewegt die Figur in eine neue Ebene XSpeed := -XSpeed; if XSpeed > 0 then begin AnimStart := 0; AnimStop := 7; X := -96; end else begin AnimStart := 8; AnimStop := 15; X := Engine.SurfaceRect.Right+96; end; Y := Random(Engine.SurfaceRect.Right-96); end; ![]() Wenn Sie nun "Figur" als "TFigur" deklarieren und in FormCreate anstatt
Delphi-Quellcode:
Figur := TImageSprite.Create(AdSpriteEngine);
. .
Delphi-Quellcode:
schreiben, dann sollte das Ganze eigentlich funktionieren.
Figur := TFigur.Create(AdSpriteEngine);
with Figur do begin Image := AdImageList1.Find('figur'); AnimActive := true; AnimLoop := true; AnimSpeed := 15; XSpeed := -150; SetLine; end; Marathon Nun ist es natürlich ein bisschen wenig, nur eine Figur über den Bildschirm laufen zu lassen. Löschen Sie am Besten die Deklaration von "Figur" uns schreiben sie einfach:
Delphi-Quellcode:
Schon rennen 6 Männchen mit unterschiedlicher Geschwindigkeit über den Bildschirm.
for i := 0 to 5 do
begin with TFigur.Create(AdSpriteEngine) do begin Image := AdImageList1.Find('figur'); AnimActive := true; AnimLoop := true; AnimSpeed := 15; XSpeed := -(random(100)+50); SetLine; end; end; Den gesammten Sourcecode gibt es ![]() Aufgaben Bis hier her haben Sie es schon einmal Geschafft. Ich habe jetzt mal noch ein paar Aufgaben für Sie:
![]() Fazit Nun kennen Sie sich schon ein wenig mit der Spriteengine aus. Im nächsten Tutorial erwartet Sie dann: Wir werden eine alte DelphiX Demo nachbauen - dort bewegt man sich, als Kugel, durch eine karierte, mit Kugeln bevölkerte, Welt. Rammt man eine andere Kugel, so verschwindet diese. Natürlich "verbessern" wir die Demo anschließend ein wenig. Ich möchte hier nocheinmal darauf hinweisen, das das Spriteengine-System nicht von mir in dieser Form entwickelt wurde - es ist ein Nachbau des Spriteengine-Systems von DelphiX, wobei es natürlich an einigen Stellen verbessert wurde. Copyright und Lizenz (c) by Andreas Stöckel März 2007 Revision 2: Oktober 2007 Der Inhalt dieses Tutorials steht unter der ![]() [edit=Jelly]Auf Wunsch des Erstellers habe ich eine Version seines Tutorials neu aufgespielt... Mfg, Jelly[/edit]
"Sollen sich auch alle schämen, die gedankenlos sich der Wunder der Wissenschaft und Technik bedienen, und nicht mehr davon geistig erfasst haben als die Kuh von der Botanik der Pflanzen, die sie mit Wohlbehagen frisst." - Albert Einstein
|
Ansicht |
![]() |
![]() |
![]() |
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 |
![]() |
![]() |