Tutorials
Andorra 2D Tutorials
Teil 1 - Initialisieren von Andorra 2D
Was ist Andorra 2D?
Andorra 2D ist eine neue 2D Engine für Delphi, Kylix und Freepascal/Lazarus. Eine 2D-Engine kümmert sich darum, Grafiken in möglichst schneller Abfolge auf den Bildschirm zu bringen, um damit zum Beispiel Spiele entwickeln zu können. Zudem sind mit einer 2D-Engine Effekte möglich, die mit den Standard Windows/Linux Grafikfunktionen nicht ohne weiteres möglich wären. Andorra 2D zeichnet sich durch folgende Features besonders aus:
- Verwendung verschiedener Grafikschnittstellen - DirectX oder OpenGL, beides ist möglich. Neue Grafikschnittstellen können einfach hinzugefügt werden - somit veraltet Andorra 2D nie!
- 3D-Beschleunigung Alle Grafikoperationen werden mit der 3D-Hardware gezeichnet, was einen enormen Geschwindigkeitsschub bringt.
- Spriteengine Andorra 2D beinhaltet eine Leistungsfähige Spriteengine mit der einfach Spiele erstellt werden können
- Canvas Andorra 2D beinhaltet eine hardwarebeschleunigte Zeichenfläche, die an das Delphi Canvas angelehnt ist.
Weitere Informationen gibt es auch auf der Website des Projekts: http://andorra.sf.net
Herunterladen und Installieren
Die nachfolgenden Schritte sind auf Delphi bezogen. Für Lazarus gibt es ein eigenes Tutorial, in dem diese dafür gezeigt werden.
Schritt 1: Herunterladen
Die aktuelle Version von Andorra 2D finden sie auf der Website unter "Downloads". Dort finden Sie auch eine Liste mit den Delphi/Lazarus Versionen, mit denen Andorra 2D kompatibel ist. Hier können Sie immer die neuste Version herunterladen.
Schritt 2: In das Delphi Verzeichnis kopieren
Kopieren Sie den Ordner "src" aus dem heruntergeladenen Archiv in das "lib" Verzeichnis Ihrer Delphi-Installation (z.B.: C:\Programme\Borland\BDS\4.0\lib\). Nennen Sie den Ordner in "Andorra" oder ähnliches um.
Schritt 3: Zum Bibliothekspfad hinzufügen
Fügen Sie ihrem Delphi diesen Pfad als Bibliothekspfad hinzu. (Meistens im Menü unter Tools/Optionen oder Tools/Umgebungsoptionen)
Nach diesen Schritten ist Andorra 2D einsatzbereit.
Nur noch ein Wort zu den Bibliotheken, die den fertig kompilierten Demo-Paketen beiliegen:
Die Bibliotheken (AndorraDX93D.dll etc.) wurden mit Turbo Delphi Explorer 2006 kompiliert. Wenn Sie diese mit einer anderen Delphiversion verwenden kann es zu Zugriffsverletzungen kommen, da zwischen Host und Bibliothek Objekte ausgetauscht werden und sich deren interner Aufbau über die verschiedenen Delphiversionen hinweg geändert haben kann. Deshalb rate ich Ihnen die Bibliotheken noch mal neu zu kompilieren.
Enthaltne Units
Möchten Sie eine Übersicht über alle verfügbaren Units erhalten, so besuchen Sie am besten:
http://andorra.sourceforge.net/docs/
Andorra 2D Initialisieren
Vorbereitungen...
Nun haben Sie Andorra 2D erfolgreich bei sich installiert und nun möchten Sie es garantiert auch ausprobieren. Dazu erstellen Sie eine neue "VCL-Formularanwendung" in Delphi.
Am besten speichern Sie das Projekt erst einmal in einen eigenen Ordner und kopieren die entsprechenden Andorra-DLLs in diesen hinein.
Fügen Sie jetzt folgende Units zur uses Klausel von Form1.pas (der Name kann abweichen, falls Sie die Datei unter einem anderem Namen gespeichert haben) hinzu:
- AdDraws: enthält den Hauptkern
- AdClasses: enthält noch einige Typen- und Klassendeklarationen, sowie Hilfsfunktionen, die oft benötigt werden.
- AdTypes: enthält Typendeklarationen
Die uses-Klausel sollte jetzt ungefähr so aussehen:
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, AdDraws, AdClasses, AdTypes;
Nun müssen Sie erst einmal ein Objekt des Typs TAdDraw deklarieren. Bei TAdDraw handelt es sich um das "Herzstück" von Andorra 2D. Es initialisiert und finalisiert die Engine und stellt die aktuelle Szene auf dem Bildschirm dar.
Fügen Sie also folgenden Code im "public" Abschnitt der Deklaration von TForm1 ein:
Nun muss eine Instanz des Objekts in OnFromCreate erzeugt werden. Wählen Sie dazu im Formulardesigner Form1 aus und doppelklicken Sie im Objektinspektor im Abschnitt "Ereignisse" hinter den Eintrag "OnCreate". Fügen Sie in den darauf hin im Codeeditor folgenden Code ein:
Dies erzeugt eine neue Instanz von TAdDraw. Das "self" ist eine Referenz auf Form1 und teilt der Engine somit mit, dass alle Grafikausgaben auf Form1 stattfinden sollen. Sie können stattdessen auch z.B. ein Panel aus der Objektpalette auf Form1 ziehen und anstatt "self" "Panel1" angeben. Dann landen die Grafikausgaben auf Panel1.
Außerdem muss die nun erzeugte Instanz von TAdDraw am Ende des Programms wieder freigegeben werden (d.h. der Speicher den Sie belegt wieder für andere Objekte zur Verfügung stellen). Fügen Sie deshalb in das "OnDestroy" Ereignis des Objekts Form1 folgenden Code ein:
Damit wird der Speicher, den die Engine verwendet, frei gegeben und die Engine selbst finalisiert.
Nun aber wieder zurück zur Initialisierung. Irgendwie müssen wir der Engine mitteilen, welches Plugin (also welche Grafikschnittstelle) sie verwenden soll. Dazu müssen wir den Eintrag "DllName" von AdDraw1 auf den Dateinamen des Plugins setzten. Der Name des Plugins für DirectX9 lautet "AndorraDX93D.dll". Sie können hier auch jedes andere Andorra 2D Plugin verwenden, es muss sich nur im Verzeichnis der Anwendung befinden, zum Beispiel das Plugin "AndorraOGL.dll", welches Andorra mit OpenGL verwendet.
Fügen Sie also die folgende Zeile zu OnCreate hinzu:
Damit wird automatisch die entsprechende DLL geladen.
Die Initialisierung...
Nun möchten wir Andorra 2D initialisieren. Dies funktioniert über die Funktion mit dem viel versprechenden Namen "Initialize". Diese Funktion versucht Andorra 2D zu initialisieren und gibt wenn dies erfolgreich passiert ist "true" zurück. Also erweitern wir die OnCreate Funktion wieder um ein paar Zeilen...
begin
// Hier geht's gleich weiter
end
else
begin
ShowMessage(AdDraw.GetLastError);
halt; //<-- Schließt die komplette Anwendung
end;
So weit wären wir schon mal. Wenn das Programm jetzt kompiliert und beim Ausführen keine Fehlermeldung erscheint ist Andorra 2D am laufen. Nur sehen tun wir davon (noch) nichts. Dies ist auch logisch, da noch überhaupt nichts ausgegeben wird.
Juhu, ein schwares Fenster
Nun müssen wir noch mal kurz zur Theorie.
Bei Spielen kommt es darauf an, das sich der Bildschirminhalt ständig ändert. Dazu kann man zu einer Quasiendlosschleife greifen, was dann in Pseudodelphicode so aussehen würde:
Berrechne_Bewegungen;
Zeichne;
if PressESC then abort := true;
until abort;
Close;
Nachteil dieser Methode ist, dass die CPU-Auslastung auf 100% steigt (und besonders bei Laptops macht sich der Nachteil eines höheren Stromverbrauchs bemerkbar, solche Programme sind also "Akku-Killer"). Die Leistung von CPU und GPU wirkt sich außerdem direkt auf die Anzahl der Schleifendurchläufe in einer Sekunde aus, was unterschiedliche Bewegungsgeschwindigkeiten hervorrufen kann (aber dieses Problem kann recht einfach gelöst werden, wie ich im nächsten Tutorial zeigen werde...)
Eine andere Möglichkeit ergibt sich in der Verwendung einer TTimer Komponente. Hier wird einfach ein Intervall in ms eingestellt und "Enabled" auf true gesetzt. In das Ereignis "OnTimer" würde man dann folgenden Code schreiben:
Zeichne;
Nachteil dieser Methode ist jedoch, dass die Hardware nicht vollständig ausgenutzt wird, da das Ereignis höchstens um die 50 mal die Sekunde ausgelöst wird.
Trotzdem allen "Nachteilen" möchten wir hier auf die erste Methode eingehen. Sie werden sich nun fragen, wo man diese Endlosschleife platzieren sollte: Intern hat jede VCL-Anwendung eine Schleife, die ungefähr wie im Folgenden dargestellt aufgebaut ist:
done: boolean;
begin
while not Application.Terminated do
begin
Application.ProcessMessages;
if Done = false then Application.OnIdle(done);
end;
end;
Wie wir sehen wird jeden Schleifendurchlauf eine Funktion namens "OnIdle" aufgerufen - und mit dieser können wir uns ganz einfach verknüpfen und dort unseren Code hinein schreiben.
Das funktioniert so:
Im "public" Teil der Deklaration von Form1 fügen wir folgende Zeile hinzu:
Nun fügen wir folgende Prozedur an unser Programm ein...
begin
if AdDraw.CanDraw then //Wenn überhaupt auf das AdDraw gezeichnet werden kann dann...
begin
//auch hier geht's bald weiter.
end;
Done := false; // Diese Zeile nicht vergessen, sonst wird der Code nur sporadisch ausgeführt.
end;
...und erweitern "OnCreate", an der Stelle wo der Kommentar "hier gehts gleich weiter" steht um folgende Zeile:
Damit wird das "OnIdle"-Event, welches wir von oben kennen mit unserer "Idle"-Funktion verknüpft.
Widmen wir uns nun der Idle Funktion, sozusagen das Herzstück unseres Programms. Hier landen alle Berechnungen und Zeichenoperationen der Engine.
Also fügen wir folgenden Code ein:
AdDraw.BeginScene;
//Zwischen diesen beiden Zeilen müssen später unsere Zeichenfunktionen stehen
AdDraw.EndScene;
AdDraw.Flip; //Präsentiert die gezeichneten Dinge auf dem Bildschirm.
Noch ein Wort zu dem AdDraw1.Flip. Wer schon mehr mit Delphi und dessen Canvas gearbeitet hat, dem wird auffallen, dass die Ausgabe zu flackern beginnt, wenn viele Grafikoperationen ausgeführt werden. Dies würde auch bei unserer Engine passieren, würden die Grafiksysteme, die dahinter stecken, nicht einen Trick anwenden: Das System verwaltet zwei Speicher. Alle Grafikausgaben landen in Speicher Nr.1. Beim Aufrufen der Flip-Funktion wird der Monitor mit den Daten aus Speicher Nr.1 gefüttert. Währenddessen ist nun Speicher Nr.2 zu dem Speicher geworden, in dem die Grafikausgaben landen. Beim nächsten aufrufen von "Flip" wird der Monitor mit den Daten aus Speicher Nr.2 gefüttert und Speicher Nr.1 wird zum Speicher für die Ausgaben. Dieses System nennt sich auch "Double-Buffering". Wer mehr dazu wissen will, sollte mal Wikipedia befragen.
Jetzt aber wieder zurück zu Delphi - wir drücken voller Erwartung die "F9" Taste oder klicken auf den grünen Pfeil in der Symbolleiste - wenn alles gut gelaufen ist sollten Sie ein schwarzes Fenster sehen. Puh - geschafft.
Der Setup-Dialog
Wenn Sie sich die Andorra 2D Demos angesehen haben, wird Ihnen sicherlich das Einstellungsfenster beim Programmstart aufgefallen sein. Diesen können Sie auch in Ihren eigenen Anwendungen einsetzen. Der Setupdialog kümmert sich dabei um die Auswahl der Bildschirmauflösung, zusätzlicher Pluginparameter und des Andorra 2D Grafikplugins.
Um den Setupdialog zu verwenden, binden Sie zunächst die Unit "AdSetupDlg" in die Uses-Klausel ein. Im OnCreate-Ereignis erstellen sie eine Variable "AdSetup" des Typs "TAdSetup":
var
AdSetup: TAdSetup;
begin
AdDraw := TAdDraw.Create(self);
AdSetup := TAdSetup.Create(AdDraw); //Erzeugt den Setupdialog und bindet ihn an die TAdDraw-Instanz
Die Klasse TAdSetup bietet Ihnen einige Einstellungsmöglichkeiten, mit denen Sie den Dialog an Ihre Bedürfnisse anpassen können:
//Die Größe des Bilderrahmens wird automatisch angepasst.
AdSetup.Image := 'logo1.png';
//Über "Sections" können Sie die angezeigten Sektionen des Dialogs Anpassen
AdSetup.Sections := [dlgResolution, dlgAdvancedOptions, dlgPlugin];
//Über "Title" können Sie den Titel des Dialogfensters Anpassen
AdSetup.Title := "CrashPoint - Das Experiment ist fehlgeschlagen"
//Über "Ini" können Sie dem Dialog ein TIniFile Objekt zuweisen,
//in dem die Einstellungen gespeichert werden
AdSetup.Ini := MyIni;
//Über "Path" können Sie den Pfad zu den Plugin-DLLs festlegen.
AdSetup.Path := './bin/dlls/andorra/'
Wenn Sie den Dialog anzeigen möchten, so können Sie dies über die Funktion "Execute" tun. Der Rückgabewert der Funktion beschreibt, ob der Benutzer auf die "OK"-Schaltfläche oder die "Cancel"-Schaltfläche geklickt hat.
//Anodrra Initialisieren
else
//Programm Beenden
Der Code
Als Referenz noch mal der Sourcecode, den wir im Verlauf des Tutorials erstellt haben:
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, AdDraws, AdClasses, AdTypes;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private-Deklarationen }
public
AdDraw:TAdDraw;
procedure Idle(Sender:TObject;var Done:boolean);
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
AdDraw := TAdDraw.Create(self);
AdDraw.DllName := 'AndorraDX93D.dll';
if AdDraw.Initialize then
begin
Application.OnIdle := Idle;
end
else
begin
ShowMessage(AdDraw.GetLastError);
halt;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
AdDraw.Free;
end;
procedure TForm1.Idle(Sender: TObject; var Done: boolean);
begin
if AdDraw.CanDraw then
begin
AdDraw.ClearSurface(clBlack);
AdDraw.BeginScene;
//Your code here
AdDraw.EndScene;
AdDraw.Flip;
end;
Done := false;
end;
end.
Fazit
Der erste Schritt in Richtung 2D via 3D-Beschleunigung wäre getan. Doch sein wir mal ehrlich, für ein schwarzes Fenster brauchen wir kein Andorra 2D. Darum lernen Sie im nächsten Tutorial:
- Wie Sie ein Bild zeichnen
- Wie Sie das Bild in gleich bleibender Geschwindigkeit über den Bildschirm bewegen
- Und wie Sie den Vollbildmodus verwenden
Dieses Tutorial ist nun ziemlich lang geworden, was daran liegt, dass ich auf alles bis ins Detail eingegangen bin. In den nächsten Tutorials werde ich die Maßstäbe (besonders in Sachen Delphi) ein wenig höher schrauben und dann geht's auch flotter.
Copyright und Lizenz
(c) by Andreas Stöckel Januar 2007
Revision 2: Oktober 2007
Revision 3: Dezember 2007
Revision 4: November 2008
Der Inhalt dieses Tutorials steht unter der GNU Lizenz für freie Dokumentation.
This page was generated with the help of the following PHP-Scripts: GeSHi a free PHP Syntax highlighter and StringParser_BBCode a free BBCode Parser.