Rob´s BB-Kurs 2

Bilder anzeigen


© Robert Gerlach 2001

www.robsite.de



Was wäre ein halbwegs modernes Spiel ohne Grafik? Genau, nichts. Langweilig, einschläfernd und allgemein dumm. Gute Textadventurs mal ausgeschlossen, aber diese kann man auch schon mit HTML machen.
Wir sind nun aber gerade dabei eine der schnellsten und besten Spieleprogrammiersprachen zu lernen und da zu guten Spielen nun mal Grafik gehört, liegen darin auch die Stärken von Blitz Basic.
So merkwürdig und mysteriös es sich anhört, die einfachen Linien- und Punktebefehle aus dem letzten Kapitel sind tatsächlich viel langsamer als das setzen eines ganzen Bildes. Warum das? Weil Blitz Basic DirectX benutzt und somit schneller fertige Bilder malen kann als Punkte. Warum genau das so ist weiß ich auch nicht, der geneigte Leser möge ein DirectX Buch seiner Wahl konsumieren...
Nun denn, weiter mit neuen Befehlen.


Wie wir im letzten Kapitel gelernt haben, kann man mit Graphics in den Grafikmodus schalten, es wird intern also DirectX initialisiert. Alles was wir dann gemalt haben war sofort auf dem Bildschirm und es blieb auch da. Wenn man nun aber mit dieser Methode z.B. eine Linie über den Bildschirm und gleichzeitig über andere Grafiken bewegen will die unter ihr sind, übermalt die gerade bewegte Linie den Hintergrund, denn es wird ja nicht eine Linie genommen und bewegt, sondern immer eine neue Linie, mit pro Durchlauf veränderten Koordinaten, immer wieder hingemalt. Das ist schlecht. Man stelle sich vor dass das mit der Maus in Windows geschehn würde. Irgendwann wär der ganze Bildschirm mit kleinen Pfeilen voll weil sie nicht gelöscht werden... Also muss man sich was anderes überlegen.
Die beste Methode ist, wenn man 2 Bildschirmseiten nimmt. Eine auf der man zeichnet und eine die angezeigt wird.


Man kann also ganz ruhig das gesamte Bild neu auf der unsichtbaren Seite (dem unsichtbaren Buffer, dem BackBuffer) malen und alles mögliche berechnen während im Vordergrund das alte Bild angezeigt wird. Dann, wenn man fertig ist, tauscht man die beiden blitzschnell aus und kann wieder von vorne das nächste Bild zeichnen.
Diese Technik, die generell bei allen Spielen und heute üblichen Programmen benutzt wird, heisst PageFlipping, DoubleBuffering oder auch BackBuffering. Ein Buffer ist wörtlich übersetzt ein Zwischenspeicher, bei uns ist er eine Bildschirmseite. Double Buffering bedeutet nun nichts weiter als dass wir 2 davon haben.

Um nun also diese grandiose Technik benutzen zu können, müssen wir am Anfang des Programms noch einen kleinen Befehl setzen:


SetBuffer BackBuffer()


Das BackBuffer bedeutet, dass wir nun auf dem nicht sichtbaren Buffer malen. Man kann auch FrontBuffer einsetzen, dann wär es das gleiche als wenn man nichts hinschreibt, denn FrontBuffer ist die Standardeinstellung, wie wir in Kapitel 7 gesehn haben.

So. Nun können wir in einer Schleife unser ganzes Zeug jedesmal neu auf den BackBuffer malen. Damit es da nicht bleibt sonder auf dem FrontBuffer angezeigt wird, müssen wir die beiden Buffer austauschen/umdrehen. Umdrehen heisst in Englisch ungefähr Flip, so also auch der Befehl dazu:


Flip


Flip sollte man nur einmal einsetzen, nämlich nachdem man alles gemalt hat. Oder auch nicht. Das ist bloß für den Anfang das beste...
Nun haben wir also auf den BackBuffer unser Zeug gemalt, das ganze getauscht und müssen den Buffer der jetzt BackBuffer ist erstmal löschen, damit wir wieder neues Zeug draufmalen können. Das geht wie immer mit Cls ganz gut.
Hier nochmal die gesamte Grundkonstruktion:


Graphics 640, 480
SetBuffer BackBuffer()



Repeat
Cls

; Dummes Zeug malen

Flip
Until KeyHit(1)




Fein. Was jetzt kommt sind die vielen schnellen Möglichkeiten mit BB Bilder zu zeichnen.

Die Blitz Basic Vollversion unterstützt drei Bildformate, .bmp, .png und .jpg. Die Demo nur .bmp. Richtig sinnvoll von den dreien ist eigentlich nur .png, es vereint die Vorteile der beiden anderen recht gut. Png komprimiert verlustfrei, jpg nicht. bmp geht zwar auch noch ist aber fürs endgültige Release viel zu groß.
Bilder speichern kann BB auch noch, allerdings nur in .bmp.

Also, was muss man nun tun um ein Bild anzuzeigen? Man muss es erstmal laden:


bildvariable = LoadImage("bild.bmp")


In bildvariable wird nicht das gesamte Bild gespeichert sondern nur die Adresse im Speicher.
Das Bild ist jetzt also im Speicher und wir können es auf den Bildschirm bringen:


DrawImage bildvariable, x, y


x und y sind die linke obere Ecke des Bildes. Falls man jetzt ein zufällig an manchen Stellen schwarzes Bild malt und das schwarz nicht sieht, liegt es daran das Schwarz (r0, g0, b0) die Standard-Transparenzfarbe ist, sie wird also nicht angezeigt. Das ist sehr praktisch. Will man nun aber trotzdem schwarz in seinen Bildern haben muss man die transparente Farbe selbst auf einen anderen Wert setzen:


MaskImage bildvariable, r, g, b


Man sollte am besten irgendeine selten verwendete, extreme Farbe als transparente nehmen, z.B. r255, g0, b255 (pink).

Was aber wenn man absolut keine transparente Farbe in seinem Bild haben will? Dann malt man es einfach ohne, als Block sozusagen:


DrawBlock bildvariable, x, y


Und gibt noch mehr. In HTML kann man mit background = "bild.bmp" ein einzelnes Bild auf dem ganzen Bildschirm verteilen. Genau das gleiche geht auch mit BB:


; Zeichnet ein Bild mit transparenter Farbe auf den ganzen Bildschirm:
TileImage bildvariable, x, y

; Zeichnet ein Bild ohne transparente Farbe auf den ganzen Bildschirm:
TileBlock bildvariable, x, y


Jetzt könne wir bilder anzeigen. Jubel.
Was aber wenn wir seit 5 Jahren an C&C 6 basteln und erstaunt feststellen dass unsere Figuren keine Animationen haben? Dann nehmen wir uns einen Keks und schauen uns LoadAnimImage an.
Blitz Basic bietet nämlich auch die Möglichkeit ganz einfach aus mehreren Einzelbildern intern "ein" animiertes zu machen. Oder besser gesagt aus einem Filmstreifen die einzelnen Bilder zu extrahieren und gemeinsam in eine Bildvariable zu laden. Also, erstmal der Befehl:


bildvariable = LoadAnimImage("bild.bmp", hoehe, breite, erstes_bild, bilder_anzahl)


hoehe und breite geben die Höhe und breite eines Einzelbildes im großen Gesamtbild an (alle Einzelbilder müssen gleich groß sein, klar). erstes_bild ist das erste Bild in der Reihe. Gewöhnlich ist es 0. bilder_anzahl ist die Gesamtanzahl der Bilder die in dem "Filmstreifen" drin sind. Wenn man sehr viele Einzelbilder hat muss man auch nicht unbedingt alle in einer Reihe haben, man kann das ganze auch wie in einem Comic anordnen, also von links nach rechts und von oben nach unten.

Da nun mehrere Bilder in einer Bildvariable sind muss man die ganzen Bilder-Mal-Befehle um einen Parameter erweitern, nämlich um die Nummer des Einzelbildes (des Frames). Einfach hinten ranhängen:


DrawImage bildvariable, x, y, frame
DrawBlock bildvariable, x, y, frame
TileImage bildvariable, x, y, frame
TileBlock bildvariable, x, y, frame


Zählt man jetzt in einer Schleife die Framezahl immer eins weiter (mit kleinen Pausen dazwischen) und fängt nach dem letzten wieder von vorne an, hat man schonmal eine einfache Animation. Kann man natürlich noch beliebig ausweiten...

Beispiel:








Zum Schluss wollte ich eigentlich noch ein bisschen über Bild-manipulations-Befehle labern, da diese aber sehr lahm sind und nur zum vorberechnen genutzt werden können, lass ich das jetzt mal. Wer Bilder vorberechnet abspeichern will sollte dies eh mit einem guten Zeichenproggy machen, ist einfach besser...







Zusammenfassung


; BB unterstützt .png, .bmp und .jpg Bilder, die Demo nur .bmp


; Um auf den BackBuffer zu zeichnen schreibe man am Anfang des Programmes:
SetBuffer BackBuffer()


; Will man auf den sichtbaren FrontBuffer zeichnen, schreibe man garnichts (weil Standardeinstellung) oder:
SetBuffer FrontBuffer()


; Um die Buffer auszutauschen:
Flip


; Ein einfaches Bild in den Speicher laden kann man mit:
bildvariable = LoadImage("bild.bmp")


; Dieses Bild dann mit transparenter Farbe malen:
DrawImage bildvariable, x, y


; Als Block, ohne transparente Farbe malen:
DrawBlock bildvariable, x, y


; Auf dem ganzen Bildschirm "kacheln":
TileImage bildvariable, x, y
und
TileBlock bildvariable, x, y


; Die transparente Farbe eines Bilder ändern:
MaskImage bildvariable, r, g, b


; Ein Filmstreifen-Bild als Animation laden:
bildvariable = LoadAnimImage("bild.bmp", hoehe, breite, erstes_bild, bilder_anzahl)


; Die jeweiligen Einzelbilder einer Animation kann man auswählen, indem man einfach die Framenummer hinten ranhängt:
DrawImage bildvariable, x, y, frame
DrawBlock bildvariable, x, y, frame
TileImage bildvariable, x, y, frame
TileBlock bildvariable, x, y, frame


Nun denn, weiter mit Kollisionsabfrage.