Allegro-Tutorial

Aus Spieleprogrammierer-Wiki
(Unterschied zwischen Versionen)
Wechseln zu: Navigation, Suche
[gesichtete Version][gesichtete Version]
Zeile 1: Zeile 1:
{{Baustelle}}
 
{{Verbesserungsbedarf}}
 
 
[[Kategorie:Tutorial]]
 
[[Kategorie:Tutorial]]
 
[[Kategorie:C++]]
 
[[Kategorie:C++]]
Zeile 7: Zeile 5:
  
 
=== Was ist Allegro? ===
 
=== Was ist Allegro? ===
Allegro ist eine in C geschriebene Bibliothek für C/C++-Multimediaanwendungen. Es läuft auf allen großen Betriebssystem und steht unter der zlib-Lizenz. Allegro umfasst Funktionen für Grafiken, Sounds, Eingabe und Zeitsteuerung. Allegro kann mit SDL oder SFML (siehe [[Spiele_programmieren_lernen#Eine_kleine_Übersicht|Übersicht im Einsteigerartikel]]) verglichen werden. Es gibt verschiedene Versionen: 4 und 5. Die Version 4 wird nicht mehr weiterentwickelt und abwärtskompatibel bis zur Version 2.
+
Allegro ist eine in C geschriebene Bibliothek für C/C++-Multimediaanwendungen, die auf allen großen betriebssystemen läuft und unter der zlib-Lizenz steht. Allegro umfasst Funktionen für Grafiken, Sounds, Eingabe und Zeitsteuerung und kann mit SDL oder SFML (siehe [[Spiele_programmieren_lernen#Eine_kleine_Übersicht|Übersicht im Einsteigerartikel]]) verglichen werden. Es gibt verschiedene Versionen: 4 und 5. Die Version 4 wird nicht mehr weiterentwickelt und abwärtskompatibel bis zur Version 2.
 
Die Version 5 hat eine komplett neue API und ist daher NICHT abwärtskompatibel zu alten Allegro Versionen.
 
Die Version 5 hat eine komplett neue API und ist daher NICHT abwärtskompatibel zu alten Allegro Versionen.
 
=== Wo bekomme ich Allegro? ===
 
Allegro kann unter http://www.allegro.cc/files herutergeladen werden. Dort finden sich auch viele Informationen rund um Allegro. Um Allegro zu nutzen, müssen nach dem Download die Header und Libraries dem Compiler bekannt gemacht werden.
 
  
== Installation von Allegro ==
+
=== Installation von Allegro ===
=== Vorkompilierte Dateien ===
+
 
Auf http://www.allegro.cc/files kann man sich Allegro runterladen. Unter "Windows Binaries" oder nur "Binary" kann man sich die vorkompilierte Version von Allegro
 
Auf http://www.allegro.cc/files kann man sich Allegro runterladen. Unter "Windows Binaries" oder nur "Binary" kann man sich die vorkompilierte Version von Allegro
für seinen Compiler runterladen. Die Dateien der Ordner \bin, \include und \lib steckt man dann einfach in die Ordner \bin, \include und \lib seines Compilers.
+
für seinen Compiler runterladen. Danach geben wir noch in den Projekteinstellungen der IDE die entsprechenden Pfade der Header- und Bibliotheksdateien an. In unserem Fall sind das die Ordner \include und \lib. Desweiterern müssen die benötigten DLLs in den Projektordner kopiert werden.
Diese liegen bei den meisten Compilern zwar im Stammverzeichnis, bei Microsoft Visual C++ aber in ..\(Name euerer Visual C++ Version\VC\.
+
  
 
=== Quellcode kompilieren ===
 
=== Quellcode kompilieren ===
 
Wenn der Quellcode für euer Betriebsystem/Compiler nicht erhältlich ist, müsst ihr Allegro erst selbst kompilieren. Dazu ladet ihr den "Source Code" von  
 
Wenn der Quellcode für euer Betriebsystem/Compiler nicht erhältlich ist, müsst ihr Allegro erst selbst kompilieren. Dazu ladet ihr den "Source Code" von  
 
http://www.allegro.cc/files für euer Betriebssytem runter. Wie man dann den Quellcode richtig kompiliert, steht ihm Ordner \docs. Dort sind verschiedene Compiler angegeben.
 
http://www.allegro.cc/files für euer Betriebssytem runter. Wie man dann den Quellcode richtig kompiliert, steht ihm Ordner \docs. Dort sind verschiedene Compiler angegeben.
 +
   
 +
== Beispielanwendung ==
 +
Um einen leichten Einstieg in die Programmierung mit Allegro zu ermöglichen, schauen wir uns ein Beispiel an, welches alle wichtigen Punkte verwendet.
 +
Dazu gehören:
 +
* Bitmap laden und bewegen
 +
* Sample abspielen
 +
* Text-Ausgabe
 +
* Timer
 +
Um all dies zu verwenden, werden wir ein Fenster erstellen, in dem man ein Bild bewegen kann, die Framenummer angezeigt wird und im Hintergrund ein Sample abgespielt wird.
  
=== Allegro verwenden ===
+
=== Header ===
Wenn ihr versucht, ein Projekt mit Allgro zu kompilieren z.B. das hier:
+
Wie (fast) jede C++-Anwedung fangen wir mit dem Einbinden der benötigten Header-Dateien an, wir benötigen dazu mehrere um alle Themen abdecken zu können.  
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
#include <allegro.h> //Füge Allegro ein
+
#include <allegro5\allegro.h>
 
+
#include <allegro5\allegro_ttf.h>
int main()
+
#include <allegro5\allegro_font.h>
{
+
#include <allegro5\allegro_image.h>
  allegro_init(); //Starte Allegro
+
#include <allegro5\allegro_audio.h>
  install_keyboard();  //Installiere die Tastatur
+
#include <allegro5\allegro_acodec.h>
    set_color_depth(32); //Setze einen 32Bit Farbmodus
+
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0); //Erstelle ein Fenster der Größe 640x480
+
    set_window_title("Test"); //Titel des Fensters wird benannnt
+
 
+
    while(!key[KEY_ESC])  //solange ESC nicht gedrückt wird
+
{
+
    //Schreibe    Bildschirm, Schriftart, X-Position, Y-Position, Schriftfarbe, Hintergrund-Farbe, Text
+
      textprintf_ex(screen, font, 300, 300, makecol(255, 255, 255), makecol(0, 0, 0), "Hallo Welt!"); 
+
}
+
return 0;
+
}
+
END_OF_MAIN();    //Sage Allegro, das das Programm vorbei ist
+
 
</sourcecode>
 
</sourcecode>
erhalten wir etwa diese Fehler:
 
  [Linker error] undefined reference to `__dyn_tls_init_callback'
 
  [Linker error] undefined reference to `__cpu_features_init'
 
  
Wir müssen hier die liballeg.a einbinden. Unter Dev-Cpp geht das so:
+
Zusäzlich müssen wir noch die ''allegro-5.0.4-monolith-md.lib'' einbinden bzw. die ''allegro-5.0.4-monolith-md-debug.lib'' wenn wir im Debug-Modus arbeiten.
Drücke ALT + P
+
Zusätzlich müssen wir noch die ''allegro-5.0.4-monolith-md.lib'' und wenn wir im Debug-Modus arbeiten die ''allegro-5.0.4-monolith-md-debug.lib'' einbinden.
gehe zum Reiter "Parameter"
+
Klicke auf Bibliothek/Objekt hinzufügen
+
wähle die liballeg.a im Ordner lib\.
+
Manchmal heißt sie auch alleg.lib.
+
  
   
+
=== Variablen-Deklaration ===
== Das erste Fenster (Allegro 5) ==
+
In diesem Tutorial  arbeiten wir, um es einfach zu halten, nur mit der Main-Funktion. Zu beginn deklarieren wir alle nötigen Variablen und Zeiger, welche wir in der Anwendung verwenden. Dazu gehören Standard-C++ Variablen aber auch Zeiger auf Allegro-Strukturen, die wir z.B. für die Bitmap benötigen.
 
+
=== Der Code ===
+
(Dieser Code ist für Allegro 5.)
+
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
// Allegro-Header einbinden
 
#include <allegro5/allegro.h>
 
 
 
int main()
 
int main()
 
{
 
{
// Konstanten für Bilschirmbreite/-höhe
+
int screenWidth = 800;
const int screenWidth = 640;
+
int screenHeight = 600;
const int screenHeight = 480;
+
bool running = true;
+
bool redraw = true;
// Zeiger für das Fenster
+
bool key[4] = {false, false, false, false};
 +
enum KEYS {UP, DOWN, LEFT, RIGHT};
 +
int posX, posY, bitmapWidth, bitmapHeight;
 +
int frameNumber = 0;
 +
 
 
ALLEGRO_DISPLAY* display = 0;
 
ALLEGRO_DISPLAY* display = 0;
 
// Zeiger für die Event-Warteliste
 
 
ALLEGRO_EVENT_QUEUE* eventQueue = 0;
 
ALLEGRO_EVENT_QUEUE* eventQueue = 0;
+
ALLEGRO_EVENT ev;
// Allegro initialisieren
+
ALLEGRO_BITMAP* bitmap = 0;
if(!al_init()) return -1;
+
ALLEGRO_SAMPLE* sample = 0;
+
ALLEGRO_FONT* font = 0;
// Fenster erzeugen
+
ALLEGRO_TIMER *timer = 0;
display = al_create_display(screenWidth, screenHeight);
+
if(!display) return -1;
+
+
// Tastatureingabe registrieren
+
al_install_keyboard();
+
eventQueue = al_create_event_queue();
+
al_register_event_source(eventQueue, al_get_keyboard_event_source());
+
+
bool running = true;
+
while(running)
+
{
+
ALLEGRO_EVENT ev;
+
al_wait_for_event(eventQueue, &ev);
+
+
if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
+
{
+
switch(ev.keyboard.keycode)
+
{
+
case ALLEGRO_KEY_ESCAPE:
+
running = false;
+
break;
+
}
+
}
+
+
// Display schwarz färben
+
al_clear_to_color(al_map_rgb(0, 0, 0));
+
+
// Fenster aktualisieren
+
al_flip_display();
+
}
+
+
al_destroy_event_queue(eventQueue);
+
al_destroy_display(display);
+
+
return 0;
+
}
+
 
</sourcecode>
 
</sourcecode>
  
=== Erklärung ===
+
Da Allegro nicht den Zustand der Tasten speichert, sondern nur über Änderungen der Zustände informiert, müssen wir den Status selbst speichern. In diesem Fall werden nur die Pfeiltasten benötigt, weshalb ein bool-Array ausreichend ist. Um eine bessere Lesbarkeit zu erreichen, erstellen wir eine Aufzählung von 0 bis 3 durch welches Element des Arrays welche Taste repräsentiert wird.
  
 +
=== Fenster erstellen ===
 +
Bevor wir das eigentliche Fenster erstellen können, müssen wir erst Allegro initialisieren. Dazu rufen wir die Funktion ''al_init'' auf und überprüfen, ob sie korrekt ausgeführt werden konnte. Wenn eine Funktion nicht korrekt ausgeführt werden konnte, setzen wir die Variable 'running' auf 'false', damit die Game-Loop gar nicht erst begonnen wird. Alterantiv könnten wir auch mit einem ''return'' das Programm beenden, allerdings wird dann der Speicher evtl. nicht richtig freigegeben.
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
#include <allegro5/allegro.h>
+
if(!al_init())
 +
running = false;
 +
</sourcecode>
 +
Ist dies der Fall, können wir mit dem Aufurf der Funktion ''al_create_display'' das Fenster erstellen. Dazu übergeben wir ihr die gewünschte Fensterhöhe, bzw. -breite. Auch hier überprüfen wir wieder ob sie korrekt ausgeführt werden konnte. ist dies der Fall, sind wir bereit mit dem Erstellen des Fensters fertig.
 +
<sourcecode lang="cpp" tab="4">
 +
display = al_create_display(screenWidth, screenHeight);
 +
if(!display)
 +
running = false;
 
</sourcecode>
 
</sourcecode>
  
Der benötigte Header für die Grundfunktionen wird eingefügt.
+
=== Bitmap laden ===
 
+
Um ein Bild darstellen zu können, muss zuerst das entsprechende Addon, das für die Bearbeitung von Bildern benötigte Addon initialisiert werden. Danach laden wir das eigentliche Bild und berechnen seine Startposition, damit es am Anfang in der Mitte des Fensters zu sehen ist. Für dieses Beispiel heißt das Bild ''Test.png''. Zeichnen können wir die Bitmap später mit der Funktion ''al_draw_bitmap''. Dazu übergeben wir den Bitmap-Zeiger, die X- und Y-Position, sowie eine ''0'' als zusätzliche Flags.
 +
[[Datei:Test.png]]
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
const int screenWidth = 640;
+
al_init_image_addon();
const int screenHeight = 480;
+
bitmap = al_load_bitmap("Test.png");
 +
if(!bitmap)
 +
running = false;
 +
bitmapWidth = al_get_bitmap_width(bitmap);
 +
bitmapHeight = al_get_bitmap_height(bitmap);
 +
posX = (screenWidth / 2) - (bitmapWidth / 2);
 +
posY = (screenHeight / 2) - (bitmapHeight / 2);  
 
</sourcecode>
 
</sourcecode>
  
In diesen Konstanten werden Bilschirmbreite und -höhe deklariert und definiert.
 
Alternativ könnte dies auch beim Aufruf von <tt>al_create_display()</tt> geschehen.
 
  
 +
=== Sample laden ===
 +
Ein Sample ist im Prinzip eine Musikdatei, die z.B. als Hintergrundmusik verwendet wird. Auch hier müssen wir erst die Audio-Schnittstelle von Allegro aktivieren bevor wir unsere Audiodatei, in diesem Fall ''Test.wav'', verwenden können. Zusätzlich muss noch die Anzahl der Samples, welche wir verwenden möchten, festgelgt werden.
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
ALLEGRO_DISPLAY* display = 0;
+
al_install_audio();
ALLEGRO_EVENT_QUEUE* eventQueue = 0;
+
al_init_acodec_addon();
 +
al_reserve_samples(1);
 +
sample = al_load_sample("Test.wav");
 
</sourcecode>
 
</sourcecode>
  
Dies sind zwei Zeiger für die spätere Verwendung eines Displays (Fenster) und einer Event-Warteschlange, wir setzen sie erst einmal auf 0, da wir sie erst später verwendet werden (siehe <tt>al_create_display</tt> und <tt>al_create_event_queue</tt>).
+
Abspielen können wir das Sample später mit der Funktion ''al_play_sample'', dieser übergeben wir den Zeiger des Samples, die Lautstärke, die Position (-1: links, 0: mittig, 1: recht),  die Geschwindigkeit (1: normal), die Wiedergabeart (ALLEGRO_PLAYMODE_ONCE oder ALLEGRO_PLAYMODE_LOOP) und eine ''0'', da der letzte Parameter für uns erstmal nicht relevatn ist.
  
 +
 +
=== Texte zeichnen ===
 +
Als nächstes beschäftigen wir uns mit dem zeichnen von Schriftzügen innerhalb des Fensters. Dazu initialisieren wir zuerst die entsprechenden Addons und laden eine ''.ttf''-Datei. Beim Laden ist zu beachten, dass wir hier eine feste Größe angeben, die wir später nicht mehr ändern können. Wenn wir zusätzlich eine andere Schriftgröße verwenden möchten, müssen wir die Datei ein zweites mal Laden, mit einem zweiten ''ALLEGRO_FONT''-Zeiger.
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
if(!al_init()) return -1;
+
al_init_font_addon();
 +
al_init_ttf_addon();
 +
font = al_load_font("Test.ttf", 16, 0);
 +
</sourcecode>
 +
Danach können wir an jeder Stelle innerhalb der Anwendung Texte in die Szene einbauen. Dazu stehen uns zwei unterschiedliche Funktionen zur Verfügung. Die erste zeichnet nur den reinen Text, die zweite kann zusätzlich noch Variablen verarbeiten (ähnlich der ''printf''-Funktion in C).
 +
<sourcecode lang="cpp" tab="4">
 +
al_draw_textf(font, al_map_rgb(r, g, b), X, Y, Flags, "text.. %i", Variablen...);
 +
al_draw_textf(font, al_map_rgb(r, g, b), X, Y, Flags, "text...");
 
</sourcecode>
 
</sourcecode>
  
Der Aufruf dieser Funktion initialisiert Allegro und gibt -1 zurück, wenn dies nicht erfolgreich war.
+
=== Timer erstellen ===
 
+
Damit wir in unserer Anwedung mit der Zeit arbeiten können, erstellen wir uns einen Timer. Dazu rufen wir die Funktion ''al_create_timer'' auf und Übergeben ihr als Parameter die Dauer eines einzelnen Frames. Wenn wir z.B. 60 FPS haben wollen, geben wir als Parameter ''1.0 / 60'' an. Danach überprüfen wir, ob der Timer erstellt werden konnte.
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
display = al_create_display(screenWidth, screenHeight);
+
timer = al_create_timer(1.0 / 60); // 60 FPS
if(!display) return -1;
+
if(!timer)
 +
running = false;
 
</sourcecode>
 
</sourcecode>
  
Hier wird ein mit den oben definierten Werten für Breite (<tt>screenWidtht</tt>) und Höhe (<tt>screenHeight</tt>) ein Fenster erzeugt. Sollte dies nicht erfolgreich sein, wird ebenfalls -1 zurückgegeben.
 
  
 +
=== Event-Quellen ===
 +
Als Event-Quellen bezeichnen wir all die Dinge, die ein Event auslösen können und somit Einfluss auf den Ablauf der Anwedung nehmen können. Für unsere Beispielanwendung sind dies:
 +
* die Tastatur
 +
* das Fenster selbst
 +
* und der Timer
 +
Damit wir die Tastatur verwenden können, machen wir sie zunächst mit der Funktion ''al_install_keyboard'' für Allegro zugänglich. Danach erstellen wir die Event-Queue, dies ist eine Art Warteschlange, in der die Events, welche noch nicht verarbeitet wurden, gespeichert werden und registrieren die oben genannten Event-Quellen.
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
al_install_keyboard();
+
// Tastatur zugänglich machen
 +
al_install_keyboard();
 +
 
 +
// Event-Queue erstellen
 +
eventQueue = al_create_event_queue();
 +
al_register_event_source(eventQueue, al_get_keyboard_event_source());
 +
al_register_event_source(eventQueue, al_get_timer_event_source(timer));
 +
al_register_event_source(eventQueue, al_get_display_event_source(display));
 +
</sourcecode>
 +
 
 +
 
 +
=== Die Game-Loop ===
 +
Die Game-Loop ist eine Schleife, die solange ausgeführt wird, bis das Programm beendet wird. Sie verarbeitet die Eingabe des Benutzers, berechnet die Szene neu und zeichnet diese dann.
 +
Bevor wir nun die Game-Loop programmieren können, zeichnen wir die Ausgangsszene Zum Zeichnen der Szene verwendet Allegro einen Front- und einen Back-Buffer. Die Szene wird in den Back-Buffer gezeichnet und dann werden die beiden Buffer vertauscht, so dass das fertige Bild auf den Monitor erscheint.
 +
<br />
 +
Um den Back-Buffer zu leeren verwenden wir die Funktion ''al_clear_to_color'', welche den Back-Buffer mit einer von uns definierten Farbe, in diesem Fall Schwarz, überschreibt. Danach zeichnen wir das erste Mal unseren Frame-Counter und unsere Bitmap in das Fenster und vertauschen die Buffer mit der Funktion ''al_flip_display''.<br />
 +
 
 +
Danach starten wir noch das Abspielen des Samples und den Timer.
 +
<sourcecode lang="cpp" tab="4">
 +
// Szene zeichnen
 +
al_clear_to_color(al_map_rgb(0, 0, 0));
 +
al_draw_textf(font, al_map_rgb(0, 125, 0), 32, 32, 0, "Frame: %i", frameNumber);
 +
al_draw_bitmap(bitmap, posX, posY, 0);
 +
al_flip_display();
 +
 
 +
// Sample abspielen
 +
al_play_sample(sample, 0.5, 0, 1, ALLEGRO_PLAYMODE_ONCE, 0);
 +
 
 +
// Timer starten
 +
al_start_timer(timer);
 
</sourcecode>
 
</sourcecode>
  
Damit später die Tastatur zum Schließen unseres ersten Fensters benutzt werden kann, müssen wir die Tastatur in Allegro installieren.
+
Nun programmieren wir die Game-Loop. Diese ist eigentlich nur eine ''while''-Schleife, die solange ausgeführt wird, bis das Fenster geschlossen wird. Sie besteht aus mehreren Teilschirtten:
 +
# Events abfragen
 +
# Frame-Counter erhöhen
 +
# Bitmap-Position updaten
 +
# Abfragen ob das Fenster geschlossen wurde
 +
# Tastatur-Status verarbeiten
 +
# Szene neu zeichnen
  
 +
Die ersten zwei Schritte sind leicht zu realisieren. Events fragen wir mit der Funktion ''al_wait_for_event'' ab. Die Funktion erhält als Parameter den Event-Queue-Zeiger und die Adresse des Event-Speichers.<br />
 +
Den Frame-Counter erhöhen wir einfach, indem wir den Framecounter in jedem Durchlauf um 1 erhöhen.
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
eventQueue = al_create_event_queue();
+
// Game-Loop
al_register_event_source(eventQueue, al_get_keyboard_event_source());
+
while(running)
 +
{
 +
// Events abfragen
 +
al_wait_for_event(eventQueue, &ev);
 +
 
 +
// Frame-Counter erhöhen
 +
frameNumber++;
 
</sourcecode>
 
</sourcecode>
  
Hier erstellen wir die Event-Warteschleife und weißen sie dem bereits vorher deklariertem Zeiger zu. Zusätzlich geben wir die Tastatur als Quelle für die Event-Warteschleife an.
+
Anschließend berechnen wir die neue Position des Bitmaps, dies soll in jedem Durchlauf, wenn die entsprechende Pfeiltaste gedrückt ist, um vier Pixel verschoben werden. Zusätzlich kontrollieren wir, dass die neue Position innerhalb des sichtbaren Bereichs des Fensters liegt, ist dies nicht der Fall, wird die Bitmap nicht verschoben. Damit dies in jedem Durchlauf passiert, kontrollieren wir ob es ein Event ist, das vom Timer ausgelöst wurde (''ALLEGRO_EVENT_TIMER''). Zusätzlich setzen wir die Variable ''redraw'' auf ''true'', damit die Szene ebenfalls neu gezeichnet wird.
 +
<sourcecode lang="cpp" tab="4">
 +
if(ev.type == ALLEGRO_EVENT_TIMER)
 +
{
 +
// Verschiebung nach oben
 +
if(key[UP] && posY >= 0)
 +
posY -= 4.0;
  
 +
// Verschiebung nach unten
 +
if(key[DOWN] && posY <= (screenHeight - bitmapHeight))
 +
posY += 4.0;
 +
 +
// Verschiebung nach links
 +
if(key[LEFT] && posX >= 0)
 +
posX -= 4.0;
 +
 +
// Verschiebung nach rechts
 +
if(key[RIGHT] && posX <= (screenWidth - bitmapWidth))
 +
posX += 4.0;
 +
 +
redraw = true;
 +
 +
}
 +
// .....
 +
</sourcecode>
 +
 +
Danach überprüfen wir, ob der Benutzter evtl. das Fenster geschlossen hat. Ist dies der Fall setzen wir die Variable ''running'' auf ''false''
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
bool running = true;
+
else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
while(running)
+
{
 +
running = false;
 +
}
 +
// .....
 
</sourcecode>
 
</sourcecode>
  
Hier beginnt unsere <tt>while</tt>-Schleife, die so lange läuft, bis <tt>running</tt> auf <tt>false</tt> gesetzt wird.
+
Als nächstes machen wir uns an das Abfragen der Tastatur. Wenn die entsprechende Taste gedrückt wird setzen wir das entsprechende Element des Arrays auf ''true'' und wenn sie wieder losgelassen wird auf ''false''.
 +
<sourcecode lang="cpp" tab="4">
 +
// Taste gedrückt
 +
else if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
 +
{
 +
switch(ev.keyboard.keycode)
 +
{
 +
case ALLEGRO_KEY_UP:
 +
key[UP] = true;
 +
break;
 +
 +
case ALLEGRO_KEY_DOWN:
 +
key[DOWN] = true;
 +
break;
 +
 +
case ALLEGRO_KEY_LEFT:
 +
key[LEFT] = true;
 +
break;
 +
 +
case ALLEGRO_KEY_RIGHT:
 +
key[RIGHT] = true;
 +
break;
 +
}
 +
}
  
 +
// Taste losgelassen
 +
else if(ev.type == ALLEGRO_EVENT_KEY_UP)
 +
{
 +
switch(ev.keyboard.keycode)
 +
{
 +
case ALLEGRO_KEY_UP:
 +
key[UP] = false;
 +
break;
 +
 +
case ALLEGRO_KEY_DOWN:
 +
key[DOWN] = false;
 +
break;
 +
 +
case ALLEGRO_KEY_LEFT:
 +
key[LEFT] = false;
 +
break;
 +
 +
case ALLEGRO_KEY_RIGHT:
 +
key[RIGHT] = false;
 +
break;
 +
 +
case ALLEGRO_KEY_ESCAPE:
 +
running = false;
 +
break;
 +
}
 +
}
 +
// .....
 +
 +
</sourcecode>
 +
 +
Am Ende zeichnen wir die Szene, falls ''redraw'' auf ''true'' gesetzt ist, neu. Dazu leeren wir zuerst wieder den Back-Buffer, zeichen anschließend die Bitmap und den Text und tauschen zum Schluss wieder beide Buffer. Die Variable ''redraw'' setzen wir auf ''false'', da die Szene erst beim nächsten Timing-Event wieder gezeichnet werden soll.
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
ALLEGRO_EVENT ev;
+
if(redraw && al_is_event_queue_empty(eventQueue))
al_wait_for_event(eventQueue, &ev);
+
{
 +
redraw = false;
 +
al_clear_to_color(al_map_rgb(0,0,0));
 +
al_draw_bitmap(bitmap, posX, posY, 0);
 +
al_draw_textf(font, al_map_rgb(0, 125, 0), 32, 32, 0, "Frame: %i", frameNumber);
 +
al_flip_display();
 +
}
 +
}
 
</sourcecode>
 
</sourcecode>
  
Hier erzeugen wir eine Variable vom Typ <tt>ALLEGRO_EVENT</tt>, die wir, wie der Name schon vermuten lässt, für das Arbeiten mit Events verwenden werden. Danach lassen wir Allegro auf ein Event warten.
+
=== Anwendung korrekt beenden ===
 +
Statt nun einfach das Programm zu beenden, wollen wir vorher noch den verwendeten Speicher freigeben, um mögliche Fehler zu vermeiden. Dazu rufen wir für jedes Objekt eine extra Funktion ''al_destroy_$object'' auf und übergeben ihr das entsprechende Objekt. Anschließend geben wir noch eine ''0'' an das Betriebssystem zurück und unsere Beispiel-Anwendung ist fertig.
 +
<sourcecode lang="cpp" tab="4">
 +
// Speicher freigeben
 +
al_destroy_sample(sample);
 +
al_destroy_font(font);
 +
al_destroy_bitmap(bitmap);
 +
al_destroy_timer(timer);
 +
al_destroy_display(display);
 +
al_destroy_event_queue(eventQueue);
  
 +
return 0;
 +
}
 +
</sourcecode>
 +
 +
=== Der gesamte Quelltext ===
 +
{{Spoiler|<xh4>Quellcode</xh4>|
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
+
/*
 +
Allegro-Beispielanwendung:
 +
- Bitmap laden und bewegen
 +
- Lied im Hintergrund abspielen
 +
- Text-Ausgabe
 +
- Timer
 +
*/
 +
 
 +
// Benötigte Header
 +
#include <allegro5\allegro.h>
 +
#include <allegro5\allegro_ttf.h>
 +
#include <allegro5\allegro_font.h>
 +
#include <allegro5\allegro_image.h>
 +
#include <allegro5\allegro_audio.h>
 +
#include <allegro5\allegro_acodec.h>
 +
 
 +
 
 +
 
 +
int main()
 
{
 
{
switch(ev.keyboard.keycode)
+
// Variablen-Deklaration
{
+
int screenWidth = 800;
case ALLEGRO_KEY_ESCAPE:
+
int screenHeight = 600;
 +
bool running = true;
 +
bool redraw = true;
 +
bool key[4] = {false, false, false, false};
 +
enum KEYS {UP, DOWN, LEFT, RIGHT};
 +
int posX, posY, bitmapWidth, bitmapHeight; // Bilddaten
 +
int frameNumber = 0;
 +
 
 +
ALLEGRO_DISPLAY* display = 0;
 +
ALLEGRO_EVENT_QUEUE* eventQueue = 0;
 +
ALLEGRO_EVENT ev;
 +
ALLEGRO_BITMAP* bitmap = 0;
 +
ALLEGRO_SAMPLE* sample = 0;
 +
ALLEGRO_FONT* font = 0;
 +
ALLEGRO_TIMER *timer = 0;
 +
 
 +
// Allegro initialisieren
 +
if(!al_init())
 
running = false;
 
running = false;
break;
+
 
 +
// Fenster erstellen
 +
display = al_create_display(screenWidth, screenHeight);
 +
if(!display)
 +
running = false;
 +
 
 +
 
 +
// Bild laden
 +
al_init_image_addon();
 +
bitmap = al_load_bitmap("Test.png");
 +
if(!bitmap)
 +
running = false;
 +
bitmapWidth = al_get_bitmap_width(bitmap);
 +
bitmapHeight = al_get_bitmap_height(bitmap);
 +
posX = (screenWidth / 2) - (bitmapWidth / 2);
 +
posY = (screenHeight / 2) - (bitmapHeight / 2);
 +
 
 +
// Sample laden
 +
al_install_audio();
 +
al_init_acodec_addon();
 +
al_reserve_samples(1);
 +
sample = al_load_sample("Test.wav");
 +
 
 +
// Text-Ausgabe vorbereiten
 +
al_init_font_addon();
 +
al_init_ttf_addon();
 +
font = al_load_font("Test.ttf", 16, 0);
 +
 
 +
// Timer erstellen
 +
timer = al_create_timer(1.0 / 60); // 60 FPS
 +
if(!timer)
 +
running = false;
 +
 
 +
// Tastatur zugänglich machen
 +
al_install_keyboard();
 +
 
 +
// Event-Queue erstellen
 +
eventQueue = al_create_event_queue();
 +
al_register_event_source(eventQueue, al_get_keyboard_event_source());
 +
al_register_event_source(eventQueue, al_get_timer_event_source(timer));
 +
al_register_event_source(eventQueue, al_get_display_event_source(display));
 +
 
 +
// Szene zeichnen
 +
al_clear_to_color(al_map_rgb(0, 0, 0));
 +
al_draw_textf(font, al_map_rgb(0, 125, 0), 32, 32, 0, "Frame: %i", frameNumber);
 +
al_draw_bitmap(bitmap, posX, posY, 0);
 +
al_flip_display();
 +
 
 +
// Sample abspielen
 +
al_play_sample(sample, 0.5, 0, 1, ALLEGRO_PLAYMODE_ONCE, 0);
 +
 
 +
// Timer starten
 +
al_start_timer(timer);
 +
 
 +
// Game-Loop
 +
while(running)
 +
{
 +
// Events abfragen
 +
al_wait_for_event(eventQueue, &ev);
 +
 
 +
// Frame-Counter erhöhen
 +
frameNumber++;
 +
 
 +
// Position updaten
 +
if(ev.type == ALLEGRO_EVENT_TIMER)
 +
{
 +
// Verschiebung nach oben
 +
            if(key[UP] && posY >= 0)
 +
                posY -= 4.0;
 +
 +
            // Verschiebung nach unten
 +
            if(key[DOWN] && posY <= (screenHeight - bitmapHeight))
 +
                posY += 4.0;
 +
 +
            // Verschiebung nach links
 +
            if(key[LEFT] && posX >= 0)
 +
                posX -= 4.0;
 +
 +
            // Verschiebung nach rechts
 +
            if(key[RIGHT] && posX <= (screenWidth - bitmapWidth))
 +
                posX += 4.0;
 +
 
 +
redraw = true;
 +
 
 +
}
 +
 
 +
// Fenster wurde mit 'X' geschlossen
 +
else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
 +
{
 +
running = false;
 +
}
 +
 
 +
// Taste gedrückt
 +
else if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
 +
{
 +
switch(ev.keyboard.keycode)
 +
{
 +
case ALLEGRO_KEY_UP:
 +
key[UP] = true;
 +
break;
 +
 +
case ALLEGRO_KEY_DOWN:
 +
key[DOWN] = true;
 +
break;
 +
 +
case ALLEGRO_KEY_LEFT:
 +
key[LEFT] = true;
 +
break;
 +
 +
case ALLEGRO_KEY_RIGHT:
 +
key[RIGHT] = true;
 +
break;
 +
}
 +
}
 +
 
 +
// Taste losgelassen
 +
else if(ev.type == ALLEGRO_EVENT_KEY_UP)
 +
{
 +
switch(ev.keyboard.keycode)
 +
{
 +
case ALLEGRO_KEY_UP:
 +
key[UP] = false;
 +
break;
 +
 +
case ALLEGRO_KEY_DOWN:
 +
key[DOWN] = false;
 +
break;
 +
 +
case ALLEGRO_KEY_LEFT:
 +
key[LEFT] = false;
 +
break;
 +
 +
case ALLEGRO_KEY_RIGHT:
 +
key[RIGHT] = false;
 +
break;
 +
 +
case ALLEGRO_KEY_ESCAPE:
 +
running = false;
 +
break;
 +
}
 +
}
 +
if(redraw && al_is_event_queue_empty(eventQueue))
 +
{
 +
redraw = false;
 +
al_clear_to_color(al_map_rgb(0,0,0));
 +
al_draw_bitmap(bitmap, posX, posY, 0);
 +
al_draw_textf(font, al_map_rgb(0, 125, 0), 32, 32, 0, "Frame: %i", frameNumber);
 +
al_flip_display();
 +
}
 
}
 
}
 +
 +
// Speicher freigeben
 +
al_destroy_sample(sample);
 +
al_destroy_font(font);
 +
al_destroy_bitmap(bitmap);
 +
al_destroy_timer(timer);
 +
al_destroy_display(display);
 +
al_destroy_event_queue(eventQueue);
 +
 +
return 0;
 
}
 
}
 
</sourcecode>
 
</sourcecode>
 +
}}
  
Hier püfen wir, ob das Event aus dem ''Herunterdrücken'' einer Taste bestand. Danach prüfen wir, ob es die Taste Escape war. Trifft dies zu, wird <tt>running</tt> auf <tt>false</tt> gesetzt, und die <tt>while</tt>-Schleife wird somit nicht weiter ausgeführt.
+
{{Spoiler|<xh4>Ergebnis</xh4>|
 +
[[Datei:AllegroTut.png]]
 +
}}
  
 +
== Weitere Techniken ==
 +
Wir haben zwar nun ein vollständige Anwendung, die alle großen Anwendungsbereiche abdeckt, allerdings wollen wir uns noch ein paar zusätzliche Dinge anschauen.
 +
 +
=== Fenstertitel ===
 +
Allegro verwendet als Fenstertitel standardmäßig, unter Windows, den Projektnamen, allerdings können wir diesen mit der Funktion ''al_set_window_title'' ändern. Der Funktion übergeben wir unseren Display-Zeiger und den gewünschten Titel.
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
al_clear_to_color(al_map_rgb(0, 0, 0));
+
al_set_window_title(display, "Beispieltitel");
al_flip_display();
+
 
</sourcecode>
 
</sourcecode>
  
Wir füllen die Anzeige mit der Farbe Schwarz und sorgen danach dafür, dass das Ganze sichtbar wird. Allegro benutzt hier einen Doppelpuffer, d.h. man zeichnet zunächst in einen unsichtbaren Speicherbereich, der dann erst durch <tt>al_flip_display</tt> sichtbar gemacht wird.
+
=== Monitor auswählen ===
 +
Nicht selten kommt es vor, dass ein Benutzer über mehr als einen Monitor verfügt. Allegro gibt uns die Möglichkeit, einen Monitor auszuwählen. Besonders wenn wir uns später den Vollbild-Modus anschauen kann dies wichtig sein, da man ein Fenster verschieben kann, aber keine Vollbild-Anwendung. Um den gewünschten Monitor auszuwählen, verwenden wir die Funktion ''al_set_new_display_adapter''. Als Paramet übergeben wir die Nummer des Monitors, wobei ''0'' der erste Monitor ist. Die Funktion muss ''vor'' dem Aufruf von ''al_create_display'' aufgereufen werden.
 +
<sourcecode lang="cpp" tab="4">
 +
al_set_new_display_adapter(0);
 +
</sourcecode>
 +
 
 +
=== Vollbild ===
 +
Richtige Spielatmosphäre kommt in einem Fenster nicht wirklich auf. Deshalb schauen wir uns als nächstes an, wie wir den Vollbildmodus aktivieren können. Dabei ist zu beachten, dass wir zuerst, wie oben beschrieben, den Monitor auswählen. Nach dieser Auswahl rufen wir, ebenfalls vor dem Aufruf von ''al_create_display'', die Funktion ''al_set_new_display_falgs'' auf und übergeben ihr den Parameter ''ALLEGRO_FULLSCREEN''.
 +
<sourcecode lang="cpp" tab="4">
 +
al_set_new_display_flags(ALLEGRO_FULLSCREEN);
 +
</sourcecode>
 +
 
 +
=== Primitiven ===
 +
Primitiven sind einfache geometrischen Strukturen. Dazu gehören z.B. Dreiecke, Vierecke, Linien und Kreise. Allegro stellt uns, um mit Primitiven zu arbeiten, ein extra Addon zur Verfügung. Um mit diesem Addon arbeiten zu können, müssen wir die ''allegro_primitives.h'' einbinden und das Addon mit ''al_init_primitives_addon'' initialisieren.
 +
<sourcecode lang="cpp" tab="4">
 +
#include <allegro5\allegro_primitives.h>
 +
 
 +
// Main-Funktion
 +
al_init_primitives_addon();
 +
</sourcecode>
  
 +
{{Spoiler|'''Beispiele'''|
 
<sourcecode lang="cpp" tab="4">
 
<sourcecode lang="cpp" tab="4">
al_destroy_event_queue(eventQueue);
+
// Ein paar Beispiele (eine komplette Liste, steht in der Allegro-Dokumentation)
al_destroy_display(display);
+
al_draw_line(startX, startY, endX, endY, al_map_rgb(r, g, b), Breite); // Eine Linie
+
al_draw_filled_rectangle(startX, startY, endX, endY, al_map_rgb(r, g, b)); // Ein Viereck
return 0;
+
al_draw_circle(mittelX, mittelY, radius, al_map_rgb(r, g, b), Breite); // Ein Kreis
 
</sourcecode>
 
</sourcecode>
 +
}}
  
Zum Schluss "zerstören" wir noch das Fenster und die Event-Warteschlange und geben 0 zurück, um das Programm zu beenden.
+
== Wie geht es jetzt weiter ==
 +
Natürlich war dies nur ein sehr kurzer Einstieg in Allegro. Allerdings sind wir nun theoretisch in der Lage ein Spiel mit Allegro zu programmieren. <br />
 +
Unser wichtigstes Hilftmittel für die Zukunft, um mit Allegro zu programmieren, ist die [http://alleg.sourceforge.net/a5docs/refman/index.html Dokumentation]. Ansonsten gilt wie immer "Learning by doing".

Version vom 23. März 2013, 03:50 Uhr

Klicke hier, um diese Version anzusehen.

Meine Werkzeuge
Namensräume
Varianten
Aktionen
Navigation
Werkzeuge