IT-Academy Logo
Sign Up Login Help
Home - Programmieren - Visual Basic - Bitmap-Fonts zur Textausgabe (VB)



Bitmap-Fonts zur Textausgabe (VB)

Dieser Artikel zeigt Ihnen, wie Sie mit einem speziellen Programm Ihre eigene Schriftart für die Verwendung im selbst programmierten Computerspiel erstellen. Für die Einbindung des Fonts wird eine Visual Basic-Klasse entwickelt.


Autor: Tobias Surmann (incsoft)
Datum: 16-04-2003, 11:47:22
Referenzen: keine
Schwierigkeit: Profis
Ansichten: 9706x
Rating: 10 (1x bewertet)

Hinweis:

Für den hier dargestellte Inhalt ist nicht der Betreiber der Plattform, sondern der jeweilige Autor verantwortlich.
Falls Sie Missbrauch vermuten, bitten wir Sie, uns unter missbrauch@it-academy.cc zu kontaktieren.

[Druckansicht] [Als E-Mail senden] [Kommentar verfassen]



Einleitung

Im Artikel zu DirectDraw habe ich gezeigt, wie man mit Hilfe von DirectDraw-Funktionen einen einfachen Text auf dem Bildschirm ausgeben kann. Leider hat man nicht allzu viele Möglichkeiten die Ausgabe zu verschönern. Man kann z. B. auch nicht seine eigene Schriftart verwenden.

Mit Bitmap-Fonts ist man in der Lage, selbst erstellte Schriftarten zu verwenden. Wie der Name dieser Technik schon sagt, wird die eigens erstellte Schriftart nicht im normalen Schriftartenformat (*.ttf bzw. *.fon) abgespeichert, sondern als eine eigenständige Bitmap (*.bmp). Man bräuchte also eigentlich nur ein einfaches Grafikprogramm um eine Bitmap-Datei für seine Schriftart zu erstellen.

Doch für diesen Zweck gibt es spezielle Programme. Da das Erzeugen einer eigenen Schriftart per normalem Grafikprogramm doch recht umständlich ist, kann man sich z.B. im Internet ein spezielles Programm besorgen. Ich arbeite mit dem Programm Bitmap Font Builder, welches man von der Internetadresse

http://www.lmnopc.com/

herunterladen kann. Die Downloadgröße beträgt ungefähr 100 kByte und sollte für jeden Modemtyp schnell zu bewältigen sein.

Hinweis: Bitmap Font Builder ist keine Freeware, sondern BlabWare. Das bedeutet, dass man nach der 30-tägigen Testzeit dem Autor zur Registrierung eine E-mail schicken muss, in der man ihm mitteilt für welchen Zweck man das Programm benutzt.

Erstellung eines Bitmap-Fonts

Nach einem Doppelklick auf



öffnet sich das Hauptfenster des Programms.



Zuerst nehmen wir einige grundlegende Einstellungen vor. Wir verbessern z.B. die Darstellungsqualität der einzelnen Zeichen, indem wir im Menü Font Smoothing die Einstellung Enable (Default) aktivieren. Um die erstellte Bitmap-Datei nachher besser in unser Spiel integrieren zu können, stellen wir im Menü Character Set den ASCII (American Standard Code for Information Interchange) Zeichensatz ein, indem wir auf Full ASCII Character Set (0-255) klicken.

Die Anzeige ändert sich nun; vor allem werden viele Kästchen sichtbar. Dies lässt sich nicht vermeiden, da es im ASCII Zeichensatz ein paar Zeichen gibt, die man nicht darstellen kann, z.B. die Taste Enter oder Space.

Auf ihrem Bildschirm sollte nun folgendes zu sehen sein.



Die Schrift ist allerdings noch zu groß, deshalb stellen wir sie auf 14 ein. Und als Schriftart benutzen wir Tahoma.



Die Einstellungen können Sie hier vornehmen.

Damit sind alle Einstellungen vollständig und wir können speichern, indem wir auf File und dann auf Save BMP klicken. Wir speichern unter dem Namen Font.bmp.

Ich habe die Datei noch mit einem Bildbearbeitungsprogramm nachbearbeitet und einige Effekte hinzugefügt. Außerdem habe ich die Farbe auf blau abgeändert. Das Ergebnis sieht so aus:



Damit ist die Erstellung des Bitmap-Fonts abgeschlossen und wir können damit anfangen, das Ergebnis in ein Spiel einzubauen.

Einbindung in das eigene Computerspiel

Dazu fügen wir zuerst dem Projekt ein neues Klassenmodul hinzu. Wir nennen die Klasse cBitmapFont. Wir wechseln in den allgemeinen Deklarationsabschnitt des neuen Klassenmoduls um eine wichtige Deklaration vorzunehmen.

Private Font_Surface As DirectDrawSurface7

Die gerade erstellte Bitmap mit der Schrift darin, wird von der Klasse in der Variablen Font_Suface als DirectDraw-Surface gespeichert, sodass wir auf die Daten innerhalb der Klasse, aber nicht außerhalb, Zugriff haben.

Die Surface muss aber erst mal mit den erforderlichen Daten gefüllt werden. Für diesen Zweck ist die Class_Initialize-Prozedur wie geschaffen.

Private Sub Class_Initialize()

    If LoadSurface(Font_Surface, App.Path + _ 	
	"\gfx\Font.bmp", 512, 512, 0) = False Then
        
        MsgBox "Bitmap Font konnte nicht geladen _		
		werden!", vbCritical, "FEHLER"
        End
        
    End If
    
End Sub
Wir laden mit Hilfe der Funktion LoadSurface (welche im DirectDraw-Artikel ausführlich behandelt wurde) die Grafikdaten aus der Bitmap-Font-Datei Font.bmp in die Font_Surface-Variable. Die Bitmap bzw. Surface ist 512x512 Pixel groß und als ColorKey wird 0 (=Schwarz) verwendet. Wenn beim Laden ein Fehler auftritt, z.B. wenn nicht genug Speicher verfügbar ist, wird eine Fehlermeldung ausgegeben und das Programm wird beendet.

Wenn also ein Objekt der Klasse cBitmapFont initialisiert wird, z.B. durch

Dim BeispielBitmapFont As New cBitmapFont

wird die Class_Initialize-Prozedur aufgerufen und die Bitmap, die die Schrift enthält, geladen. Somit ist für die weiteren Operationen auf jeden Fall eine gültige Font_Surface vorrausgesetzt.

Um einzelne Zeichen der Schrift zeichnen zu können, schreiben wir eine Methode für die cBitmapFont-Klasse. Diese heißt DrawBmpText. Sie ist folgendermaßen deklariert:

Public Function DrawBmpText(x As Integer, y As _ 
Integer, text As String)

End Function
Die Funktionsparameter erklären sich eigentlich von selbst. So geben x und y an, an welcher Bildschirmposition der Text ausgegeben werden soll. Mit dem Parameter text kann man den auszugebenden Text festlegen.

Bevor ich Ihnen nun den Quelltext der Funktion zeige und erkläre, müssen wir noch einige Überlegungen anstellen. Dazu sehen wir uns die folgende Abbildung an.



Taktik zur Einbindung des Bitmap-Fonts.

Unsere Datei ist wie schon erwähnt 512x512 Pixel groß. In jeder Zeile und in jeder Spalte befinden sich jeweils 16 Zeichen. Die Breite bzw. Höhe jedes Zeichens entspricht also 32 Pixel.

Als Beispiel für weitere Überlegungen habe ich das Zeichen "Z" ausgewählt. Dieses befindet sich an den Koordinaten x=320, y=160 in der Bitmap. Diese Koordinaten müssen wir nun ausrechnen. Folgendes ist gegeben:

Spalten: 16
Zeilen: 16
ASCII-Zeichen Nr.: 90
Breite: 32
Höhe: 32

Welcher Zusammenhang ergibt sich zwischen diesen Vorgaben?

Am Besten wir fangen erst mal mit der Berechnung des x-Wertes an. Dabei müssen wir zuerst wissen, in welcher Spalte sich das "Z" befindet. Natürlich ist es Spalte 11 wie wir in Abbildung 6 sehen können. Doch wir möchten das berechnen. Das einfache Teilen von 90 durch 16 ergibt nach erster Vermutung nicht das richtige Ergebnis: 5,625. Aber behalten wir das im Hinterkopf. Mit dem Teilen liegen wir nämlich gar nicht so weit von der Lösung entfernt, wir müssen nur die Modulo-Division nehmen, also den Rest der Division. 90 durch 16 ergibt den Rest 10. Dazu könnten wir jetzt 1 addieren, um auf Spalte Nr. 11 zu kommen. Aber wir multiplizieren die 10 einfach mit der Breite eines Zeichens, also 32; ergibt 320, also das richtige Ergebnis. Warum wir nicht noch vorher die 1 hinzuaddiert haben ist ganz klar: In der ersten Spalte möchten wir das Ergebnis 0 haben, also muss anstatt 32 * 1 = 32 (falsch) 32 * 0 = 0 (richtig) gerechnet werden.

Für den x-Wert habe ich Ihnen gesagt, dass Sie das Ergebnis der normalen Teilung 90 / 16 = 5,625 im Hinterkopf behalten sollten. Wenn man die Integer-Teilung durchführt, also 90 \ 16, erhält man 5. Das ist wieder 1 weniger als die eigentliche Spalte (6) in der sich das Zeichen "Z" befindet. Mit 32 multipliziert ergibt das das richtige Ergebnis 160.

Das hört sich jetzt alles ziemlich kompliziert an, und sieht nach einer langen Formel aus, das ist es aber gar nicht, wie ich Ihnen mit diesem Quellcode beweisen kann:

Public Function DrawBmpText(x As Integer, y As _ 
Integer, text As String)

Dim i As Integer
Dim ascNummer As Integer
Dim srcRECT As RECT

    For i = 1 To Len(text)
    
        ascNummer = Asc(Mid$(text, i, 1))
                srcRECT.Left = 32 * (ascNummer Mod 16)
        srcRECT.Top = 32 * (ascNummer \ 16)
        srcRECT.Right = srcRECT.Left + 32
        srcRECT.Bottom = srcRECT.Top + 32
        
        BackBuffer.BltFast x + (14 * i), y, _ 				
		Font_Surface,srcRECT, DDBLTFAST_SRCCOLORKEY _		
		Or DDBLTFAST_WAIT
        
    Next i

End Function
Zuerst deklarieren wir den Zähler i für die Schleife, ascNummer um die ASCII-Nummer eines Zeichens zu speichern und srcRECT zur Auswahl eines rechteckigen Bereichs.

Mit der For...Next-Schleife navigieren wir durch jedes Zeichen des Strings.

Die ASCII-Nummer des aktuellen Zeichens speichern wir wie gesagt in ascNummer:

        ascNummer = Asc(Mid$(text, i, 1))
Mit srcRect wählen wir den Ausschnitt, welcher das Zeichen, das wir zeichnen möchten, enthält.

        srcRECT.Left = 32 * (ascNummer Mod 16)
        srcRECT.Top = 32 * (ascNummer \ 16)
        srcRECT.Right = srcRECT.Left + 32
        srcRECT.Bottom = srcRECT.Top + 32
Die beiden ersten Zeilen beinhalten die Formeln, die wir anhand des Beispiels "Z" herausgesucht haben. Da jedes Zeichen eine Breite und Höhe von 32 Pixeln besitzt, müssen wir zu srcRECT.Left und srcRECT.Top nur 32 hinzuaddieren.

Damit hätten wir dann alles um endlich zeichnen zu können.

        BackBuffer.BltFast x + (14 * i), y, _ 				
		Font_Surface,srcRECT, DDBLTFAST_SRCCOLORKEY _		
		Or DDBLTFAST_WAIT#
Zu dem errechneten x-Wert addieren wir nochmal (14 * i) hinzu, damit zwischen den Zeichen ein Abstand von 14 Pixeln bleibt und die Schrift dadurch besser lesbar ist.

Beispiel Um die neue Schrift in ein Spiel zu integrieren, benötigen wir zuerst ein cBitmapFont-Objekt. Dieses deklarieren wir als Private.

Private cBF As New cBitmapFont

In der Prozedur DrawSurfaces (Prozedur zur Grafikausgabe) kommentieren wir danach die Anweisungen zur "normalen" Textausgabe aus.

''Fonteigenschaften setzen
'GameForm.Font.Size = 14
'GameForm.Font.Name = "Westminster"
'
'BackBuffer.SetFont GameForm.Font
'
''Status anzeigen
'BackBuffer.SetForeColor &HFF&
'
'BackBuffer.DrawText 10, 10, "Energie: " & _ 
'sprSpieler.Energy, False
'BackBuffer.DrawText 120, 10, "Punkte: " & _ 
'PunkteStand, False
Um jetzt unsere eigene Schrift zu verwenden, rufen wir die DrawBmpText-Methode unseres cBitmapFont-Objekt cBF auf.

cBF.DrawBmpText 600, 10, "Punkte: " & PunkteStand
cBF.DrawBmpText 600, 30, "Energie: " & _ 
sprSpieler.Energy
cBF.DrawBmpText 600, 50, "FPS: " & FPS
Die Statusanzeige wird in der rechten oberen Ecke des Bildschirms dargestellt (Bildschirmauflösung: 800x600).

Speichern Sie die Änderungen nun ab und verwenden Sie als Dateinamen für die Bitmap-Font-Klasse cBitmapFont.cls.


[back to top]



Userdaten
User nicht eingeloggt

Gesamtranking
Werbung
Datenbankstand
Autoren:04508
Artikel:00815
Glossar:04116
News:13565
Userbeiträge:16552
Queueeinträge:06243
News Umfrage
Ihre Anforderungen an ein Online-Zeiterfassungs-Produkt?
Mobile Nutzung möglich (Ipone, Android)
Externe API Schnittstelle/Plugins dritter
Zeiterfassung meiner Mitarbeiter
Exportieren in CSV/XLS
Siehe Kommentar



[Results] | [Archiv] Votes: 1144
Comments: 0