Das Bitmap

Kommen wir nun zu einer der wichtigsten Sachen in Allegro, ich würde sogar sagen der Wichtigsten: Dem BITMAP-Objekt (ist in Wahrheit ein struct, aber wir wollen mal nicht so kleinkariert sein, BITMAP-Struct klingt einfach doof). Allegro kann Bilder laden, bearbeiten und verändern, sowie Anzeigen, das alles funktioniert über das BITMAP-Objekt.

Ein Bitmap Erzeugen und bearbeiten

Zuerst ein Code-Beispiel

#include <AllegroW/Allegro.hpp>
 
 
int main()
{
    //Allegro einschalten
    allg::initialisieren(1024, 768);
 
 
   BITMAP *Bild1 = create_bitmap(1024, 768);
   clear_to_color(Bild1, makecol(255,0,255));
 
   blit(Bild1, screen, 0, 0, 128, 128, 768, 512);
   _sleep(5000);
   return 0;
 
}
END_OF_MAIN()

Denkt daran, alle cpp-Files aus dem Source-Ordner zum Projekt hinzuzufügen.

Ein Bitmap erzeugen

So Wie man sieht sind 4 Zeilen hinzu gekommen. Das BITMAP-Objekt wird IMMER als Zeiger erzeugt. Man kann dann ein Bitmap erstellen, oder laden, aber das werden wir später sehen. Also create_bitmap() nimmt als Parameter Länge und Höhe des zu erzeugenden Bitmaps.

Ein Bitmap komplett einfärben

Was clear_to_color() macht sagt an sich schon der Funktionsname, das Bild wird komplett mit einer Farbe übermalt, wobei makecol() aus 3 Integern, die die RGB werte angeben, eine Hex-Zahl macht, mit der clear_to_color() arbeitet. Die Hex-Zahl die Im Codebeispiel entsteht ist 0xFF00FF.

Ein Bitmap anzeigen (Die blit-Funktion)

void blit(BITMAP *source, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h);

Mit blit() kann man ein Bitmap auf ein anderes Zeichnen. Das sind die Parameter: Das erste ist ein Zeiger auf ein BITMAP-Object, das ist die Quelle, die wird dann auf etwas anderes gezeichnet.

Das 2te ist wieder ein Zeiger auf ein BITMAP-Object dieses Mal das Ziel, also das Bild auf das gezeichnet wird.

Das dritte und vierte Parameter geben die Koordinaten des Punktes an, von dem aus von der Quelle auf das Ziel gezeichnet werden soll.

Das fünfte und sechste Parameter werden genutzt um die X und Y Werte des Punktes anzugeben, an die Quelle auf das Ziel gezeichnet werden sollen.

und die Beiden letzten Parameter geben die Länge und Höhe des Vierecks an, das aus der Quelle ausgeschnitten wird um aufs Ziel gezeichnet zu werden.

Da das Ganze schwer zu erklären ist, hier eine Grafik:

Andere Blit-Funktionen

Es gibt auch noch eine funktion, die heißt masked_blit() und ist exakt das selbe wie blit(), mit der Ausnahme, dass die Farbe Lila (0xFF00FF bzw makecol(255, 0, 255)) als durchsichtig gillt, das ist sehr nützlich, und wir werden es uns später genauer ansehen. Außerdem gibt es noch diverse andere blit()-Funktionen, die z.B. ein Bitmap verzerren, spiegeln, oder drehen können.

Nachzulesen sind diese wie immer im Allegro-Manual

Der Bildschirm als Bitmap

Wie ihr vielleicht bemerkt habt habe ich als Ziel screen angegeben. Das ist ein globaler Zeiger auf das BITMAP-Object, das den Bildschirm präsentiert. Denn in Allegro ist der Bildschirm einfach nur ein weiteres Bild.

Ein Bitmap laden und zerstören

Zuerst muss ich sagen, damit der Code funktioniert braucht ihr eine Datei namens Bild.bmp in dem Arbeitsverzeichnis eures Programms.

Ich weiß nicht, ob es unter Linuxsystemen das Bitmap-Format gibt, aber eine Bild Datei des Formats LBM, PCX, oder TGA tut es auch, ich hoffe, dass da der Linux-Standard auch bei ist. Ihr müsst dann lediglich den Pfad im Quellcode ein Bisschen anpassen:

#include <AllegroW/Allegro.hpp>
 
using namespace allg;
 
void draw_to_center(BITMAP*);
 
int main() {
    initialisieren(1024, 768);
 
    BITMAP *Bild = load_bitmap("./Bild.bmp", NULL);
    draw_to_center(Bild);
    _sleep(5000);
    destroy_bitmap(Bild);
    Bild = NULL;
 
    return 0;
 
}
END_OF_MAIN()
 
void draw_to_center(BITMAP *Pic){
    draw_sprite(screen, Pic, (SCREEN_W/2) - (Pic->w/2), (SCREEN_H/2) - (Pic->h/2));
}

So wie ihr seht benutzen wir wieder unsere eigenen Allegro-Funktionen

Ein Bitmap Laden (load_bitmap())

Wie ihr sehen könnt wird load_bitmap benutzt um ein Bild zu laden. Allegro kann mit Bildern der Folgenden Formate umgehen:

  • BMP
  • LBM
  • PCX
  • TGA

Das zweite Parameter ist die benutzte Farbpalette, ich weiß selber nicht ganz genau wie das funktioniert, allerdings kann ich euch sagen, dass die Farbpalette die Farben enthält die das Bild enthalten darf. Wenn man sie auf NULL setzt wird die Standardpalette verwendet, was bei true-color Bildern sowieso das sinnvollste ist (also 24-Bit zum speichern von Farbinformationen pro Pixel und mehr). Wenn man ein Bild nicht in True-color verwendet sollte man die Palette optimieren, nachzulesen wie genau das geht, ist es im Allegro-Manual

draw_sprite()

Die Funktion draw_sprite(), die in draw_to_center() verwendet wird ist im Endeffekt das selbe wie blit(), nur dass es weniger Parameter nimmt. blit benutzt man normaler weise wenn man einen Ausschnitt eines Bildes auf ein anderes Zeichnen will, während man draw_sprite() verwendet, wenn man ein komplettes Bild auf ein anderes Zeichnen möchte. So muss man nur noch Ziel, Quell, und X&Y-Koordinaten auf dem Ziel angeben. Die Berechnung sorgt dafür, dass das Bild genau im Zentrum angezeigt werden. SCREEN_W und SCREEN_H sind Makros die die Länge und Breite des Monitors angeben. Bei einem normalen BITMAP-Zeiger kann man ganz einfach per Pic→w und Pic→h darauf zugreifen.

destroy_bitmap()

Diese Funktion zerstört - wie der Name schon so schön sagt - ein Bitmap, und gibt somit seinen Speicher wieder frei. In diesem Programm ist der Aufruf völlig sinnfrei, da das Programm danach beendet wird, und der Speicher sowie so freigegeben. Doch in größeren Projekten macht es durchaus Sinn diese Funktion zu benutzen, da sich sonst eine ganze Menge nicht mehr gebrauchte Information im RAM anhäufen. Denn die Bitmaps werden nicht zerstört wenn man die Funktion, in der sie erzeugt wurden verlässt.

Das erstellen eines eigenen Bitmap-Objekts

So, da wir nun die nötigsten Sachen über das Bitmap in Allegro wissen, werden wir natürlich auch ein Objekt daraus machen.

Der Header ( AllegroW/Header/TGRAPHIKOBJEKT.h )

Also fangen wir mit dem Header an, der sieht so aus:

#ifndef GRA
#define GRA
 
#include <string>
#include <Vector>
 
namespace allg{
 
    class TGRAPHIKOBJEKT{
            private:
 
            protected:
                BITMAP *Bild, *Ziel;
                int    x,y;
 
            public:
                TGRAPHIKOBJEKT();
                TGRAPHIKOBJEKT(char *quelle, int xx = 0, int yy = 0);
                TGRAPHIKOBJEKT(BITMAP*);
                ~TGRAPHIKOBJEKT();
                void ZielSetzen(BITMAP *ziel);
                void PositionSetzen(int xx, int yy);
                void BildLaden(char* Pfad);
                void BildLaden(BITMAP*);
                int Anzeigen(bool masked = false);
                void Einfaerben(int r = 0, int g = 0, int b = 0);
                int get_x();
                int get_y();
                BITMAP *get_Bild();
    };
};
 
#endif

Dieser code beinhaltet natürlich lange nicht alles, was Allegro mit einem Bitmap anstellen kann, aber dafür geben wir notfalls auch ganz unten die Möglichkeit direkt auf das eigentlich Bitmap zuzugreifen. Ihr dürft die Klasse natürlich auch gerne euren eigenen Wünschen entsprechend erweitern ;)

Kurz zu den Konstruktoren: Wir brauchen natürlich einen Standard-Konstruktor, dann mache ich in meinen Klassen immer noch gerne einen Konstruktor, der die Wichtigsten Informationen direkt angibt, und der dritte ist für Bilder da, die erst irgendwie erstellt wurden, und dann doch ganz praktisch wären für diese Klasse. Ein Copy-Konstruktor wird von den meisten Compilern automatisch erstellt, deshalb ist der hier nicht drin.

Die Methode Ziel setzen dient dazu, festzulegen auf welches Bild gezeichnet werden soll, wenn die Methode Anzeigen aufgerufen wird.

BildLaden sollte vom Namen her eindeutig sein. Und einfärben ist nichts anderes als ein clear_to_color() auf das Bitmap anzuwenden.

Der Source ( AllegroW/SRC/TGRAPHIKOBJEKT.cpp )

#include "../Allegro.hpp"
 
#include <sstream>
#include <ctype.h>
 
using namespace allg;
 
 
TGRAPHIKOBJEKT::TGRAPHIKOBJEKT() {
    x = 0;
    y = 0;
 
    Ziel = screen;
    Bild = NULL;
}
//------------------------------------------------------------------------------
TGRAPHIKOBJEKT::TGRAPHIKOBJEKT(char *quelle, int xx, int yy) {
    x = xx;
    y = yy;
 
    Ziel = screen;
    Bild = load_bitmap(quelle,NULL);
}
//------------------------------------------------------------------------------
TGRAPHIKOBJEKT::TGRAPHIKOBJEKT(BITMAP* B){
    Bild = B;
}
//------------------------------------------------------------------------------
TGRAPHIKOBJEKT::~TGRAPHIKOBJEKT() {
    destroy_bitmap(Bild);
}
//------------------------------------------------------------------------------
void TGRAPHIKOBJEKT::BildLaden(char* Pfad){
    Bild = load_bitmap(Pfad,NULL);
}
//------------------------------------------------------------------------------
void TGRAPHIKOBJEKT::BildLaden(BITMAP* B){
    Bild = B;
}
//------------------------------------------------------------------------------
void TGRAPHIKOBJEKT::ZielSetzen(BITMAP *ziel){
    Ziel = ziel;
}
//------------------------------------------------------------------------------
int TGRAPHIKOBJEKT::Anzeigen(bool masked){
    if(!masked){
        blit(Bild, Ziel, 0, 0, x,
            y, Bild->w, Bild->h);
    }else{
        masked_blit(Bild, Ziel, 0, 0, x,
            y, Bild->w, Bild->h);
    }
    return 0;
 
}
//------------------------------------------------------------------------------
void TGRAPHIKOBJEKT::Einfaerben(int r, int g, int b){
    clear_to_color(Bild, makecol(r, g, b));
}
//------------------------------------------------------------------------------
void TGRAPHIKOBJEKT::PositionSetzen(int xx, int yy){
    x = xx;
    y = yy;
}
//------------------------------------------------------------------------------
int TGRAPHIKOBJEKT::get_x(){
    return x;
}
//------------------------------------------------------------------------------
BITMAP* TGRAPHIKOBJEKT::get_Bild(){
    return Bild;
}
//------------------------------------------------------------------------------
int TGRAPHIKOBJEKT::get_y(){
    return y;
}
//-----------------------------------------------------------------------------

Diese Datei dürfte eigentlich keinen Code enthalten, den ihr so nicht verstehen könntet. Bei fragen postet im Forum, oder schreibt mir eine E-Mail an mein.rest@web.de und bitte keinen Spam.

Allegro.hpp

Die Allegro.hpp müsst ihr jetzt natürlich auch verändern, und zwar so: ergänzt diese Zeile:

#include "header/TGRAPHIKOBJEKT.h"

Das Ganze sollte dann so aussehen:

/*je nach Laune, and time, I used a tolle Mischung aus Englisch and German.
 *who takes Anstoß at this, der soll diese Klassen nicht benutzen. */
 
#ifndef ALLEGROHPP
#define ALLEGROHPP
 
typedef const char* coch;
 
#include <allegro.h>
 
#include "header/Functions.h"
#include "header/TGRAPHIKOBJEKT.h"
//hier kommt später noch mehr dazu
 
#endif

Zurück zu: Erste Schritte in Allegro Weiter zu: Die Textausgabe