Jetzt lerne ich Spiele programmieren mit Blitz Basic GERMAN

464

Click here to load reader

Transcript of Jetzt lerne ich Spiele programmieren mit Blitz Basic GERMAN

Page 1: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

Spiele programmierenmit Blitz Basic

j e t z t l e r n e i c h

Page 2: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

Unser Online-Tippfür noch mehr Wissen …

... aktuelles Fachwissen rund um die Uhr – zum Probelesen,

Downloaden oder auch auf Papier.

www.InformIT.de

Page 3: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

j e t z t l e r n e i c h

RENÉ MEYER

Spiele programmmierenmit Blitz BasicBlitzschnell zum eigenen Spiel

Markt+Technik Verlag
© Copyright-Hinweis
Copyright Daten, Texte, Design und Grafiken dieses eBooks, sowie die eventuell angebotenen eBook-Zusatzdaten sind urheberrechtlich geschützt. Dieses eBook stellen wir lediglich als persönliche Einzelplatz-Lizenz zur Verfügung! Jede andere Verwendung dieses eBooks oder zugehöriger Materialien und Informationen, einschliesslich der Reproduktion, der Weitergabe, des Weitervertriebs, der Platzierung im Internet, in Intranets, in Extranets, der Veränderung, des Weiterverkaufs und der Veröffentlichung bedarf der schriftlichen Genehmigung des Verlags. Insbesondere ist die Entfernung oder Änderung des vom Verlag vergebenen Passwortschutzes ausdrücklich untersagt! Bei Fragen zu diesem Thema wenden Sie sich bitte an: [email protected] Zusatzdaten Möglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die Zurverfügungstellung dieser Daten auf unseren Websites ist eine freiwillige Leistung des Verlags. Der Rechtsweg ist ausgeschlossen.
praktit01
Notiz
Completed festgelegt von praktit01
praktit01
Notiz
MigrationConfirmed festgelegt von praktit01
Page 4: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

Bibliografische Information Der Deutschen BibliothekDie Deutsche Bibliothek verzeichnet diese Publikation in der DeutschenNationalbibliografie; detaillierte bibliografische Daten sind im Internetüber <http://dnb.ddb.de> abrufbar.

Die Informationen in diesem Produkt werden ohne Rücksicht auf eineneventuellen Patentschutz veröffentlicht.Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt.Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter Sorgfalt vorgegangen.Trotzdem können Fehler nicht vollständig ausgeschlossen werden.Verlag, Herausgeber und Autoren können für fehlerhafte Angabenund deren Folgen weder eine juristische Verantwortung nochirgendeine Haftung übernehmen.Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag undHerausgeber dankbar.

Alle Rechte vorbehalten, auch die der fotomechanischenWiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigtenModelle und Arbeiten ist nicht zulässig.

Fast alle Hardware- und Software-Bezeichnungen, die in diesem Bucherwähnt werden, sind gleichzeitig auch eingetragene Warenzeichenoder sollten als solche betrachtet werden.

Umwelthinweis:Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt.

10 9 8 7 6 5 4 3 2 1

05 04 03

ISBN 3-8272-6544-4

© 2003 by Markt+Technik Verlag,ein Imprint der Pearson Education Deutschland GmbH,Martin-Kollar-Straße 10–12, D-81829 München/GermanyAlle Rechte vorbehaltenLektorat: Birgit Ellissen, [email protected]: Claudia Bäurle, [email protected]: independent Medien-Design, MünchenCoverlayout: adesso, MünchenTitelillustration: Karin DrexlerSatz: text&form GbR, FürstenfeldbruckDruck und Verarbeitung: Bosch, ErgoldingPrinted in Germany

Page 5: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

5

jetz

t le

rne

ich

Übersicht

Willkommen! 171 Es war einmal ... 192 Die ersten Schritte 273 Die Grundpfeiler von Programmen 374 Variablen 555 Zahlen und Zeichenketten 716 Arbeiten im Grafikmodus 997 Zeichnen 1078 Bilder 1159 Sichtfenster und Aufsätze 13110 Pixeleien 13511 Text und Fonts 13912 Maus abfragen 14513 Tastatur abfragen 15114 Joystick abfragen 15715 Töne und Musik 16116 Videos 16917 Dateien 17318 Datenaustausch im Netzwerk 19519 Grafikseminare 20920 Programmieren wir ein Spiel! 25521 3D-Grafik mit Blitz Basic 3D 32122 Bedienoberflächen mit Blitz Plus 34123 Programmierstil und Fehlersuche 36724 Von der Idee zum Spiel 381Anhang A: Die Buch-CD 405Anhang B: Der Editor von Blitz Basic 407Anhang C: Tabellen 413Stichwortverzeichnis 417

Auf der CD-ROM finden Sie noch zusätzlich:

25 Vertriebsformen von Spielen VERTRIEB.PDFLösungen zu den Aufgaben AUFGABENLÖSUNGEN.PDFMenüpunkte des Editors MENÜPUNKTE.PDF

Page 6: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

»A programmer is just a tool which converts caffeine into code«

(anonym)

Im Sinne dieses bekannten und vielsagenden Zitats widmen Ihnen die Autoren undLektoren der Buchreihe »Jetzt lerne ich« in jeder Ausgabe ein Rezept mit oder rund umdas belebende und beliebte Getränk. Sollten Sie gerade ohne Bohnen oder Pulver sein:Über die Adresse http://www.kaffee.mut.de können Sie einen eigens entwickeltenMarkt+Technik Programmiererkaffee bestellen.

Viel Spaß und Genuß!

Panocha do Brasil

––––––––––––––––––––––––––––––––––––––

400 g brauner Rohrzucker1/2 Tasse starker Kaffe2 Teelöffel Honig40 g Butter1 Päckchen Vanillezucker60 g gehackte Paranüsse

––––––––––––––––––––––––––––––––––––––

In einem Saucenpfännchen Zucker, Kaffee und Honig vermischen. Bei leichter Hitzeunter ständigem Umrühren ankochen lassen, bis der Zucker geschmolzen ist. Das Pfänn-chen vom Herd nehmen, die Butter dazugeben, ohne jedoch umzurühren, und auf lau-warm abkühlen lassen. Vanillezucker beifügen, dann mit einer Gabel die Mischung schla-gen, bis sie ihr glänzendes Aussehen verliert. Dann die Nüsse untermengen. Die Masse ineine rechteckige Form gießen, kaltstellen und in kleine längliche Vierecke zerteilen.

Panocha sind Maiskolben. Die Fantasie machte im Kaffeeland Brasilien aus diesemRezept ganz einfach »brasilianische Maiskolben«.

Das Kaffeerezept wurde entnommen aus:

»Kaffee«Dr. Eugen C. BürginSigloch Edition, BlaufeldenISBN: 3-89393-135-X

Mit freundlicher Genehmigung des Verlags.

Page 7: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

7

jetz

t le

rne

ich

Inhaltsverzeichnis

Willkommen! 17

1 Es war einmal ... 191.1 Wie spricht ein Computer? 201.2 Basic 221.3 Blitz Basic 231.4 Drei Versionen 241.5 Erwerb schwergemacht 25

2 Die ersten Schritte 272.1 Der Editor 272.2 Text ausgeben 292.3 Variablen 312.4 Eingaben 332.5 Kommentare 332.6 Befehlstrenner 342.7 Programmnamen festlegen 342.8 Ganzer Bildschirm 342.9 Aufgaben 35

3 Die Grundpfeiler von Programmen 373.1 Verzweigungen 373.1.1 Programm beenden 373.1.2 Die If-Verzweigung 383.1.3 EndIf 393.1.4 Die Case-Verzweigung 403.2 Schleifen 413.2.1 Die For-Schleife 413.2.2 Sofort aussteigen 443.2.3 Die Repeat-Schleife 443.2.4 Die While-Schleife 45

Page 8: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

8

Inhaltsverzeichnisj e t z t l e r n e i c h

3.3 Sprünge 453.4 Unterprogramme 473.5 Funktionen 483.5.1 Globale Variablen 513.6 Rekursion 523.7 Aufgaben 54

4 Variablen 554.1 Datentypen 554.1.1 Ganze Zahlen 564.1.2 Fließkommazahlen 564.1.3 Zeichenketten 584.1.4 Typumwandlung 584.2 Konstanten 594.3 Felder 604.4 Daten einlesen 624.4.1 Zeiger versetzen 634.5 Blitz Arrays 644.6 Benutzerdefinierte Typen 654.6.1 Dim-Felder aus Typen 674.6.2 Dynamische Type-Liste 674.7 Aufgaben 70

5 Zahlen und Zeichenketten 715.1 Das Mathe-1x1 715.1.1 Modulo 715.1.2 Zahlen runden 725.1.3 Vorzeichen 725.1.4 Die Konstante Pi 735.1.5 Potenz berechnen 735.1.6 Wurzel ziehen 735.1.7 Logarithmus-Funktion 735.2 Winkelberechnungen 745.2.1 Rechtwinklige Dreiecke 745.2.2 Beliebige Dreiecke 755.2.3 Winkelfunktionen mit Blitz Basic 765.3 Logische Operatoren 775.3.1 Not 775.3.2 And und Or 775.3.3 Xor 785.3.4 True und False 785.4 Bytes, Hexzahlen und binäres Rechnen 795.4.1 Befehlscode 805.4.2 Hexzahlen 815.4.3 Binär- und Hexzahlen mit Blitz Basic 835.4.4 Binäre Manipulationen 835.5 Messen der Zeit 845.5.1 Pause 845.5.2 Zeitspannen 855.5.3 Datum und Uhrzeit ermitteln 865.6 Zufallszahlen 86

Page 9: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

9

Inhaltsverzeichnis j e t z t l e r n e i c h

5.7 Verändern von Zeichenketten 875.7.1 Rechtsbündiger Text 895.7.2 Text verschlüsseln 905.7.3 Rückwärts-Text 915.7.4 Glücksrad 915.8 Daten sortieren 925.8.1 Daten suchen 945.8.2 Binäre Suche 955.9 Aufgaben 97

6 Arbeiten im Grafikmodus 996.1 Grafikmodus 996.1.1 Auflösung 1006.1.2 Farbtiefe 1016.1.3 Fenstermodus 1016.2 Verfügbare Treiber und Modi abfragen 1026.2.1 Ansteuern verschiedener Treiber 1026.2.2 Ansteuern verschiedener Auflösungen 1036.2.3 Größe des Grafikspeichers ermitteln 1036.3 Bildschirmpuffer 1046.4 Koordinaten 1056.5 Bildschirm löschen 1056.6 Das Grafikgerüst 1056.7 Aufgaben 106

7 Zeichnen 1077.1 Punkte zeichnen 1077.1.1 Linien 1087.1.2 Vierecke 1087.1.3 Kreise und Ovale 1097.2 Farben 1117.3 Aufgaben 113

8 Bilder 1158.1 Bild laden 1178.2 Bild anzeigen 1188.3 Bildgröße ermitteln 1198.4 Bildgröße verändern 1208.5 Bild drehen 1208.6 Bezugspunkt ändern 1228.7 Ausschnitte von Bildern 1238.8 Ausschnitt kopieren 1248.9 Transparenz 1258.9.1 Transparenzfarbe ändern 1258.9.2 Ohne Transparenz zeichnen 1268.10 Bildpuffer 1268.10.1 Bild verändern 1268.10.2 Ausschnitt in Bild kopieren 1278.10.3 Bild kopieren 1278.10.4 Bild erzeugen 1288.10.5 Bild speichern 1288.10.6 Bild in Puffer laden 129

Page 10: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

10

Inhaltsverzeichnisj e t z t l e r n e i c h

8.11 Puffer abspeichern 1298.12 Aufgabe 130

9 Sichtfenster und Aufsätze 1319.1 Aufgabe 133

10 Pixeleien 13510.1 Rot, Grün, Blau 13510.2 Puffer und Punkte 13710.3 Puffer sperren 13710.4 Aufgabe 138

11 Text und Fonts 13911.1 Text 13911.2 Fonts 14111.2.1 Font laden 14111.2.2 Font verwenden 14211.3 Fontgröße ermitteln 14311.4 Font löschen 14411.5 Aufgabe 144

12 Maus abfragen 14512.1 Drücken von Maustasten ermitteln 14512.2 Mausklicks zählen 14712.3 Mauspuffer löschen 14712.4 Mausrad abfragen 14712.5 Mausposition ermitteln 14812.6 Mausposition festlegen 14912.7 Mausbewegung feststellen 14912.8 Aufgabe 150

13 Tastatur abfragen 15113.1 Zeichen von der Tastatur einlesen 15113.2 Scancode ermitteln 15313.3 Tastendrücke zählen 15513.4 Tastenpuffer löschen 15513.5 Aufgabe 156

14 Joystick abfragen 15714.1 Art des Joysticks ermitteln 15714.2 Joystick-Tasten abfragen 15814.3 Bewegung des Steuerknüppels feststellen 15814.4 Aufgabe 160

15 Töne und Musik 16115.1 Toneffekte 16215.2 Musik 16315.3 Audio-CDs 16415.4 Musikkanäle und Steuerbefehle 16515.4.1 Kanal anhalten 16515.4.2 Lautstärke regeln 16615.4.3 Balance einstellen 16615.4.4 Frequenz ändern 16715.5 Aufgabe 168

Page 11: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

11

Inhaltsverzeichnis j e t z t l e r n e i c h

16 Videos 16916.1 Video öffnen 16916.2 Abspielen eines Videos 17016.3 Größe eines Videos ändern 17116.4 Video schließen 17116.5 Wiederholtes Abspielen 17216.6 Aufgabe 172

17 Dateien 17317.1 Verteilte Quelltexte 17317.2 Lesen und Verändern von Verzeichnissen 17417.2.1 Ordnernamen ermitteln 17417.2.2 Ordner auslesen 17417.2.3 Ordner wechseln 17617.2.4 Ordner erstellen 17717.2.5 Ordner löschen 17717.2.6 Datei löschen 17717.2.7 Datei kopieren 17717.3 Öffnen von Dateien 17717.3.1 Lesen und Schreiben von Daten 17817.3.2 Little Endian Format 18117.3.3 Eof() 18117.3.4 Dateizeiger ändern 18117.4 Speicherbänke 18217.4.1 Speicherbank erstellen 18317.4.2 Speicherbank beschreiben und auslesen 18317.4.3 Datenaustausch zwischen zwei Speicherbänken 18417.4.4 Datenaustausch zwischen Datei und Speicherbank 18417.5 Patch programmieren 18517.6 Ordner des Betriebssystems erfragen 18817.7 Andere Programme ausführen 18817.8 DLLs ausführen 18917.8.1 CallDLL 19017.8.2 UserLibs 19017.9 Parameter übergeben 19117.10 Fehlermeldung erzeugen 19317.11 Aufgaben 193

18 Datenaustausch im Netzwerk 19518.1 Netzwerkspiel einrichten 19618.2 Spieler erstellen 19818.3 Nachricht versenden 19818.4 Nachricht empfangen 19918.5 Systemnachrichten 20018.6 Details einer Nachricht erfragen 20018.7 Nachricht interpretieren 20218.8 Netzwerkverbindungen mit UDP 20418.8.1 Nachricht empfangen und lesen 20518.8.2 Empfänger ermitteln 20518.8.3 Nachricht senden 20518.8.4 Beispiel 20618.9 Aufgabe 207

Page 12: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

12

Inhaltsverzeichnisj e t z t l e r n e i c h

19 Grafikseminare 20919.1 Animationen 20919.1.1 Figur animieren 21019.1.2 Figur animieren II 21119.1.3 Explosionen 21319.2 Kollisionen 21419.2.1 Rand testen 21419.2.2 Überlappung von zwei Bereichen 21619.2.3 Kollision eines Bilds mit einem Bereich 21719.2.4 Kollision zweier Bilder 21919.2.5 Programmieren von Schaltern 22019.2.6 Eigene Berechnung der Kollision 22219.3 Frame-Rate berechnen 22219.4 Sternenhimmel 22319.5 Bunte Linien 22619.6 Sinuskurve 22719.7 Flugbahnen 22819.8 Drehung um die eigene Achse 22819.9 Eingabefunktion 23019.10 Laufschrift 23119.11 Schreibmaschineneffekt 23319.12 Zeilenumbruch erzwingen 23419.13 Beweglicher Hintergrund 23519.14 Übergänge gestalten 23719.15 Bildschirm »wackeln« lassen 23919.16 Gamma-Wert ändern 23919.17 Energiebalken 24219.17.1 Balken aus zehn Teilen 24219.17.2 Balken mit stufenloser Farbänderung 24519.17.3 Balken aus einer Grafik 24519.18 Ablaufsteuerung 24719.18.1 Ampel steuern 24819.18.2 Ampel programmieren 25019.19 Ballphysik 253

20 Programmieren wir ein Spiel! 25520.1 Menüs gestalten 25620.2 Spielschleife und Timing 26020.2.1 Taktfrequenz 26120.2.2 Takt programmieren 26220.2.3 Timer-Befehle 26220.2.4 Delay 26320.3 Gerüst für einen Weltraum-Shooter 26320.3.1 Schiff steuern 26420.3.2 Rand einrichten 26420.3.3 Schüsse 26420.3.4 Gegner 26620.3.5 Kollision 26920.3.6 Ausblicke 27220.4 Gerüst für Pac-Man & Co. 27220.4.1 Level einlesen 273

Page 13: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

13

Inhaltsverzeichnis j e t z t l e r n e i c h

20.4.2 Level zeichnen 27420.4.3 Spielfigur darstellen 27520.4.4 Spielfigur bewegen 27520.4.5 Gegner 27620.4.6 Zusammenstöße 27820.4.7 Ausblicke 28220.5 Gerüst für Sokoban 28220.5.1 Auswertung 28320.5.2 Ausblicke 28720.6 Gerüst für ein Verschiebe-Puzzle 28720.6.1 Spielsteine drucken 28820.6.2 Mauszeiger einzeichnen 29020.6.3 Mausposition auswerten 29120.6.4 Aktives Feld hervorheben 29320.6.5 Stein verschieben 29320.6.6 Auswertung 29420.6.7 Ausblicke 29720.7 Gerüst für ein Jump'n'Run-Spiel 29720.7.1 Kachel-Scrolling 29720.7.2 Springen 30020.7.3 Kollisionsabfrage 30120.7.4 Aufwendigere Levels 30220.7.5 Scrolling 30320.7.6 Ausblicke 30620.8 Gerüst für ein Abenteuer-Spiel 30620.9 KI-Beispiel mit »Nimm weg« 31220.10 Service-Funktionen 31620.10.1 Spielstand speichern 31620.10.2 Cheat 31720.10.3 Pause-Modus 31720.10.4 Screenshot-Taste 318

21 3D-Grafik mit Blitz Basic 3D 32121.1 Grafikmodus 32221.2 Das Gerüst eines 3D-Programms 32221.3 3D-Koordinaten 32421.4 Einfache Körper erstellen 32421.4.1 Kugel 32521.4.2 Zylinder 32521.4.3 Kegel 32621.4.4 Würfel 32621.5 Körper färben 32621.6 Körper bewegen 32621.7 Körper drehen 32721.8 Texturen 32921.9 Meshes 32921.10 Sprites 33221.11 Kamera 33321.11.1 Hintergrund 33321.11.2 Sichtfeld festlegen 33321.11.3 Zoomstufe festlegen 334

Page 14: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

14

Inhaltsverzeichnisj e t z t l e r n e i c h

21.12 Licht 33521.12.1 Umgebungslicht 33521.12.2 Örtliches Licht 33521.13 Ebenen 33621.14 Terrains 33721.15 Ausblicke 33921.16 Aufgabe 339

22 Bedienoberflächen mit Blitz Plus 34122.1 Fenster erstellen 34222.1.1 Größe verändern 34222.1.2 Größe abfragen 34322.1.3 Statuszeile ändern 34322.2 Menüs 34322.2.1 Menüpunkt (de)aktivieren 34522.2.2 Name eines Menüpunkts ändern 34622.3 Toolbars 34622.3.1 Toolbar beschriften 34722.3.2 Icons deaktivieren 34722.4 Ereignisse 34722.5 Hotkeys 34922.6 Gadgets 35022.7 Gruppen und Panele 35122.8 Schalter 35222.8.1 Schalter auswerten 35322.9 Textausgabe 35322.10 Texteingabe 35422.10.1 TextField 35422.10.2 Textarea 35522.11 Listen 35622.12 Register 35722.13 Scrollbalken 35922.14 Baumstrukturen 36022.15 Standardfenster 36122.15.1 Hinweis 36122.15.2 Bestätigung 36222.15.3 Fontauswahl 36322.15.4 Farbauswahl 36322.15.5 Ordnerauswahl 36322.15.6 Dateiauswahl 36422.15.7 Fortschrittsanzeige 36422.15.8 HTML-Anzeige 36522.16 Grafikfenster 36522.17 Aufgaben 366

23 Programmierstil und Fehlersuche 36723.1 Fehlersuche 37023.1.1 Variablen 37023.1.2 Division durch 0 37023.1.3 Funktionen 37023.1.4 Zählung ab 0 371

Page 15: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

15

Inhaltsverzeichnis j e t z t l e r n e i c h

23.1.5 Auskommentieren 37123.1.6 Überschlafen 37123.1.7 Beta-Test 37123.1.8 Debugger 37223.1.9 DebugLog 37323.2 Optimierung I: Programmstruktur 37423.2.1 Überflüssiges meiden 37423.2.2 Fließkommazahlen vermeiden 37423.2.3 Werte vorausberechnen 37423.2.4 Shl und Shr 37523.2.5 Konstanten statt Variablen 37523.2.6 Datenfelder statt Types 37523.2.7 Schleifen entschlacken 37523.2.8 Schleifen verkürzen 37523.2.9 Schleifen vermeiden 37523.2.10 If-Bedingungen vereinfachen 37623.2.11 If-Bedingungen zusammenfassen 37623.2.12 Gosub statt Function 37623.2.13 Sprünge vermeiden 37623.3 Optimierung II: Grafik 37723.3.1 Geringere Farbtiefe 37723.3.2 Geringere Auflösung 37723.3.3 Vollbildmodus 37723.3.4 Punkte beschleunigen 37723.3.5 Linien beschleunigen 37723.3.6 Schnelle Pixelbilder 37823.3.7 Farblesen beschleunigen 37823.3.8 Schnelles Kopieren 37823.3.9 Bilder laden 37823.3.10 Gleichzeitig kopieren und einzeichnen 37823.3.11 Auf Cls verzichten 37823.3.12 Kollisionsprüfung optimieren 37823.3.13 Bildgröße ändern 37923.3.14 Bilder drehen 37923.3.15 Grafiken vorausberechnen 37923.3.16 Platz freischaufeln 37923.4 Datensicherung 380

24 Von der Idee zum Spiel 38124.1 Spielidee 38224.2 Projektplanung 38724.3 Arbeiten im Team 38724.4 Namensfindung 39324.4.1 Teamname 39324.4.2 Spielnamen 39524.4.3 Namen für Spielfiguren 39624.5 Spieldesign 39724.5.1 Motivation 39824.5.2 Schwierigkeitsgrad 39924.5.3 Bedienung 39924.5.4 Speichern 399

Page 16: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

16

Inhaltsverzeichnisj e t z t l e r n e i c h

24.5.5 Cheats 40024.5.6 Hilfe 40024.6 Das Spielpaket 40024.6.1 Icon erstellen 40024.6.2 Elektronische Anleitungen 40124.6.3 FILE_ID.DIZ 40224.6.4 ZIP-Archiv 40224.6.5 Installer 403

Anhang A: Die Buch-CD 405

Anhang B: Der Editor von Blitz Basic 407

Anhang C: Tabellen 413

Stichwortverzeichnis 417

Auf der CD-ROM finden Sie noch zusätzlich:

25 Vertriebsformen von Spielen VERTRIEB.PDF25.1 Freeware c 125.2 Shareware c 225.3 Jugendschutz c 525.4 Kommerzieller Erfolg c 625.4.1 Kontakt zu einem Verlag c 625.4.2 Unterlagen sorgfältig vorbereiten c 825.4.3 Mögliche Erlöse c 925.4.4 Der Vertrag c1225.5 Werbespiele c1425.6 Online-Vertrieb c1525.7 Verbreitungshilfen c1725.7.1 Website c1725.7.2 Softwarearchive c1925.7.3 Zeitschriften c2025.7.4 CD-ROM c2125.7.5 Pressearbeit c2125.7.6 PR-Agentur c2325.8 Beruf Spieleentwickler? c24

Lösungen zu den Aufgaben AUFGABENLÖSUNGEN.PDFMenüpunkte des Editors MENÜPUNKTE.PDF

Page 17: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

17

jetz

t le

rne

ich

Willkommen!

Wenn Sie bisher nicht programmieren konnten, aber auf einfache Weise selbst Spieleentwickeln möchten, sind Sie hier goldrichtig. Blitz Basic ist kein Baukastensystem, beidem Sie vorgefertigte Elemente zusammensetzen, sondern eine »richtige« Program-miersprache, die Ihren Ideen keine Grenzen setzt. Bereits nach wenigen Stunden wer-den Sie Ihre ersten Programme schreiben, einfache Spiele schon nach einigen Tagen.

Dieses Buch führt Sie in die Grundlagen von Blitz Basic ein und beschreibt alle Elemen-te, die Sie für das Entwickeln eigener Spiele benötigen: Wie zeichnet man ein Bild aufden Bildschirm? Wie fragt man Maus und Tastatur ab? Wie lässt man den Computer»klug« reagieren?

Im Allgemeinen ist das Entwickeln von Spielen unter Windows eine komplizierte An-gelegenheit und die bisher geschriebenen Bücher richten sich an Experten. Blitz Basicist eine fabelhafte Chance für Anfänger. Diese Chance galt es zu wahren, durch beson-ders leicht verständliche Beschreibungen, kurze Beispiele und einen Schwierigkeits-grad, der durchgehend niedrig bleibt. Der beste Lehrmeister ist ohnehin die Erfahrung.Arbeiten Sie mit der Sprache, denken Sie sich einfache Aufgaben aus und lösen Siesie. Auf der Buch-CD finden Sie weiterführende Anleitungen.

Falls Sie Fragen zu Blitz Basic haben oder einmal nicht mehr weiterwissen, sollten Siesich an das Internetforum www.blitzforum.de wenden. Dort helfen Ihnen erfahreneBlitz-Programmierer und auch der Autor dieses Buchs liest mit.

1Oberflächlich gesehen definieren wir Menschen uns durch unser Aussehen, unser Ge-sicht und unsere Stimme. Doch was wäre die Haut ohne das stützende Skelett, ohneOrgane und Adern? Ähnlich verhält es sich mit Spielen. Auch sie fallen durch ihr Äu-ßeres auf, durch ihre Grafik und ihren Sound. Es ist sehr einfach, ein Bild auf den Bild-schirm zu pinnen. Aufwendig wird es, wenn es den Pfeiltasten folgen soll. Ein Spielbesteht vor allem aus Regeln bezüglich des Umgangs mit Grafik und Tönen und nichtaus dem Präsentieren für Auge und Ohr selbst. Daher befasst sich ein Großteil desBuchs nicht etwa mit Bildern und Klängen, sondern mit den Helfern im Hintergrund.

Page 18: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

18

Willkommen!j e t z t l e r n e i c h

Der AutorRené Meyer, Jahrgang 1970, erlernte bereits in den achtziger Jahren das Program-mieren an Homecomputern. Zu dieser Zeit entstanden seine ersten Spiele – natürlichin Basic. Seit elf Jahren arbeitet der Leipziger als Journalist für Computerthemen,überwiegend für die Frankfurter Allgemeine Zeitung. Seine Vorliebe gilt der Verbin-dung aus Spielen und Technik. Sie kam in mehr als fünfzig veröffentlichten Büchernzum Vorschein. Die von ihm mitaufgebaute Website www.mogelpower.de zählt zu denmeistbesuchten Adressen rund um Spiele. Meyer ist verheiratet und hat einen ein-jährigen Sohn.

Der Autor und der Verlag sind jederzeitoffen für Kritik und Verbesserungsvorschlä-ge. In diesem Falle können Sie sich gernemit einer E-Mail an den Autor wenden.Seine Adresse im Verlag Markt+Technik:[email protected]

Es gibt zwei Arten, sich einer Programmiersprache zu nähern: die angenehme unddie sinnvolle. Das Problem bei der angenehmen Herangehensweise ist, dass Ihnen ir-gendwann das Sinnvolle fehlen wird. Aus diesem Grund werden einige Themen spä-ter behandelt, als Sie sich sicher wünschen würden. Das müssen Sie aber nicht so hin-nehmen: Nach den Anfangskapiteln »Die ersten Schritte mit Blitz Basic« und »DieGrundpfeiler von Programmen« unternehmen Sie getrost einen Ausflug in die Gebie-te Grafik und Eingaben, bevor Sie den Rest der »Theorie« absolvieren. Einige Berei-che, wie Arbeiten mit Dateien, Multiplayer-Spiele und Typen, schieben Sie weit nachhinten, wenn Ihnen zunächst die Lust dazu fehlt. Abschnitte, die kein Grundwissenenthalten und vergleichsweise anspruchsvoll sind, wurden in der Überschrift mit Agekennzeichnet. Das heißt nicht, dass diese Teile überflüssig sind. Sie behandeln fort-geschrittene Themen, die für die ersten Wochen nicht notwendig sind. BestimmteBeispiele waren Opfer des linearen Aufbaus eines Buchs: Zeige ich Ihnen zuerst Gra-fiken, kann ich keine Maus- und Tastaturbefehle zum Verschieben von Bildern vor-aussetzen. Behandle ich zuerst das Thema Eingaben, kennen Sie die Grafikbefehlenoch nicht, mit denen Sie Bilder per Maus steuern.

Als Einsteigerbuch kann dieses Buch nicht allzu sehr in die Tiefe gehen. Unmengenan weiterführendem Material finden Sie auf der Buch-CD, darunter Workshops undBlitz-Basic-Programme, die Sie studieren sollten. Die Silberscheibe enthält darüberhinaus zahllose Hilfsmittel rund um das Programmieren, etwa eine Reihe von Grafik-programmen.

Page 19: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

19

jetz

t le

rne

ich

KAPITEL 1

Es war einmal ...

... ein starkes Gefühl: In jenen Zeiten, als flatternde Banner und blinzelnde Smileysnoch nicht erfunden waren, als niemand in Fenster hineinblickte, weil nichts aus Win-dows herausschaute, ging es gar nicht anders. Durch Programmierung erweckte derComputerfreund – recht simple – Grafiken zum Leben. Sich dabei als Herr jedes ein-zelnen Pixels zu fühlen, war im Umgang mit dem Homecomputer allerdings auch einleichtes Spiel. Nach dem Einschalten befand man sich sofort »im Basic«: Blinkend war-tete der Cursor auf die Eingabe eines Befehls – und sonst tat sich rein gar nichts. Wermehr wollte, war gezwungen, sich mit der weit verbreiteten Programmiersprache aus-einander zu setzen. In deren Namen steht das B für Beginner. Diesem wurde es rechteinfach gemacht. Die etwas pfiffigeren Programmierer beklagten häufig die mangeln-de Eleganz von Basic und die verzopften Wege der Codezeilen, mit denen man etwabefahl, es solle ein Kreuz von links nach rechts über den Bildschirm huschen.

Verglichen mit diesen Zuständen ist heute für den Benutzer alles viel einfacher: Manschaltet den PC ein und schon fängt dieser an, munter zu telefonieren und Videos ab-zuspielen. Weil eben alles so multimedial zugeht, gestaltet sich die Programmierungheute allerdings weitaus komplizierter. Die Entwicklungsumgebungen sind Byte-Mons-ter, die Dokumentationen umfassen Hunderte von Seiten. Und wer etwa ein Spiel ent-wickeln will, sollte sich zudem mit der Schnittstelle DirectX beschäftigen, die als Ver-mittler zur multimedialen Hardware dient.

Doch die Zeiten, in denen man bereits nach einer Stunde Selbststudium erste Abläufezusammensetzen konnte, lassen sich zurückholen. Blitz Basic kümmert sich gar nichtum die Tücken der Windows-Welt wie Fensterverwaltung, Menüpunkte oder Objekt-orientierung, sondern bietet dem Hobbydesigner einen schwarzen Bildschirm, der sichnach Belieben mit Interaktion füllen lässt. Innerhalb eines Tages kann ein Anfängereinfache Textspielchen entwerfen, innerhalb einiger Wochen ein ganzes Projekt im Stilvon »Pac-Man« umsetzen.

Allerdings: Programmieren allein reicht nicht, um ein gutes Spiel zu entwickeln. EineIdee sollte man schon haben, um daraus ein Konzept zu entwickeln, das als Gerüst mit

Page 20: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

20

Es war einmal ...1j e t z t l e r n e i c h

Grafik und Tönen gefüllt werden muss. Wohl lassen sich die Ton- und Bildschnipsel dermitgelieferten Beispielprogramme nutzen, doch wer eigene Ideen umsetzen will,kommt nicht umhin, auch den Umgang mit einem Grafikprogramm zu erlernen, umHintergrundbilder und Figuren zu gestalten – oder jemanden zu finden, der ihm dieseArbeit abnimmt.

1.1 Wie spricht ein Computer?

Programmiersprache, das klingt so, als ob Computer sprechen würden. Vor allemklingt es kompliziert. Würden sich Computer miteinander unterhalten, dann bestimmtnicht in einer Sprache, die wir verstehen. Es wäre eher etwas wie $%T~G48§2GK;Tz.

Ein Computer ist keine besonders schlaue Maschine. Er führt unablässig Befehle aus.Selbst wenn ein Computer zu »denken« scheint, sind seine Verhaltensmuster program-miert. Sicher haben Sie schon davon gehört, dass ein Bit die Grundlage elektronischerRechner ist. Stellen Sie sich ein Bit als Lichtsignal vor: Das Licht ist entweder ein oderaus. Die Glühlampe speichert eine von zwei möglichen Informationen. Doch was kannman damit anfangen?

Nehmen wir an, die Glühlampe befindet sich in einem Raum. Und im Nachbarraum istebenfalls eine Glühlampe. Damit haben wir zwei einzelne Speicher von Informationen.Die Zauberei beginnt an der Stelle, an der wir beide Leuchten zu einer Einheit zusam-menfassen. Damit haben wir nämlich eine von vier Informationen:

Benjamin »Inarie« Bisping, www.inarie.de.vu: »Blitz Basic eignen Sie sich (wie diemeisten Dinge im Leben) durch »Learning by doing« an, durch Praxis: Der Versuchmacht klug. Tutorials und Bücher sollen und können nur die Grundlagen vermitteln.Selbst nach der Lektüre eines starken Buches werden Sie kein Experte sein. Auch dasstumpfe Abtippen von Codes hilft kaum weiter. Programmieren Sie! Denken Sie sichkleinere Aufgaben aus, setzen Sie sie um. Selbst wenn Sie scheitern – die gewonneneErfahrung ist unschätzbar. Mit wachsenden Fähigkeiten lösen Sie Probleme immerschneller und eleganter. Doch tüfteln Sie nicht nur im stillen Kämmerlein. Lesen SieCodes von anderen Programmierern, verfolgen Sie Diskussionsforen, um immerneue Impulse zu erhalten.«

Marc Kamradt, www.spieleentwickler.org: »Computerspiele zu entwickeln ist fürviele ein Traum. Das Hobby wird zum Beruf, man wird vom Konsument zum Macher.So ungefähr stellen sich viele Einsteiger die Arbeit in der Branche vor. Jedoch mussman sich darüber im klaren sein, dass die Entwicklung von Computerspielen (genauwie jeder anderen Software) ein unglaublich komplexer Vorgang ist, den man inmühevoller Kleinarbeit lernen und begreifen muss. Der Einstieg in die Spieleentwick-lung ist also nicht »mal eben schnell« möglich. Schon gar nicht wird man sich in derersten Zeit mit Firmen und deren Produkten messen können, die schon über vieleJahre eine Vielzahl von Spielen entwickelt haben. Es ist also immens wichtig, sich amAnfang nicht in unrealistische Vorstellungen zu verlieben. Leider zählt auch in dieserBranche der Satz: Jeder hat mal klein angefangen.«

Page 21: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

21

Wie spricht ein Computer? j e t z t l e r n e i c h

Mithilfe der Lampen vereinbaren wir mit einem Vertrauten ein geheimes Signal. Wiewäre es damit: In einer Serie von hell erleuchteten Räumen verschlüsseln wir die Infor-mation, an welchem Tag wir uns treffen wollen. Nun hat aber ein Monat bis zu 31 Ta-ge. Mit unseren beiden Schaltern können wir nur eine von vier Informationen ange-ben. Wir brauchen mehr Lampen. Mit einer dritten Leuchte erhöhen wir die Zahl derMöglichkeiten bereits auf 8, mit einer vierten auf 16 und mit einer fünften auf 32.

Es ist wohl kein Geheimnis mehr: Jede weitere Glühlampe verdoppelt die bisherigenMöglichkeiten. 100 Leuchten ergeben so viele Stellungen, wie sie eine ganze Stadt einMenschenleben lang nicht ausführen könnte. Mithilfe eines Taschenrechners ermittelnSie leicht, wie viele Lampen wie viele Möglichkeiten ergeben: Sie rechnen einfach »2hoch x«, wobei x für die Zahl der Leuchten steht.

Um eine Zahl von 1 bis 31 zu entschlüsseln, reichen fünf Lampen aus. Ich nehme malfür »Aus« eine Null und für »Ein« eine Eins, um Ihnen das zu zeigen:

Tag 1: 00001Tag 2: 00010Tag 3: 00011Tag 4: 00100Tag 5: 00101Tag 6: 00110Tag 7: 00111...Tag 30: 11110Tag 31: 11111

Es genügt das Leuchten von fünf Deckenlampen in einer bestimmten Kombination,um einem Eingeweihten mitzuteilen, an welchem Tag das Treffen stattfindet. Er mussnur am Haus vorbeilaufen und einen Blick auf die Fenster werfen. Mit zusätzlichenLampen verleihen wir der Botschaft mehr Details, geben etwa die Uhrzeit an.

So arbeiten Computer, nur mit etwas mehr Leuchten. In den Anfängen des Compu-terzeitalters waren es einige hundert, dann einige tausend. Heute sind es Millionen. Die»Glühlampen«, die zur Anwendung kommen, sind winzige Schalter, Transistoren ge-nannt. Jeder Buchstabe, jede Zahl eines Computerprogramms ist eine Folge vonSchaltzuständen, die Sie mit Glühlampen vergleichen können.

Nun kann ein Computer nicht nur speichern, sondern auch rechnen. KomplizierteAufgaben wie das Ziehen der Wurzel basieren auf Regeln, umgesetzt durch Transistor-schaltungen. Wenn Sie mit einem Computer 5 + 2 rechnen wollen, dann zerlegt er diebeiden Zahlen in Lämpchenfolgen und addiert die Lämpchen einzeln. Das Ergebniswird dann wieder in eine für uns lesbare Zahl umgewandelt.

Solche grundlegenden Rechenoperationen sind im Prozessor fest verankert. Mannennt die Gesamtheit der Programme im Prozessor Microcode. Dieser legt das Ver-halten von Transistoren fest. Programmierer können den Microcode nicht direkt steu-ern. Der Prozessor stellt ihnen eine Programmiersprache zur Verfügung. Sie besteht

Lampe 1: AUS Lampe 2: AUS

Lampe 1: AN Lampe 2: AUS

Lampe 1: AUS Lampe 2: AN

Lampe 1: AN Lampe 2: AN

Page 22: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

22

Es war einmal ...1j e t z t l e r n e i c h

eigentlich nur aus Zahlen und wird als Maschinensprache bezeichnet. Weil Program-me, die nur aus Zahlen bestehen, schwer zu programmieren, zu lesen und zu wartensind, verwendet man leichter zu merkende Kürzel zum Programmieren. Ein Überset-zer, der Assembler, wandelt am Ende die Kürzel wieder in Zahlen um. Jeder Computerkann in Maschinensprache programmiert werden. Doch das ist ziemlich mühselig undkompliziert. Es ist genauso, wie wenn Sie mit dem Auto fahren wollten, aber es dazuerst zusammenbauen müssten. Um die Arbeit zu erleichtern, entstanden Hochspra-chen wie Basic. Sie verwenden Schlüsselbegriffe, die noch leichter zu merken sind, undvereinfachen den Aufbau von Programmen enorm. Ein Befehl in Basic entspricht ofteiner Handvoll Assembler-Befehle.

Ein Programm ist eine Liste von Befehlen, die ein Computer abarbeitet. Das ist nichtviel anders als bei einem Kochrezept. Mehrere Schritte müssen hintereinander aus-geführt werden. Ein Programm, das nicht in Maschinensprache vorliegt, sondern inAssembler oder einer höheren Sprache, nennt man Quelltext (Source, Source-Code).Ein Quelltext muss erst in Maschinensprache übersetzt werden, bevor ihn der Com-puter ausführen kann. Das Ergebnis ist – meist – eine EXE-Datei (executable = aus-führbar).

1

1.2 Basic

Basic ist eine ziemlich alte Programmiersprache. Sie wurde bereits 1964 entwickelt.Ihre Erfinder heißen John G. Kemeny und Thomas E. Kurtz. Sie unterrichteten in denUSA am Dartmouth College und wollten ihren Studenten den Einstieg in das Program-mieren erleichtern. Dazu vereinten sie Elemente zweier noch betagterer Sprachen,Algol und Fortran.

Basic ist die Abkürzung für Beginner's All-Purpose Symbolic Instruction Code, alsofür einen Befehlscode, der anfängerfreundlich ist, auf Symbolen basiert und für vieleZwecke einsetzbar ist. Die Aufschlüsselung ist nicht besonders glücklich. Zu vermutenist, dass die Buchstaben des Worts BASIC mit halbwegs sinnvollen Erklärungen verse-hen werden sollten, um die gewünschte Doppelbedeutung zu erzielen: Basic ist zu-gleich der englische Begriff für »grundlegend«. Vermutlich hätten sich die Erfindermehr Mühe bei der Namensfindung gegeben, wenn sie geahnt hätten, dass ihr Werkvierzig Jahre später immer noch eine der am meisten benutzten Computersprachenist.

Der erste Computer, auf dem Basic lief, war ein Großrechner von General Electric,Modell Nummer GE-225. In den folgenden Jahren kam kaum ein Computer auf denMarkt, für den Basic nicht umgesetzt wurde. Maßgeblichen Anteil daran hatte Micro-soft. Sie entwickelten zehn Jahre nach seiner Erfindung ein Basic für den erstenHomecomputer, den Altair 8080, und später für viele weitere Rechner. MicrosoftBasic wurde damit praktisch zum Standard.

Oft wird Ihnen beim Programmieren der Begriff Syntax begegnen. Damit beschreibtman den Aufbau von Befehlen, also die Weise, wie sie geschrieben und verwendetwerden.

Page 23: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

23

Blitz Basic j e t z t l e r n e i c h

1.3 Blitz Basic

Blitz Basic war ursprünglich eine Entwicklung für den Commodore Amiga. Seit Mitteder 80er Jahre, als für PCs noch Schwarzweißmonitore üblich waren und die Grafik-karten allenfalls 16 Farben unterstützten, bis Anfang der 90er Jahre war der Amiga derTraumrechner für alle Spiele-Freunde. Die Spiele, die damals auf dem Amiga erschie-nen, können sich heute, zehn Jahre später, mit Freeware für den PC durchaus messen.Blitz Basic ermöglichte es, mit wenig Programmierkünsten Spiele für den Amiga zuentwerfen. Die schwindende Bedeutung des Commodore-Computers war für den neu-seeländischen Entwickler Mark Sibly Anlass, eine PC-Version zu entwickeln.

Blitz Basic ist eine Programmiersprache, die für das Schreiben von Spielen entwickeltwurde. Besonders reichhaltig sind die Möglichkeiten, mit Bilddateien und Klängen zujonglieren. Der Interaktivität dienen Funktionen, um Tastatur, Maus und Joystick abzu-fragen. Dateibefehle erlauben es zum Beispiel, den Spielstand abzuspeichern, währendZeichenkettenbefehle etwa helfen, eine Spielwelt in einer kompakten Datei unterzu-bringen oder aus Namen eine Bestenliste zu erzeugen. Ohne besonderen Aufwandlässt sich der Kontakt zu verbundenen PCs aufbauen, um sich Daten gegenseitig zuzu-senden.

Obwohl Ihnen sicher bereits das Wasser im Mund zusammenläuft, möchte ich Sie inBezug auf all diese feinen Sachen auf später vertrösten und Ihnen zunächst die Grund-lagen von Basic beibringen. So, wie man vor dem Autofahren erst lernen muss, welcheBedeutung die Verkehrszeichen haben, wo der Blinkerhebel liegt und wie man denTankdeckel öffnet, müssen Sie zunächst ein paar elementare Dinge lernen. Erst da-nach können Sie die Bausteine nutzen, um ein Spiel zusammenzusetzen. Damit es Ih-nen nicht langweilig wird, werden die Erklärungen durch Beispiele untermalt.

Robert Gerlach, www.robsite.de: »Blitz Basic ist meiner Meinung nach die besteSpiele-Programmiersprache für kleine bis mittelgroße Spiele unter Windows. Durchdie leicht zu erlernende und fehlertolerante Basic-Syntax kommen besonders Anfän-ger schnell zu kleinen Programmen; dank des einfachen Zugriffs auf DirectX sindauch bunte Bilder kein Problem. Der Rest ist ebenfalls schnell zu entwickeln. Die er-stellten Programme sind ziemlich schnell und vor allem stabil, falls man nicht geradeselbst Fehler gemacht hat. Andere Spiele-Sprachen sind da etwas anfälliger ... Dieserganze Komfort hat aber auch Nachteile. Objektorientierte Programmierung (OOP)wurde der Einfachheit wegen weggelassen. OOP ist zwar etwas schwerer zu verste-hen als der prozedurale Ansatz von Blitz Basic, hilft aber bei großen Projekten unge-mein. Auch ein direkter Zugriff auf das System (z.B. Assembler-Code oder Nutzenvon Windows-Ressourcen) ist nicht möglich. Man ist also größtenteils auf die Blitz-eigenen Befehle angewiesen. Derer gibt es aber viele hundert, was für die meistenSpiele ausreichen müsste. Blitz Basic soll auch kein Konkurrent zu den etabliertenSystemen sein, eher eine Erweiterung. Viele Spielideen werden zunächst mit BlitzBasic 'ausprobiert' und dann später mit C++/DirectX etc. 'richtig' entwickelt. Es gibtim Moment keine Programmiersprache für Spiele, die so einfach und schnell ist undso viele Features bietet. Mit ein paar Monaten Übung haben Sie gute Chancen, eingrößeres Projekt durchzuziehen.«

Page 24: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

24

Es war einmal ...1j e t z t l e r n e i c h

Es gibt zwei Möglichkeiten, um ein Programm auszuführen. In der Vergangenheit wur-de Basic überwiegend als Interpreter-Sprache genutzt. Beim Ablaufen eines Pro-gramms wird jeder Befehl nacheinander in den Maschinencode übersetzt, den der Pro-zessor versteht. Der Nachteil dabei ist, dass keine selbst ablaufenden Anwendungenentstehen, und die Ausführung ist recht langsam.

Der Gegensatz dazu ist ein Compiler, der den Quelltext in eine EXE-Datei übersetzt, dieselbstständig abläuft. Blitz Basic ist eine Compiler-Sprache. Mit ihr lassen sich EXE-Da-teien erzeugen, die auf jedem PC auch ohne Blitz Basic funktionieren und denen manihre Herkunft nicht unbedingt anmerkt.

1

1.4 Drei Versionen

Derzeit existieren drei verschiedene Versionen von Blitz Basic.

Blitz Basic eignet sich nur für 2D-Spiele. Daher wird es oft als Blitz Basic 2D bezeich-net. Zugunsten der beiden anderen Versionen wird es seit Anfang 2003 nicht mehrweiterentwickelt. Die jüngste Version 1.80 ist allerdings ziemlich ausgereift und nahezufehlerfrei. Wer nur 2D-Spiele im Vollbild-Modus entwickeln will, ist damit bestens auf-gehoben.

Blitz Basic 3D oder Blitz 3D enthält den gleichen Leistungsumfang, bietet aber zu-sätzlich mehr als 200 Befehle für 3D-Grafik.

Im Februar 2003 erschien Blitz Plus als Nachfolger von Blitz Basic 2D. Der Compilerwurde von Grund auf neu geschrieben und enthält neben den Fähigkeiten der 2D-Ver-sion zusätzlich rund hundert Befehle zum Verwenden der Elemente der Windows-Be-dienoberfläche (Graphical User Interface, GUI), wie Fenster und Schalter.

Die Wahl fällt nicht leicht: Blitz Basic 2D genügt für 2D-Spiele, wird aber nicht mehrweiterentwickelt (was aber in meinen Augen nicht schlimm ist, da keine Wünsche offenbleiben). Blitz Plus bietet die GUI-Befehle, aber kein 3D. Und Blitz Basic 3D hat 3D-Befehle, aber keine GUI-Unterstützung.

Meine Empfehlung: Blitz Basic ist eine Programmiersprache für Spiele, nicht für An-wendungen. Für diesen Zweck gibt es andere, ausgereiferte Sprachen. Ich rate daher,sich entweder preiswert ein Blitz Basic 2D zu besorgen (zum Beispiel über eBay oderIdigicon, dazu gleich mehr) oder Blitz Basic 3D zu kaufen. Vielleicht wird man irgend-wann beide Zusätze in einem Programm erhalten.

In Entwicklung ist Blitz Max, mit dem sich Programme parallel für Windows, Mac OSund Linux entwickeln lassen sollen. Der Erscheinungstermin ist ungewiss; er kann sichbis weit ins Jahr 2004 hinziehen.

Basic genießt unter Spieleentwicklern keinen guten Ruf. Viele vertreten die Auffas-sung, man müsste C++ lernen, um Spiele zu programmieren. Freilich ist Blitz Basiceine Anfängersprache, doch für die meisten bietet sie genau den richtigen Einstieg.Selbst wer mühsam C++, DirectX und Windows-Programmierung lernt, wird kaumandere Spiele entwickeln, als er mit Blitz Basic hervorbringen würde – nur dort ebenmit erheblich geringerem Aufwand.

Page 25: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

25

Erwerb schwergemacht j e t z t l e r n e i c h

1

1.5 Erwerb schwergemacht

Blitz Basic ist eine fabelhafte Software. Ich würde mir wünschen, das vom Vertriebauch sagen zu können. Doch dort geht es drunter und drüber. Es ist nicht möglich, BlitzBasic im Geschäft oder bei einem Online-Händler wie Amazon.de zu erwerben. Wohlgibt es einen deutschen Vertrieb (www.schatztruhe.de), doch bei dem kann Blitz Basicnur direkt bezogen werden. Das wäre nicht so schlimm, wenn sich der Entwickler derSoftware nicht im März 2003 zu einem folgenschweren Schritt entschlossen hätte:

Es werden nur noch Käufer unterstützt, die ihr Blitz Basic direkt von www.blitz-basic.com beziehen. Wer seine Version von einem anderen Händler erwirbt, erhältkeinen Support, vor allem keine Updates.

Glück im Unglück: Da der Kauf über den international auftretenden Anbieter Share-it!(www.shareit.de, Telefon Deutschland 0221/31088-20) abgewickelt wird, ist – an-ders als sonst bei Auslandskäufen – keine Kreditkarte nötig. Es kann auch per Über-weisung gezahlt werden.

Blitz Plus kostet rund 60 Euro, Blitz Basic 3D rund 100 Euro. Blitz Basic (2D) wirdnicht mehr angeboten.

Allerdings ist der Kauf mit einer Einschränkung verbunden: Zumindest zur Manuskript-abgabe des Buchs waren nur Download-Versionen erhältlich. Das heißt, man lädt sichdie nackte Software herunter und bekommt nichts in die Hand. Das ist besonders scha-de, da Verkaufsverpackungen von Blitz Basic und Blitz Basic 3D existieren, mit CD-ROM und gedrucktem (wenngleich englischsprachigen) Handbuch. Diese können wei-terhin von www.schatztruhe.de sowie dessen Partner www.idigicon.com bezogenwerden. Nur gibt es für diese Verkaufsverpackungen eben keinen Support mehr undder Ausschluss von künftigen Updates ist ein empfindlicher Nachteil. Wie das zukünftigaussieht, ist ungewiss. Vom Entwickler von Blitz Basic (der ohnehin diesem Buchpro-jekt gegenüber ein bemerkenswertes Desinteresse demonstrierte) war keine Aufklä-rung zu erhalten. Doch es ist offensichtlich, dass er sich von seinem bisherigen Vertriebdistanziert.

Dennoch möchte ich auf einen preiswerten Umstand hinweisen: Die Download-Ver-sion von Blitz Basic 2D kostet bei www.idigicon.com (ein fürchterlicher Name übri-gens; ich kann ihn mir nie merken :-) nur 20 Euro. Trotz fehlender Updates ist das einAngebot, das eine Überlegung wert ist.

Von Blitz Basic erscheinen im Abstand von wenigen Wochen neue Versionen. Sie be-seitigen kleinere Fehler; häufig kommen neue Befehle hinzu, im Einzelfall fallen Be-fehle weg. Diese Updates lassen sich nur mit der Vollversion verwenden, sind aberkostenlos. Die Demos sind auf einem älteren Stand und lassen sich nicht updaten.

Page 26: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

26

Es war einmal ...1j e t z t l e r n e i c h

Abb. 1.1: Nach der

Registrierungauf www.bltz-

basic.com unddem Eingeben

des Code-schlüssels

(BUID) könnenjederzeit

Updates gela-den werden.

0Das Downloaden von Updates ist etwas umständlich. Entscheidende Voraussetzungist eine Codenummer, die BUID (Blitz User ID). Sie erhalten sie beim Kauf. Registrie-ren Sie sich zunächst auf www.blitzbasic.com, indem Sie rechts oben auf Signup kli-cken. Dadurch erhalten Sie einen zusätzlichen Menüpunkt Account. Wählen Sie ihnan und klicken Sie auf Register product. Hier registrieren Sie sich unter Angabe derBUID für Ihre Blitz-Version. Nun ist im gleichen Menüpunkt die Auswahl Product up-dates zugänglich, wo die Downloads bereitliegen. Interessant ist außerdem das Ver-sion History Document. Es listet für jede Version die beseitigten Fehler und neuenFunktionen auf.

Page 27: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

27

jetz

t le

rne

ich

KAPITEL 2

Die ersten Schritte

Die Demoversion von Blitz Basic befindet sich auf der Buch-CD. Sie unterscheidet sichvor allem in einem Punkt von der Kaufversion: Sie können keine EXE-Dateien erzeu-gen, also keine Programme übersetzen, die selbstständig ablaufen und sich weiterge-ben lassen. Der überwiegende Teil des Buchs lässt sich mit allen drei Versionen vonBlitz Basic nachvollziehen; Unterschiede habe ich gekennzeichnet. Die Demo-Versio-nen von Blitz Basic 3D und Blitz Plus lassen sich allerdings nur dreißig Mal star-ten. Danach verweigern sie ihre Arbeit. Daher sollten Sie für Ihre Anfänge Blitz Basic(2D) verwenden.

Falls Sie einen Internetanschluss haben, empfehle ich Ihnen, nach einer neueren Ver-sion Ausschau zu halten. Sie finden sie unter dem Menüpunkt Blitz 3D/Demos oderBlitzPlus/Demos auf der Seite www.blitzbasic.com. Lohnen wird es sich vermutlichnicht: Die Demos werden selten an den Stand der Vollversionen angepasst.

02.1 Der Editor

Sie installieren Blitz Basic wie jede andere Software. Es gibt nur eine Programmdatei;sie startet den Editor. Hier entstehen Ihre Werke. Seine Oberfläche erinnert an eineTextverarbeitung und ein Programm schreiben Sie so ähnlich wie einen Brief. Beimersten Starten mögen Sie über den dunkelgrünen Hintergrund aufstöhnen. Die Farb-gebung verdient keinen Preis – doch man kann sich daran gewöhnen.

1

Falls Blitz Basic beim Starten fälschlich bemängelt, dass kein Internet Explorer abVersion 4.0 installiert sei, verwenden Sie den Patch auf der Buch-CD.

Im Anhang erkläre ich Ihnen, wie Sie die Farben ändern. Außerdem gibt es eine Be-schreibung des Editors BlitzView, den Sie als Alternative zum Standard-Editor ver-wenden können. Er bietet erheblich mehr Komfort.

Page 28: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

28

Die ersten Schritte2j e t z t l e r n e i c h

Blitz Basic unterstützt Ihr Schaffen, indem es die einzelnen Elemente eines Programmsunterschiedlich einfärbt (Syntax Highlighting) und Schlüsselwörter selbstständig mitpassender Groß- und Kleinschreibung versieht. Es spielt keine Rolle, ob Sie Befehleklein (repeat), in Blockschrift (PRINT) oder gemischt (Repeat) schreiben – Blitz Basic wirdsie notfalls automatisch umwandeln, so dass sie mit einem großen Anfangsbuchstabenbeginnen.

0

Jederzeit können Sie Ihr Programm abspeichern (FILE/SAVE). Aus Sicherheitsgründensollten Sie das auch dann regelmäßig tun, wenn Sie mehrere Stunden hintereinanderan Ihrem Werk sitzen. Später laden Sie es wieder mit FILE/OPEN.

Im Anhang sind alle Menüpunkte von Blitz Basic erklärt. Die Menüs FILE, EDIT und HELP

enthalten Einträge, wie Sie sie von vielen Programmen her gewohnt sind. Im MenüPROGRAM sind in erster Linie zwei Punkte interessant, die Sie schneller über eine Funk-tionstaste erreichen: Ï überprüft Ihr Programm auf Fehler. Í führt es aus. SindSie mit dem Ergebnis zufrieden, erstellt CREATE EXECUTABLE (in der Vollversion) eineselbst ablaufende EXE-Datei.

0

Oft genug kommen Sie in die Verlegenheit, eine Aktion im Editor ungeschehen ma-chen zu wollen, etwa wenn Sie versehentlich einen ganzen Abschnitt mit Programm-zeilen gelöscht haben. Es ist unerklärlich, wieso der Editor keinen Menüpunkt miteiner Rückgängig-Funktion bietet, wie es seit vielen Jahren Standard bei allen Text-programmen ist. Über eine Tastenkombination lässt sich der Rettungsanker dennocherreichen: Drücken Sie Ÿ+Z, um die letzte Eingabe zurückzunehmen.

Blitz Basic speichert den Quelltext automatisch ab, wenn Sie das Programm aus demEditor heraus starten und zuvor ein Dateiname festgelegt wurde. Das ist meistenssinnvoll: Bei logischen Fehlern kann das Programm abstürzen und Blitz Basic mit indie Tiefe reißen. Die letzten Änderungen wären damit verloren. Manchmal ist dasVerhalten aber unerwünscht, etwa dann, wenn Sie ein fertiges Programm verändern,um etwas zu überprüfen. Auch wenn Sie nicht die Absicht haben, diese Veränderun-gen abzuheften, speichert Blitz Basic trotzdem beim Starten des Programms unge-fragt ab. Um das zu vermeiden, öffnen Sie ein neues Programmfenster, kopieren Siedas Programm hinein und starten Sie es von diesem Fenster aus. Oder Sie speicherndie Datei unter einem anderen Namen ab, bevor Sie die Veränderungen vornehmen.

In jüngeren Versionen speichert Blitz Basic auch dann ab, wenn beim Start keinName festgelegt wurde. Der Quelltext ist als TMP.BB im Blitz-Ordner TMP zu finden.Das ist einerseits nett, hat aber andererseits einen Nachteil: Das Programm wird imOrdner TMP gestartet. Es kann Grafiken und Sounds, die im Hauptordner von BlitzBasic liegen und die normalerweise ohne Pfadangaben geladen werden, nicht mehrfinden. Drei Lösungen bieten sich an: notwendige Dateien in den TMP-Ordner ko-pieren, Pfad im Quelltext anpassen oder die Datei normal abspeichern und dann star-ten. Übrigens: Im Abschnitt über Speicherbänke erstellen wir einen Patch, der diesesVerhalten korrigiert.

Page 29: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

29

Text ausgeben j e t z t l e r n e i c h

Sehr hilfreich ist die Taste É. Wenn Sie den Cursor auf einen Befehl setzen und ein-mal É drücken, sehen Sie in der Statuszeile (ganz unten) eine kurze Beschreibung,wie der Befehl eingesetzt wird. Drücken Sie É noch einmal, bekommen Sie eine aus-führliche Hilfe für diesen Befehl.

1Die rechte Spalte des Editors dient als Gliederungshilfe für größere Programme. Mit ih-rer Hilfe erreichen Sie die einzelnen Teile (Unterprogramme, Funktionen, Sprungmar-ken) schnell.

2.2 Text ausgeben

Starten Sie Blitz Basic und schreiben Sie in ein neues Fenster (FILE/NEW) die folgendenZeilen:

Print "Hallo, Zauberlehrling!"Waitkey

Wenn Sie nun Í drücken, wird Blitz Basic sich nach dem Namen der Datei erkun-digen, unter dem Ihr Text gespeichert werden soll. Schreiben Sie etwas wie TEST.BBhinein (oder drücken Sie einfach È, um es nicht zu speichern) und bestätigen Sie.Blitz Basic wird ein kleines schwarzes Fenster öffnen und den Text

Hallo, Zauberlehrling!

hineinschreiben. Voilà! Das ist bereits ein Programm. Noch sieht es ein bisschen un-scheinbar aus. Aber wir können es verlängern und mehr als eine Zeile ausgeben lassen:

Print "Hat der alte Hexenmeister"Print "Sich doch einmal wegbegeben!"Print "Und nun sollen seine Geister"Print "Auch nach meinem Willen leben."WaitKey

Noch mehr Zeilen? Ich denke, das Prinzip ist klar. Print druckt einen Text aus. WaitKeywartet auf einen beliebigen Tastendruck. Damit wird am Programmende verhindert,dass sich das Fenster schließt und das Ergebnis verschwindet.

Doch Print kann noch mehr. Stellt man ihm eine Matheaufgabe, so löst er sie brav:

Print "2+3"WaitKey

Oh! Macht er nicht? Probieren Sie es so:

Print 2+3WaitKey

Diese Hilfe ist normalerweise in Englisch. Auf der Buch-CD befindet sich einedeutschsprachige Online-Hilfe für den Editor.

Page 30: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

30

Die ersten Schritte2j e t z t l e r n e i c h

Abb. 2.1:Die Bedien-

oberfläche vonBlitz Basic.

Schlicht, aberausreichend

Der Befehl Print gibt alles auf dem Bildschirm aus, was in Anführungsstrichen steht,egal, ob es sich dabei um Buchstaben, Zahlen oder Sonderzeichen wie ein Kommahandelt. Soll er jedoch dabei eine mathematische Aufgabe lösen, fallen die Hochkom-mas weg. Beide Varianten lassen sich mit einem Plus kombinieren, wie Sie schön amfolgenden Beispiel sehen:

Print "2+3 ist " + (2+3)WaitKey

1

Freilich kann Blitz Basic nicht nur zusammenzählen. Auch Subtrahieren (-), Multiplizie-ren (*) und Dividieren (/) steht auf dem Programm:

Print 2+3Print 2-3Print 2*3Print 2/3

Die Ergebnisse: 5, -1, 6 überzeugen. Aber 2 geteilt durch 3 ist 0? Belassen wir es imMoment dabei. Sie erfahren später mehr über Rechenoperationen.

Blitz Basic erkennt nicht immer von allein, ob ein Plus zum Addieren oder zum Zu-sammenfügen von Texten gemeint ist. Daher habe ich die Addition in Klammern ge-setzt. Ansonsten hätte der Compiler die Zahlen als Zeichenketten behandelt und(2+3) statt 5 geschrieben.

Page 31: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

31

Variablen j e t z t l e r n e i c h

Der Befehl Print hat die Eigenschaft, den Cursor in die nächste Zeile zu setzen. Nichtimmer ist das erwünscht. Daher gibt es mit Write einen ganz ähnlichen Befehl. Er ar-beitet genauso, lässt aber die Schreibmarke in der aktuellen Zeile. Das folgende Pro-gramm:

Print "2"Print "5"Print "6"Write "2"Write "5"Write "6"WaitKey

bringt daher folgenden Ausdruck auf den Bildschirm:

256256

2.3 Variablen

Aus der Mathematik kennen Sie Variablen. Sie dienen als Platzhalter für verschiedeneWerte. Die Formel V = a³ berechnet das Volumen eines Würfels. Die Variable a ist hierder Platzhalter für die Seitenlänge des Würfels. In Computersprachen läuft nichts ohneVariablen. Sie speichern Eingaben des Nutzers und merken sich Zwischenergebnisse,etwa den Punktestand und die Anzahl der verbleibenden Leben in einem Spiel.

In Blitz Basic setzen Sie zwei Arten von Variablen ein. Der eine Typ speichert eineZahl. Der andere Typ merkt sich eine Zeichenkette, womit man alles das benennt, waskeine Zahl ist: ein Wort, Sonderzeichen wie "!" oder eine Mischung aus Buchstabenund Zahlen ("Haus47"). Mit Zahlen kann man rechnen, mit einer Zeichenkette wie"Zauberlehrling" nicht. Daher gibt es diese Unterscheidung.

Eine umständlichere Darstellung von:

Print 2+3

wäre folgende:

Ergebnis = 2+3Print Ergebnis

Und noch umständlicher:

Zahl1 = 2Zahl2 = 3Ergebnis = Zahl1 + Zahl2Print Ergebnis

Als Name einer Variable kann fast jedes Wort gewählt werden. Verboten sind nur:

� Umlaute wie ä und Sonderzeichen

� Leerzeichen

� Ziffern am Anfang

Page 32: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

32

Die ersten Schritte2j e t z t l e r n e i c h

2

0

Beinahe genauso bilden Sie Variablen für Zeichenketten. Der einzige Unterschied:Dem Namen folgt ein Dollarzeichen:

Vorname$ = "Han"Nachname$ = "Solo"

Vergessen Sie nie das $ bei einer Zeichenkettenvariable! Blitz übersieht nämlich, wasSie bei einem Befehl wie:

Name = "Luke"

bezweckt haben. Statt einer Zeichenkettenvariable mit dem Wert "Luke" bekommenSie eine Zahlenvariable mit dem Wert 0.

Mit dem Pluszeichen verbinden Sie zwei Zeichenkettenvariablen:

Print Vorname$ + Nachname$

Huch! Da fehlt eine Leerstelle. Noch einmal:

Vorname$ = "Han"Nachname$ = "Solo"Name$ = Vorname$ + " " + Nachname$Print Name$

Noch netter:

Print "Der Name ist " + Name$ + "."

1

In vielen Sprachen muss das Verwenden einer Variable vorher angemeldet werden.Programme beginnen dort mit einem Vereinbarungsteil, in dem alle genutzten Vari-ablen aufgelistet werden. In Blitz Basic dagegen nehmen Sie eine Variable, wann esIhnen passt. Der Nachteil: Sie müssen höllisch darauf achten, dass Sie sich nicht beieinem Variablennamen verschreiben. Für Blitz Basic wäre das dann eine neue Vari-able.

Was die Sprache außerdem unterscheidet: Variablen können die Namen von Basic-Befehlen tragen. Ich rate Ihnen jedoch, beim Bilden von Variablen auf solche Schlüs-selnamen wie Input zu verzichten. Zum einen könnten Sie beim Lesen von Program-men durcheinander kommen. Zum anderen ist es möglich, dass in künftigen Versio-nen der Compiler strenger ist und solche Namen nicht mehr zulässt.

Für den Begriff Zeichenkette ist der englische Begriff String weit verbreitet. Die An-führungszeichen ("") begrenzen eine Zeichenkette, sind aber kein Teil von ihr. Späterführe ich Sie tiefer in die Welt der Variablen und Datenformate wie Zahlen und Zei-chenketten ein.

Page 33: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

33

Eingaben j e t z t l e r n e i c h

2.4 Eingaben

Auch Eingaben des Nutzers werden in Variablen gespeichert. Dazu gibt es den BefehlInput(). Er hält das Programm an und wartet auf die Eingabe einer ganzen Zeile, diemit Æ abgeschlossen wird. Damit der Text nicht verloren geht, geben Sie den Befehlnicht einzeln an, sondern verwenden eine Variablenzuweisung:

Variable = Input$(Zeichenkette)

In Klammern können Sie eine Eingabeaufforderung schreiben, die vorher ausgedrucktwird. Das Verfahren eignet sich zum Beispiel für die Abfrage des Spielernamens:

Name$ = Input$("Geben Sie Ihren Namen ein: ")Print "Hallo, " + Name$ + "!"WaitKey

Vergessen Sie dabei nicht, eine Zeichenkettenvariable zu verwenden. Die Zuweisungfunktioniert zwar mit einer Zahlenvariable, aber sie erhält statt des Namens den Wert 0.

Später erfahren Sie noch ausführlich, wie Sie einzelne Tastendrücke auswerten sowieMaus und Joystick abfragen. Dennoch weise ich Sie noch einmal auf einen Befehl hin,der Ihnen beim Entwickeln sehr nützlich sein wird: WaitKey hält das Programm so langean, bis eine beliebige Taste gedrückt wurde. Danach wird der Ablauf fortgesetzt:

Print "Drücken Sie eine Taste, wenn ich weitermachen soll."WaitKeyPrint "Ok."

WaitMouse arbeitet ähnlich, wartet aber auf einen Mausklick.

12.5 Kommentare

Im Quelltext stehen normalerweise nur gültige Befehle. Häufig möchte man jedoch ei-gene Kommentare einfügen, sei es ein einleitender Text, Zwischenüberschriften oderDetails zu Programmfunktionen. Damit der Compiler diese Kommentare übersieht,gibt es ein Spezialzeichen: Alles, was in einer Zeile nach einem Semikolon (;) steht,wird ignoriert.

...;; NamenseingabeName$ = Input$("Geben Sie Ihren Namen ein: ")Print "Hallo, " + Name$ + "!";; Auswertung des Namens...

Ein Semikolon steht am Anfang einer Zeile oder hinter einem Befehl.

Beim Entwickeln größerer Programme leisten die Befehle wertvolle Dienste. Sie hal-ten das Programm so lange an, bis Sie eine bestimmte Ausgabe oder ein Bild ge-sehen haben.

Page 34: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

34

Die ersten Schritte2j e t z t l e r n e i c h

2.6 Befehlstrenner

Üblicherweise schreibt man jeden Befehl in eine einzelne Zeile. Es bieten sich bei län-geren Programmen sogar Auflockerungen durch Leerzeilen an. Dennoch erlaubt esBlitz Basic, mehrere Befehle in eine Zeile zu setzen. Empfehlenswert, aber keinePflicht ist dabei das Setzen eines Doppelpunkts als Trennzeichen:

Print "Drücken Sie eine Taste." : WaitKey

Früher, in der Ära der Homecomputer, war diese Schreibweise üblich. Damals gab eskeine bequemen Editoren, mit denen man schnell durch den Text scrollen konnte. Da-her war man bemüht, so viele Befehle wie möglich auf einer Bildschirmseite darzustel-len. Heute ist der Doppelpunkt selten geworden. Ich verwende ihn gelegentlich, ummehrere sehr kurze und zusammengehörende Befehle in einer Zeile zusammenzufas-sen.

2.7 Programmnamen festlegen

Ihre Quelltexte speichern Sie mit der Dateiendung .BB auf der Festplatte. In der Voll-version von Blitz Basic können Sie eigenständige EXE-Dateien erzeugen: Aus demQuelltext MONSTER.BB erstellt der Compiler das Programm MONSTER.EXE. Den-noch bleibt die Titelleiste des Fensters, in dem das Programm läuft, leer. Auch in derTaskleiste von Windows ist der Name nicht zu sehen. Um das zu erreichen, müssen Sieausdrücklich einen Namen festlegen. Das geben Sie über den Befehl AppTitle an:

AppTitle "Monsterfangen"

Beginnen Sie jedes größere Programm mit einem AppTitle-Befehl.

2.8 Ganzer Bildschirm

Normalerweise wird jedes Programm in Blitz Basic in einem Fenster ausgeführt. Soll esden ganzen Bildschirm einnehmen, lassen Sie es mit dem Befehl

Graphics 640,480

beginnen. Wir werden uns noch detailliert mit dem Befehl beschäftigen, doch bis dahinsollen Sie nicht auf das Vollbild verzichten müssen. Eins noch: Der Debug-Modus mussausgeschaltet sein, ansonsten läuft das Programm trotzdem im Fenster.

1Blitz Plus unterscheidet sich bei einigen Befehlen von Blitz Basic und Blitz Basic 3D.Der entscheidende Unterschied: Print, Write und Input (sowie Locate, zu dem wirspäter kommen) sind nicht im Vollbildmodus möglich. Stattdessen öffnet Blitz Plus einweiteres Fenster, um den Text auszugeben. Dieses Fenster wird als Konsole bezeich-net, obwohl es sich optisch nicht von einem »normalen« Fenster unterscheidet. ImKonsolenfenster werden deutsche Umlaute nicht korrekt wiedergegeben, Tastenein-gaben (und damit WaitKey) funktionieren nicht und das Fenster muss manuell mit derMaus oder Ç+¢Leertaste£, S geschlossen werden.

Page 35: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

35

Aufgaben j e t z t l e r n e i c h

2.9 Aufgaben

1. Wo hat sich im Editor die Rückgängig-Funktion (Undo) versteckt?

2. Was ist ein String?

3. Schreiben Sie ein Programm, das den Nutzer nach seinem Namen fragt und ihndann persönlich begrüßt.

4. Schreiben Sie ein Programm, das nach der Kantenlänge eines Würfels fragt. Be-rechnen Sie daraus das Volumen des Würfels. (Hinweis: Das Volumen entsprichtder Seitenlänge hoch 3.)

5. Womit legen Sie fest, ob ein Programm im Windows-Fenster oder im Vollbild läuft?

1Drei goldene Regeln für den Anfang:

1. Programmieren lernt man durch ... Programmieren. Denken Sie sich kleine Auf-gaben aus und lösen Sie sie, auch wenn sie nicht zu einem Spiel als Ziel führen.Die wachsende Erfahrung hilft Ihnen später beim Entwickeln von größeren Pro-jekten.

2. Lernen Sie von anderen Quelltexten, aber »programmieren« Sie nicht, indem Siefremde Codes nur leicht verändern. Dadurch lernen Sie nichts. Versuchen Sie,die Verfahren zu verstehen, und schreiben Sie die Lösungen von Grund auf neu– mit Ihrem Code.

3. Übernehmen Sie sich nicht. Beginnen Sie mit kleinen, überschaubaren Aufga-ben. Zunächst muss die Technik stimmen, dann das Aussehen. Quiz, Würfelspiel,Zahlenraten – das sind richtige Anforderungen für den Anfang.

Page 36: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 37: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

37

jetz

t le

rne

ich

KAPITEL 3

Die Grundpfeiler von Programmen

Bisher laufen unsere Programme hintereinander. Sie beginnen mit dem ersten Befehlund enden mit dem letzten. Verzweigungen ermöglichen es, anhand bestimmter Be-dingungen den Programmlauf in verschiedene Bahnen zu lenken.

3.1 Verzweigungen

Ähnlich wie ein Baum, der sich vom Stamm aus in verschiedene Äste, Zweige undBlätter verzweigt, können sich Programme gliedern. Auf dem Bildschirm jedoch bleibtein Programm eine lange Liste von Zeilen und Seiten.

3.1.1 Programm beendenBevor Sie sich im Gestrüpp der Befehlsschlangen verheddern, nenne ich Ihnen eineuniverselle Rettung: Mit dem Befehl End beenden Sie ein Programm, egal an welcherStelle Sie den Befehl einsetzen.

1End wird außerdem mit Nachsätzen wie Function verwendet. In diesem Fall wird nichtdas gesamte Programm beendet, sondern nur ein Nebenzweig. Später erfahren Siemehr darüber.

Page 38: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

38

Die Grundpfeiler von Programmen3j e t z t l e r n e i c h

3.1.2 Die If-VerzweigungStellen Sie sich einen Eisautomaten vor. Zwei Sorten stehen zur Auswahl, Vanille undSchoko. Das Programm würde ungefähr so beginnen:

; EIS1.BBPrint "Willkommen beim Ice-O-Mat!"Print "Welche Sorte möchten Sie?"Print "1 - Vanille"Print "2 - Schoko"Sorte = Input$("Drücken Sie eine Taste: ")

Damit sind wir mit unserem Latein am Ende. Wir bräuchten einen Befehl wie ...

Wenn Sorte = 1 Dann Print "Sie haben Vanille gewählt."

... um die Eingabe weiterzubearbeiten. Genau so, nur mit englischen Begriffen, siehtder Basic-Befehl aus:

If Sorte = 1 Then Print "Sie haben Vanille gewählt."If Sorte = 2 Then Print "Sie haben Schoko gewählt."

Neben dem neuen Befehlspaar If/Then habe ich eine zweite Neuigkeit hineingemo-gelt. Bisher kannten Sie das Gleichheitszeichen (=) nur für die Zuweisung eines Werteszu einer Variablen. Nun wird es für einen Vergleich verwendet: Der Computer erhältdie Anweisung, zu testen, ob die Variable Sorte dem Wert 1 entspricht.

Genauso gut können Sie abfragen, ob ein Wert größer, kleiner oder einfach ungleich ist:

Geld = Input$("Wie viel Geld haben Sie? ")If Geld < 0 Then Print "Was, Sie haben Schulden?"If Geld = 0 Then Print "Gar nichts?"If Geld > 0 Then Print "Schau an."

Auch »kleiner gleich« und »größer gleich« sind möglich:

If Geld <= -1 Then Print "Was, Sie haben Schulden?"If Geld >= 1 Then Print "Schau an."

Manchmal wäre es hilfreich, einen Befehl nicht nur von einer Bedingung abhängig zumachen, sondern von mehreren:

Wenn Sorte = 1 oder Sorte = 2 dann ...

Wenn Sorte = 1 und Sahne = 1 dann ...

Statt einer einfachen Bedingung können Sie mehrere Teilbedingungen zu einer Ge-samtbedingung verknüpfen. Sie verwenden dazu die Verbindungen Or für »oder« undAnd für »und«:

If Sorte<>1 And Sorte<>2 Then Print "Ungültige Sorte!"If Sorte=1 Or Sorte=2 Then Print "Gültige Sorte!"

Beide Beispiele bewirken das Gleiche: Wenn die Sorte weder 1 noch 2 ist, erscheinteine Fehlermeldung. Der Übersicht halber bietet es sich an, die Teilbedingungen je-weils in Klammern zu fassen:

If (Sorte<>1) And (Sorte<>2) Then Print "Ungültige Sorte!"

Ebenso vergleichen Sie Zeichenketten miteinander: Eine Kette ist kleiner als eine an-dere, wenn man sie alphabetisch vorher sortiert.

Später werden Sie mehr über diese so genannten logischen Operatoren erfahren.

Page 39: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

39

Verzweigungen j e t z t l e r n e i c h

03.1.3 EndIfHinter Then können mehrere Befehle folgen. Blitz Basic weiß aber nicht von allein,dass bei der folgenden Schreibweise ...

If Sorte = 1 Then Print "Sie haben Vanille gewählt." Vanille = Vanille - 1If Sorte = 2 Then Print "Sie haben Schoko gewählt." Schoko = Schoko - 1

... die zweite Zeile zum ersten If gehören soll. Es führt sie als eigenständigen Befehl aufjeden Fall aus. Deswegen teilen Sie mit dem Befehl EndIf das Ende der If-Bedingungmit. Existiert ein EndIf, dann behandelt Blitz Basic alle Befehle zwischen Then undEndIf als Teil der If-Bedingung:

If Sorte = 1 Then Print "Sie haben Vanille gewählt." Vanille = Vanille - 1EndIf

Der besseren Übersicht wegen bietet sich eine Einrückung an.

1

Die Else-AlternativeWenn es nur zwei Möglichkeiten gibt, wie im Beispiel mit dem Eisautomaten, ...

If Sorte = 1 Then Print "Sie haben Vanille gewählt."If Sorte = 2 Then Print "Sie haben Schoko gewählt."

... dürfen Sie die zweite Möglichkeit durch ein schlichtes »Ansonsten« ersetzen. Stattzwei Wenn-Dann-Fragen wird also ein Befehl »Wenn-Dann-Ansonsten« verwendet:

If Sorte = 1 Then Print "Sie haben Vanille gewählt."Else Print "Sie haben Schoko gewählt."EndIf

Dabei sollten Sie mit Bedacht vorgehen, denn die beiden Beispiele unterscheiden sich:Der Schoko-Satz wird im ersten Beispiel nur ausgedruckt, wenn Sorte=2 ist. Im zweitenBeispiel, wenn Sorte<>1 ist, also auch dann, wenn als Sorte zum Beispiel 3 eingegebenwurde. Ein guter Programmierer stellt sicher, dass Variablen keinen ungültigen Werthaben. Denkbar wäre eine Abfrage wie:

If Sorte > 2 Then Print "Ungültige Sorte! Bitte noch mal wählen."

Blitz Basic erlaubt es Ihnen, das Wort Then wegzulassen. Ich empfehle Ihnen jedoch,es zu verwenden, um Verwirrungen zu vermeiden.

Normalerweise wechseln Sie nach Belieben in eine neue Zeile. Bei Then müssen Siejedoch eine Besonderheit beachten: Folgt Then in der gleichen Zeile ein Befehl, dannhängt Blitz Basic automatisch ein (unsichtbares) EndIf an und schließt die Befehlsket-te damit ab. Wenn Sie nach Then mehrere Befehle folgen lassen wollen, dann müssenSie direkt nach Then Æ drücken. Übrigens kann EndIf getrennt als End If geschrie-ben werden.

Page 40: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

40

Die Grundpfeiler von Programmen3j e t z t l e r n e i c h

1ElseIfAuch bei mehr als zwei Auswahlmöglichkeiten ...

If Sorte = 1 Then Print "Sie haben Vanille gewählt."If Sorte = 2 Then Print "Sie haben Schoko gewählt."If Sorte = 3 Then Print "Sie haben Erdbeer gewählt."If Sorte = 4 Then Print "Sie haben Knoblauch gewählt."

... bietet Blitz Basic eine alternative Schreibweise an:

; EIS2.BBIf Sorte = 1 Then Print "Sie haben Vanille gewählt."ElseIf Sorte = 2 Then Print "Sie haben Schoko gewählt."ElseIf Sorte = 3 Then Print "Sie haben Erdbeer gewählt."ElseIf Sorte = 4 Then Print "Sie haben Knoblauch gewählt."EndIf

3.1.4 Die Case-VerzweigungFalls es nicht nur zwei oder drei, sondern viele Verzweigungen geben soll, ist das Han-tieren mit vielen If-Befehlen unhandlich:

If Sorte = 1 Then Print "Sie haben Vanille gewählt."If Sorte = 2 Then Print "Sie haben Schoko gewählt."If Sorte = 3 Then Print "Sie haben Erdbeer gewählt."If Sorte = 4 Then Print "Sie haben Knoblauch gewählt."If Sorte = 5 Then Print "Sie haben Zitrone gewählt."If Sorte = 6 Then Print "Sie haben Himbeer gewählt."

Blitz Basic bietet dafür den Verteiler Select/Case. Wie Sie ihn verwenden, zeigt das fol-gende Beispiel:

; EIS3.BBSorte = Input$("Drücken Sie eine Taste: ")Select Sorte Case 1 Print "Sie haben Vanille gewählt." Case 2 Print "Sie haben Schoko gewählt." Case 3 Print "Sie haben Erdbeer gewählt." Case 4 Print "Sie haben Knoblauch gewählt." Case 5 Print "Sie haben Zitrone gewählt." Case 6 Print "Sie haben Himbeer gewählt."End SelectWaitKey

Diese Variante ist nicht nur kürzer und übersichtlicher. Sie hat einen weiteren Vorteil:Sie können einen Zweig festlegen, der eingeschlagen wird, wenn am Ende keine Be-dingung zutraf. Beim Eisautomaten wäre das zum Beispiel die Eingabe der Sorte 8.Den »Ansonsten«-Zweig beginnen Sie mit Default:

Eine If/Then/Else-Verbindung schließen Sie mit EndIf ab.

Page 41: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

41

Schleifen j e t z t l e r n e i c h

Select Sorte Case 1 Print "Sie haben Vanille gewählt." Case 2 Print "Sie haben Schoko gewählt." Default Print "Leider haben wir nur 2 Sorten."End Select

Natürlich dürfen Sie statt einer Zahl eine Zeichenkette als Gegenstand der Bedingungangeben. Und statt eines Werts sind mehrere Ausdrücke erlaubt, getrennt jeweils durchein Komma:

Case 1, 2 Print "Gültige Sorte"

3.2 Schleifen

Neben Verzweigungen zählen Wiederholungen zu den Elementen eines Programms,die am häufigsten eingesetzt werden. Statt eine Folge von Befehlen mehrfach einzu-setzen, fasst man sie in einer Schleife zusammen. Basic bietet gleich mehrere Möglich-keiten an, um ein Programmteil zu wiederholen.

3.2.1 Die For-SchleifeAngenommen, Sie wollen fünfmal die gleiche Zeile ausdrucken:

Print "Hallo, Zauberlehrling!"Print "Hallo, Zauberlehrling!"Print "Hallo, Zauberlehrling!"Print "Hallo, Zauberlehrling!"Print "Hallo, Zauberlehrling!"WaitKey

Eine elegantere Lösung ist das Verwenden einer Zählschleife. Dieser geben Sie vor, siesoll fünfmal den Print-Befehl ausführen:

For I=1 To 5Print "Hallo, Zauberlehrling!"NextWaitKey

Freilich, auf den ersten Blick sieht das viel komplizierter aus. Nehmen wir die Zeilendoch einmal auseinander. Eine Zählschleife wird mit dem Befehl For eingeleitet. Sienutzt eine Variable, um den Stand des Zählers zwischenzuspeichern. Wir haben I alsVariable gewählt, hätten jedoch jeden anderen Namen verwenden können. Der Start-wert ist 1, der Endwert ist 5 – mit diesen Vorgaben wird die Schleife fünfmal durchlau-fen.

In der nächsten Zeile steht der Befehl, der wiederholt werden soll. Hier könnten Sieauch eine ganze Reihe von Zeilen eintragen. Der Computer weiß anhand des BefehlsNext, dass die Schleife zu Ende ist. Next meint: »Der nächste Durchlauf, bitte.«

Wie bei der If-Bedingung ist es empfehlenswert, den Inhalt (Körper) einer Schleife ausGründen der Übersicht einzurücken:

For I=1 To 5 Print "Hallo, Zauberlehrling!"NextWaitKey

Page 42: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

42

Die Grundpfeiler von Programmen3j e t z t l e r n e i c h

Drei Eigenschaften der For-Schleife machen sie zu einem mächtigen Verbündeten:

� Sie legen Start- und Zielwert frei fest.

� Sie können die Zählervariable in der Schleife verwenden, wobei sie bei jedemDurchlauf erhöht wird.

� Eine For-Schleife kann weitere For-Schleifen enthalten.

Ich zeige Ihnen ein kleines Beispiel zum Aufwärmen:

For I=1 To 8 Print "Das Quadrat von " + I + " ist " + I * INextWaitKey

Die Ausgabe:

Das Quadrat von 1 ist 1Das Quadrat von 2 ist 4Das Quadrat von 3 ist 9...Das Quadrat von 8 ist 64

For-Schleifen bieten sich für alle Wiederholungen an, deren Anzahl festgelegt ist. Sokönnen Sie schnell die Fakultät einer Zahl berechnen, das fortlaufende Produkt einerZahlenreihe. Die Fakultät von 5 ist 1 x 2 x 3 x 4 x 5 = 125. Man schreibt dazu auch5! = 125.

; FAKULTÄT.BBZahl = Input("Zahl eingeben: ")Fakultaet = 1For I=1 To Zahl Fakultaet = Fakultaet * INextPrint Zahl + "! = " + FakultaetWaitKey

(Die Ergebnisse werden rasch so groß, dass sie die Arithmetik von Blitz Basic überfor-dern. Sie sollten daher nur Zahlen zwischen 1 und 12 abfragen.)

Verschachtelte SchleifenDas Verschachteln von For-Schleifen empfiehlt sich dann, wenn mehrspaltige Tabellenbearbeitet werden sollen. Stellen Sie sich ein Haus als Tabelle vor. Die Etagen sind dieZeilen, die Wohnungen sind die Spalten. Um alle Wohnungen eines Hauses mit 4 Eta-gen und jeweils 3 Wohnungen aufzulisten, verwenden Sie eine Schleife wie diese:

; WOHNUNG.BBFor Etage=1 To 4 Write "Etage " + Etage + ": " For Wohnung=1 To 3 Write "E" + Etage Write "W" + Wohnung + " " Next PrintNextWaitKey

Page 43: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

43

Schleifen j e t z t l e r n e i c h

Das Programm druckt folgende Liste aus:

Etage 1: E1W1 E1W2 E1W3Etage 2: E2W1 E2W2 E2W3Etage 3: E3W1 E3W2 E3W3Etage 4: E4W1 E4W2 E4W3

1

Zähler und Schrittweite verändernUm die Schleife zu verwirren, setzen Sie die Zählvariable in der Schleife selbst auf ei-nen anderen Wert. Stellen Sie sich vor, Sie möchten von 0 bis 9 zählen, aber dabei die5 auslassen:

For I=0 To 9 If I=5 Then I=6 Write INextWaitKey

Die Ausgabe:

012346789

Sie könnten diesen Trick verwenden, um nur mit jedem zweiten oder dritten Wert zuarbeiten, etwa nur mit geraden Zahlen. Weil das recht oft gebraucht wird, bietet BlitzBasic dafür eine Erweiterung der For-Schleife: Mit dem zusätzlichen Schlüsselwort Stepgeben Sie die Schrittweite an:

For I=1 To 10 Step 2 Write I + " "NextWaitKey

Die Ausgabe:

1 3 5 7 9

Wählen Sie eine negative Schrittweite, um die Schleife rückwärts zählen zu lassen. Ver-gessen Sie dabei nicht, den Start- und den Zielwert zu vertauschen:

For I=10 To 1 Step -2 Write I + " "NextWaitKey

Die Ausgabe:

10 8 6 4 2

Geraten Sie nicht durcheinander, welches Next zu welcher Schleife gehört! In vielenBasic-Varianten ist es erlaubt, hinter das Next die Zählvariable zu setzen (Next Etage),um einen besseren Überblick zu erhalten. Blitz Basic lässt das leider nicht zu. Behal-ten Sie die Übersicht durch Einrückungen. Notfalls setzen Sie die betreffende Variableals Kommentar hinter Next.

Page 44: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

44

Die Grundpfeiler von Programmen3j e t z t l e r n e i c h

1

3.2.2 Sofort aussteigenMit dem Befehl Exit verlassen Sie eine For-Schleife sofort. Das kommt bei Zählschlei-fen kaum vor und ergibt eher bei den anderen Schleifen einen Sinn. Dennoch wollteich es Ihnen der Vollständigkeit halber sagen. So ist die Ausgabe des Programms ...

For I=1 To 10 Write I If I=5 Then ExitNextWaitKey

... nur die Zeile:

12345

3.2.3 Die Repeat-SchleifeEine For-Schleife ist nützlich, wenn Sie genau wissen, wie oft sie ausgeführt werdensoll. Nicht immer ist das jedoch vorher bekannt. Oft soll ein Vorgang so lange wieder-holt werden, bis ein bestimmtes Ereignis eintritt: Der Spieler hat alle Leben verloren,er möchte nicht mehr spielen oder er hat das Lösungswort erraten. Eine weitereSchleifenform hilft dabei. Bei ihr wird erst am Ende eines Durchlaufs geprüft, ob siewiederholt wird:

Repeat (Wiederhole)<Befehle>Until (Bis) <Bedingung>

Damit lässt sich der Eisautomat aus dem vorigen Abschnitt verbessern. Wir fragennach der Ausgabe einer Kugel, ob der Benutzer eine weitere Kugel möchte. Antworteter mit »j«, ist die Bedingung erfüllt und die Schleife wird wiederholt. Bei jeder anderenAntwort endet die Schleife.

; EIS4.BBPrint "Willkommen beim Ice-O-Mat!"Print "1 - Vanille"Print "2 - Schoko"Repeat Print "Welche Sorte möchten Sie?" Sorte = Input$("Drücke eine Taste: ") If Sorte = "1" Then Print "Einmal Vanille, bitte sehr." If Sorte = "2" Then Print "Einmal Schoko, bitte sehr." Antwort$ = Input$("Noch ein Eis (j/n)?")Until Antwort$ <> "j"WaitKey

Je nachdem, ob die Bedingung erfüllt ist, wird eine Repeat-Schleife einmal, zehnmaloder unbegrenzt oft ausgeführt. Falls Sie vorhaben, die Schleife unendlich oft auszu-führen, können Sie eine Abbruchbedingung verwenden, die nie Realität wird:

Until 1=2

Anders als die Werte für For und Next, darf die Schrittweite Step während des Ab-arbeitens der Schleife nicht geändert werden. Ja, es ist nicht einmal möglich, eine Va-riable einzusetzen. Sie müssen hinter Step eine Zahl oder – dazu später mehr – eineKonstante setzen.

Page 45: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

45

Sprünge j e t z t l e r n e i c h

Besser ist es jedoch, auf ein eigenes Schlüsselwort zurückzugreifen. Damit die Schleifenie endet, schreiben Sie statt des Until-Befehls Forever:

; EIS5.BBRepeat Print "Welche Sorte möchten Sie?" Sorte = Input$("Drücken Sie eine Taste: ") If Sorte = "1" Then Print "Einmal Vanille, bitte sehr." If Sorte = "2" Then Print "Einmal Schoko, bitte sehr."ForeverWaitKey

13.2.4 Die While-SchleifeMit Repeat/Until wird die Abbruchbedingung erst nach dem Schleifendurchlauf ge-prüft. Manchmal wollen Sie jedoch vor dem Ausführen testen, ob die Schleife über-haupt ausgeführt werden soll. Das ist sinnvoll bei einem Eisautomaten, bei dem vor derFrage nach der Sorte festgestellt wird, ob überhaupt noch Eismasse verfügbar ist. Wirgehen davon aus, dass in der Variable Eis die Anzahl der zur Verfügung stehenden Ku-geln gespeichert ist.

Die While-Schleife beginnt mit einer Bedingung. Ist sie nicht erfüllt, wird die Schleifenicht (mehr) ausgeführt. Wend schließt die Schleife ab.

; EIS6.BBWhile Eis > 0 Print "Welche Sorte möchten Sie?" Sorte = Input$("Drücken Sie eine Taste: ") If Sorte = "1" Then Print "Einmal Vanille, bitte sehr." If Sorte = "2" Then Print "Einmal Schoko, bitte sehr."WendWaitKey

Der wichtigste Unterschied zwischen Repeat/Until und While/Wend: Eine Repeat-Schleife wird mindestens einmal ausgeführt. Erst am Ende wird geprüft, ob sie ein wei-teres Mal durchlaufen werden soll. Eine While-Schleife wird im ungünstigsten Fall über-haupt nie ausgeführt, nämlich dann, wenn bereits vor dem ersten Durchlauf die Bedin-gung nicht erfüllt wird. Beide Schleifenarten haben ihre Berechtigung und Sie werdensie noch oft verwenden.

13.3 Sprünge

Den nicht besonders guten Ruf, den Basic oft genießt, hat es zu einem guten Teil demBefehl Goto zu verdanken. Er stammt aus der Zeit, als Basic-Programme noch mit Zei-lennummern versehen waren:

Genauso wie die anderen Schleifen verlassen Sie eine Repeat-Schleife sofort mit demBefehl Exit.

Genauso wie die anderen Schleifen verlassen Sie eine While-Schleife sofort mit demBefehl Exit.

Page 46: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

46

Die Grundpfeiler von Programmen3j e t z t l e r n e i c h

10 Print "Hallo!"20 Name$=Input$("Wie ist Ihr Name: ")30 Print "Guten Tag, " + Name$

Die Zeilen dienten zwei Zwecken: Früher hatten Computer nicht so komfortable Edi-toren wie heute. Während man heute eine ganze Seite auf einmal sieht und blitzschnellblättern kann, ließ sich früher nur eine einzelne Zeile auf einmal editieren. Zeilennum-mern sorgten hier für eine schnelle Orientierung.

Der zweite Grund war der Befehl Goto. Er unterbricht den Programmablauf und setztihn an anderer Stelle fort. Ein Endlosprogramm, das fortwährend den Namen erfragtund ausgibt, würde folgendermaßen aussehen:

10 Print "Hallo!"20 Name$=Input$("Wie ist Ihr Name: ")30 Print "Guten Tag, " + Name$40 Goto 20

In Zeile 40 springt das Programm zurück in Zeile 20.

Meistens arbeitete man mit Zehnerschritten, um zwischendurch vergessene Pro-grammbefehle eintragen zu können. Wo das nicht ausreichte, sprang man mit Goto zueiner anderen Stelle und danach wieder zurück. Die wilden Sprünge sorgten für Un-übersichtlichkeit und führten zum so genannten »Spagetti-Code«.

Auch in Blitz Basic blieb der Goto-Befehl erhalten. Da es keine Zeilennummern mehrgibt, geben Sie als Ziel eine Marke (englisch Label) an. Ähnlich wie bei einer Variablenwählen Sie einen beliebigen Namen. Damit Blitz Basic weiß, dass Sie eine Marke ge-setzt haben, stellen Sie ihr einen Punkt voran:

.Marke1

Diese Marke springen Sie mit Goto an:

Goto Marke1

Unser Beispiel in Schreibweise von Blitz Basic:

; GOTO.BBPrint "Hallo!".MarkeName$=Input$("Wie ist Ihr Name: ")Print "Guten Tag, " + Name$Goto Marke

Solche Endlosschleifen erzeugen Sie freilich auch mit dem Befehlspaar Repeat/For-ever.

If und Goto zusammen ermöglichen bedingte Sprünge:

If Eingabe$="j" Then Goto WeiterIf Eingabe$="n" Then Goto Ende

1Ein guter Programmierer, so sagt man, verwendet kein Goto. Sie kommen dank Un-terprogrammen, Funktionen und eines strukturierten Aufbaus leicht ohne denSprungbefehl aus. Der Streit um Für und Wider des Sprungbefehls währt schon vieleJahre. Letztendlich ist die Frage akademisch: Alle Elemente, mit denen man Goto um-geht, werden letztendlich – mit dem Übersetzen in die Maschinensprache – ohnehinSprungbefehle. Dennoch sollte auf den Befehl verzichtet werden. Er verleitet zu un-übersichtlichen Programmen, in denen Fehler schwer zu finden sind.

Page 47: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

47

Unterprogramme j e t z t l e r n e i c h

3.4 Unterprogramme

In komplexen Programmen müssen vielfach die gleichen Aufgaben vollbracht werden.Denken Sie an das Laden eines Levels, das Zeichnen von Grafiken oder die Befehlebeim Zusammenstoß der Spielfigur mit einem Monster.

Solche häufig eingesetzten Programmteile fassen Sie in einem so genannten Unter-programm zusammen. Mit dem Befehl Gosub springen Sie zu dem separaten Teil. Erarbeitet ähnlich wie Goto. Auch hier legen Sie eine Marke als Ziel fest:

Gosub LadeLevel

Sind alle Befehle des Unterprogramms abgearbeitet, springt Blitz Basic selbstständigzu der Stelle zurück, wo das Unterprogramm aufgerufen wurde. Das heißt, das Pro-gramm wird mit dem Befehl fortgesetzt, der Gosub folgt. Das ist ein großer Vorteil ge-genüber Goto. Mit zwei Goto-Befehlen ließe sich ein Unterprogramm erstellen, das nurvon einer Stelle im Programm aufgerufen werden kann, weil das zweite Goto zu einerfestgelegten Marke springt:

; Hauptprogramm<Befehle>Goto Unterprogramm ; nur 1 Aufrufstelle möglich.Zurueck<Befehle>; Programmende;; Unterprogramm.Unterprogramm<Befehle>Goto Zurueck

Unterprogramme, die Sie mit Gosub erreichen, beenden Sie mit dem Befehl Return.Return springt dorthin zurück, wo das Unterprogramm mit Gosub aufgerufen wurde.Sie können ein Unterprogramm von jeder Stelle aus aufrufen – mit Return findet es denrichtigen Weg zurück:

; Hauptprogramm<Befehle>Gosub Unterprogramm ; 1. Aufruf<Befehle>Gosub Unterprogramm ; 2. Aufruf<Befehle>Gosub Unterprogramm ; 3. Aufruf<Befehle>; Programmende;; Unterprogramm.Unterprogramm<Befehle>Return

Unterprogramme haben keinen Einfluss auf die Wirkung von Variablen. In einem Un-terprogramm lesen und verändern Sie alle Variablen, die im Hauptprogramm verein-bart wurden. Veränderungen im Unterprogramm beeinflussen auch das Hauptpro-gramm:

Page 48: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

48

Die Grundpfeiler von Programmen3j e t z t l e r n e i c h

; UNTERPROGRAMM.BBI = 10Print "Hauptprogramm"Print "I = " + IPrint "J = " + JGosub TestPrint "Wieder im Hauptprogramm"Print "I = " + IPrint "J = " + JWaitKeyEnd;.TestPrint "Unterprogramm"J = 20Print "I = " + IPrint "J = " + JReturn

03.5 Funktionen

Unterprogramme sind sehr praktisch, wenn Sie eine Befehlsfolge von mehreren Stel-len aus aufrufen. Außerdem halten sie Ihr Programm übersichtlicher. Wenn Sie ein Un-terprogramm zur Ermittlung eines Werts verwenden wollen, dann sollten Sie dafür eineFunktion verwenden.

Vergleichen Sie die Verwendung des Befehls Input mit anderen, wird Ihnen eine Be-sonderheit auffallen. Normalerweise stehen Befehle einzeln:

Print "Hallo"

Input hingegen lässt sich nur in Zusammenhang mit einer Variable einsetzen:

A$ = Input("Ihr Name: ")

Das macht auch Sinn, denn Input liefert einen Wert, der in einer Variable gespeichertwird und dort bearbeitet werden kann. Befehle, die Werte zurückliefern, nennt manFunktionen.

Das Ergebnis kann nicht nur gespeichert, sondern direkt ausgedruckt werden. DieKurzform von

A$ = Input("Ihr Name: ")Print A$

ist daher:

Print Input("Ihr Name: ")

Blitz Basic bietet jede Menge eingebauter Funktionen. Im nächsten Kapitel werden vie-le von ihnen vorgestellt. Hier ein Beispiel, um dem vorzugreifen: Die Funktion Sqr(x)liefert die Quadratwurzel einer Zahl:

Print Sqr(64)

Beachten Sie, dass ein Unterprogramm auch dann abgearbeitet wird, wenn BlitzBasic von allein darauf stößt. Daher schließen Sie Ihr Programm mit dem Befehl Endab, bevor die Unterprogramme folgen.

Page 49: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

49

Funktionen j e t z t l e r n e i c h

Sie können solche Funktionen für Ihr Programm selbst erstellen. Sie dürfen ihnen ei-nen beliebigen Namen geben und ihre Verwendung unterscheidet sich nicht von denFunktionen, die Blitz Basic bereits mitliefert. Funktionen helfen Ihnen dabei, längereQuelltexte übersichtlich zu halten.

Angenommen, Sie müssen im Rahmen eines größeren Programms häufig DM in Euroumrechnen. Natürlich könnten Sie jedes Mal:

Euro = Betrag / 1,95583

rechnen, aber eine eigene Funktion ist eleganter und einfacher im Umgang. So könnteder Befehl:

Print Euro(45)

ausdrucken, wie viel Euro 45 DM sind.

Wie stellt man es an? Eine Vereinbarung für eine Funktion nehmen Sie mit dem BefehlFunction vor. Sie sagen ihm,

� wie Ihre Funktion heißt (Beispiel: Doppelt),

� welche Werte sie entgegennehmen soll (Beispiel: X)

� und welchen Wert sie als Ergebnis liefern soll (Beispiel: X * 2):

Function Doppelt(X) Return X * 2End Function

Sie können die Funktion Doppelt nun von jeder Stelle aus aufrufen, und sie wird eineZahl für Sie verdoppeln:

Print Doppelt(8)

1Eine Funktion ist beliebig viele Befehlszeilen lang. Sie eignet sich für kleine, aber häufigbenutzte Berechnungen ebenso wie für umfangreiche Programmabschnitte. Es ist keinProblem, alle Elemente eines Spiels auf Funktionen zu verteilen und ein minimalesHauptprogramm zu verwenden, das diese Funktionen aufruft.

Mit der Anweisung Return legen Sie fest, welchen Wert die Funktion zurückgeben soll.Eine umständlichere Beschreibung der Funktion wäre:

Function Doppelt(X) A = X * 2 Return AEnd Function

Beachten Sie dabei, dass der Name einer Funktion den Typ haben muss, den sie zu-rückgeben soll. Eine Funktion, die eine Zeichenkette ausgibt, muss im Namen dieKennzeichnung $ tragen:

Function Doppelt$(X$) Y$ = X$ + X$ Return Y$End Function

Die Übergabewerte an und von Funktionen bezeichnet man auch als Parameter.Eine Funktion kann nur einen Wert zurückliefern.

Page 50: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

50

Die Grundpfeiler von Programmen3j e t z t l e r n e i c h

1Sie dürfen einer Funktion beliebig viele Werte übergeben. Meistens wird es nur einWert sein, den es zu bearbeiten gilt, doch auch zwei oder drei Parameter sind häufiganzutreffen. Wenn Sie eine Funktion etwa mit

Function Drucken(A, B, C)

einleiten und sie im Hauptprogramm mit

Print Drucken(1, 2, 3)

aufrufen, dann werden den Funktionsvariablen A, B und C die Werte 1, 2 und 3 zuge-wiesen. Sie müssen dabei drei Parameter übergeben; bei der Zeile

Print Drucken(1, 2)

würde Blitz Basic streiken. Es ist allerdings möglich, einen Wert für einen Parametervorher einzustellen:

Function Drucken(A, B, C=3)

Das bedeutet: Hat der Funktionsaufruf drei Parameter, werden alle drei übergeben.Ruft man die Funktion aber nur mit zwei Parametern auf, bekommt die dritte VariableC den Wert 3. Das Programm

; FUNKTION.BBFunktion (1, 2)Funktion (1, 2, 4)WaitKey;Function Funktion (A, B, C=3) Write A Write B Write C Print ReturnEnd Function

gibt daher Folgendes aus:

123124

Beim ersten Aufruf fehlt der dritte Parameter; Blitz Basic nimmt daher die Voreinstel-lung 3. Beim zweiten Aufruf wird die Voreinstellung überschrieben.

Eine Funktion muss keinen Wert zurückgeben. Wenn Blitz Basic ein Return ohne Pa-rameter findet, beendet es die Funktion und gibt eine Null zurück. Hat die Funktionkein Return, endet sie mit der letzten Zeile. Da Sie keinen Rückgabewert erwarten,können Sie natürlich die Funktion aufrufen, ohne sie mit einer Variablen zu verbinden.

Anders als bei Unterprogrammen wird eine Funktion nicht versehentlich abgearbei-tet, weil die Befehle »an der Reihe« sind. Sie brauchen also nicht End zu verwenden,um Ihr Programm zu beenden, bevor die Definitionen für die Funktionen beginnen.

Page 51: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

51

Funktionen j e t z t l e r n e i c h

0

3.5.1 Globale VariablenFunktionen haben eine wichtige Besonderheit gegenüber Unterprogrammen. Variab-len aus dem Hauptprogramm können Sie in einer Funktion normalerweise nicht ver-wenden:

; GLOBAL1.BBA = 10Print APrint TestFunktion(A)WaitKeyEnd;Function TestFunktion(B) Return AEnd Function

Das seltsame Ergebnis:

100

Die Variable A wurde im Hauptprogramm auf 10 gesetzt. In der Funktion wird die Va-riable A als Rückgabewert festgelegt. Warum ist er dann 0? Die Antwort: weil Variablenin Funktionen nicht mit übernommen werden. Auf der anderen Seite verändert eineFunktion keine Variablen des Hauptprogramms:

; GLOBAL2.BBA = 10Print APrint TestFunktion(A)Print AWaitKeyEnd;Function TestFunktion(B) A = 20 Return AEnd Function

Das Ergebnis:

102010

Obwohl A in der Funktion auf 20 gesetzt wurde, hat die Variable im Hauptprogrammwieder den Wert 10.

Übrigens können Sie Funktionen von Blitz Basic überschreiben, indem Sie einfacheine neue Funktion mit dem gleichen Namen erstellen. So ist es möglich, eine Funk-tion Sqr() zu definieren, die nicht die Wurzel zieht, sondern zum Beispiel multipliziert.Einzige Einschränkung: Die Funktion darf sich nicht selbst aufrufen; in der Beschrei-bung der Funktion Sqr() darf kein Aufruf von Sqr() erfolgen.

Page 52: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

52

Die Grundpfeiler von Programmen3j e t z t l e r n e i c h

Sie haben zwei Möglichkeiten, um Variablen aus dem Hauptprogramm in einer Funk-tion zu verwenden:

1. Sie übergeben sie als Parameter der Funktion. So können Sie sie zwar nicht ver-ändern, aber immerhin auslesen, um sie in der Funktion sinnvoll zu verarbeiten.

2. Sie legen bei der ersten Verwendung einer Variablen fest, dass sie überall gültig ist,egal, ob im Hauptprogramm oder in einer Funktion. Das tun Sie, indem Sie bei ih-rer ersten Nennung den Befehl Global voranstellen:

Global A=10

Unser leicht abgewandeltes Beispiel dieses Phänomens zeigt den Unterschied:

; GLOBAL3.BBGlobal A = 10Print APrint TestFunktion(A)WaitKeyEnd;Function TestFunktion(B) A = 20 Return AEnd Function

Die Ausgabe:

1020

1Sie müssen der Variable beim Verwenden von Global (und Local) keinen Wert überge-ben. Es ist also möglich, am Anfang des Programms eine globale Variable zu definieren...

Global A

... und ihr erst später einen Wert zuzuweisen. Außerdem dürfen Sie mehrere Variablenauf einmal, getrennt durch ein Komma, einrichten:

Global A,B,CGlobal A=10, B=20, C=30

A3.6 Rekursion

Keine Angst: Hinter dem Wort Rekursion steckt nichts Kompliziertes. Rekursiv bedeu-tet: Ein Programmteil ruft sich selbst auf. Das kann sinnvoll sein, wenn eine zunächstunbekannte Anzahl von Programmschritten wiederholt werden soll. Etwa: Wir suchenden Ausgang aus einem Labyrinth, wissen aber nicht, wie viele Schritte notwendigsind. An einem einfachen Beispiel soll das verdeutlicht werden:

Das Gegenteil des Schlüsselworts Global ist Local. Lokale Variablen sind entwedernur im Hauptprogramm oder nur in einer Funktion gültig. Variablen ohne den Vor-satz Global sind automatisch lokal, daher müssen Sie Local nicht extra angeben.

Page 53: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

53

Rekursion j e t z t l e r n e i c h

; REKURSIV1.BBGlobal Grund = 10Tiefe = 0Graben(Tiefe)WaitKey;Function Graben(Tiefe) If Tiefe <> Grund Then Tiefe = Tiefe + 1 Print "Tiefe nun: " + Tiefe Graben(Tiefe) Print "Position nun: " + Tiefe EndIfEnd Function

Die Funktion gräbt jeweils einen Schritt weiter in die Tiefe und ruft sich selbst auf, umimmer weiterzustoßen. Es bedarf einer Abbruchbedingung, sonst endet das Programmnie. Der Einfachheit halber haben wir etwas getrickst und mit Grund=10 eine greifbareAbbruchbedingung geschaffen. Es macht normalerweise keinen Sinn, rekursiv zu pro-grammieren, wenn man bereits vorher weiß, wann das Ziel erreicht ist.

Die Funktion ruft sich selbst immer wieder auf, bis der Grund erreicht ist. Die VariableTiefe hat dann den Wert 10. An diesem Punkt kommen wir zur Besonderheit der Re-kursion: Endet die tiefste Funktion, springt das Programm nach und nach eine Stufezurück. Jede Funktion wird damit ein zweites Mal angesteuert. Aus diesem Grund wirdin unserem Beispiel die Tiefe mit den Zahlen 1 bis 10 gedruckt, die Position aber von10 bis 1. Die Zeile

Print "Position nun: " + Tiefe

wird nämlich erst dann ausgeführt, wenn der Grund erreicht und das Abbruchziel erfülltist. Erst in dieser Situation ruft sich die Funktion nicht weiter auf, sondern beendet sich,so dass die höher gelegene Funktion erreicht wird, die sich wiederum beendet ... Klingtverwirrend?

Noch einmal: In der Rekursion gräbt sich eine Funktion stufenweise in die Tiefe. Ist dieAbbruchbedingung erfüllt, steigt sie stufenweise wieder hinauf. Das funktioniert soähnlich wie bei einem Stapel Teller. Um den untersten Teller zu erreichen, müssennach und nach alle oberen entfernt werden. Am Schluss stellt man die Teller in umge-kehrter Reihenfolge wieder aufeinander.

Technisch funktioniert das so ähnlich. Der Computer benutzt für die Rekursion einenStapelspeicher (englisch: Stack). Wenn eine Funktion oder ein Unterprogramm auf-gerufen wird, notiert sich der Computer die aktuelle Position auf einem Notizzettel. Aufdiese Weise findet er zurück, wenn die Funktion beendet ist. Bei der Rekursion bildetsich ein ganzer Stapel dieser Zettel. Ist die Ende-Bedingung erfüllt, schließt der Com-puter nach und nach die Funktionen, indem er die Zettel in umgekehrter Reihenfolgenimmt und zu der notierten Adresse springt.

1Dieses Verfahren nennt man auch LIFO – Last In First Out: Der Wert, der zuletzt inden Stack gelegt wurde, wird als Erstes wieder entnommen.

Page 54: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

54

Die Grundpfeiler von Programmen3j e t z t l e r n e i c h

Anders als beim normalen Arbeitsspeicher, den Windows notfalls durch den Festplat-tenspeicher ergänzt, um Engpässe auszugleichen, ist der Stack begrenzt. Das bedeutet:Es ist nicht möglich, unendlich oft rekursiv Funktionen aufzurufen. Setzen wir probe-halber die maximale Tiefe nicht auf 10, sondern auf 100000, dann dürfte unser Pro-gramm nicht zu Ende laufen, sondern mittendrin abstürzen. Manchmal meldet es sichmit Stack Overflow, manchmal reißt es den Blitz-Editor mit in die Tiefe.

; REKURSIV2.BB; Achtung: Programm stürzt ab!Global Grund = 100000Tiefe = 0Graben(Tiefe)WaitKey;Function Graben(Tiefe) If Tiefe <> Grund Then Tiefe = Tiefe + 1 Print "Tiefe nun: " + Tiefe Graben(Tiefe) EndIfEnd Function

Auf meinem PC stürzte das Programm nach rund 36.000 Durchläufen ab. Das ist frei-lich eine ganze Menge. Sicherheitshalber sollten Sie rekursive Teilprogramme auf einezu erwartende Tiefe von einigen hundert Selbstaufrufen begrenzen.

Rekursives Programmieren zeigt gut die unterschiedliche Handhabung von globalenund lokalen Variablen: Wir haben Grund global gesetzt, damit alle Funktionsaufrufe aufden gleichen Wert zugreifen. Alternativ hätten wir jeder Funktion die Variable überge-ben können. Doch das macht keinen Sinn und verschwendet Speicher. Der Wert vonTiefe ändert sich hingegen bei jeder Rekursionsstufe. Daher übergeben wir jederInstanz der Funktion ihren aktuellen Wert. Grundsätzlich hätten wir hier auch mit einerglobalen Variable arbeiten können. Dem Graben täte es keinen Abbruch. Nur beimHinaufsteigen gäbe es eine entscheidende Änderung: Die Variable Tiefe würde sichnicht mehr ändern. Die Zeile

Print "Position nun: " + Tiefe

würde immer 10 ausgeben. In unserem ersten Beispiel ändert sich die Grabtiefe auchin dieser Zeile, weil sich jede Funktion ihre eigene lokale Kopie der Variable merkt.

3.7 Aufgaben

1. Was ist der maßgebliche Unterschied zwischen einer Repeat/Until- und einerWhile/Wend-Schleife?

2. Womit programmieren Sie eine Schleife, die nie enden soll?

3. Schreiben Sie ein Programm, das die Zahlen 1 bis 100 auf den Bildschirm ausgibt.Dabei sollen jeweils zehn Zahlen in einer Zeile stehen.

Page 55: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

55

jetz

t le

rne

ich

KAPITEL 4

Variablen

In Blitz Basic verwenden Sie zwei Arten von Daten: Zeichenketten und Zahlen. Siespeichern Daten in Variablen

4.1 DatentypenA = 5B = "Hallo"

Sie verändern die Datentypen mithilfe von Befehlen. Zahlen werden etwa miteinanderaddiert, Zeichenketten erweitert oder verkleinert.

Blitz Basic unterscheidet dabei zwei Formen von Zahlen:

� ganze Zahlen (ohne Kommastellen)

� reelle Zahlen oder Fließkommazahlen (mit Kommastellen)

Der Computer geht mit beiden Formaten auf eigene Weise um. Daraus ergeben sichunterschiedliche Einsatzmöglichkeiten.

1In vielen Programmiersprachen existieren eine Reihe von Zahlentypen. Sie unter-scheiden sich vor allem in ihrem Speicherverbrauch. So gibt es häufig einen Typ, dernur ein Byte verbraucht, dafür aber nur Werte zwischen 0 und 255 speichern kann.Die Zahlen in Blitz Basic hingegen werden immer in vier Byte großen Variablen ge-speichert, egal, ob es sich um ganze oder reelle Zahlen handelt.

Page 56: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

56

Variablen4j e t z t l e r n e i c h

Eine Variable speichert entweder eine Zeichenkette oder eine ganze Zahl oder eine re-elle Zahl. Sie bestimmen das, indem Sie die Variable bei ihrer ersten Verwendung miteiner Kennung versehen:

% steht für eine ganze Zahl(Beispiel: A% = 5)

# steht für eine reelle Zahl(Beispiel: A# = 5.25)

$ steht für eine Zeichenkette(Beispiel: A$ = "Hallo")

Fehlt die Kennung, erhält die Variable den Typ Ganzzahl. Selbst wenn Sie zum Beispiel...

A = "Hallo"

... schreiben, ist A eine Zahlenvariable mit dem Wert 0.

Die Kennung müssen Sie nur beim ersten Auftauchen der Variable setzen. Später kannsie entfallen.

4.1.1 Ganze ZahlenGanze Zahlen (englisch: Integer) sind in Blitz Basic im Bereich von –2 bis +2 Milliar-den möglich (genauer: –2.147.483.648 bis 2.147.483.647). Es ist nicht lösbar, in ei-ner Variable eine Zahl zu speichern, die außerhalb dieser Grenzen liegt. (Falls Sie esdoch einmal tun müssen, dann als Zeichenkette. Damit sind aber keine Berechnungenmöglich. Sie müssten spezielle Programme schreiben, um mit solchen Zahlen zu rech-nen.)

Wenn Sie mit ganzen Zahlen so rechnen, dass eine Kommazahl herauskommt, etwabeim Wurzelziehen oder beim Teilen, dann schneidet Blitz Basic den Teil hinter demKomma des Ergebnisses ab. 5/3 ergäbe somit 1.

Behalten Sie stets in Erinnerung: Wenn Sie eine Zahlenvariable ohne Typangabe ver-wenden, dann weist ihr Blitz Basic das Format »ganze Zahl« zu. Das Miniprogramm:

A = 2.345Print A

hat daher als Ergebnis 2 und nicht etwa 2.345.

Ebenso wie bei Fließkommazahlen können Sie Variablen zwingend für ganze Zahlenfestlegen. Sie nehmen dazu die Kennung %:

Zahl% = 5

4.1.2 FließkommazahlenWenn Sie Kommastellen brauchen, dann verwenden Sie Fließkommazahlen (englisch:Float, Floating Point). Der Vorteil gebrochener Zahlen wird aber teuer erkauft: Zumeinen ist das Rechnen mit Fließkommazahlen aufwendiger und daher langsamer. Zumanderen sind Fließkommazahlen ungenau. Je häufiger Sie mit einem Wert rechnen,desto mehr weicht der errechnete Wert vom tatsächlichen ab. Der Grund ist folgender:Wenn Sie 10 durch 3 teilen, ist das Ergebnis 3,3333 ... Der Computer kann sich aber

Page 57: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

57

Datentypen j e t z t l e r n e i c h

nicht unendlich viele Nachkommastellen merken, sondern nur eine Hand voll. So ent-stehen kleine Ungenauigkeiten, die sich bei einer Vielzahl von Rechnungen summieren.Dennoch lassen sich Fließkommazahlen für viele Vorhaben nicht vermeiden.

Um eine Variable für Fließkommazahlen einzurichten, geben Sie ihr die Kennung #:

Zahl# = 3.25

Das Doppelkreuz ist nur bei der ersten Verwendung notwendig; später können Sie ein-fach schreiben:

Zahl = Zahl + 1

Eine Rechenaufgabe findet immer auf Fließkommaebene statt, wenn mindestens einOperator eine Fließkommazahl ist. Während das Programm:

A = 1Print A / 3B = 1Print B / 3WaitKey

nur:

00

ausgibt, führt:

A# = 1Print A / 3B = 1Print B / 3.0WaitKey

zur richtigen Ausgabe:

0.3333330.333333

1Schauen wir uns die Genauigkeitsprobleme bei Fließkommazahlen an einem kleinenBeispiel an:

; FLOAT1.BBA# = 1.5For I=1 To 10A = A / 4NextPrint AFor I=1 To 10A = A * 4NextPrint AWaitKey

Gut zu wissen: Schreiben Sie 3.0 statt 3, schaltet Blitz Basic auf Fließkommarech-nung.

Page 58: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

58

Variablen4j e t z t l e r n e i c h

Die Ausgabe:

0.0000011.500000

Bereits bei zehn Divisionen erhalten Sie kaum noch eine brauchbare Ausgabe. DassBlitz Basic in der Umkehrrechnung dennoch wieder auf 1.5 kommt, ist der Tatsache zuverdanken, dass Blitz Basic intern mit mehr Stellen rechnet, als angezeigt werden.Wenn Sie jedoch beide For-Schleifen nicht bis 10, sondern 100 rechnen lassen, istBlitz Basic bereits überfordert:

0.0000000.000000

Lassen Sie sich also während der Entwicklung Zwischenergebnisse ausgeben, um un-erfreuliche Überraschungen zu vermeiden.

1

4.1.3 ZeichenkettenZeichenketten (englisch: Strings) sind nichts weiter als eine Aneinanderreihung vonBuchstaben und Sonderzeichen wie "!§$%&/()=?". Eine Variable, die Zeichenkettenenthält, bekommt die Kennung $:

Wort$ = "Hallo"

Ebenso möglich sind Leerstellen (" ").

0

4.1.4 TypumwandlungSie wandeln eine ganze Zahl leicht in eine Fließkommazahl um – und umgekehrt. Dazugenügt es, sie einer Variable zuzuweisen, die das gewünschte Format hat:

A# = 5B% = 6A = BPrint A

B ist eine Variable für ganze Zahlen. Die 6 ist damit ebenfalls eine ganze Zahl. Bei derZuweisung A=B erhält die 6 das Format der Fließkommavariable B. Der »Beweis«: Statt6 wird 6.000000 ausgegeben.

In jeder Programmiersprache wird statt des Kommas ein Punkt geschrieben, um dengebrochenen Teil reeller Zahlen abzutrennen. In den USA, dem Vaterland der Com-puterstandards, ist der Punkt üblich. Meistens wird Blitz Basic das fehlerhafte Verwen-den eines Kommas ankreiden. Wo es nicht passiert, können Ihnen unerklärliche Feh-ler viel Kopfzerbrechen bereiten.

Genauso wie bei den Kennungen # und % müssen Sie $ nur bei der Einführung einerVariablen verwenden. Damit unterscheidet sich Blitz Basic von anderen Basic-Ver-sionen, wo $ bei jedem Einsatz einer Zeichenkettenvariablen zu setzen ist. Ich emp-fehle Ihnen dennoch, $ immer zu verwenden, damit Sie die Variablentypen besserunterscheiden können.

Page 59: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

59

Konstanten j e t z t l e r n e i c h

Umgekehrt funktioniert das genauso, wobei zur nächsten ganzen Zahl gerundet wird.Neben dieser »automatischen« Zuweisung bietet Blitz Basic Funktionen zur Typum-wandlung. Int(X) liefert den Wert von X als ganze Zahl, unabhängig davon, ob X eineZeichenkette oder eine reelle Zahl ist. Float(X) liefert X als reelle Zahl.

; FLOAT2.BBA# = 6.5Print APrint Int(A)B% = 6Print BPrint Float(B)

Die Ausgabe:

6.500000666.000000

Selbst Zeichenketten und Zahlen verbinden Sie auf diese Weise. Das Programm

A$ = "5"A$ = A$ + 3Print A$

gibt daher 53 aus. In den meisten anderen Programmiersprachen ist eine solche Ver-knüpfung nicht möglich. Sie müssen dort die Zahl vorher in eine Zeichenkette umwan-deln, bevor Sie sie an einen anderen String hängen können. Blitz Basic bietet dennocheine Funktion, die eine Zahl in eine Zeichenkette formt:

Print 5 + 3Print 5 + Str$(3)

Das Ergebnis:

853

Die Funktion Str$() ist sinnvoll, wenn Sie spezielle Zeichenkettenbefehle direkt aufZahlen anwenden wollen.

1

4.2 Konstanten

Variablen sind praktische Platzhalter für Werte. Sie können ihren Inhalt jederzeit än-dern. Wenn sich der Inhalt einer Variable nach dem Festlegen nicht mehr ändern soll,verwenden Sie besser eine Konstante. Sie unterscheidet sich von einer Variable nurdadurch, dass ihr Wert durch die anfängliche Festlegung fest eingebrannt wird:

Const Leben=3Const A=5, B=6

Sie können nur den Typ von Daten ändern. Der Typ einer Variable wird beim erstenGebrauch festgelegt und lässt sich dann nicht ändern. Wohl können Sie den Wert ei-ner Zeichenkettenvariable als Ganzzahl auslesen und einer Zahlenvariablen zuweisen.Mit der Zeichenkettenvariable selbst werden Sie aber nicht rechnen können.

Page 60: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

60

Variablen4j e t z t l e r n e i c h

Sie stellen der Zuweisung einfach das Schlüsselwort Const voran, um aus einer Variableeine Konstante zu bilden. Blitz Basic weist bereits beim Kompilieren des ProgrammsVeränderungen wie:

Const Leben=3Leben=4

mit einer Fehlermeldung zurück ("Constant can not be assigned to").

14.3 Felder

Variablen merken sich alle möglichen Dinge, zum Beispiel die Position des Spielers.Denkbar wären hier die Variablen SpielfigurX und SpielfigurY für die Koordination.Doch in einem Spiel gibt es normalerweise noch mehr Figuren. Denken Sie an dieHeerscharen von Monstern, die dem Helden auf der Spur sind. Freilich könnte maneine Vielzahl von Variablen wie Monster1X, Monster1Y, Monster2X, Monster2Y verwen-den. Das würde aber einen sehr großen Aufwand erfordern: Man müsste zum Beispieldie Bewegung jeder Figur einzeln vornehmen. Eine For-Schleife wäre praktisch, lässtsich aber nicht anwenden, weil die Monsternummern Teil des Variablennamens sind.

Blitz Basic lässt Sie eine solche Gruppe von Variablen zu einer Liste zusammenfassen.Stellen Sie sich eine Getränkekiste vor, die 10 Flaschen aufbewahren kann. Sie wollenfür jede Position in der Kiste (1–10) feststellen, ob dort eine Flasche steckt (1) odernicht (0). In Blitz Basic können Sie dazu Variablen von Flasche(1) bis Flasche(10) be-nennen. Der große Vorteil: Sie sprechen gezielt eine Flasche an, deren Nummer in ei-ner Variablen steckt (Flasche(x)). Dadurch setzen Sie mit einer For-Schleife einfachalle Flaschen auf 1:

For I=1 To 10 Flasche(I) = 1Next

Um ein solches Feld zu verwenden, müssen Sie es vor der Verwendung kurz anmelden,besser: dimensionieren. Dazu sagen Sie Blitz Basic, wie es heißen soll und wie vieleEinträge es haben soll:

Dim Flasche(10)

Damit werden elf Variablen eingerichtet, Flasche(0) bis Flasche(10). (Häufig genugverwenden Programmierer die 0. Variable nicht, weil der Mensch es gewohnt ist, von1 an zu zählen. Auch ich beginne gern bei 1.)

Solche Listen werden meistens Felder oder Arrays genannt.

Auf Papier gebracht, können Sie alle Einträge von Flasche(10) in eine Spalte eintra-gen. Daher nennt man es eindimensionales Feld. Sie können gern mehrere Dimen-sionen anlegen, um zum Beispiel nicht nur die Flaschen einer, sondern von 100 Kistenzu speichern:

Dim Flasche(100,10)

Konstanten geben Ihnen die Sicherheit, dass Sie Werte, die unverändert bleiben sol-len, nicht versehentlich ändern. Ein weiterer Vorteil: Konstanten werden vom PCschneller verarbeitet als Variablen. Konstanten sind automatisch global.

Page 61: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

61

Felder j e t z t l e r n e i c h

Auf diese Weise sprechen Sie jede Flasche in jeder Kiste direkt an. Der Befehl:

Flasche(55,8) = 1

würde der achten Flasche in Kiste 55 den Wert 1 (= Flasche vorhanden) geben. Aufdem Blatt Papier wäre das eine Tabelle – die Spalten stellen die einzelnen Flaschen dar,die Zeilen entsprechen den einzelnen Kisten. Zeile 55, Spalte 8, sozusagen.

Aber wir können die Sache noch weiter treiben: 10 Flaschen passen in eine Kiste. 50Kisten passen auf eine Palette. Es gibt 100 Paletten:

Dim Flasche(100,50,10)

Dieses dreidimensionale Feld stellen Sie sich am besten als Papierblock vor: Jede Seitespeichert die Belegung einer Palette. Und je Seite/Palette sind die einzelnen Kistenwieder in je einer Zeile gespeichert. Deren Spalten enthalten die Flaschen. Felder mitmehr als drei Dimensionen werden nur selten verwendet.

Der Speicher für ein Feld wird von Blitz Basic gleich zu Beginn der Programmausfüh-rung reserviert. Um den Platzbedarf abzuschätzen, multiplizieren Sie die einzelnenWerte der Dimensionen miteinander: Das Paletten-Feld braucht 100 x 50 x 10 =50.000 Speichereinheiten für Variablen. Und da eine Zahlenvariable 4 Byte ver-braucht, nimmt das Feld 50.000 x 4 = 200.000 Byte in Beschlag.

Für die Definition eines Feldes gelten ähnliche Regeln wie für normale Variablen: Fehlteine Typangabe, bereitet Blitz Basic ein Feld für ganze Zahlen vor. Um Fließkomma-zahlen oder Zeichenketten zu speichern, ergänzen Sie den Feldnamen um die Ken-nung # oder $:

Dim Name$(10,2)

Der Typ gilt für jedes Element des Feldes. Sie können in einem Feld nicht Zahlen undZeichenketten mischen. Falls das notwendig ist, zum Beispiel in einer Punkteliste mitNamen und Punkten, gehen Sie wahlweise wie folgt vor:

1. Falls Sie sie nicht mehr zum Rechnen benötigen, wandeln Sie die Zahlen in Zei-chenketten um, bevor Sie sie in dem Feld speichern.

2. Sie nutzen mehrere Felder parallel. Für unsere Bestenliste etwa Name$(10) undPunkte(10).

3. Sie verwenden den großen Bruder des Feldes, den benutzerdefinierten Typ (Type-Feld).

1Dim-Felder sind immer global und müssen im Hauptprogramm vereinbart werden. Dasich ein Feld im Laufe des Programms neu dimensionieren lässt, auch mit einer an-deren Anzahl von Feldern, greifen Sie zu einem Trick, um ein Feld dennoch auf eineFunktion zu beschränken: Im Hauptprogramm richten Sie ein Platzhalterfeld derForm Dim Feld(0) ein. In einer Funktion erzeugen Sie nun ein Feld der Art DimFeld(100).

Page 62: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

62

Variablen4j e t z t l e r n e i c h

4.4 Daten einlesen

Mit Feldern verwalten Sie leicht große Datenmengen. Wenn alle Feldeinträge den glei-chen Inhalt erhalten sollen, genügt eine For-Schleife, um sie schnell zu füllen. WennEinträge mit den verschiedensten Werten zu belegen sind, müssten Sie jede Zuweisungeinzeln vornehmen:

Feld(1) = 363Feld(2) = 713Feld(3) = 518...Feld(20) = 264

Das ist ziemlich aufwendig. Einfacher geht es mit dem Befehlspaar Read und Data. MitData legen Sie eine Liste von Werten an:

Data 363, 713, 518, ..., 264

Mit Read teilen Sie Variablen diese Werte zu:

Read A, B, C, ..., T

Der Befehl Read weist der aktuellen Variable den nächsten Data-Wert zu. Sie verwen-den so viele Data- und Read-Befehle, wie Sie möchten. Und jeder Befehl enthält einoder mehrere Daten oder Variablen. Besonders bequem lesen Sie Data-Werte mit einerFor-Schleife in ein Feld:

For I=1 To 20 Read Feld(I)Next

Während Sie Zahlen nacheinander in einer Data-Zeile aufreihen, setzen Sie Zeichen-ketten in Anführungsstriche:

Data "Gryffindor", "Hufflepuff", "Ravenclaw", "Slytherin"

Ein Beispiel liest die Namen von sechs berühmten Schriftstellern aus Data-Feldern. So-bald Nach- und Vorname eingelesen sind, wird der ganze Name (Vorname zuerst) in ei-ner Zeile ausgedruckt.

; DIM1.BBDim Name$(6,2)Print "Berühmte Schriftsteller:"For I=1 To 6 For J=1 To 2 Read Name$(I,J) Next Print Name$(I,2) + " " + Name$(I,1)NextWaitKey;Data "May", "Karl", "Verne", "Jules"Data "Meyer", "René", "Dominik", "Hans"Data "Fallada", "Hans", "Christie", "Agatha"

1 Übrigens dürfen in einer Data-Zeile nicht nur Zeilen und Zeichenketten stehen, son-dern auch die Namen von Konstanten. Mit Read wird dann der Inhalt der Konstanteausgelesen.

Page 63: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

63

Daten einlesen j e t z t l e r n e i c h

4.4.1 Zeiger versetzenSie können Data-Werte nur nacheinander auslesen. Allerdings setzen Sie mit dem Be-fehl Restore den Zähler wieder auf den ersten Wert. Egal, wie oft Sie schon Read ver-wendet haben, mit:

Restore

liest der nächste Read-Befehl wieder den ersten Data-Wert ein. Deswegen gibt das Bei-spiel:

Read ARestore10Read BPrint APrint BData 10, 20WaitKey

die beiden Zahlen:

1010

aus und nicht:

1020

– wie man auf den ersten Blick erwarten könnte.

Praktisch am Restore-Befehl ist, dass er nicht nur den Sprung an den Anfang ermög-licht, sondern an eine beliebige Stelle. Dazu benutzen Sie Marken, so wie bei Goto undUnterprogrammen auch. Sie stellen vor eine Gruppe von Data-Befehlen eine Markeund die gleiche Marke verwenden Sie mit Restore:

...; Daten für SpielerRestore SpielerDatenRead Spieler(1), Spieler(2) ......; Daten für MonsterRestore MonsterDatenRead Monster(1), Monster(2) ......End.SpielerDatenData ....MonsterDatenData ...

Der Vorteil daran ist, dass Sie nicht sklavisch an die exakte Reihenfolge der Data/Read-Werte gebunden sind und jederzeit die Daten einlesen können, die Sie möchten.

1Bereits bei einigen Dutzend Werten wird der Umgang mit Data/Read unkomfortabel.Große Datenmengen sollten Sie besser aus einer separaten Datei lesen.

Page 64: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

64

Variablen4j e t z t l e r n e i c h

A4.5 Blitz Arrays

Sollen Felder im kleinen Rahmen eingesetzt werden, bietet sich eine einfachere Art an,das so genannte Blitz Array. Es wird eingesetzt wie ein normales Dim-Feld, hat aber ei-nige Besonderheiten:

� Es kann nur eindimensional ein.

� Der Indexwert steht nicht in runden, sondern in eckigen Klammern.

� Es wird nicht mit Dim, sondern mit Global oder Local vereinbart. Daraus ergibt sich,dass ein Blitz Array nicht global sein muss, sondern auf eine Funktion beschränktsein kann.

� Wie beim Dim-Feld, speichert ein Blitz Array einen speziellen Datentyp, also ent-weder Zeichenketten oder Ganzzahlen oder Festkommazahlen. Den Typ legen Siebei der Vereinbarung des Feldes fest. Wichtig: Seltsamerweise darf die Typken-nung, also $ oder #, nur bei der Definition verwendet werden. Beim Verwenden desBlitz Arrays muss sie entfallen.

� Es kann als Parameter einer Funktion übergeben werden.

� Es kann als Element für ein Type-Feld verwendet werden (dazu gleich mehr).

Vor allem die beiden letzten Punkte machen Blitz Arrays interessant. Freilich könnenSie auch die globalen Dim-Felder im Rahmen einer Funktion bearbeiten, doch die Über-gabe als Parameter ist eleganter, zumal Sie auf diese Weise verschiedene Arrays mit ei-ner Funktion einsetzen können. Abgesehen von der Definition, unterscheiden sichBlitz Arrays nicht in der Verwendung von Dim-Feldern:

; BLITZ1.BBGlobal A$[5]Data "Eins", "Zwei", "Drei", "Vier", "Fünf"

For I=1 To 5 Read A[I] Next

For I=1 To 5 Write A[I] + " "Next

WaitKey

2Ein zweites Beispiel soll die Übergabe eines Blitz Arrays an eine Funktion illustrieren.Dazu erstellen wir ein Blitz Array namens Daten[10] und füllen es mit Testdaten. An-schließend schreiben wir eine Funktion, die ein Blitz Array als Parameter übernimmtund alle zehn Elemente ausdruckt. Weil das Array Zahlen[10] nur lokal innerhalb der

Vergessen Sie nicht, dass der Variablentyp eines Blitz Arrays nur bei seiner Definitionverwendet werden darf. Schreiben Sie im oben stehenden Listing etwa Read A$[I]statt Read A[I], kommt es zu der Fehlermeldung Variable Type Mismatch.

Page 65: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

65

Benutzerdefinierte Typen j e t z t l e r n e i c h

Funktion existiert, kann der Funktion ein beliebiges Blitz Array übergeben werden. Siemüssen darauf achten,

� dass beide Arrays die gleiche Anzahl Einträge haben (hier: 10) und

� dass beim Aufruf der Funktion das Blitz Array ohne Index-Wert übergeben wird.

Das bedeutet, die Zeile

Function Name( Array[Zahl] )

wird mit einer Fehlermeldung quittiert; richtig wäre:

Function Name( Array )

Im Ganzen also:

; BLITZ2.BBLocal Daten[10]Data 4, 17, 38, 11, 45Data 67, 8, 67, 24, 52

For I=1 To 10 Read Daten[I]Next

ZehnZahlen(Daten)WaitKey;Function ZehnZahlen( Zahlen[10] ) For I=1 To 10 Print Zahlen[I] NextEnd Function

1

A4.6 Benutzerdefinierte Typen

Mit Feldern verwalten Sie Listen von Daten recht angenehm. Ihr Nachteil ist, dass sienur jeweils ein Datenformat erlauben: In einem Zahlenfeld können Sie keine Zeichen-ketten speichern. Oder plastischer ausgedrückt: Sie können sich in einem Feld zumBeispiel die Belegung von Flaschenkisten merken, kistenweise, palettenweise, LKW-weise. Aber Sie können den LKW nicht noch mit Brot und Joghurt füllen, nur mit Fla-schen.

1

Die großen Geschwister von Feldern sind benutzerdefinierte Typen (Type-Felder) undSpeicherbänke. In Typen fassen Sie verschiedene Variablen in einem »Container« zu-sammen. Speicherbänke sind ähnliche Gebilde wie Felder. Mit ihnen verwalten Sieplatzsparend viele Daten. Dafür ist es komplizierter, sie zu verwenden.

Ehe ich fortfahre: Der Abschnitt ist nicht einfach zu verstehen. Das macht nichts.Zum einen können Sie sich ihn einige Wochen später noch einmal vornehmen, zumanderen ist er kein »Muss«. Ich mag es nicht, mit Typen zu arbeiten, und habe es bis-her immer vermeiden können.

Page 66: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

66

Variablen4j e t z t l e r n e i c h

In einem Spiel muss man häufig verschiedene Arten von Daten unter einen Hut be-kommen. Allein für ein Monster wären das etwa:

� Art des Monsters

� Lebensenergie in Prozent

� Koordinaten x, y

� derzeitige Bewegungsrichtung

Wohl könnten wir einzelne Variablen dafür nehmen oder ein Feld. Doch es wäre hilf-reich, wenn wir nicht immer überlegen müssten, wo etwas abgelegt ist. Blitz Basic bie-tet mit benutzerdefinierten Typen eine kompliziertere, aber mächtige Lösung, umeine Handvoll Daten für einen Zweck in einen Sack zu stecken. Zunächst legen Siefest, aus welchen Einzelvariablen Ihr selbst gebauter Datentyp bestehen soll:

Type Monster Field Art, Energie, x, y, RichtungEnd Type

Falls Sie viele Variablen benötigen, nehmen Sie mehrere Field-Zeilen:

Type Monster Field Art Field Energie Field x, y Field RichtungEnd Type

Darunter können auch Zeichenketten- und Fließkommavariablen sein; kennzeichnenSie diese, wie üblich, mit $ oder #. Für mehrere gleichartige Eigenschaften eignet sichein Blitz Array:

Type Monster Field x, y Field Eigenschaften[10]End Type

Was wir damit erschaffen haben, ist eine Schablone. Sie speichern mit der Schablonekeine Daten. Aber Sie erzeugen mit der Schablone beliebig Variablen des Typs »Mons-ter«, bestehend aus fünf Teilvariablen wie Art und Energie:

Monster1.Monster = New MonsterEndgegner.Monster = New MonsterSaurier.Monster = New Monster

Bleiben wir bei Saurier.Monster. Um die Teilvariablen anzusprechen, verbinden Sie siedurch einen umgekehrten Schrägstrich mit dem Namen der Container-Variable:

Saurier\Art = 1Monster1\Art = 2Endgegner\Art = 5Saurier\Energie = 100Monster1\Energie = 100Endgegner\Energie = 500Monster\Eigenschaften[1] = 64

Also: Zuerst erstellen Sie mit Type die Feld-Schablone, die alle Variablen erhält. Im An-schluss erzeugen Sie einen Abzug der Schablone in Form einer verwendbaren Contai-ner-Variable (New). Sie enthält alle Teilvariablen, auf die Sie direkt zugreifen (\).

Page 67: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

67

Benutzerdefinierte Typen j e t z t l e r n e i c h

4.6.1 Dim-Felder aus TypenStatt eines einzelnen Sauriers können Sie gleich ein ganzes Feld mit 100 Ungeheuernvereinbaren:

Dim Saurier.Monster(100)

Allerdings legen Sie jeden Feldeintrag erst mit New an, bevor Sie ihn verwenden:

For I=1 To 100 Saurier(I) = New MonsterNext

Nun warten 100 Urzeitechsen darauf, von Ihnen mit Leben erfüllt zu werden. Ein ein-zelner Zugriff sieht so aus:

Saurier(1)\Art = 2

Um alle Saurier zu verarzten, verwenden Sie am besten wieder eine For-Schleife. DieZeilen ...

For I=1 To 100 Saurier(I)\Energie = 100Next

... würden allen Saurier eine Startenergie von 100 zukommen lassen. Sollen sich dieSaurier unterscheiden, lesen Sie ihre Daten mit Read/Data oder über Ihre Extradatei ein(wenn sie bei jedem Spielstart gleich sein sollen) oder verwenden Sie Zufallszahlen(wenn sie bei jedem Start neue Eigenschaften wie Startfeld haben sollen). Später wirdnoch genauer auf das Thema Spielfiguren eingegangen.

Der Übersicht halber soll hier ein vollständiges Beispiel folgen:

; TYPE1.BB; Typ "Monster" erstellen:Type Monster Field Art, Energie, x, y, RichtungEnd Type

; Variablenfeld "Saurier" des Typs "Monster" erstellen:Dim Saurier.Monster(100)

; 100 Feldeinträge erzeugen:For I=1 To 100 Saurier(I) = New MonsterNext

; Teilvariable Energie mit Daten füllen:For I=1 To 100 Saurier(I)\Energie = 100Next

4.6.2 Dynamische Type-ListeDie Verbindung mit einem Dim-Feld ist die einfachste Methode, mit Typen zu arbeiten.Der einzige Nachteil: Sie müssen wissen, wie viele Einträge Sie vornehmen wollen.Nun gibt es Szenarien, in denen Sie Daten speichern müssen, deren Menge am An-fang nicht bekannt ist. Bleiben wir bei unangenehmen Gestalten:

Page 68: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

68

Variablen4j e t z t l e r n e i c h

Type Aliens Field Leben, X, YEnd Type

Nun erzeugen wir 50 Aliens:

For I=1 To 50 Alien.Aliens = New AliensNext

Das Problem ist nur: Wie greifen wir auf ein einzelnes Alien zu? In Verbindung mit ei-nem Dim-Feld hatte jeder Feldeintrag eine Indexnummer. Das ist hier nicht der Fall: AlleEinträge haben exakt den gleichen Namen. Aus diesem Grund ist immer nur ein Feld-eintrag gleichzeitig ansprechbar. Erst müssen Sie den gewünschten Eintrag »einstel-len«, dann können Sie Daten lesen oder schreiben. Doch wie macht man das, wenn eskeine Nummerierung gibt? Mit relativen Beschreibungen wie »erster«, »letzter«, »nächs-ter« Eintrag:

Um zum fünften Eintrag zu gelangen, wechseln Sie mit First zum ersten Eintrag undsetzen viermal After ein:

Alien.Aliens = First AliensAlien.Aliens = After (Alien)Alien.Aliens = After (Alien)Alien.Aliens = After (Alien)Alien.Aliens = After (Alien)

Beachten Sie dabei, dass Sie bei First und Last genauso wie bei New den Container-Namen angeben, bei Before und After hingegen den Namen des Eintrags in Klam-mern. Sein Inhalt steht Ihnen nun offen:

Print Alien\Leben

Wenn Sie den Eintrag nicht mehr benötigen, löschen Sie ihn mit Delete:

Delete Alien

Das hat den gleichen Effekt, wie wenn Sie ein Blatt aus einem Stapel Papier ziehenwürden – die Lücke wird sofort wieder gefüllt, indem alle Elemente einen Platz nachunten rutschen.

Beim Hinzufügen mit New wird ein neuer Eintrag grundsätzlich ans Ende der Liste ge-hängt, er ist also Last. Allerdings lässt sich der gerade »eingestellte« Eintrag mit Insertan eine beliebige Stelle verschieben, etwa vor (Before) das erste (First):

Insert Alien Before First Aliens

Wie viele Einträge die Liste überhaupt hat, erfahren Sie nur, indem Sie bei jedem Newparallel eine Zählvariable laufen lassen. Dennoch dürfen Sie mit einer speziellenSchreibweise eine For-Schleife auf eine solche Liste anwenden:

First erster Feldeintrag einer ListeLast letzter Feldeintrag einer ListeBefore voriger Feldeintrag einer ListeAfter nächster Feldeintrag einer Liste

Page 69: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

69

Benutzerdefinierte Typen j e t z t l e r n e i c h

For Alien.Aliens = Each Aliens ...Next

wendet die For-Schleife nacheinander auf jedes Element (Each) an:

For Alien.Aliens = Each Aliens Print Alien\LebenNext

Begonnen wird beim ersten (First) Element. Auf ähnliche Weise löschen Sie jedes Ele-ment:

Delete Each Aliens

Um zu prüfen, ob das ausgewählte Element vorhanden ist, verwenden Sie Null:

If Alien = Null Then Print "nicht vorhanden"

Ein kleines Beispiel soll Ihnen das Arbeiten mit einer dynamischen Liste verdeutlichen:

; TYPE2.BBType Aliens Field Art, X, YEnd Type

For I=1 To 50 Alien.Aliens = New Aliens Alien\Art = INext

Alien.Aliens = First AliensWrite Alien\Art + " "Alien.Aliens = After (Alien)Write Alien\Art + " "Alien.Aliens = After (Alien)Write Alien\Art + " "

Print

For Alien.Aliens = Each Aliens Write Alien\Art + " "Next

Print

Alien.Aliens = Last AliensAlien.Aliens = After (Alien)If Alien = Null Then Print "1 - leer"

Alien.Aliens = First AliensIf Alien = Null Then Print "2 - leer"

Delete Each AliensAlien.Aliens = First AliensIf Alien = Null Then Print "3 - leer"

WaitKey

Ich vermute, ich konnte Sie in diesem Abschnitt von meiner Abneigung gegen dyna-mische Listen überzeugen. Typen haben für bestimmte Einsatzzwecke Vorteile. Doch

Page 70: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

70

Variablen4j e t z t l e r n e i c h

in meinen Augen zählt es mehr, dass Dim-Felder wesentlich einfacher zu handhabensind. Zudem sind sie schneller.

1

4.7 Aufgaben

1. Programmieren Sie eine kleine Adressbuch-Verwaltung. Sie soll einerseits das Ein-geben von Name, Vorname und Telefonnummer erlauben. Andererseits soll sie aufdie Eingabe eines Namens warten und die dazugehörige Nummer ausgeben.

2. Durch welche Kürzel weisen Sie einer Variablen den Typ Zeichenkette, Ganz- undFließkommazahl zu? Wie wandeln Sie Daten von einem Typ in den anderen um?

Für das häufige Verwenden von Types ist das Befehlspaar Handle/Object hilfreich.Handle liefert die Kennung (Handle) eines Type-Eintrags. Object erstellt eine Con-tainer-Variable, die auf diese Kennung zeigt. Eine genaue Beschreibung mit Beispielfinden Sie in der Online-Hilfe. Die beiden Anweisungen sind undokumentiert; siekönnen in künftigen Versionen entfallen oder ihre Syntax ändern.

Page 71: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

71

jetz

t le

rne

ich

KAPITEL 5

Zahlen und Zeichenketten

5.1 Das Mathe-1x1

Mit den vier Grundrechenarten vermischen Sie Zahlen und Variablen miteinander:

A=5Print A + 3Print 6 * 7Print ((27+38) * 13) - 34

Aber natürlich können Sie mit Blitz Basic noch viel mehr anstellen.

15.1.1 ModuloBeim Dividieren geht die Rechnung nicht immer auf. Der Operator Mod ermittelt denRestwert, der beim Teilen zweier ganzer Zahlen übrig bleibt. 20 geteilt durch 3 ist 6,Rest 2 (6 * 3 = 18; 20 - 18 = 2). Die Zeile:

Print 20 Mod 3

druckt daher 2 aus.

Sie nutzen Mod auf eine raffinierte Weise, um immer die gleichen Zahlenfolgen zu er-zeugen. So gibt das Beispiel:

For I = 1 To 20 Print I Mod 4Next

Die alte Grundschulregel »Punktrechnung geht vor Strichrechnung« gilt auch in BlitzBasic. Verwenden Sie wie auf kariertem Papier Klammern, um diese Regelung außerKraft zu setzen.

Page 72: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

72

Zahlen und Zeichenketten5j e t z t l e r n e i c h

immer wieder die Folge 1, 2, 3, 0 aus. Je höher der Teiler (hier: 4), desto länger wirddie Zahlenfolge. Auf einfache Weise erzeugen Sie damit Regelmäßigkeiten, legen etwadas Tor fest, aus dem neue Monster in einem Spiel schlüpfen, oder schaffen in Verbin-dung mit Zeitmessbefehlen einen Rhythmus, wann was passiert.

5.1.2 Zahlen rundenDie Ergebnisse von Fließkommaberechnungen haben häufig mehrere Kommastellen.Nicht immer ist eine so hohe Genauigkeit gewünscht. Auch wenn der Computer dankausgefeilter Strategien glüht: Der Spieler möchte mit 820 Goldtalern umgehen – undnicht mit 819,7815. Langer Rede kurzer Sinn: Mitunter müssen Zahlen gerundet wer-den. Dazu nehmen Sie die Funktionen Ceil() und Floor().

Ceil() rundet auf die nächsthöhere ganze Zahl. Aus 5.123 würde damit 6 werden. Die-se Regel gilt auch für negative Zahlen. Aus -5.123 wird allerdings -5, weil -5 höher istals -5,123.

Der Befehl Floor() arbeitet entgegengesetzt: Er rundet auf die nächstniedrige ganzeZahl; die Zeile:

Print Floor(5,123)

druckt schlicht:

5

aus.

5.1.3 VorzeichenHäufig muss geprüft werden, ob eine Zahl größer als null ist. Dafür gibt es eine einfa-che Abfrage:

If x > 0 Then ...

Dennoch bietet Blitz Basic dafür eine eigene Funktion Sgn(). Sie liefert das Ergebnis

� 1, wenn der Parameter eine positive Zahl, also größer als null ist

� 0, wenn der Parameter gleich null ist

� -1, wenn der Parameter eine negative Zahl, also kleiner als null ist:

; SGN.BBKonto = Input("Wieviel haben Sie auf dem Konto? ")If Sgn(Konto) = 1 Then Print "Sie haben Guthaben."If Sgn(Konto) = 0 Then Print "Sie sind blank."If Sgn(Konto) = -1 Then Print "Sie haben Schulden."WaitKey

Um ein (mögliches) Vorzeichen zu entfernen, nehmen Sie die Funktion Abs(). Sie lie-fert den absoluten Wert einer Zahl, ohne Vorzeichen. Abs(-4) und Abs(4) ergeben dasGleiche, nämlich 4.

Um das Vorzeichen einer Variable zu ändern, multiplizieren Sie sie mit –1. Außerdemgibt es eine raffiniertere Lösung: Schreiben Sie einfach ein Minus vor den Variablen-namen.

Zahl = Zahl * -1Zahl = -Zahl

Page 73: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

73

Das Mathe-1x1 j e t z t l e r n e i c h

5.1.4 Die Konstante PiDie Zahl Pi (π) gibt das Verhältnis des Umfangs eines Kreises zu seinem Durchmesseran. Es hat den festen Wert von 3,141 ... zu 1. Mit Pi errechnen Sie den Umfang einesKreises, wenn Sie seinen Durchmesser kennen:

Umfang = π ∗ Durchmesser

Davon ausgehend führen Sie weitere Berechnungen aus, ermitteln etwa die Füllmengeeines Zylinders. Blitz Basic hat den Wert von Pi bereits in der gleichnamigen Konstanteeingespeichert:

; PI.BBFor I=1 To 5 Print "Durchmesser: " + I + " - Umfang: " + I * PiNextWaitKey

5.1.5 Potenz berechnenHäufig muss die Potenz berechnet werden, ein Produkt gleicher Faktoren. Die erstePotenz einer Zahl ist sie selbst, die zweite Potenz nennt man Quadrat. So ist das Qua-drat von 8 (= 8 hoch 2) gleich 64, weil 8 * 8 = 64. Die Dreierpotenz von 8 (8 hoch 3)ist 8 * 8 * 8 = 512. Mithilfe des Operators ̂ berechnen Sie eine Potenz. Geben Sie da-bei die Basis und den Exponenten an:

Print 8 ^ 3

5.1.6 Wurzel ziehenDas Gegenteil der Potenzierung ist das Wurzelziehen. Für die Quadratwurzel stellt BlitzBasic die Funktion Sqr() zur Verfügung:

Print "Die Wurzel von 64 ist " + Sqr(8) + "."

Für die Kubikwurzel und jede folgende Wurzel verwenden Sie eine Formel:

Kubikwurzel = Zahl hoch (1/3)

In Basic-Deutsch:

Kubikwurzel = Float(Zahl) ^ (Float(1) / Float(3))

Für die vierte Wurzel ändern Sie die 3 in 4 und so weiter.

15.1.7 Logarithmus-FunktionEine andere Umkehrfunktion der Potenz ist der Logarithmus. In der Gleichung 10 ^ x= y lässt sich mithilfe des dekadischen Logarithmus (deka = 10) der Wert x anhandvon y berechnen. Blitz Basic stellt dafür die Funktion Log10() zur Verfügung.Log10(1000) ergibt den Wert 3, weil 10 ^ 3 gleich 1000 ist.

Für den Logarithmus zur Basis 2 bietet Blitz Basic keinen Befehl an – die meistenTaschenrechner tun das allerdings auch nicht. Erinnern Sie sich an das Beispiel am An-fang des Buchs? Mit x Lampen lassen sich 2 hoch y Zustände (= Zahlen) speichern.

Sqr ist die Abkürzung von Square root, dem englischen Begriff für Quadratwurzel.

Page 74: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

74

Zahlen und Zeichenketten5j e t z t l e r n e i c h

Das errechnet die Potenzfunktion. Für den umgekehrten Weg – wie viele Lampen sindnötig, um y Zustände zu speichern – brauchen wir den Logarithmus zur Basis 2:Log(y) / Log(2). Da das Ergebnis gebrochen ist, runden wir es auf: Ceil( Log(y) /Log(2) ). Die Zeile

Print Ceil( Log(300) / Log(2) )

ergibt 9 – so viele Bit sind nötig, um die Zahl 300 zu speichern. So viele Lampenbraucht es, um zwischen 300 Zuständen zu unterscheiden.

Für bestimmte mathematische Berechnungen wird der natürliche Logarithmus zurBasis e benötigt. Die Eulersche Zahl e ist wie π eine Konstante (2,718 ...) und hat ei-nen ähnlichen Nutzen wie ihre berühmtere Schwester. Sie wird unter anderem für Be-rechnungen von Kurven, Wahrscheinlichkeiten und Zinsen verwendet. In der Glei-chung e ^ x = y kann der Exponent x durch die Funktion Log(y) berechnet werden;die Exponentialfunktion Exp(x) ermittelt y.

A5.2 Winkelberechnungen

Winkelfunktionen berechnen die Verhältnisse zwischen Seitenlängen und der Gradzahlvon Winkeln eines Dreiecks. Sie sind sicher nicht das aufregendste Thema der Schul-mathematik. In Zusammenhang mit Spielen helfen sie jedoch, mit wenig Aufwand an-sehnliche Effekte zu erzielen. So kann eine Sinuskurve dazu verwendet werden, dieFlugbahn von feindlichen Raumschiffen festzulegen. Mit Dreiecksformeln ermitteln Sieden Abstand zweier Objekte auf einer Fläche.

1Ein Dreieck besteht aus drei Seiten und drei Innenwinkeln. Das Ziel der Dreiecksbe-rechnungen, der Trigonometrie, ist es, fehlende Stücke aus dem bereits Vorhandenenzu ermitteln.

5.2.1 Rechtwinklige DreieckeAm einfachsten sind diese Berechnungen im rechtwinkligen Dreieck. Der rechte Win-kel ist mit 90 Grad der größte Winkel in dem Dreieck. Ihm gegenüber liegt die längsteSeite. Sie heißt Hypotenuse. Die beiden anderen Seiten bezeichnet man als Katheten.Die Gegenkathete eines Winkels ist die Kathete, die ihm gegenüberliegt. Die Anka-thete dementsprechend die, die direkt am Winkel liegt.

Die wichtigsten Winkelfunktionen heißen Sinus, Cosinus und Tangens. Für das recht-winklige Dreieck gilt:

Sinus-Winkel = Gegenkathete / Hypotenuse

Cosinus-Winkel = Ankathete / Hypotenuse

Tangens-Winkel = Gegenkathete / Ankathete

Diese kleinen Funktionen lassen sich einfach nach der gesuchten Größe umstellen; so-mit errechnen sich fehlende Werte leicht.

Dieser Abschnitt entstand unter maßgeblicher Zusammenarbeit mit Frank »Triton«Neumann, dem Betreiber der Seite www.silizium-net.de.

Page 75: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

75

Winkelberechnungen j e t z t l e r n e i c h

Hilfreich ist der berühmte Satz des Pythagoras. Er berechnet die Länge der drittenSeite eines Dreiecks, wenn die anderen zwei Längen bekannt sind:

Kathete1 ^ 2 + Kathete2 ^ 2 = Hypotenuse ^2

Die Summe der Quadrate beider Katheten entspricht dem Quadrat der Hypotenuse (a²+ b² = c²). Auch diese Formel lässt sich leicht nach der gesuchten Seite umstellen.

5.2.2 Beliebige DreieckeHat das Dreieck keinen rechten Winkel, sind die Berechnungen aufwendiger. Grund-lagen sind der Sinussatz nebst Umkehrung ...

a/sin(alpha) = b/sin(beta) = c/sin(gamma)

sin(alpha)/a = sin(beta)/b = sin(gamma)/c

sowie der Cosinussatz:

a² = b² + c² - 2bc * cos(alpha)

b² = a² + c² -2ac * cos(beta)

c² = a² + b² - 2ab * cos(gamma)

Dabei stehen a, b und c für die drei Seiten des Dreiecks, alpha, beta und gamma sinddie Winkel, die jeweils den drei Seiten gegenüberliegen.

Die Formeln machen sich zu Nutze, dass sich jedes Dreieck so spalten lässt, dass zweirechtwinklige Dreiecke entstehen. In beiden Teildreiecken werden die Winkel einzelnberechnet, wie oben dargestellt.

Abb. 5.1:Dreiecksberech-nungen lösen viele Probleme aufwendiger Computerspie-le. Was die Schulmathema-tik vergessen hat, frischen Websites und Bücher wieder auf.

Page 76: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

76

Zahlen und Zeichenketten5j e t z t l e r n e i c h

1

5.2.3 Winkelfunktionen mit Blitz BasicBlitz Basic versteht neben den gebräuchlicheren Funktionen Sinus, Cosinus und Tan-gens auch weniger oft benutzte Ableitungen:

Die Parameter werden dabei in Grad übergeben; 360 Grad sind ein Vollwinkel. Auchohne mathematisches Gespür lassen sich die Ergebnisse von Winkelfunktionen dazunutzen, leicht wellenartige Linien zu zeichnen. Man braucht nur die Koordinaten an-hand der Sinuswerte zu ermitteln:

Die Ergebnisse steigen von 0 spitz zu 1, fallen wieder auf 0 zurück, gehen nun insNegative und kehren am Ende, bei 360 Grad, wieder zu 0 zurück. Folgendes Beispiellegt anhand des Sinuswerts (bis 180 Grad) die Länge einer Sternenlinie fest.

; SIN.BBFor I = 1 To 180 Step 10 Zeile$ = "" For A = 1 To Sin(I) * 50 Zeile$ = Zeile$ + "*" Next

Die Summe aller Innenwinkel in einem Dreieck beträgt immer 180 Grad. Dadurchlässt sich leicht der dritte Winkel ausrechnen, wenn bereits zwei Winkel bekannt sind.Weiterführendes finden Sie etwa auf der Seite www.mathe-online.at/galerie/trig/trig.html. Das Besondere: Dort werden die Verhältnisse und Größenangaben visuelldargestellt. Mit der Maus verschieben Sie Seiten und Winkel.

Sin() Sinus

Asin() ArcusSinus

Cos() Cosinus

Acos() ArcusCosinus

Tan() Tangens

ATan() ArcusTangens

ATan2() ArcusTangens aus zwei Werten

Grad Sinus

0 0

45 0.7

90 1

135 0.7

180 0

225 0.7

270 –1

315 –0.7

360 0

Page 77: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

77

Logische Operatoren j e t z t l e r n e i c h

Print Zeile$NextWaitKey

Ich weiß: Das wirft einen nicht vom Hocker. Später, bei den Grafikbefehlen, zeige ichIhnen ein besseres Beispiel einer Sinuskurve.

5.3 Logische Operatoren

Im Abschnitt über die If-Bedingung wurden Ihnen die Grundlagen logischer Operato-ren wie And erklärt. Jetzt soll das Arbeiten mit diesen Operatoren vertieft werden.

Der If-Strang wird nur ausgeführt, wenn die gestellte Bedingung zutrifft:

If Sorte=1 Then Print "Sie möchten Vanille."

Man sagt dazu: Die Bedingung (hier: Sorte=1?) muss wahr sein. Der Else-Teil wird ab-gearbeitet, wenn der If-Teil nicht zutrifft, also falsch ist.

15.3.1 NotMit Not (englisch für nicht) kehren Sie eine Bedingung um. Aus wahr wird falsch – undumgekehrt:

If Not Sorte = 1 Then Print "Sie wählten Schoko."

Zunächst ermittelt der Computer, ob die Bedingung wahr oder falsch ist, um anschlie-ßend das Ergebnis umzudrehen. Besonders oft wird Not nicht verwendet, weil es meis-tens eine elegante Umgehung gibt. So wäre es verständlicher zu schreiben:

If Sorte <> 1 Then Print "Sie wählten Schoko."

5.3.2 And und OrMithilfe von And und Or verknüpfen Sie mehrere Teilbedingungen zu einer Gesamtbe-dingung:

If Sorte<>1 And Sorte<>2 Then Print "Ungültige Wahl!"If Sorte=1 Or Sorte=2 Then Print "Gültige Wahl!"

Beide Zeilen enthalten jeweils zwei Teilbedingungen. Sie sind entweder jeweils wahroder falsch. And und Or verbinden beide Teile zu einer wahren oder falschen Gesamt-bedingung. Der Computer verwendet dazu feste Regeln:

Operatoren, die keine Ergebnisse wie 3 oder 5, sondern die Antworten wahr oderfalsch ergeben, nennt man logische Operatoren oder boolesche Operatoren (be-nannt nach ihrem »Erfinder«, dem Mathematiker George Boole).

Teilbedingungen Gesamtbedingung

wahr And wahr wahr

wahr And falsch falsch

falsch And wahr falsch

falsch And falsch falsch

Page 78: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

78

Zahlen und Zeichenketten5j e t z t l e r n e i c h

Das sieht komplizierter aus, als es ist: Eine And-Bedingung ist wahr, wenn beide Teil-bedingungen wahr sind. Eine Or-Bedingung ist wahr, wenn mindestens eine Teilbedin-gung wahr ist.

5.3.3 XorAnd und Or haben einen Bruder namens Xor. Das ist eine Abkürzung für exklusivesOder. Xor ist nicht so vertraut wie And und Or, die wir als Und bzw. Oder auch in derUmgangssprache verwenden. Dennoch ist der Operator nicht schwer zu verstehen:Das Ergebnis einer Xor-Verknüpfung ist nur wahr, wenn genau eine Teilbedingungwahr ist:

Die Bedingung:

If 3>4 Xor 3<4 Then Print "Ja!"

ist damit wahr. (Leider fällt mir kein schlaueres Beispiel ein. Xor wird selten zum Ver-gleichen eingesetzt; mehr dazu erfahren Sie im nächsten Abschnitt.)

5.3.4 True und FalseNatürlich arbeitet der Computer selbst nicht mit wahr und falsch. Er setzt sie in seinegeliebten Binärzahlen um. Sie haben den Wert "1" und "0":

Print 3>4Print 3<4

Sie können daher diese Schreibweise verwenden:

If 3<4 = 1 Then Print "Ja!"

Oder übersichtlicher in Klammern:

If (3<4) = 1 Then Print "Ja!"

In englischer Sprache heißen wahr und falsch true und false. Blitz Basic hat zweigleichnamige Konstanten mit den Werten 1 und 0 voreingestellt. Daher ist folgendeNotation möglich:

If (3<4) = True Then Print "Ja!"

wahr Or wahr wahr

wahr Or falsch wahr

falsch Or wahr wahr

falsch Or falsch falsch

Teilbedingungen Gesamtbedingung

wahr Xor wahr falsch

wahr Xor falsch wahr

falsch Xor wahr wahr

falsch Xor falsch falsch

Teilbedingungen Gesamtbedingung

Page 79: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

79

Bytes, Hexzahlen und binäres Rechnen j e t z t l e r n e i c h

Ebenfalls lässt sich das Ergebnis einer logischen Operation mit Case verteilen:

; ALTER.BBAlter = Input("Wie alt sind Sie: ")Select Alter < 18 Case True Print "Ich darf Sie nicht hineinlassen!" Case False Print "Kommen Sie herein, wenn Sie kein Schneider sind."End SelectWaitKey

Genau genommen interpretiert der Computer alles, was nicht 0 ist, als wahr. Die Zahl4 etwa ist für den Computer wahr. If-Abfragen lassen sich deshalb verkürzen, indemSie den Teil "<> 0" oder "> 0" einfach weglassen.

If Sorte > 0 Then ...

lässt sich gleichermaßen als:

If Sorte Then ...

schreiben. Das Ergebnis aller Funktionen, die entweder 0 oder 1 als Ergebnis liefern,fragen Sie auf diese Weise etwas kürzer ab. Nur wenn Sie für mehrere Werte ungleich0 verschiedene Regeln einführen, ...

If Sorte = 1 Then ...If Sorte = 2 Then ...

... müssen Sie die gewohnte längere Notation verwenden. Das funktioniert freilichnicht nur mit If-Bedingungen, sondern auch mit While und Until.

A5.4 Bytes, Hexzahlen und binäres Rechnen

Am Anfang des Buchs habe ich Ihnen am Beispiel von Glühlampen das Bit erklärt: DerInformationsgehalt einer Glühlampe als Zeichen lässt sich in einem Bit speichern. EinBit kann zwei (= binäre) Zustände annehmen: Null oder Eins, Ja oder Nein, Grün oderBlau, Lampe ein oder aus.

Rein technisch ist ein Bit nur ein Schaltzustand, der nach Belieben interpretiert wird.Ein Bit allein sagt nicht viel aus, aber je mehr Bits kombiniert werden, desto mehr Mög-lichkeiten lassen sich vereinbaren. Jedes neue Bit verdoppelt die Anzahl der schon vor-handenen Zeichen. Etwas mathematischer betrachtet, können n Bit 2 hoch n Zuständedarstellen. Kaum vorstellbar, aber jedes Spiel ist nichts weiter als eine schier endloseFolge von Bits, von Nullen und Einsen.

Freilich macht es nicht unbedingt Spaß, mit dem binären System, endlosen Kolonnenvon Nullen und Einsen, zu hantieren. So, wie 100 Cent einen Euro ergeben, fasst man8 Bit zu einer (größeren) Informationseinheit zusammen, dem Byte. Wieso gerade 8?Nun, 8 ist ein Vielfaches von 2, die der Computer so sehr liebt, und der Wertebereichvon 8 Bit, nämlich 256 Möglichkeiten, hat sich als praktisch erwiesen.

1In Kurzform: Ein Computer speichert alles binär ab, also als 0 oder 1. Eine Folge wie01001011 ist die einzige Sprache, die er versteht. Ein Bit merkt sich eine solche 0oder 1, deren Bedeutung willkürlich, aber nicht sonderlich vielgestaltig festgelegt wer-den kann. Deswegen fasst man mehrere Bits zu einer Einheit zusammen, die einegrößere Kapazität hat: Zwei Bit speichern vier Zeichen (00, 01, 10, 11) und n Bitspeichern 2 hoch n Zeichen. Die Folge von acht Bit nennt man Byte. Ein Byte kanneinen Wert von 00000000 bis 11111111 annehmen bzw. Werte von 0 bis 255.

Page 80: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

80

Zahlen und Zeichenketten5j e t z t l e r n e i c h

Ein Byte enthält entweder einen Teil des Programmcodes oder Daten, zum Beispiel dieAnzahl der Leben, die noch übrig sind, oder einen Buchstaben.

Ein Byte ist die kleinste Speichereinheit, die ein PC lesen und schreiben kann. Deswe-gen sagt man, der Speicher ist in Zellen unterteilt, die je ein Byte Kapazität besitzen.Dafür mussten natürlich Vereinbarungen geschaffen werden. Die Intel-Prozessorenund die Chips der Mitbewerber verstehen einen einheitlichen Befehlssatz. Und für Texthat man eine Normierung geschaffen, den so genannten ASCII-Code (AmericanStandard Code for Information Interchange). Der Bitfolge 01000001 wurde zumBeispiel der Buchstabe A zugewiesen. Mithilfe des ASCII-Codes ist etwa gewährleistet,dass Ihr Drucker weiß, dass er ein A drucken soll, wenn Ihr PC ihm die Bitfolge01000001 schickt. Dadurch lassen sich Texte zwischen verschiedenen Programmenund Computersystemen austauschen. Jeder Buchstabe, jede Zahl dieses Buchs wird imPC als Byte abgelegt.

15.4.1 BefehlscodeJedes Byte in einem PC gehört zu einer der Gruppen Befehl, Datum oder Adresse.Ein Befehl ist eine Anweisung für den Prozessor. Ein Datum kann alles Mögliche sein:ein einzelner Buchstabe, eine Zahl, ein Teil eines Namens ... Eine Adresse als Spezial-form des Datums kennzeichnet eine Speicherzelle. Diese kann eine weitere Adressesowie Daten oder Befehle enthalten.

Alle Daten liegen in Binärform, somit als Bitketten, vor. Es ist nur aus dem Kontext er-kennbar, ob der Inhalt einer Speicherzelle nun ein Datum oder einen Befehl enthält, dasich beide den gleichen Speicherbereich teilen können.

Oder anders ausgedrückt: Wenn dem Prozessor weisgemacht wird, ein Speicherbe-reich, der Daten enthält, sei ein Programm, das er ausführen darf, gibt es Ärger, derzum Absturz führen kann.

Befehle werden in der Regel hintereinander, sequentiell, abgearbeitet. Sprünge, dieman in bedingte und unbedingte einteilt, ändern die Reihenfolge der Befehlsabarbei-tung. Eine spezielle Prozessorvariable, der Programmzähler, zeigt auf den als Nächstesabzuarbeitenden Befehl.

Die Abarbeitung eines Programms setzt sich aus Teilschritten zusammen, die der Pro-zessor fortwährend ausführt: Als Erstes wird der Programmzähler auf den nächsten Be-fehl gesetzt. Anschließend wird der Befehl, der sich an der Adresse befindet, eingele-sen. Dort wird er von einer Bitfolge in den internen Mikrocode übersetzt. DieserMikrocode ist die absolute Ursprache. Auf dieser Ebene werden Befehle tatsächlich ab-gearbeitet, indem das Verhalten von Transistoren beeinflusst wird. Die Logik ist dafürverantwortlich, dass tatsächlich etwas Sinnvolles passiert.

Ein typischer Befehl an den Prozessor kann so aussehen:

Addiere zu der Prozessorvariable A eine 4!

Als Bitfolge stünde der Befehl etwa so im Speicher:

Üblicherweise wird der ASCII-Code als Dezimal- oder Hexadezimalzahl geschrieben.Die Funktion Asc() nennt Ihnen den ASCII-Code eines Zeichens. Chr$() wiederumerwartet einen ASCII-Code und liefert Ihnen das passende Zeichen.

Page 81: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

81

Bytes, Hexzahlen und binäres Rechnen j e t z t l e r n e i c h

10101011 ; als Befehl "Addiere zu A"00000010 ; als Operand 4

Die ersten Programmierer mussten tagein, tagaus Nullen und Einsen eintippen, wahr-lich kein Vergnügen. Aus diesem Grund entwickelte man eine Schreibweise, die sichaus für den Menschen einigermaßen verständlichen Kürzeln zusammensetzt, natürlichin Englisch. Danach könnte der oben genannte Prozessor- oder Maschinenbefehl so:

add a, 4

aussehen – addiere Variable A mit der Zahl 4.

Diese Kürzel nennt man Mnemonics, was so viel wie »leicht einzuprägen« heißt. Unddas sind sie in der Tat.

Die erste Programmiersprache war geboren – Assembler, abstammend von dem eng-lischen assemble, zusammensetzen. Ein Assembler-Befehl ist das genaue Abbild einesProzessorbefehls.

1Im Laufe der Jahre entwickelte man mit Hochsprachen die Möglichkeit, Programmeviel abstrakter zu schreiben – mehr dem menschlichen Denken angepasst als dem Be-fehlssatz des Prozessors. Sprachen wie Basic, Pascal oder C setzen sich aus Befehlenzusammen, die der Mensch leichter erlernen kann. In Hochsprachen schreibt man Pro-gramme viel schneller als in Assembler; nahezu alle Spiele werden heutzutage in einerHochsprache entwickelt. Dass der Computer mehr Arbeit hat, sie in Maschinenspra-che umzuwandeln, soll uns nicht weiter stören.

Das Übersetzen in Maschinensprache übernimmt entweder ein Compiler oder (selte-ner) ein Interpreter. Ein Compiler zerlegt ein Programm in seine Befehlswörter undübersetzt sie hintereinander in Maschinensprache. Dazu steht ihm eine Bibliothek zurVerfügung, welche die Maschinenbefehle für jede einzelne Hochsprachenanweisungenthält. Diese nennt man Laufzeitbibliothek oder Runtime Library. Das Ergebnis istdann ein Maschinenprogramm, dem man es nicht ansieht, auf welche Weise es gebo-ren wurde. Aus diesem Grund ist eine eindeutige Rückwärtsübersetzung (Re-Compi-ling) in eine Hochsprache nicht möglich.

5.4.2 HexzahlenIm Dezimalsystem, mit dem wir Menschen rechnen, steht eine Ziffer für einen der zehnWerte zwischen 0 und 9. Im Binärsystem gibt es nur zwei Ziffern. Ansonsten ist dieZählung im Binärsystem nicht ungewöhnlich: 0, 1, 10, 11, 100, 101, 110, 111. Bi-närzahlen lassen sich in Dezimalzahlen umwandeln und umgekehrt. Der ASCII-Codefür den Buchstaben A, die Bitfolge 01000001, hat so den dezimalen Wert 65. VieleTaschenrechner, auch der unter Windows zur Verfügung stehende, können zwischenbeiden Formaten konvertieren.

Dabei taucht ein Schönheitsfehler auf: Das Dezimalsystem, mit dem wir aufgewachsensind, ist nicht ideal als Ersatz für binäre Zahlen. Nehmen wir 4 Bit, die 16 Zuständespeichern können:

Als Assembler bezeichnet man auch den Übersetzer von Assembler-Programmen inProzessorbefehle – aus add a, 4 werden ein paar Hexzahlen, die im Speicher abge-legt werden. Das Gegenstück ist der Disassembler.

Page 82: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

82

Zahlen und Zeichenketten5j e t z t l e r n e i c h

0000 binär entspricht 00 dezimal 1000 binär entspricht 08 dezimal0001 binär entspricht 01 dezimal 1001 binär entspricht 09 dezimal0010 binär entspricht 02 dezimal 1010 binär entspricht 10 dezimal0011 binär entspricht 03 dezimal 1011 binär entspricht 11 dezimal0100 binär entspricht 04 dezimal 1100 binär entspricht 12 dezimal0101 binär entspricht 05 dezimal 1101 binär entspricht 13 dezimal0110 binär entspricht 06 dezimal 1110 binär entspricht 14 dezimal0111 binär entspricht 07 dezimal 1111 binär entspricht 15 dezimal

Um die Dezimalzahlen von 0 bis 9 binär darzustellen, benötigen Sie 4 Bit. Es geht abernicht genau auf: 3 Bit reichen für nur 8 Dezimalzahlen, 4 Bit aber bereits für 16 Zah-len. 3 Bit sind damit zu wenig und 4 Bit sind Verschwendung, weil die Binärzahlen1010 bis 1111 ungenutzt bleiben.

Deshalb führten schlaue Köpfe ein Zahlensystem ein, das außer den Ziffern 0 bis 9noch die restlichen sechs Stellen ausfüllt, die zur Darstellung einer 4-Bit-Zahl notwen-dig sind. Und mangels geeigneter Ziffernsymbole nahm man die Buchstaben A bis F.Diese Hexadezimalzahlen oder kurz Hexzahlen zählen nach der 9 von A bis F, dannfolgt die 10. Nach 19 folgt 1A und nach 1F kommt die 20:

0 ... 9, A, B ... F, 10, 11 ... 19, 1A, 1B ... 1F, 20 ... 99, 9A ... 9F, A0 ... FF, 100,101 ... 109, 10A ...

1Weil eine Hexzahl sehr einfach in eine Binärzahl konvertiert werden kann, bildet sie dieGrundlage für Adressrechnung und Zahlenspeicherung: Jede Hexziffer entspricht ei-ner 4-Bit-Zahl und nichts bleibt übrig. Das Verwandeln einer Dezimalzahl wie 1000 ineine Hexzahl kann recht umständlich mit Papier und Bleistift und angenehmer mit ei-nem Taschenrechner bewerkstelligt werden. Falls Ihr Taschenrechner nicht mit denTasten HEX, BIN und DEC ausgerüstet ist, nehmen Sie den Windows-Rechner (wo Sieden Schalter ANSICHT/WISSENSCHAFTLICH anklicken).

Mitunter stellt man Hexzahlen eine oder mehrere Nullen voran. Das hat nur optischeGründe, die Hexzahl 0123 hat den gleichen Wert wie 123. In der Regel wird eine Hex-zahl durch ein abschließendes H gekennzeichnet. In Programmiersprachen wird einerHexzahl oft $ oder 0x vorangestellt, um sie von einer Dezimalzahl zu unterscheiden.

Das Hexadezimalsystem wurde eingeführt, weil das Rechnen mit Binärzahlen keinenSpaß macht, sich Binärzahlen aber nicht optimal in Dezimalzahlen umwandeln las-sen.

Hexadezimal Dezimal

00.00.00.0A 10

00.00.00.63 99

00.00.00.64 100

00.00.00.FF 255 (der höchste Wert für ein Byte)

00.00.7F.FF 32767

00.00.FF.FF 65535 (der höchste Wert für zwei Byte)

00.FF.FF.FF 16.777.215 (der höchste Wert für drei Byte)

FF.FF.FF.FF 4.294.967.295 (der höchste Wert für vier Byte)

Page 83: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

83

Bytes, Hexzahlen und binäres Rechnen j e t z t l e r n e i c h

Was bisher außen vor blieb, sind negative Werte. Wie merkt sich der Computer, dassvor einer Zahl ein Minus steht? Er reserviert ein Bit, um das Vorzeichen festzustellen,womit sich der maximale Betrag auf die Hälfte reduziert, weil die zweite Hälfte fürnegative Zahlen gedacht ist. Bei einem Vier-Byte-Wert nutzt er eben 31 Bit für denBetrag und das 32. Bit für das Vorzeichen: Ist es 1, wird die Zahl negativ. In einer4 Byte (= 32 Bit) langen Ganzzahlvariable lassen sich in Blitz Basic mehr als 4 Milliar-den (2 hoch 32) Zustände speichern. Das ergibt zwei Milliarden positive und zwei Mil-liarden negative Zahlen.

5.4.3 Binär- und Hexzahlen mit Blitz BasicBlitz Basic unterstützt das Arbeiten mit binären und hexadezimalen Zahlen im ausrei-chenden Maß. Sie benutzen sie genauso wie dezimale Zahlen. Damit Blitz Basic weiß,welches Format Sie meinen, stellen Sie einer Hexzahl $ voran und einer Binärzahl %:

Print $84 + $20Print %1010101

Blitz Basic rechnet zwar korrekt, druckt aber das Ergebnis immer dezimal aus. Um eineZahl in eine Hex- oder Binärzahl umzuwandeln, verwenden Sie die Funktionen Hex$()und Bin$():

Print Hex$($84 + $20)Print Bin$(%1010101)

Das Ergebnis sind allerdings keine wirklichen Hex- oder Binärzahlen, sondern Zeichen-ketten.

5.4.4 Binäre ManipulationenWirklich sinnvolle Anwendungszwecke für Binär- und Hexzahlen sind selten. Trickrei-che Programmierer verwenden Manipulationen auf binärer Ebene, um mit wenig Auf-wand Zahlen zu verändern. Dabei helfen die Operatoren Or, And und Xor. Vielleicht ha-ben Sie sich schon über das seltsame Ergebnis gewundert, wenn Sie zwei Zahlen zumBeispiel mit And verknüpfen: 45 And 72 ist 8. Merkwürdig, nicht? Wenn Sie logischeOperatoren auf Zahlen anwenden, finden die Rechnungen bitweise statt. Beide Zahlenwerden in Binärzahlen umgewandelt, ehe anschließend die Regeln für And Bit für Bitzum Einsatz kommen:

0101101 (45) And1001000 (72)------------0001000 (8)

And verwenden Sie, um von einer Zahl gezielt einzelne Bits zu löschen. Sie verknüpfensie einfach mit einer Maske, bei der diese Bits auf 0 stehen. Da And nur dann 1 liefert,wenn beide Bits auf 1 sind, ist das Ergebnis auf jeden Fall 0:

; AND.BBPrint 495835945 + " And"Print 175435234 + " ="Print 495835945 And 175435234PrintPrint Bin$(495835945) + " And"Print Bin$(175435234) + " ="Print Bin$(495835945 And 175435234)

Page 84: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

84

Zahlen und Zeichenketten5j e t z t l e r n e i c h

Or ist der Gegensatz: Der Operator setzt gezielt Bits auf 1, weil das Ergebnis dann 1 ist,wenn mindestens ein Bit 1 ist. Diese Art der Veränderung nennt man Maskieren.

Eine interessante Eigenschaft weist die Xor-Verknüpfung auf: Sie ist umkehrbar. WennSie eine Zahl etwa mit dem Wert 47 »xor-en« und das Ergebnis wieder mit 47 »xor-en«,dann erhalten Sie Ihre Ursprungszahl zurück. Später, bei der Beschreibung der Befehlezum Bearbeiten von Zeichenketten, zeige ich Ihnen ein kleines Verschlüsselungsbei-spiel.

Zum Schluss nenne ich Ihnen drei besonders geheimnisvolle Operatoren. Shl (eine Ab-kürzung von shift left) verschiebt die Bits einer Binärzahl nach links. Links überstehen-de Bits fallen dabei weg; rechts wird mit 0 aufgefüllt. Es ist eine raffinierte Weise, eineZahl mit 2 zu multiplizieren. Als zweiten Operanden geben Sie die Zahl der zu verschie-benden Stellen an:

Print Bin$(24)Print Bin$(24 Shl 2)

Der Gegenpart von Shl ist Shr – er verschiebt die Bits nach rechts. Für negative Zahlen,bei denen das 32. Bit als Vorzeichen erhalten bleiben muss, gibt es außerdem Sar(shift arithmethic right). Der Operand verschiebt nach rechts, lässt aber das 32. Bitunberührt. (Logisch wäre der Operator Sal, zumal Intel-Prozessoren einen entspre-chenden Befehl haben. Sie führen Sal allerdings genauso aus wie Shl. Daher wurde ernicht in den Sprachschatz von Blitz Basic aufgenommen.)

5.5 Messen der Zeit

Viele Spiele beziehen die Komponente Zeit in das Geschehen mit ein. Beliebt sindZeitspannen, innerhalb derer ein Level geschafft werden muss (Countdown). Auf deranderen Seite sind Zeitmesser verbreitet, die angeben, wie lange jemand für einen Le-vel benötigt hat, um danach zum Beispiel den Punktestand zu berechnen. Blitz Basicunterstützt das Messen der Zeit mit einer Reihe von Befehlen. In diesem Abschnitt wer-den die entsprechenden Grundlagen beschrieben. Später kommen wir auf das Themawieder zurück, wenn wir mithilfe von Zeitgebern (Timer) den Spielfluss steuern.

5.5.1 PauseDer Befehl Delay hält das Programm für die angegebene Anzahl von Tausendstel-sekunden an:

Delay 5000

(1000 Tausendstel- oder Millisekunden sind eine Sekunde.) Dieser Befehl ist sinnvoll,um etwa Bildschirme im Vorspann oder Abspann nach einer bestimmten Zeit automa-tisch zu wechseln.

1 Quälen Sie den Spieler nicht mit unnötigen Zeitverzögerungen, die sich nicht abbre-chen lassen. Bereits ein Zwangswarten von fünf Sekunden wird bei häufiger Betrach-tung als lästig empfunden.

Page 85: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

85

Messen der Zeit j e t z t l e r n e i c h

Während des Spiels bremsen Minipausen die Bewegungen der Figuren auf ein realis-tisches Maß. Sie sollten dazu unbedingt einen Zeitbefehl und nicht etwa eine Verzöge-rung der Art:

For I=1 To 100000 A=1+1Next

verwenden. Denn diese Schleifen-Pause ist abhängig von der Geschwindigkeit desPCs, auf dem sie ausgeführt wird. Spiele, die solche »Tricks« einsetzen, werden in eini-gen Jahren unspielbar schnell, weil die Rechenkraft der Prozessoren stetig zunimmt.

05.5.2 ZeitspannenBlitz Basic bietet Ihnen zwei Möglichkeiten, wie Sie Zeitspannen messen können. Aufdiese Weise finden Sie heraus, wie lange gespielt wird. Die entsprechende Grundlageist die Funktion MilliSecs(). Sie übergibt die Zeit, die seit dem Start des PCs vergan-gen ist (in Tausendstelsekunden). Um eine Zeitspanne zu ermitteln, fragen Sie Milli-Secs() am Anfang und am Ende ab und ermitteln die Differenz.

; ZEIT.BB; Dieses Programm funktioniert nicht im Konsolenfenster von Blitz PlusAnfang = MilliSecs()Print "Ein paar Sekunden warten"Print "und dann eine Taste drücken"WaitKeyEnde = MilliSecs()Spanne = Ende - AnfangPrint Spanne / 1000 + " Sekunden vergangen"WaitKey

Auf diese Weise messen Sie leicht die Spielzeit – und beschränken sie gegebenenfalls.

0

Mitunter müssen mehrere Zeiten gleichzeitig berechnet werden. Nehmen wir an, derSpieler kann Power-ups einsammeln, die seine Kräfte für einen bestimmten Zeitraum(etwa eine Minute) verstärken. Wenn es verschiedene Power-ups gibt und der Spielermehrere bei sich tragen kann, dann muss für jedes Power-up eine unabhängige Mes-sung vorgenommen werden. Eine gute Lösung hierbei ist ein Dim-Feld, das sich für je-des Special die Zeit merkt, zu der es aufgenommen wurde – oder eine Null, falls dasfragliche Power-up derzeit nicht zur Verfügung steht.

Eine bessere Möglichkeit zum Steuern der Geschwindigkeit ist das Verwenden einesTimers.

Ich empfehle Ihnen, nicht leichtfertig eine Zeitbegrenzung einzubauen. Bei Arcade-Spielen wie »Moorhuhn« ist es freilich Sinn der Sache, innerhalb eines begrenztenZeitraums so viele Punkte wie möglich zu erzielen. Bei einem Jump'n'Run-Spiel aberhat der Spieler genug Herausforderung durch Schluchten und Gegner. Er sollte nichtzusätzlich durch Zeitdruck frustriert werden, indem er etwa kurz vor dem Ende den-noch den Level nicht abschließen kann, weil die Zeit nicht gereicht hat.

Page 86: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

86

Zahlen und Zeichenketten5j e t z t l e r n e i c h

5.5.3 Datum und Uhrzeit ermittelnBlitz Basic gibt Ihnen in je einer Zeichenkette das aktuelle Datum und die aktuelle Uhr-zeit zurück:

Print CurrentDate$()Print CurrentTime$()

Halten Sie dieses Wissen des Computers in Ihren Spielen besser zurück: Es wäre einesinnlose Information, etwa auf der Titelseite das Datum anzuzeigen. Eine bessere Ideeist es, das Datum neben dem Namen und der Punktzahl in die Bestenliste zu setzen.Ganz besonders hilfreich ist es, wenn Sie beim Laden von Spielständen Tag und Uhr-zeit des Speicherns angeben.

15.6 Zufallszahlen

Die Variable Glück spielt bei vielen Spielen eine große Rolle. Nehmen wir ein Würfel-spiel: Es ist einfach Glück, zum richtigen Zeitpunkt die richtige Augenzahl zu würfeln.

Mit »Glück« können Computer nicht dienen, wohl aber mit einer (scheinbaren) Darstel-lung von »Zufall«. Der PC kann Ihnen zufällig ermittelte Zahlen nennen, und das sogarin einem von Ihnen festgelegten Rahmen.

Sie sagen ihm: »Zufallszahlen zwischen 1 und 6« und er liefert Ihnen Würfelergebnisse.Sie sagen ihm: »Zufallszahlen zwischen 1 und 2« und er sagt Ihnen, ob das Monsternach links oder rechts gehen soll. Sie sagen ihm: »Zufallszahlen zwischen 1 und 1000«und können auf dieser Basis ein Quizspiel programmieren, bei dem Fragen zufällig aus-gewählt werden.

Um eine Zufallszahl zu erhalten, verwenden Sie die Funktion Rand(). Als Parameterübergeben Sie ihr den Mindest- und den Höchstwert und legen somit ein Limit fest.Fehlt der Mindestwert, wird er automatisch auf Null gesetzt:

Print Rand(10)Print Rand(10,20)WaitKey

Wie zufällig die Auswahl tatsächlich ist, überprüfen Sie schnell:

; ZUFALL.BBFor I=1 To 100000 A = A + Rand(1,10)NextPrint "Durchschnitt nach 100.000 Durchläufen:"Print A / 100000

Alles wäre so einfach, wenn es nicht einen Haken gäbe: Bei jedem Programmstart er-halten Sie die gleichen Zufallszahlen. Blitz Basic verwendet einen bestimmten Wertzum Erzeugen der Zufallszahlen. Diesen Wert nennt man Saat (englisch: Seed). BlitzBasic verwendet immer die gleiche Saat und erzeugt damit stets die gleiche Folge vonZufallszahlen. Unser Beispielprogramm erhält damit immer dieselbe Zahl als Mittel-wert, weil alle 100.000 erzeugten Zufallszahlen identisch sind.

Blitz Basic kann Datum und Zeit nur ermitteln, nicht setzen.

Page 87: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

87

Verändern von Zeichenketten j e t z t l e r n e i c h

Das ist natürlich in der Praxis wenig brauchbar. Deswegen können Sie mit dem BefehlSeedRnd die Saat festlegen. Nun wäre es nicht sinnvoll, wenn Sie eine feste Zahl alsSaat angeben würden – und eine Zufallszahl können Sie auch nicht wählen, weil dasDilemma nur aufgeschoben wäre: Blitz Basic würde zwar eine andere als die sonstigeFolge erzeugen, aber dennoch immer die gleiche.

Die Lösung wäre eine Saat, die sich ständig ändert, egal auf welchem PC das Spiel ge-startet wird und egal wie oft es gestartet wurde. Und hierfür passt prächtig Milli-Secs(), also die Funktion, die angibt, wie viele Tausendstelsekunden seit dem jüngstenStart des PCs vergangen sind. Selbst wenn die Funktion nur Zehntelsekunden ausge-ben würde, wäre die Wahrscheinlichkeit äußerst gering, dass ein Spieler mehrmals hin-tereinander mit der gleichen Saat und damit der gleichen Folge von Zufallszahlen kon-frontiert würde. Aber Tausendstelsekunden! Das ist wirklich ... Zufall. Stellen Sie alsojeder Verwendung der Funktion Rand() die Zeile:

SeedRnd MilliSecs()

voran. Ein kleines Beispiel gefällig? Basteln wir rasch ein Miniwürfelspiel zusammen.Die Augenzahl bestimmt der Zufall:

; WÜRFEL.BBDim Augen$(6)Data "Eins", "Zwei", "Drei", "Vier", "Fünf", "Sechs"For X=1 To 6 Read Augen(X)Next;SeedRnd MilliSecs()Computer = Rand(1,6)Print "Computer würfelt eine " + Augen(Computer) + "."Mensch = Rand(1,6)Print "Sie würfeln eine " + Augen$(Mensch) + "."If Computer > Mensch Then Print "Computer hat gewonnen."If Computer = Mensch Then Print "Gleichstand."If Computer < Mensch Then Print "Sie haben gewonnen."WaitKey

1

5.7 Verändern von Zeichenketten

Wie viele andere Programmiersprachen auch, bietet Ihnen Blitz Basic viele Möglich-keiten, Zeichenketten (Strings) zu verändern. Mithilfe einer Reihe von Funktionen kön-nen Sie zum Beispiel:

� alle Zeichen in Großbuchstaben verwandeln

� den linken oder rechten Teil abschneiden

� ein Wort durch ein anderes ersetzen

� überprüfen, ob eine Zeichenkette ein bestimmtes Wort enthält

Rand() ist eine Abkürzung von random, dem englischen Wort für zufällig. NebenRand() gibt es die ähnliche Funktion Rnd(). Sie liefert statt einer ganzen Zahl eine ge-brochene wie 4.826471. RndSeed() liefert den Wert zurück, mit dem der Zufallsgene-rator initialisiert wurde, also die Zahl, die zuvor SeedRnd übergeben wurde. BeideFunktionen dürften nur selten Anwendung finden.

Page 88: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

88

Zahlen und Zeichenketten5j e t z t l e r n e i c h

Auf den ersten Blick sehen die Funktionen kompliziert aus. In Wirklichkeit ist es kin-derleicht, sie zu benutzen. Im Folgenden erhalten Sie daher nur eine Aufzählung inKurzform. Jeder Befehl wird durch ein oder zwei Beispiele veranschaulicht.

� Upper$(Zeichenkette)

Wandelt alle Buchstaben (außer Umlaute!) in Großbuchstaben um.

Beispiel: Upper$("Hallo")Ergebnis: "HALLO"

� Lower$(Zeichenkette)

Wandelt alle Buchstaben (außer Umlaute!) in Kleinbuchstaben um.

Beispiel: Lower$("Hallo")Ergebnis: "hallo"

� Left$(Zeichenkette,x)

Liefert die linken x Zeichen der Zeichenkette.

Beispiel: Left$("Zauberlehrling", 6)Ergebnis: "Zauber"

� Right$(Zeichenkette,x)

Liefert die rechten x Zeichen der Zeichenkette.

Beispiel: Left$("Zauberlehrling", 8)Ergebnis: "lehrling"

� Mid$(Zeichenkette, x, y)

Liefert einen Teilstring ab Zeichen x, und zwar y Zeichen lang. Wenn y fehlt, biszum Ende des Worts.

Beispiel: Mid$("Zauberlehrling", 5, 4)Ergebnis: "erle"

Beispiel: Mid$("Zauberlehrling", 7)Ergebnis: "lehrling"

� Trim$(Zeichenkette)

Entfernt alle Leerzeichen (und Umlaute sowie »ß«!) am Anfang und am Ende derZeichenkette.

Beispiel: Trim$(" Hallo! ")Ergebnis: "Hallo!"

� LSet$(Zeichenkette,x)

Hängt rechts so viele Leerzeichen an die Kette, bis sie x Zeichen lang ist (links-bündig).

Beispiel: LSet$("Nemesis", 10)Ergebnis: "Nemesis "

� RSet$(Zeichenkette,x)

Hängt links so viele Leerzeichen an die Kette, bis sie x Zeichen lang ist (rechts-bündig).

Beispiel: RSet$("Nemesis", 10)Ergebnis: " Nemesis"

Page 89: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

89

Verändern von Zeichenketten j e t z t l e r n e i c h

� Instr(Zeichenkette, Suchwort, x)

Sucht in der Zeichenkette ein Wort. Liefert die Zeichenposition der Fundstelle. Istdas Suchwort nicht enthalten, wird 0 geliefert. Ist x vorhanden, wird erst ab Zei-chen x mit der Suche begonnen.

Beispiel: Instr("Zauberlehrling", "erle")Ergebnis: 5

Beispiel: Instr("Zauberlehrling", "erle", 6)Ergebnis: 0

� Replace$(Zeichenkette, Alt, Neu)

Ersetzt in der Zeichenkette alle Vorkommen des Worts Alt durch das Wort Neu.

Beispiel: Replace$("Brautkleid bleibt Brautkleid", "Brautkleid", "Geschenkt")

Ergebnis: "Geschenkt bleibt Geschenkt"

� String$(Zeichenkette, x)

Wiederholt die Zeichenkette x-mal (nicht mit Str$() zu verwechseln, das eine Zahlin eine Zeichenkette verwandelt!).

Beispiel: String$("XXOO",3)Ergebnis: "XXOOXXOOXXOO"

� Len(Zeichenkette)

Gibt die Anzahl der Zeichen der Zeichenkette aus.

Beispiel: Len("Hallo")Ergebnis: 5

1Sie verwenden die Funktionen in der bekannten Form wie

a$ = Upper$("Hallo")

Natürlich können Sie statt einer Zeichenkette auch eine String-Variable nehmen:

a$ = Upper$(b$)

Lassen wir die Helfer einige praktische Aufgaben lösen.

5.7.1 Rechtsbündiger TextDer Print-Befehl gibt Text linksbündig aus. Das bedeutet, er wird am linken Rand aus-gerichtet. Manchmal wünscht man sich eine rechtsbündige Anordnung, etwa bei einerListe von Zahlen. Diese erreichen wir, indem wir vor jede Zeile eine bestimmte Anzahlvon Leerzeichen setzen, so dass alle Zahlen in der gleichen Spalte enden. Darauf könn-ten Sie selbst achten, doch wofür haben Sie Programmieren gelernt? Damit Ihnen derComputer die Arbeit abnimmt. (Die wir ohne ihn nicht gehabt hätten. Na gut, das warein Kalauer.)

Beachten Sie, dass Trim$ nicht mit deutschen Umlauten und dem »ß« funktioniert –die Zeichen werden ebenfalls abgeschnitten, wenn sie sich am Anfang oder Ende ei-ner Zeichenkette befinden.

Page 90: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

90

Zahlen und Zeichenketten5j e t z t l e r n e i c h

Schreiben wir eine Funktion, die eine Zahl rechtsbündig ausrichtet. Wir übergeben ihrdie Zahl sowie die Zahl der gewünschten Stellen. Nehmen wir die Zahl 1000 und dieStellenanzahl 7, dann wollen wir als Ergebnis » 1000« – drei Leerstellen sowie vierStellen für die Zahl selbst, macht sieben Stellen. Keine Frage, dass das Ergebnis eineZeichenkette sein muss.

; USING.BBFunction Using$(Zahl$, Stellen) While Len( Zahl$ ) < Stellen Zahl$ = " " + Zahl$ Wend Return Zahl$End Function

Das Erweitern lösen wir elegant in einer Schleife: Solange die Zahl noch nicht lang ge-nug ist, wird ihr eine Leerstelle vorangestellt. Anschließend wiederholt sich der Test.Das funktioniert nicht nur mit Zahlen, sondern mit Zeichenketten jeder Art – die Funk-tion erwartet eine Zeichenkette als Parameter. Selbst wenn ihr eine Zahl übergebenwird, wandelt Blitz Basic sie in eine Zeichenkette um.

Print Using$(1345, 7)Print Using$(24, 7)Print Using$(50000, 7)WaitKey

gibt aus:

1345 24 50000

Die Funktion verwenden wir an beliebiger Stelle in größeren Programmen, natürlichauch zusammen mit dem Text-Befehl im Grafik-Modus, zu dem wir später kommen.

15.7.2 Text verschlüsselnIm Folgenden schreiben wir ein kleines Programm, das einen Text verschlüsselt. Dazurufen wir uns die Xor-Verknüpfung in Erinnerung: Da sie umkehrbar ist, können wirden gleichen Algorithmus zum Entschlüsseln nehmen, den wir zum Verschlüsseln ein-setzen. Für unser Programm lesen wir nacheinander jedes Zeichen des zu verschlüs-selnden Textes aus, ermitteln seinen ASCII-Code, behandeln ihn mit Xor und wandelnden Code zurück in ein Zeichen.

; XOR.BBEingabe$ = Input$("Text eingeben: ")For I=1 To Len(Eingabe) Code$ = Code$ + Chr$( Asc( Mid$(Eingabe$, I, 1) ) Xor 47 )NextPrint "Code: " + Code$WaitKey

Ich habe die Funktion Using$() genannt, in Anlehnung an eine ähnliche Funktiongleichen Namens anderer Programmiersprachen. Damit lässt sich die Ausgabe vonZahlen komfortabel steuern, auch mit Tausenderpunkt.

Page 91: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

91

Verändern von Zeichenketten j e t z t l e r n e i c h

Die eingegebene Zeichenkette wird zerlegt. Der ASCII-Code jedes Zeichens wird mit47 »ge-xor-t«. Das Ergebnis ist ein Kauderwelsch, aus "Test" wird etwa "{J\[". GebenSie den verschlüsselten Text ein, bekommen Sie den Klartext zurück. Dieses Verfahrenist für erfahrene Tüftler nicht schwer zu knacken, reicht aber für Spieletexte aus, die inden Dateien unlesbar abgelegt werden sollen. Für wirkliche Sicherheit suchen Sieeinen langen Schlüssel und »xor-en« jeden Buchstaben mit einem anderen Teil desCodes.

Noch ein Zeichenketten-Beispiel? Gern.

5.7.3 Rückwärts-TextEin eingegebenes Wort soll rückwärts ausgedruckt werden. Dazu ermitteln wir die Län-ge des Worts und fragen von der letzten Stelle an nacheinander jeden Buchstaben ein-zeln ab:

; RÜCKWÄRTS.BBWort$ = Input("Welches Wort: ")Write("Das heißt rückwärts: ")For I = Len(Wort$) To 1 Step -1 Write (Mid$(Wort$, I, 1))NextWaitKey

Das war leicht, nicht?

5.7.4 GlücksradProbieren wir etwas Besseres: ein kleines Wortratespiel, ähnlich Glücksrad oder Gal-genraten.

Aus einer Datenbank von eingespeicherten Wörtern (hier: 10) wählt der Computer zu-fällig eins aus. Am Anfang druckt er genauso viele Sterne, wie das Wort Buchstabenhat. Nacheinander muss je ein Buchstabe geraten werden. Ist der Buchstabe Teil desgesuchten Worts, wird er aufgedeckt ("*a**e"). Damit beim Probespielen aus wenigenMöglichkeiten das richtige Wort schwerer zu finden ist, habe ich gleich lange Begriffegewählt.

; GLÜCKSRAD.BB; Wortsammlung einlesenAnzahl=10Data "knopf", "augen", "honig", "rinde", "teich"Data "musik", "katze", "mauer", "baron", "dolch"Dim Woerter$(Anzahl)For I = 1 To Anzahl Read Woerter$(I)Next

; Wort "ausdenken"SeedRnd MilliSecs()Wort$ = Woerter$(Rand(1,Anzahl))Geraten$ = String$("*",Len(Wort$))Versuche = 1

Page 92: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

92

Zahlen und Zeichenketten5j e t z t l e r n e i c h

; Raten beginntRepeat Print Versuche + ". Versuch: " + Geraten$ + "'" Eingabe$ = Input("Welcher Buchstabe fehlt: ") If Instr(Wort$,Eingabe$) Then Geraten$ = Left$(Geraten$, Instr(Wort$,Ein-gabe$) -1) + Eingabe$ + Mid$(Geraten$, Instr(Wort$,Eingabe$) +1) Versuche = Versuche + 1Until Geraten$ = Wort$

Print Wort$ + " ist richtig!"WaitKey

5.8 Daten sortieren

Häufig kommt der Programmierer in die Verlegenheit, eine Gruppe von Werten sor-tieren zu müssen – Zahlen nach ihrer Größe, Zeichenketten alphabetisch. Ein nahelie-gender Einsatz ist eine Bestenliste, die natürlich nach der Anzahl der erreichten Punktepräsentiert wird.

Das Ziel ist, alle Werte vom kleinsten an der ersten Position bis zum größten an der letztenStelle zu sortieren. Es gibt eine Reihe von Sortierverfahren. Die bekannteste Methode ar-beitet wie Blasen, die nach oben steigen. Und so nennt man sie auch: Bubble Sort.

Sie vergleichen jeweils zwei Werte miteinander. Ist der erste Wert größer als der zweite,dann vertauschen Sie sie. Danach beginnen Sie wieder von vorn. Auf diese Weise»blubbern« langsam die großen Werte nach hinten. Das klingt ziemlich einfach und istauch leicht umzusetzen. Bubble Sort arbeitet zwar sehr langsam, genügt bei geringenDatenmengen jedoch durchaus.

Anhand eines Dim-Felds, bestehend aus zehn Einträgen, zeige ich das Aufsteigen derBlasen praktisch. Blitz Basic bietet keinen speziellen Befehl, um die Inhalte zweier Va-riablen miteinander zu tauschen. Sie benötigen daher eine dritte Variable als Zwischen-speicher. Den Inhalt von A und B tauschen Sie wie folgt:

X = AA = BB = X

Zunächst erstellen wir ein Dim-Feld und füllen es mit zufälligen Daten:

Dim A(10)For I=1 To 10 A(I) = Rand(100) Write A(I) + " "Next

Nun sortieren wir die Daten:

For I=1 To 9 If A(I) > A(I+1) Then X = A(I) : A(I) = A(I+1) : A(I+1) = X I=0 EndIfNext

Vom ersten Element an wird ein jedes mit seinem jeweils nächsten verglichen. Weildem zehnten Element kein weiteres folgt, geht die For-Schleife nur bis 9. Ist das linkeElement größer als das rechte, werden beide vertauscht und die For-Schleife beginnt

Page 93: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

93

Daten sortieren j e t z t l e r n e i c h

wieder ganz von vorn: I wird auf 0 gesetzt, um durch Next auf 1 erhöht zu werden, wasder Ausgangsbedingung der Schleife entspricht.

Wenn Sie für jeden Durchlauf alle Elemente ausdrucken, sehen Sie, in welchen Schrit-ten die Sortierung erfolgt:

; SORTIEREN.BBGraphics 640,480Dim A(10)For I=1 To 10 A(I) = Rand(100) Write A(I) + " "Next;For I=1 To 9 If A(I) > A(I+1) Then X = A(I) : A(I) = A(I+1) : A(I+1) = X I=0 ; Print For J=1 To 10 Write A(J) + " " Next EndIfNextWaitKey

Am Ende sind alle zehn Zahlen sortiert. Das funktioniert ebenso mit Zeichenkettenfel-dern. Allerdings erhöht sich die Sortierzeit exponentiell mit der Zahl der Einträge. Sol-len 100 Zahlen geordnet werden, braucht das Programm 100.000 Durchläufe. Bei1000 sind es bereits 100 Millionen! Selbst flotte PCs benötigen dafür eine Rechenzeitvon einer halben Minute.

Leicht kommen wir dahinter, was so lange dauert: Unser Algorithmus ist nicht effektiv.Wir tauschen immer nur ein Zahlenpaar, dann beginnen wir ganz von vorn. Das ist ge-nauso, wie wenn wir einen Eimer Wasser von A nach B schleppen müssten, aber nachjedem Meter den Eimer abstellen, zum Start zurück und wieder zum Eimer laufen wür-den. So gelangen wir zwar ans Ziel, führen aber jede Menge überflüssige Vergleicheaus.

Wir bauen das Programm etwas um: Jede Zahl wird in einem Zug so weit wie möglichnach vorn geschickt. Wir verwenden dazu zwei verschachtelte For-Schleifen: Die äuße-re tastet sich von Eintrag zu Eintrag vor, die innere lässt die niedrigen Zahlen nach vornblubbern.

; SORTIEREN2.BBGraphics 640,480Dim A(10)For I=1 To 10 A(I) = Rand(100) Write A(I) + " "Next;For I = 1 To 10 For J = I To 10 If A(I) > A(J) Then X = A(I) : A(I) = A(J) : A(J) = X Print

Page 94: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

94

Zahlen und Zeichenketten5j e t z t l e r n e i c h

For Y=1 To 10 Write A(Y) + " " Next EndIf Next Next WaitKey

Die Zahl der eigentlichen Vertauschungen ist bei beiden Verfahren gleich. Doch imzweiten Programm sind erheblich weniger Abfragen enthalten. Bereits bei den zehnFeldeinträgen reduziert sich der Rechenaufwand um die Hälfte. Würden wir jedoch1000 Zahlen sortieren, wären es statt der 100 Millionen Schleifendurchläufe nur noch500.000!

Leicht lässt sich das Programm so anpassen, dass es auch mit Zeichenketten funktio-niert. Die Reihenfolge entscheidet der ASCII-Code. Ganz vorn stehen dabei das Leer-zeichen und Sonderzeichen wie »(« und »)«. Danach folgen die Ziffern, einige weitereSonderzeichen, die Großbuchstaben, noch ein paar Sonderzeichen und die Kleinbuch-staben. Um eine Anordnung unabhängig von der Groß- und Kleinschreibung zu erzie-len, sortieren Sie nicht die zu durchsuchenden Zeichenketten, sondern die klein odergroß geschriebene Fassung davon. Verwenden Sie dazu die Funktion Lower$() oderUpper$():

If Lower$(A$(I)) > Lower$(A$(I+1)) ...

5.8.1 Daten suchenUm einen bestimmten Wert in einer Menge von Daten zu suchen, bleibt uns nichts an-deres übrig, als jeden Eintrag durchzugehen und ihn mit dem gewünschten Betrag zuvergleichen. Das schauen wir uns anhand eines kleinen Beispiels näher an: Aus einemDim-Feld sollen der kleinste und der größte Wert ermittelt werden. Dazu füllen wir es amAnfang mit zufälligen Daten, setzen die Variable Kleinster auf einen sehr hohen Wert(höher als alle Feldeinträge) und Groesster im Gegenzug auf einen sehr kleinen Wert –0. Wir sehen uns nach und nach alle Feldeinträge an. Wenn wir einen Wert finden, dergrößer ist als Groesster, dann ersetzen wir den Inhalt der Variable damit. Auf diese Wei-se haben wir uns am Ende den größten Wert gefischt.

; KLEINSTER.BBAnzahl = 1000 ; so viele FeldeinträgeMax = 100000 ; mit Werten von 1 bis Max

; Feld erstellen und zufällig füllenDim Feld(Anzahl)SeedRnd MilliSecs()For I=1 To Anzahl Feld(I) = Rand(1, Max)Next

Kleinster = Max + 1Groesster = 0

; Kleinsten und Größten suchenFor I=1 To Anzahl If Feld(I) > Groesster Then Groesster = Feld(I)

Page 95: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

95

Daten sortieren j e t z t l e r n e i c h

If Feld(I) < Kleinster Then Kleinster = Feld(I)NextPrint "Kleinster: " + Kleinster + " - Größter: " + GroessterWaitKey

Das wäre schneller gegangen, wenn die Daten in sortierter Form vorgelegen hätten:Dann müssten wir nur den ersten und letzten Feldeintrag auslesen. Doch auch wennwir nach einem beliebigen Wert Ausschau halten, nützt uns das Sortieren.

5.8.2 Binäre SucheAngenommen, wir haben ein Dim-Feld mit 1000 Zahlen. Wir wollen wissen, ob ein be-stimmter Wert im Feld enthalten ist – oder welcher Feld-Index die gesuchte Zahl ent-hält. Wir stellen wir das an? Ähnlich wie eben beschrieben: Wir durchsuchen mit einerFor-Schleife das gesamte Feld.

For I=1 to 1000 If Feld(I) = Suchzahl Then ...Next

Durchschnittlich fünfhundertmal wird die Schleife durchlaufen, bis der gesuchte Wertenthalten ist, bzw. tausendmal, wenn die Zahl gar nicht zu finden ist.

Dieser Aufwand lässt sich erheblich verkürzen, wenn das Feld sortiert ist. In diesem Fallgehen wir so vor: Wir fragen nicht jedes Feld der Reihe nach ab, sondern jeweils dasMittelfeld, am Anfang also Nummer 500. Ist der Inhalt von Index 500 größer als dergesuchte Wert, wissen wir, dass unsere Zahl nicht in den Feldeinträgen 500 bis 1000enthalten sein kann. Wir brauchen sie also nicht einzeln zu durchsuchen, sondern be-rücksichtigen sie gar nicht mehr. Damit haben wir mit einer Anfrage die Zahl der zuprüfenden Felder halbiert.

Nun gehen wir von einem 500 Einträge großen Feld aus, fragen wieder in der Mitteund halbieren anhand des Ergebnisses erneut die Zahl der übrig gebliebenen Einträge.

Wenn wir uns vor Augen halten, dass jede Zahl in einer Reihe von Bits gespeichert wirdund dass jedes zusätzliche Bit den möglichen Wertebereich verdoppelt (2 Bit für 0 bis3, 3 Bit für 0 bis 7 ... 8 Bit für 0-255, 9 Bit für 0-511 ...), dann bedeutet eine Halbie-rung des Wertebereichs ein Reduzieren von Bits. Bei jedem Durchlauf nehmen wir einBit weg. Daher nennt man dieses Verfahren binäre Suche. Sie benötigt maximal einenDurchlauf mehr, als Bits notwendig sind, um die Anzahl der Feldeinträge zu speichern.

1Es liegt auf der Hand, dass sich mit der binären Suche auch große Datenmengen sehrschnell durchsuchen lassen – wenn sie eben sortiert sind.

Schauen wir uns das praktisch an. Wir erstellen ein Feld, füllen es zufällig mit Datenund sortieren es. Dann fragen wir nach einer bestimmten Zahl per Binärsuche. DasProgramm registriert die Anzahl der Durchläufe. Ist die gewünschte Zahl nicht enthal-ten, wird die nächstgelegene genannt – kleiner Dienst am Kunden.

Wie viele Bit genau notwendig sind, verrät uns der Logarithmus zur Basis 2, den wirbereits besprochen haben: Ceil( Log(X) / Log(2) ).

Page 96: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

96

Zahlen und Zeichenketten5j e t z t l e r n e i c h

; BINAER.BB

Anzahl = 1000 ; so viele FeldeinträgeMax = 100000 ; mit Werten von 1 bis MaxGesucht = 250 ; diese Zahl wird gesucht

; Feld erstellen und zufällig füllen

Dim Feld(Anzahl)SeedRnd MilliSecs()For I=1 To Anzahl Feld(I) = Rand(1, Max)Next

; Feld sortieren

For I = 1 To Anzahl For J = I To Anzahl If Feld(I) > Feld(J) Then X = Feld(I) : Feld(I) = Feld(J) : Feld(J) = X EndIf Next Next

; Binärsuche

Von = 1Bis = AnzahlSchritt = 1; Gesucht = Feld( Rand(1, Anzahl) ) ; falls Wert enthalten sein soll

Print "Gesucht wird: " + GesuchtPrint

Repeat Mitte = Von + (Bis - Von) / 2 Print Schritt + ". Schritt: Mitte = Index " + Mitte + " (enhält " + Feld(Mitte) + ")"

If Feld(Mitte) = Gesucht Then Print Print "Gefunden - Index: " + Mitte Exit EndIf

If (Mitte < Von) Or (Mitte > Bis) Then Print Print "Nicht enthalten. Nächster Wert: " + Feld(Mitte) Exit EndIf

If Feld(Mitte) < Gesucht Then Von = Mitte + 1

If Feld(Mitte) > Gesucht Then Bis = Mitte - 1

Schritt = Schritt + 1ForeverWaitKey

Page 97: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

97

Aufgaben j e t z t l e r n e i c h

Die drei Variablen am Anfang passen Sie nach Belieben an. Um das Programm an-hand eines Werts zu testen, der in einem Feldeintrag enthalten ist, ändern Sie die Zu-weisung des gesuchten Werts:

Gesucht = Feld( Rand(1, Anzahl) )

Das ist natürlich erst möglich, nachdem das Feld erstellt wurde. Die Zeile ist bereits imListing enthalten, aber auskommentiert. Die Ausgabe des Programms könnte folgen-dermaßen aussehen:

Gesucht wird: 21127 1. Schritt: Mitte = Index 500 (enthält 51613)2. Schritt: Mitte = Index 250 (enthält 25760)3. Schritt: Mitte = Index 125 (enthält 12362)4. Schritt: Mitte = Index 187 (enthält 18648)5. Schritt: Mitte = Index 218 (enthält 21928)6. Schritt: Mitte = Index 202 (enthält 19980)7. Schritt: Mitte = Index 210 (enthält 21127) Gefunden - Index: 21

Die Binärsuche lässt sich für viele Zwecke einsetzen. Stellen Sie sich eine Datenbankmit Millionen von Telefonnummern vor. Wenn sie sortiert sind, lässt sich blitzschnellder Besitzer eines Anschlusses ermitteln.

5.9 Aufgaben

1. Schreiben Sie eine Funktion, die ausgibt, wie oft jeder Buchstabe in einer beliebi-gen Zeichenkette enthalten ist.

2. Erweitern Sie das Programm WÜRFEL.BB so, dass der Würfelvorgang wiederholtwird. Der Punktestand soll gespeichert und bei jedem Durchgang ausgedruckt wer-den.

3. Erweitern Sie das Programm GLÜCKSRAD.BB um folgende Funktionen:

3a. Groß- und Kleinschreibung sollte nicht beachtet werden.

3b. Kommt ein Buchstabe im Wort mehrfach vor, dann sollen alle Vorkommen auf-gedeckt werden. Im Moment können solche Wörter (wie »weber«) nicht gefun-den werden.

3c. Das Programm soll die mehrfache Eingabe eines Buchstabens zurückweisen.

Page 98: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 99: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

99

jetz

t le

rne

ich

KAPITEL 6

Arbeiten im Grafikmodus

In den ersten Kapiteln kämpften wir uns durch die technischen Grundlagen. Sie sindnotwendig, um das Skelett jedes Spiels aufzubauen. Nun wollen wir es einkleiden, mitbewegten Bildern.

1

6.1 Grafikmodus

Sie haben es schon oft erlebt: das Knacken Ihres Monitors, wenn Sie ein Spiel starten.Es ist wie eine kleine Explosion und schon hat sich der Windows-Desktop in ein far-benprächtiges Spektakel verwandelt. Diese »Explosion« ist das Umschalten in einen an-deren Grafikmodus. Um Grafiken in Blitz Basic zu verwenden, initialisieren Sie einenGrafikmodus. Das erledigt der Befehl Graphics für Sie:

Graphics Breite, Höhe, Farbtiefe, Fenstermodus

Seine Parameter sehen wir uns nun ausführlich an.

Um Grafiken zu verwenden, müssen Sie in den Grafikmodus schalten. Dort gibt eszwei Bildschirmseiten (Puffer). Der Monitor zeigt stets die Vorderseite an. Sie zeich-nen üblicherweise auf die Rückseite. Mit einem Befehl schaltet Blitz Basic im Bruch-teil einer Sekunde zwischen beiden Seiten um, so dass der Inhalt der Rückseite sicht-bar wird. Diese Technik bedingt, dass die Befehle Graphics, SetBuffer und FlipBestandteil Ihrer Programme werden, wenn Sie mit Grafiken arbeiten. Und dass Siesich vorher durch einige Seiten Theorie quälen müssen, auf denen ich Ihnen alles de-tailliert erkläre. Bitte tun Sie das besonders aufmerksam.

Page 100: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

100

Arbeiten im Grafikmodus6j e t z t l e r n e i c h

0

6.1.1 AuflösungDie wichtigste Entscheidung legen Sie mit der Auflösung, also der Breite und Höhe desSpielbildschirms in Bildpunkten (Pixeln) fest. Übliche Auflösungen sind 640 x 480,800 x 600 oder 1024 x 768. Das ist ein Verhältnis von 4:3 und entspricht damit denMaßen eines Monitors. Von anderen Auflösungen rate ich Ihnen ab:

� Verhältnisse jenseits von 4:3 füllen die Bildfläche des Monitors nicht vollständigaus.

� Schräge Modi wie etwa 753 x 511 werden meist von der Grafikkarte nicht unter-stützt.

� Zu hohe Auflösungen werden mit verringerter Bildwiederholrate dargestellt und er-höhen den Rechenaufwand. Während bei 640 x 480 insgesamt 307.200 Bild-punkte versorgt werden müssen, sind es bei der Auflösung 1024 x 768 schon786.432 und bei 1600 x 1200 bereits 1.920.000.

Welche Auflösung empfehlenswert ist, lässt sich nicht pauschal beantworten. Mit 640x 480 laufen Ihre Spiele problemlos auf älteren PC-Konfigurationen. Zunächst werdenIhre Spiele noch nicht so ausgefeilt sein. Daher ist es ratsam, Reserven zu haben unddas System nicht auszulasten.

In höheren Auflösungen lassen sich dafür mehr Inhalte unterbringen. 1024 x 768 bie-tet Platz für mehr als doppelt so viele Punkte wie in 640 x 480. Auch kleine Objektekönnen relativ komplex gestaltet sein. Freilich muss man abwägen: Zu überladen solltedas Spielgesehen nicht sein, zu klein dürfen die Einheiten jedoch auch nicht sein.

Im Zeitalter von TFT-Monitoren kommt ein weiterer Aspekt hinzu: Leuchtkristallbild-schirme haben eine feste Anzahl von Bildpunkten, zum Beispiel 1024 x 768. AndereAuflösungen werden simuliert, indem mehrere Pixel zu einem scheinbaren Punkt zu-sammengefasst werden. Diese Interpolation geht oft mit einer verringerten Qualitätder Darstellung einher. Wenn Sie mehrere Auflösungen anbieten, kann der Spieler dieauswählen, die am besten zu seinem Monitor passt.

Unabhängig davon, wie Sie sich entscheiden: Programmieren Sie möglichst so, dassSie selbst im Laufe der Entwicklung die Auflösung ändern können. Vor allem, wenn Siedie Auflösung erhöhen, geht das relativ problemlos. Arbeiten Sie besser nicht mit fes-ten Koordinaten, sondern mit relativen. Für den Mittelpunkt etwa »Auflösungsbreitegeteilt durch 2«:

MaxBreite = 1024MitteBreite = MaxBreite / 2

1

Falls Sie technische Schwierigkeiten haben, in den Grafikmodus zu schalten, instal-lieren Sie frische Treiber für Ihre Grafikkarte sowie eine aktuelle Version von DirectX(www.microsoft.com/windows/directx/). DirectX ist die Multimedia-Schnittstelle, diezwischen Windows-Programmen und Hardware-Komponenten wie Grafikkarte ver-mittelt.

Für »Bildpunkt« wird häufig der Begriff Pixel verwendet. Das Kunstwort ist eine Ab-kürzung aus Picture Element (Bildelement).

Page 101: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

101

Grafikmodus j e t z t l e r n e i c h

6.1.2 FarbtiefeWahlweise geben Sie an, mit wie vielen Farben Sie maximal arbeiten möchten. VieleFreeware- und Shareware-Spiele basieren auf 256 Farben. Vollpreisspiele glänzen oftmit 32.000 oder mehr Farben. Die Faustregel: Je mehr Farben Sie verwenden, destolebensechter sieht das Spiel aus. Erst einen Modus mit 16,7 Millionen und mehr Far-ben bezeichnet man als »True Color« oder Echtfarben. Häufig genügen jedoch wenigerAbstufungen.

Die Anzahl der Farben bezeichnet man als Farbtiefe. Man gibt sie in Bit an. 256 Far-ben stellen eine Farbtiefe von 8 Bit dar, weil 8 Bit notwendig sind, um eine Wertskalabis 256 (genauer: von 0 bis 255) zu speichern.

Auch der Befehl Graphics erwartet die Angabe in Bit.

Wenn Sie den Parameter weglassen oder im Fenstermodus arbeiten, wählt Blitz Basicdie Farbtiefe aus, mit der Windows läuft. (Mit der Funktion GraphicsDepth() ermittelnSie die eingestellte Farbtiefe.)

6.1.3 FenstermodusMit dem letzten Parameter sagen Sie Blitz Basic, in welcher Fensterform Ihr Spiel dar-gestellt werden soll. Lassen Sie den Parameter weg, wählt Blitz Basic den Vollbild-schirm bei der normalen Ausführung und ein Windows-Fenster bei der Ausführung imDebug-Modus.

Blitz Basic ist optimiert für den Vollbildmodus. Im Fenster sollten Sie nur zu Test-zwecken arbeiten, um etwa gleichzeitig Bildschirmausschriften und Ihren Quelltext zusehen.

Farbtiefe Anzahl der Farben

4 Bit (nicht mit Blitz Basic möglich) 16 Farben

8 Bit (nicht mit Blitz Basic möglich) 256 Farben

16 Bit (»High Color«) 65.536 Farben

24 Bit (»True Color«) 1.677.216 Farben

32 Bit 1.677.216 Farben plus jeweils 256 Transparenz-abstufungen

Reiner Prokein, www.reinerstileset.de: »Verwenden Sie für Ihre Spiele eine Farbtiefevon höchstens 16 Bit. High Color weist nur einen minimalen sichtbaren Unterschiedzu True Color auf. Er ist quasi nur in fließenden Übergängen zu sehen. Dafürschrumpft die Größe eines Bilds auf zwei Drittel gegenüber True Color. Das spartPlatz auf der Festplatte, Download-Zeit und Rechner-Ressourcen, denn es müssenauch weniger Daten berechnet werden.«

Page 102: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

102

Arbeiten im Grafikmodus6j e t z t l e r n e i c h

Meistens genügt es, wenn Sie einfach

Graphics 640,480

wählen.

1

A6.2 Verfügbare Treiber und Modi abfragen

Es geht in Ordnung, wenn Sie Ihrem Spiel eine feste Auflösung und Farbtiefe zuwei-sen. Sollten Sie verschiedene Auflösungen berücksichtigen, dann bietet Ihnen BlitzBasic einen Satz Funktionen, mit denen Sie die möglichen Auflösungen und sogar –bei mehreren eingebauten Grafikkarten – die vorhandenen Treiber erfragen und dannPassendes festlegen.

16.2.1 Ansteuern verschiedener TreiberManche PCs haben nicht nur eine, sondern mehrere Grafikkarten. Für solche Fällekönnen Sie den Spieler fragen, welche Ihr Programm nutzen soll. Notwendig dürfte esallerdings nicht sein.

Die Funktion CountGfxDrivers() ermittelt die Zahl der installierten Grafiktreiber. Dasentspricht in der Regel der Zahl der Karten und ist meistens 1.

Welcher tatsächliche Treibername sich hinter einer Nummer verbirgt, verrät IhnenGfxDriverName$() mit einer Nummer als Parameter:

Print GfxDriverName$()

Leider ist die Ausgabe meistens rätselhaft wie "Primärer Anzeigetreiber", was derStandardgrafikausgabe entspricht.

Mit SetGfxDriver wählen Sie schließlich einen bestimmten Treiber aus. Und nun allesauf einmal:

Parameter Wirkung

0 oder keiner Vollbild, im Debug-Modus-Fenster

1 Vollbild

2 Fenster mit fester Größe

3 Fenster mit veränderbarer Größe

Den Parameter für den Fenstermodus können Sie nur zusammen mit dem Parameterfür die Farbtiefe verwenden. Einige Seiten weiter zeige ich Ihnen, wie Sie herausfin-den, welche Auflösungen überhaupt möglich sind.

Diesen Abschnitt werden Sie vermutlich nie brauchen: Ihre Spiele werden Sie in gän-gigen Auflösungen und Farbtiefen veröffentlichen, die ohnehin von nahezu jedemPC-System unterstützt werden.

Page 103: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

103

Verfügbare Treiber und Modi abfragen j e t z t l e r n e i c h

; GRAFIKTREIBER.BBAnzahl = CountGfxDrivers()For I = 1 To Anzahl Print I + " - " + GfxDriverName(I)NextTreiber = Input("Welcher Treiber soll verwendet werden? ")SetGfxDriver Treiber

6.2.2 Ansteuern verschiedener AuflösungenManchmal liegt es nahe, verschiedene Auflösungen anzubieten. Der Spieler wird dannbei einem langsamen PC zu einer niedrigen und bei einem schnellen PC zu einer hö-heren Auflösung greifen. Mancher bevorzugt die größeren Abbildungen, die gewöhn-lich bei niedrigen Auflösungen dargestellt werden. Üblicherweise werden mindestensdie Auflösungen 640 x 480, 800 x 600 und 1024 x 768 angeboten; mitunter geht dasFormat bis zu 1600 x 1200. Welche Auflösungen dazwischen möglich sind, hängt vonder verwendeten Grafikkarte und den installierten Treibern ab.

Mit CountGfxModes() ermitteln Sie die Anzahl der verfügbaren Modi. Jeder Modus hateine Nummer, eine Breite, eine Höhe und eine Farbtiefe. Diese Angaben fragen Siemit folgenden Funktionen ab:

� GfxModeWidth(Modus) liefert die Breite

� GfxModeHeight(Modus) liefert die Höhe

� GfxModeDepth(Modus) liefert die Farbtiefe in Bit

Damit listen Sie dem Benutzer Ihres Programms schön auf, welche Modi möglich sind:

; GRAFIKMODUS.BBAnzahl = CountGfxModes()For I=1 To Anzahl Print I + " - " + GfxModeWidth(I) + "x" + GfxModeHeight(I) + " @ " + GfxMode-Depth(I) + " Bit"Next

Alternativ erfragen Sie mit GfxModeExists(Breite, Höhe, Tiefe) direkt, ob ein be-stimmter Modus verfügbar ist. Leider erfahren Sie nur, ob es ihn gibt (1) – welcher esist, müssen Sie selbst herausfinden (indem Sie jeden Modus einzeln abfragen).

Mit Graphics schalten Sie den PC schließlich in den gewünschten Modus.

6.2.3 Größe des Grafikspeichers ermittelnJedes geladene Bild verbraucht Videospeicher. Mit den Funktionen AvailVidMem() undTotalVidMem() ermitteln Sie die Größe des freien und des gesamten Videospeichers inByte.

Print"Graphikspeicher insgesamt: " + TotalVidMem() / 1024 + " KB"Print "Graphikspeicher frei : " + AvailVidMem() / 1024 + " KB"WaitKey

Auf der Buch-CD finden Sie in der Datei GRAFIKSPEICHER.BB ein etwas umfangreiche-res Beispiel, ausgeführt im Grafikmodus. Es zeigt den freien Videospeicher vor undnach dem Laden von Grafiken.

Page 104: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

104

Arbeiten im Grafikmodus6j e t z t l e r n e i c h

Der Videospeicher ist direkt auf der Grafikkarte untergebracht. Er ist nicht zu verwech-seln mit dem Arbeitsspeicher des PCs. Heutige Grafikkarten basieren auf dem VGA-Standard (VGA = Video Graphics Array, zuweilen auch Video Graphics Adapter)von 1987. Die ersten Exemplare waren mit 256 KB Speicher ausgerüstet. Heute wei-sen Grafikkarten bis zu tausend Mal mehr Speicher auf. Selbst einige Jahre alte Gra-fikkarten haben kaum weniger als 16384 Kbyte an verfügbarem Speicher.

6.3 Bildschirmpuffer

Haben Sie sich schon einmal gefragt, wie die Grafik eines Spiels auf den Bildschirm ge-zeichnet wird? Wie bewegt sich eine Spielfigur? Man könnte sie fortwährend von deralten Stelle löschen und an die neue Stelle zeichnen. Das wäre ein rechter Aufwand,wenn viel Trubel auf dem Monitor herrscht. Zumal es ein technisches Problem gibt: Eskriselt auf dem Bildschirm, sobald neue Bilder zu bestehenden Grafiken gegeben wer-den.

Eine Kombination aus zwei Methoden löst beide Probleme.

� Der gesamte Inhalt des Bildschirms wird mehrfach (meist 20 bis 100 Mal) pro Se-kunde neu gezeichnet. Um eine Grafik zu löschen, wird sie beim nächsten Durch-gang einfach weggelassen.

� Man verbirgt den Vorgang des Zeichnens vor dem Spieler. Erst, wenn der Bild-schirm komplett fertig ist, wird das Bild aufgedeckt. Was man dazu braucht, sindmindestens zwei Bildschirmseiten: eine, die man gerade sieht, und eine, auf der ge-rade Grafiken aufgebaut werden. Außerdem benötigt man einen Mechanismus,der rasch beide Seiten auswechselt.

Grafikkarten unterstützen das Verwalten von zwei Bildschirmseiten – einer sichtbarenund einer unsichtbaren – und sie vertauschen beide blitzschnell miteinander. Man be-zeichnet die Seiten als Puffer (englisch: Buffer) und da es zwei sind, nennt man das Ver-fahren Double Buffering. Wie für Blitz Basic üblich, ist der Umgang damit einfach.

Die sichtbare Seite heißt Frontbuffer. Die unsichtbare Seite bezeichnet man als Back-buffer. Sie können in beide Puffer zeichnen. Der einzige Unterschied: Das Zeichnenim Frontbuffer wird sofort sichtbar. Das Zeichnen im Backbuffer erst dann, wenn Sieumschalten.

In welchen Puffer gezeichnet wird, legen Sie mit SetBuffer fest. Sie übergeben als Pa-rameter den gewünschten Puffer, FrontBuffer() oder BackBuffer():

SetBuffer FrontBuffer()

Genau genommen handelt es sich dabei um zwei Befehle, denn FrontBuffer() oderBackBuffer() sind normale Funktionsaufrufe. Sie liefern ihren Puffer als Kennung zu-rück. Manche Befehle wirken gezielt auf einen Puffer. In diesem Fall teilen Sie ihn alszusätzlichen Parameter mit.

Die Funktion GraphicsBuffer() nennt die Kennung des gerade aktiven Puffers, also derSeite, die mit SetBuffer festgelegt wurde und in die gezeichnet wird. Mit einem Ver-gleich wie

If GraphicsBuffer() = FrontBuffer() ...

Page 105: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

105

Koordinaten j e t z t l e r n e i c h

stellen Sie fest, welcher Puffer aktiv ist. Ein Wissen, das Sie freilich kaum benötigenwerden, denn Sie wählen ja den aktiven Puffer selbst aus.

Nun fehlt nur noch ein Befehl, der beide Seiten miteinander vertauscht: Der Inhalt desBackbuffers wird damit sichtbar, das bisherige Bild verschwindet. Das geschieht einfachmit Flip.

26.4 Koordinaten

Nach dem Umschalten in den Grafikmodus denken Sie nur noch in Bildpunkten. Siekönnen jede beliebige Stelle des Bildschirms ansteuern, wenn Sie deren Koordinatenkennen. Das heißt nicht viel mehr als die Zeile und Spalte, in der sich etwa ein Bild-punkt befindet. Wenn Sie mit einer Auflösung von 640 x 480 arbeiten, dann ist derMittelpunkt ungefähr die Koordinate 320,240. (Genauer gesagt: Er liegt zwischen denKoordinaten 320,240 und 321,241.)

16.5 Bildschirm löschen

Bevor ich Ihnen erkläre, wie Sie mit der Kreide zeichnen, zeige ich Ihnen den rettendenSchwamm: Mit dem Befehl Cls löschen Sie den Bildschirm.

1

6.6 Das Grafikgerüst

Aus den Ausführungen der vergangenen Seiten ergibt sich ein Standardgerüst für Pro-gramme, die im Grafikmodus arbeiten:

Graphics 640,480SetBuffer BackBuffer()Cls...<Grafikbefehle>...FlipWaitKey

In Blitz Basic und Blitz Basic 3D aktiviert Graphics den FrontBuffer. Zeichen- undGrafikbefehle arbeiten damit standardmäßig im sichtbaren Bereich. Bei Blitz Pluswird jedoch der Backbuffer eingestellt. Das bedeutet: Ohne Flip sehen Sie nichts.

Beachten Sie, dass sich das Zählsystem von den Koordinaten der Schulmathematikunterscheidet. Die Koordinaten 0,0 hat der Punkt in der linken oberen Ecke. Ver-gessen Sie nicht, dass auch hier die Zählung bei 0 beginnt.

Cls ist die Kurzform von Clear Screen, Bildschirm löschen. Üblicherweise zeichnenSie alle Bilder in den Backbuffer und schalten danach um. Weil nach Flip der Inhaltdes Frontbuffers in den Backbuffer kopiert wird, löschen Sie zunächst mit Cls seinenBildschirm, bevor Sie mit dem Zeichnen beginnen.

Page 106: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

106

Arbeiten im Grafikmodus6j e t z t l e r n e i c h

Für einfache Programme, die nur einmal Grafiken auf den Bildschirm ausgeben, ge-nügt für Blitz Basic und Blitz Basic 3D eine verkürzte Variante – man zeichnet direkt inden Frontbuffer:

Graphics 640,480...<Grafikbefehle>...WaitKey

Das ist aus unerfindlichen Gründen unter Blitz Plus nicht mehr möglich. Der jüngsteSpross der Blitz-Familie hat drei entscheidende Veränderungen erfahren:

1. Mit dem Graphics-Befehl aktivieren Blitz Basic und Blitz Basic 3D den Frontbuffer,Blitz Plus aber den Backbuffer.

2. Bei Blitz Plus ist die Grafikausgabe in den Frontbuffer gar nicht mehr möglich. AlleAusgaben müssen in den Backbuffer gezeichnet werden, danach erfolgt ein Um-schalten mit Flip. In Blitz Basic und Blitz Basic 3D lassen sich Bilder in den Front-buffer zeichnen, sie sind somit sofort sichtbar.

3. Blitz Basic und Blitz Basic 3D stellen bei Graphics ein neutrales Schwarz als Hin-tergrundfarbe ein. Blitz Plus tut das zwar auch, aber bei der ersten Version (auf derdie Demo basiert) wurde das Löschen des Bildschirms vergessen: Ohne zusätzli-ches Cls ist der Hintergrund in hässliches Hellgrau getaucht. Mit dem ersten Up-date wurde der Effekt korrigiert.

Hinzu kommen weitere zweifelhafte Neuerungen: Wie an anderer Stelle beschrieben,funktionieren Input, Print und Write nicht mehr im Grafikmodus. Die AnweisungenWaitTimer, FontWidth() und StringHeight() waren in der Erstversion 1.10 (die derDemo-Version auf der Buch-CD entspricht) entfallen und nach Protesten der Nutzer imersten Update wieder aufgenommen worden.

Die Buchlistings sind so angepasst, dass sie mit allen Versionen von Blitz Basic funkti-onieren. Das heißt in erster Linie, dass grundsätzlich mit BackBuffer(), Cls und Flipgearbeitet wird. Abgesehen von geringfügig mehr Schreibarbeit bedeutet das für Sieeher einen Vorteil: Größere Programme lassen sich ohnehin nur mit Double Bufferingumsetzen und es kann nicht schaden, dass die Technik in »Fleisch und Blut« übergeht.

16.7 Aufgaben

1. Erläutern Sie Vor- und Nachteile einer hohen und einer niedrigen Bildschirmauflö-sung.

2. Beschreiben Sie das Prinzip des Double Buffering.

3. Nennen Sie die Unterschiede zwischen Blitz Basic (3D) und Blitz Plus beim Initia-lisieren des Grafikmodus und die Konsequenzen für Ihre Programme.

Weiterführendes zum Thema Grafikgerüst finden Sie in den Abschnitten Timing undDie Spiel-Schleife.

Page 107: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

107

jetz

t le

rne

ich

KAPITEL 7

Zeichnen

Das Darstellen von Grafikdateien ist der übliche Weg, um den Bildschirm zu füllen.Trotzdem bietet Blitz Basic eine Reihe von Befehlen zur Erstellung einfacher Zeichnun-gen wie Punkte, Linien, Rechtecke und Kreise. In fertigen Spielen werden Sie dieseStrichzeichnungen kaum einsetzen, von Kleinigkeiten wie Trennlinien abgesehen. Sokann ein Viereck als Begrenzung für das Spielfenster dienen. In der Entwurfsphase er-stellen Sie rasch Platzhalter für spätere Menüs, Logos und anderes.

7.1 Punkte zeichnen

Die einfachste Grafik ist ein Punkt. Mit dem Befehl Plot zeichnen Sie einen Punkt aufdem Bildschirm. Sie teilen ihm einfach die Koordinaten mit:

Plot 250,250

Natürlich können Sie auch mehrere Punkte auf einmal zeichnen. Eine Folge von Punk-ten ist eine Linie:

; LINIE.BBGraphics 640,480SetBuffer BackBuffer()ClsFor I=200 To 400 Plot I, 200NextFlipWaitKey

Und vier Linien ergeben ein Quadrat:

; QUADRAT.BBGraphics 640,480SetBuffer BackBuffer()Cls

Page 108: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

108

Zeichnen7j e t z t l e r n e i c h

For I=200 To 300 Plot I, 200 Plot I, 300 Plot 200, I Plot 300, INextFlipWaitKey

Und ein Kreuz durch den Mittelpunkt:

; KREUZ.BBGraphics 640,480SetBuffer BackBuffer()ClsFor I=1 To 200 Plot 320+I, 240+I Plot 320+I, 240-I Plot 320-I, 240+I Plot 320-I, 240-INextFlipWaitKey

7.1.1 LinienEinfacher geht es mit einem speziellen Befehl zum Zeichnen von Linien. Sie geben ein-fach Start- und Endpunkt an:

Line 200,200, 250,200

7.1.2 ViereckeVier Linien ergeben ein Viereck. Auch hierfür bietet Blitz Basic den passenden Befehl.Ihm nennen Sie die Koordinaten der linken oberen Ecke sowie die Länge und die Brei-te der Fläche in Pixeln. Ein Rechteck von den Koordinaten 100,100 bis 250,250 zeich-nen Sie daher wie folgt:

Rect 100,100,150,150

Ein fettes, gefülltes Quadrat. Sie haben ein »leeres« Quadrat erwartet? Können Sie ha-ben. Mit einem zusätzlichen Parameter bestimmen Sie, ob das Quadrat ausgefüllt oderdurchsichtig ist. Normalerweise ist es gefüllt, mit dem Parameter 0 besteht es nur ausvier Linien.

Was stellen Sie damit an? Ich zeige Ihnen ein kleines Beispiel:

; GITTER1.BBGraphics 640,480SetBuffer BackBuffer()ClsFor B=0 To 39 For H=0 To 29 Rect B*16,H*16,16,16,0 NextNextFlipWaitKey

Page 109: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

109

Punkte zeichnen j e t z t l e r n e i c h

Damit wird ein Gitter auf dem Bildschirm gezeichnet, erstellt aus mehr als 1000 klei-nen Quadraten.

Legen wir noch eins drauf. Wir zeichnen in unser Gitter an zufälligen Stellen hundertausgefüllte Quadrate. Dabei runden wir die erhaltenen Zufallszahlen auf die nächst hö-here Zahl und multiplizieren sie genauso mit 16, damit sie an den richtigen Plätzen desGitters erscheinen:

; GITTER2.BBGraphics 640,480SetBuffer BackBuffer()ClsFor B=0 To 39 For H=0 To 29 Rect B*16,H*16,16,16, 0 NextNextSeedRnd MilliSecs()For I=1 To 100 Rect Rand(0,39) * 16, Rand(0,29) * 16, 16,16, 1NextFlipWaitKey

Abb. 7.1:Gitternetz, gezeichnet mit Linien.

7.1.3 Kreise und OvaleWo man Vierecke zeichnen kann, sind Kreise nicht weit. Sie zeichnen sie mit dem Be-fehl Oval. Ähnlich wie bei Vierecken geben Sie die Startkoordinaten an, diesmal denoberen linken Rand, die Breite und die Tiefe. Sind Breite und Tiefe gleich groß, han-delt es sich um einen Kreis:

Oval 100,100,150,150

Page 110: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

110

Zeichnen7j e t z t l e r n e i c h

Unterscheiden sich Breite und Länge, wird ein Oval gezeichnet:

Oval 100,100,250,150

Auch hier gilt wieder: Geben Sie als fünften Parameter eine Null an, bleibt das rundeEtwas leer. Im folgenden Beispiel werden 100 Ovale gezeichnet, jeweils in Positionund Größe etwas verschoben:

; OVAL1.BBGraphics 640,480SetBuffer BackBuffer()ClsFor I=1 To 100 Oval 100 + I, 100 + I, 100+I, 100+INextFlipWaitKey

Nett, nicht? Oder so, als Light-Variante:

; OVAL2.BBGraphics 640,480SetBuffer BackBuffer()ClsFor I=1 To 100 Step 5 Oval 100 + I, 100 + I, 100+I, 100+I, 0NextFlipWaitKey

1 Abb. 7.2:

Mit einfachenSchleifen las-

sen sich selbstaus den Grund-formen interes-

sante Gebildeschaffen.

Ich empfehle Ihnen, ruhig eine Weile mit diesen Befehlen zu experimentieren. Mit Li-nien, Vierecken und Kreisen in Verbindung mit Zufallszahlen erzielen Sie bereits mitwenigen Befehlen viele schöne Effekte.

Page 111: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

111

Farben j e t z t l e r n e i c h

7.2 Farben

Nach dem ersten Aha-Effekt ist der Reiz des Neuen schnell verflogen: So schwarzweißwie jetzt sehen die Grafiken irgendwie ... farblos aus.

Sie können in Blitz Basic die Farbe des Hintergrunds und die Farbe jedes einzelnenPunkts bestimmen. Leider ist das nicht ganz so leicht, da Sie nicht einfach »grün« sagendürfen. Das liegt daran, dass sich viel mehr Farben verwenden lassen, als es Namen da-für gibt. Bereits bei einer Farbtiefe von 16 Bit sind mehr als 65.000 Farben möglich.Notwendig ist daher eine genauere Abstufung.

Wie Sie vielleicht wissen, lassen sich alle Farbtöne dieser Welt aus den drei Grundfar-ben Rot, Grün und Blau mischen. Häufig werden in der Computerwelt Farben mit dreiZahlen angegeben, nämlich mit ihren Anteilen an Rot, Grün und Blau auf einer Skalavon 0 bis 255. Man sagt dazu auch RGB-Wert. Einige Beispiele:

Die Faustregel: Je niedriger die Anteile, desto dunkler wird eine Farbe. Weitere Farb-codes entnehmen Sie der deutschen Online-Hilfe.

Die RGB-Farbe setzen Sie in zwei Befehlen ein. Color legt die Farbe fest, mit der ge-zeichnet wird:

Color 255,255,0

Damit wählen Sie den Farbstift aus, der die nächsten Grafiken wie Punkte, Viereckeund Kreise zeichnet – so lange, bis Sie die Farbe wieder wechseln.

Farbe RGB-Wert

Rot 255, 0, 0

Weinrot 127, 0, 0

Violett 128, 0, 128

Hellblau 0, 255, 255

Blau 0, 0, 255

Dunkelblau 0, 0, 127

Grün 0, 255, 0

Dunkelgrün 0, 127, 0

Gelb 255, 255, 0

Olivgrün 127, 127, 0

Weiß 255, 255, 255

Hellgrau 192, 192, 192

Schwarz 0, 0, 0

Grau 127, 127, 127

Page 112: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

112

Zeichnen7j e t z t l e r n e i c h

2

Mit ClsColor bestimmen Sie die Farbe des Hintergrunds. Es empfiehlt sich, danach Clszu benutzen. Das Löschen färbt den Bildschirm in der von Ihnen gewählten Farbe:

ClsColor 255,0,0Cls

In Verbindung mit den neuen Farbbefehlen verschönern Sie die Spielereien mit Ovalenund Linien. In Verbindung mit Zufallszahlen lassen sich hübsche Effekte erzielen, etwawillkürlich gesetzte Ovale unterschiedlicher Größen und Farben:

; OVAL3.BBGraphics 640,480SetBuffer BackBuffer()ClsFor I=1 To 100 Color Rand(255), Rand(255), Rand(255) Oval Rand(640), Rand(480), Rand(100), Rand(100)NextFlipWaitKey

Mit relativ wenig Aufwand erstellen Sie auf diese Weise eine einfache Zeichnung:

; HAUS1.BBGraphics 640,480SetBuffer BackBuffer()ClsColor 0,0,255Cls

; WieseColor 0,255,0Rect 0,440,640,40,1

; SonneColor 255,255,0Oval 500,100,50,50

; HausColor 0,0,127Rect 100,290,200,150,1

; 2 BäumeColor 50,0,0Rect 450,320,15,120Rect 520,330,15,110Color 0,200,0

Nur in Grafikmodi mit 24 Bit (= 3 Byte) und mehr Farbtiefe werden die RGB-Anteileso gemischt, wie Sie es vorgesehen haben, da für jede der drei Grundfarbe ein Bytezur Verfügung steht. Weil bei 16 Bit weniger Kombinationen möglich sind, erhaltenSie eine Annäherung an die gewünschten Werte. Falls Sie es genauer wissen wollen:Bei einer Farbtiefe von 16 Bit werden jeweils fünf Bit auf Rot und Blau sowie sechsBit auf Grün verteilt. Daraus ergibt sich, dass Rot und Blau nur 32 Abstufungen ha-ben (von 0 bis 248, im Abstand von 8). Grün hat 64 Abstufungen (von 0 bis 254, imAbstand von 4). Mit diesem Wissen können Sie Farben verwenden, die im 16-Bit-Mo-dus exakt so dargestellt werden, wie Sie es vorgesehen haben.

Page 113: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

113

Aufgaben j e t z t l e r n e i c h

Oval 433,280,50,60Oval 503,290,50,60

FlipWaitKey

Abb. 7.3:Einfache Strich-grafik, erstellt mit Zeichen-befehlen.

Diese Zeichnung können Sie nun beliebig um weitere Elemente, etwa einen Zaun, Tü-ren und Fenster, ein Schrägdach und Sonnenstrahlen, ergänzen. Sie bekommen dabeiein Gefühl für Farbwerte und festigen Ihre Erfahrung im Umgang mit Koordinaten.Greifen Sie ruhig zum Taschenrechner, um bestimmte Abstände zu ermitteln.

7.3 Aufgaben

1. Zeichnen Sie im Grafikmodus eine Sinus-Kurve.

2. Zeichnen Sie ein Oval, das alle vier Seiten des Bildschirms berührt.

3. Erweitern Sie das Haus-Beispiel um eine kleine Animation, etwa ein vorbeifahren-des Auto (wofür ein Rechteck genügt).

Page 114: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 115: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

115

jetz

t le

rne

ich

KAPITEL 8

Bilder

Theoretisch könnten die Bilder während des Programmlaufs (in »Echtzeit«) gezeichnetwerden; wenige Befehl genügen, um Punkte, Vierecke und Kreise entstehen zu lassen.In der Praxis ist es aber zu aufwendig, etwa die Spielfigur an jeder Position von Grundauf neu entstehen zu lassen. Hier verwendet man ein Bild, das den kompletten Körperzeigt. Mit einem Befehl wird es in den Arbeitsspeicher geladen und kann nun vielfältigeingesetzt werden.

Bilddateien liegen in den verschiedensten Formaten (GIF, BMP, JPG, TIF ...) vor. MitBlitz Basic können Sie nur drei von ihnen verwenden: BMP, JPG und PNG. Das istaber nicht weiter tragisch, weil sich ein Format leicht in das andere umwandeln (kon-vertieren) lässt.

BMP steht für Bitmap. Dieses Format ist der Klassiker unter den Bildformaten. Es ent-spricht ungefähr dem Speicherabbild des Dargestellten und ist besonders einfach auf-gebaut. Dafür benötigt BMP relativ viel Speicher, vor allem, wenn die Grafik bild-schirmfüllend ist. BMP ist in 2 (schwarzweiß), 16, 256 und 16,7 Millionen Farbenmöglich. Die Demo von Blitz Basic unterstützt nur BMP, keine anderen Formate.

JPG (bzw. JPEG) ist die Abkürzung für Joint Photographic Experts Group. Das For-mat wird vor allem dazu eingesetzt, um digitale Fotos möglichst platzsparend abzuspei-chern. Die Bilder werden auf Kosten der Qualität zusammengepresst. Je nachdem,welcher Kompressionsgrad verwendet wird, schrumpft eine BMP-Datei als JPG auf einHundertstel zusammen. JPG-Bilder haben grundsätzlich 16,7 Millionen Farben.

PNG, Portable Network Graphics, ist ein relativ neues Format. Es wurde 1995 entwi-ckelt und sollte als Nachfolger von GIF zum Standard für Webgrafiken werden. Bis heu-te hat es jedoch bei weitem nicht die Popularität seines Vorbilds erreicht. Für Blitz Basicist PNG gut geeignet, da es verlustfrei arbeitet und dennoch komprimiert wird, also we-niger Speicher als ein Bitmap einnimmt. PNG unterstützt Farbtiefen bis zu 48 Bit proBildpunkt.

Page 116: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

116

Bilder8j e t z t l e r n e i c h

1

Um eine Bilddatei zu bewegen, muss sie zunächst vorhanden sein. Programmierkennt-nisse allein genügen nicht, um ein Spiel zu entwerfen: Musikstücke müssen kompo-niert und Toneffekte gesammelt werden, in erster Linie müssen aber Grafiken entste-hen. Mit etwas Übung und einem normalen Grafikprogramm, wie es etwa jederWindows-Version beiliegt, gelingen bereits respektable Ergebnisse. Viele Spielen ent-stehen in Arbeitsteilung. Vielleicht hilft Ihnen ein talentierter Bekannter.

Egal, mit welchem Format Sie arbeiten, Blitz Basic wandelt intern jede Grafik in einBitmap um. Komprimierte Formate sparen daher nur Platz auf der Festplatte, nichtim Arbeitsspeicher. Mit dem kostenlosen Werkzeug IrfanView (www.irfanview.de,auf der Buch-CD) führen Sie schnell Umwandlungen von einem Format ins anderedurch. Mit diesem Werkzeug ändern Sie außerdem Größe und Farbtiefe von Grafik-dateien.

Matthias Hampel, www.blitz2d.de: »Als Hobby-Spieleprogrammierer haben Sie oftnicht die Möglichkeit, teure Software zu kaufen oder einen Grafiker für Ihr Projekteinzustellen. Eine Alternative sind kostenlose Bilder aus dem Internet. UnzähligeWebsites bieten Material an, das kostenlos verwendet werden darf. Die deutscheBlitz-Basic-Gemeinschaft bietet auf www.blitzbasic-pc.de eine kleine Sammlung anGrafiken an. Eine deutlich größere Galerie wartet auf www.3dcafe.com. Weitere Sei-ten nennt Ihnen die Linkliste auf www.blitz2d.de. Wenn Sie Texturen als Hinter-grundmuster verwenden, sollten Sie darauf achten, dass sie kachelbar sind, also sichzusammensetzen lassen, ohne dass der Spieler sieht, dass sich die Textur wiederholt.Als Format für Grafiken und Texturen aller Art eignet sich am besten das PNG-For-mat. Es hält die Dateigröße klein, ohne dass Sie Einbußen an der Qualität hinnehmenmüssen. Achten Sie auf die Nutzungsbedingungen beim Verwenden fremder Grafi-ken. Manche Bilder lassen sich völlig frei verwenden, einige nicht für kommerzielleSpiele, und manchmal erwartet der Autor das Nennen seines Namens – was aber be-reits der Anstand gebietet.«

Reiner Prokein, www.reinerstileset.de: »Wenn Sie niemanden finden, der Grafikenfür Sie erstellt, heißt es: selbst Hand anlegen. Vermeiden sollten Sie es, Bilder aus an-deren Spielen zu »borgen«. Sie verletzen damit das Urheberrecht des Erzeugers. Undselbst wenn Sie seine Genehmigung haben: Ihr Spiel erhält keinen einmaligen Cha-rakter und sieht »zusammengestoppelt« aus. Es gibt mehrere Wege, eigene Grafikenzu erstellen:

1. Sie malen auf Papier und scannen Ihr Werk ein.

2. Sie verwenden für Objekte und Hintergründe ein Malprogramm. Im einfachstenFall genügt sogar das Windows beiliegende Paint.

3. Sie begeben sich in die Tiefen des Modellierens, Renderns und Raytracings, umdreidimensionale Objekte zu gestalten.

Page 117: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

117

Bild laden j e t z t l e r n e i c h

8.1 Bild laden

Bevor Sie eine Bilddatei anzeigen, laden Sie sie von der Festplatte mit LoadImage() inden Arbeitsspeicher. Dabei erhalten Sie von Blitz Basic eine Kennziffer (englisch:Handle), die Sie in einer Variablen speichern. Allein über diese Kennziffer sprechenSie das Bild später an:

bild = LoadImage("cow.bmp")

Falls die Kennziffer den Wert 0 hat, konnte die Datei nicht geladen werden. Sie solltendaher eine Sicherheitsabfrage einbauen ...

If bild = 0 Then Print "Fehler! Bilddatei nicht gefunden."

... und das Programm abbrechen.

Wenn ein Bild nicht mehr benötigt wird, sollten Sie es mit FreeImage aus dem Speicherlöschen:

FreeImage bild

1

Ich bevorzuge das dritte Verfahren. Gemaltes erfordert einen immensen Aufwand,egal ob am Bildschirm oder auf dem Papier. Andererseits benötigt ein Renderpro-gramm einige Übung und Einarbeitung, bis etwas Brauchbares zustande kommt. Wieman es also dreht und wendet: Grafik ist und bleibt der aufwendigste Teil. Das sollteSie aber nicht entmutigen. Versuchen Sie, eigene Grafiken zu erstellen und in IhrenProgrammen zu verwenden. Jeder, der Bilder bastelt, hat einmal damit angefangen.Suchen Sie den Kontakt zu einschlägigen Internetforen, stellen Sie Fragen. Alle Pro-grammierforen haben auch einen Grafikbereich.

Das Referenzprogramm für 3D-Modelle ist 3ds max von Discreet (www.discreet.de).Allerdings ist es mit einem Preis von 4000 Euro zum Ausüben eines Hobbys eineüberzogene Anschaffung. Ich verwende Truespace von Caligari (www.softline.de).Die aktuelle Version ist mit 300 Euro gleichfalls nicht billig, doch ältere Versionen gibtes schon für einen Bruchteil des Preises (über bhv, www.bhv.de).

Das Kopieren anderer Ideen ist ein brauchbarer Weg für den Anfang. Doch wenn Sieden Bogen heraushaben, sollten Sie Ihren eigenen Stil entwickeln. Nur dadurcherhalten Ihre Spiele einen unverwechselbaren Charakter. Erstellen Sie liebenswerteFiguren. Achten Sie darauf, dass Objekte einen Schatten in immer die gleiche Rich-tung werfen und die gleiche Neigung haben. Auch die Größenverhältnisse unterein-ander wollen beachtet werden.«

Wenn Sie Ihr Spiel weitergeben, dann dürfen Sie die Bild- und Klangdateien nichtvergessen. Sie werden beim Kompilieren nicht Bestandteil der EXE-Datei. Für dieBeispiele im Buch verwende ich nur die Beispielbilder, die mit Blitz Basic mitgeliefertwerden. Es sind mehr als hundert, ausreichend für eigene Experimente. Sie sind, jenach Version von Blitz Basic, im Unterordner HELP\RESOURCES\SAMPLES\GRAPHICS, HELP\SAMPLES\GRAPHICS oder EXTRAS\GRAPHICS abge-legt. Alle Bilder, die ich verwendet habe, sind zusätzlich im gleichen Ordner wie dieBeispiellistings untergebracht. So lassen sich die Programme ohne weitere Vor-kehrungen starten.

Page 118: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

118

Bilder8j e t z t l e r n e i c h

8.2 Bild anzeigen

Gezeichnet wird eine zuvor geladene Bilddatei mit dem Befehl DrawImage. Dieser Be-fehl benötigt die Kennziffervariable sowie die Koordinate des oberen linken Bildpunkts:

DrawImage bild, 100, 100

Ein einfaches Beispiel, um ein Bild darzustellen, sieht daher so aus:

Graphics 640, 480SetBuffer Backbuffer()bild = LoadImage("cow.bmp")DrawImage bild, 100, 100FlipWaitKey

So wenig Zeilen und schon »glotzt« uns ein Tier vom Bildschirm an. Das lassen wir unsgleich mit einer ganzen Herde gefallen:

; KUH1.BBGraphics 640, 480SetBuffer BackBuffer()Clsbild = LoadImage("cow.bmp")For I=1 To 30 DrawImage bild, Rand(600), Rand(440)NextFlipWaitKey

Abb. 8.1:Mit nur wenigenZeilen lässt sichder Bildschirmmit vielen Gra-

fiken füllen.

Page 119: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

119

Bildgröße ermitteln j e t z t l e r n e i c h

Vielleicht sollten wir eine Kuh über den Bildschirm wandern lassen. Dazu müssten wirin einer Schleife die Position der Kuh ändern. Damit die alten Kühe verschwinden, lö-schen wir innerhalb der Schleife den Bildschirm, bevor wir erneut zeichnen. Es emp-fiehlt sich eine Pause nach jedem Schritt, sonst erleben wir den Spaß gar nicht, weil erviel zu schnell vorbei ist:

; KUH2.BBGraphics 640, 480SetBuffer BackBuffer()bild = LoadImage("cow.bmp")For I=1 To 10 Cls DrawImage bild, I*50, 200 Flip Delay 300NextWaitKey

1Soll immer nur das gleiche Bild nacheinander gezeichnet werden, nehmen Sie den Be-fehl TileBlock. Er zeichnet ein Bild so lange, bis der gesamte Bildschirm gefüllt ist:

; TILE.BBGraphics 640, 480SetBuffer BackBuffer()bild = LoadImage("stars.bmp")TileBlock bildFlipWaitKey

8.3 Bildgröße ermitteln

Eine Bilddatei hat eine festgelegte Größe. Das Bild ist eine bestimmte Punktzahl breitund hoch. Normalerweise kennen Sie das Format der Bilddateien in Ihren Spielen, wosie sich doch exakt in das Spielgeschehen eingliedern müssen. Jede Software zur Gra-fikbearbeitung nennt Ihnen die Maße, doch mit zwei Funktionen erfahren Sie die Wer-te auch: ImageWidth() benennt die Breite eines Bilds in Punkten, ImageHeight() liefertseine Höhe.

; MASZE.BBGraphics 640, 480SetBuffer BackBuffer()Clsbild = LoadImage("cow.bmp")Print "Höhe des Bilds: " + ImageWidth(bild)Print "Breite des Bilds: " + ImageHeight(bild)FlipWaitKey

Bilddateien sind immer rechteckig, selbst wenn das Motiv eine Sonne oder einenBaum darstellt. Stellen Sie sich vor, dass jedes Bild auf einem Blatt Papier eingezeich-net ist: Nicht (nur) das Bild, sondern das ganze Blatt ist auf dem Monitor zu sehen.

Page 120: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

120

Bilder8j e t z t l e r n e i c h

8.4 Bildgröße verändern

Blitz Basic kann die Größe eines Bilds verändern, sie etwa verdoppeln. Man nennt die-sen Vorgang Skalieren. Blitz Basic stellt dafür den Befehl ScaleImage zur Verfügung.Jeweils ausgehend vom Wert 1 für die Originalbreite und Originalhöhe legen Sie denVeränderungsfaktor fest: 2 entspricht einer Verdoppelung, 3 bedeutet eine Verdreifa-chung, 0.5 eine Halbierung der Größe.

; KUH3.BBGraphics 640, 480SetBuffer BackBuffer()Clsbild = LoadImage("cow.bmp")ScaleImage bild, 2, 2DrawImage bild, 100, 100FlipWaitKey

Alternativ zu diesem Befehl geben Sie an, wie breit und wie hoch das Bild in Punktensein soll. ResizeImage arbeitet ähnlich wie ScaleImage. Statt des Zoomfaktors teilen Siehier aber die genaue Größe des Bilds mit:

; KUH4.BBGraphics 640, 480SetBuffer BackBuffer()Clsbild = LoadImage("cow.bmp")ResizeImage bild, 200, 200DrawImage bild, 100, 100FlipWaitKey

1

8.5 Bild drehen

Auf ähnlich einfache Weise drehen Sie mit RotateImage ein Bild. Dabei geben Sie denDrehwinkel im Uhrzeigersinn an. 0 Grad steht für das Originalbild; 360 Grad bedeuteneine volle Drehung (und damit wieder das Originalbild). 180 Grad stellen ein Bild aufden Kopf, 90 und 270 Grad legen es zur Seite:

RotateImage bild, 180

Wenig Aufwand bedarf es, um mit einer For-Schleife nette Dreheffekte zu erstellen:

; KUH5.BBGraphics 640, 480SetBuffer BackBuffer()Clsbild = LoadImage("cow.bmp")

Beide Befehle verändern ein zuvor geladenes Bild im Speicher. Sie zeigen es nicht an.Die Verfahren arbeiten recht langsam. Ich empfehle Ihnen stattdessen, mit einer Gra-fiksoftware die Bilder vor ihrer Verwendung an die gewünschte Größe anzupassen.Zu einem dritten Befehl kommen wir später: Mit LoadBuffer spannen Sie ein Bildüber die gesamte Bildschirmfläche, wobei es notfalls vergrößert wird.

Page 121: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

121

Bild drehen j e t z t l e r n e i c h

For I=1 To 8 RotateImage bild, 45 DrawImage bild, 320, 240 Flip Delay 100NextWaitKey

Abb. 8.2:Das Rotieren von Grafiken ist sehr langsam. Empfehlens-wert ist es, die Bilder vorzu-berechnen, mit Grafiken zu ar-beiten, in denen die gewünschte Position bereits eingebrannt ist.

Sie erkennen daran gut, dass sich das Bild nicht um seinen Mittelpunkt dreht, sondernum seine linke obere Ecke. DrawImage zeichnet das Bild nicht an die angegebenen Ko-ordinaten, sondern im gewünschten Winkel zum Originalbild. Wenn Sie das Bild etwaum 180 Grad drehen, dann erscheint es so, als ob es nach oben geklappt würde. DerDrehwinkel steht nicht in Beziehung zum Originalbild, sondern zum Zustand der letz-ten Drehung. Das heißt, zweimal um 90 Grad gedreht:

RotateImage bild, 90RotateImage bild, 90

hat die gleiche Wirkung wie einmal um 180 Grad gedreht:

RotateImage bild, 180

0RotateImage arbeitet sehr langsam. Etwas schneller geht es, wenn Sie mit TFormFil-ter 0 die Kantenglättung bei schrägen Linien (Antialiasing) abschalten. Dadurch ver-meiden Sie zugleich Verfälschungen durch fortwährendes Drehen und Glätten. DasDeaktivieren des Filters hat ebenfalls Auswirkungen auf ResizeImage und ScaleImage.Mit TFormFilter 1 setzen Sie den Zustand auf seinen schöneren Standardwert.

Page 122: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

122

Bilder8j e t z t l e r n e i c h

8.6 Bezugspunkt ändern

Der Bezugspunkt eines Bilds ist normalerweise links oben. Zeichnen Sie ein Bild an dieStelle 100,100, dann wird sein linker oberer Punkt an diese Position gesetzt.

Um ein Bild so zu positionieren, dass ein Punkt seine Mitte trifft, müssten Sie sein Zen-trum berechnen. Das ist nicht weiter schwer (Sie müssten nur seine Maße halbieren),aber Blitz Basic nimmt Ihnen mit MidHandle die Arbeit ab. Mit MidHandle bestimmenSie, dass sich der Bezugspunkt eines bestimmten Bilds in der Mitte befindet:

MidHandle bild

Wenn Sie den Befehl dem Beispiel mit der sich drehenden Kuh hinzufügen, ...

; KUH6.BBGraphics 640, 480SetBuffer BackBuffer()Clsbild = LoadImage("cow.bmp")MidHandle bildFor I=1 To 8 RotateImage bild, 45 DrawImage bild, 320, 240 Flip Delay 100NextWaitKey

... dreht sich die Kuh um ihren Mittelpunkt.

Gefällt Ihnen das so gut, dass jedes Bild den Bezugspunkt in der Mitte haben soll? Pro-bieren Sie es damit:

AutoMidHandle 1

Soll der Bezugspunkt für jedes Bild wieder links oben sein, machen Sie die Aktion rück-gängig:

AutoMidHandle 0

Mit wahlweise der ersten Ecke oder der Mitte als Bezugspunkt kann man gut leben.Falls Sie dennoch den Wunsch verspüren, den Bezugspunkt eines Bilds an eine belie-bige Position zu versetzen, hilft Ihnen HandleImage. Sie teilen dem Befehl das ge-wünschte Bild und die Position des Bezugspunkts (innerhalb des Bilds selbst) mit:

HandleImage bild, 10, 10

Die Funktionen ImageXHandle() und ImageYHandle() liefern Ihnen die waagerechte unddie senkrechte Koordinate des Bezugspunkts zurück. Normalerweise werden Sie sienicht benötigen: Standardmäßig ist der Bezugspunkt 0,0. Wenn Sie ihn mittig setzen,dann errechnen Sie den Bezugspunkt ebenso leicht anhand der Größe des Bilds. Undwenn Sie den Bezugspunkt manuell festlegen, dann kennen Sie ja die Werte selbst ambesten. Ein Beispiel verdeutlicht das:

; KUH7.BBGraphics 640, 480bild = LoadImage("cow.bmp")Print ImageXHandle(bild) + "," + ImageYHandle(bild)MidHandle bild

Page 123: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

123

Ausschnitte von Bildern j e t z t l e r n e i c h

Print ImageXHandle(bild) + "," + ImageYHandle(bild)HandleImage Bild, 10, 10Print ImageXHandle(bild) + "," + ImageYHandle(bild)WaitKey

8.7 Ausschnitte von Bildern

Statt eines gesamten Bilds können Sie einen Ausschnitt davon ausgeben. Auf dieseWeise lassen sich viele Teilbilder in einer Datei speichern. Und im Spiel laden Sie nureine Datei, die zwei, fünf, zehn oder zwanzig einzelne Bilder enthält. Stellen Sie sichdabei ein kariertes A4-Blatt vor, das Sie mit einer Reihe von Aufklebern bestücken. Umeinen bestimmten Aufkleber auszuwählen, müssen Sie auf das Blatt zeigen und die Ko-ordinaten des Motivs nennen. Ähnlich funktioniert das mit Grafikdateien, die neben-und untereinander viele einzelne Bilder enthalten können. Viele der Beispieldateien,die Blitz Basic beiliegen, sind gefüllt mit Teilbildern. Eine davon habe ich ausgewählt:

bild = LoadImage("face_32by38.bmp")

Sie enthält sechs Köpfe nebeneinander:

Abb. 8.3:Mehrere Einzel-grafiken in einer Datei.

DrawImage bild, 100, 100

Mit DrawImageRect wählen Sie einen rechteckigen Ausschnitt aus und stellen ihn aufdem Bildschirm dar. Dazu geben Sie neben der Zielposition auf dem Bildschirm die An-fangskoordinaten innerhalb des Bilds an, seine Breite und seine Höhe in Bildpunkten:

DrawImageRect bild, 100, 100, 0, 0, 32, 38

Normalerweise müssten Sie die Größe der Teilbilder erst ermitteln. Dankenswerterwei-se gibt uns in diesem Fall der Dateiname selbst einen deutlichen Hinweis auf das For-mat. Lassen wir 20 Köpfe an zufälliger Stelle auf dem Bildschirm erscheinen:

; AUSSCHNITT1.BBGraphics 640, 480SetBuffer BackBuffer()Clsbild = LoadImage("face_32by38.bmp")For I=1 To 20 DrawImageRect bild, Rand(600), Rand(440), Rand(7) * 32, 0, 32, 38NextFlipWaitKey

Oder wir füllen den gesamten Bildschirm mit Mauerteilen und Böden:

; AUSSCHNITT2.BBGraphics 640, 480SetBuffer BackBuffer()Cls

Page 124: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

124

Bilder8j e t z t l e r n e i c h

bild = LoadImage("Bkgd_Tiles2_16by16.bmp")For I=0 To 624 Step 16 For J=0 To 464 Step 16 DrawImageRect bild, I, J, Rand(7) * 16, Rand(2) * 16, 16, 16 NextNextFlipWaitKey

8.8 Ausschnitt kopieren

Um einen Ausschnitt des Bildschirms an eine andere Stelle zu kopieren (nicht verschie-ben!), verwenden Sie den Befehl CopyRect. Der Befehl erwartet eine Menge Parame-ter:

� Koordinaten X,Y der Quelle

� Breite und Höhe der Quelle

� Koordinaten X,Y der Zielposition

Falls von einem Puffer in den anderen kopiert werden soll, geben Sie zusätzlich an:

� Startpuffer und Zielpuffer

Nehmen wir einen Ausschnitt der Kuh und kopieren ihn an eine andere Position:

; AUSSCHNITT3.BBGraphics 640,480SetBuffer BackBuffer()Clsbild = LoadImage("cow.bmp")DrawImage bild,100,100CopyRect 120,120,50,30,300,300FlipWaitKey

Der Befehl kommt selten zum Einsatz, weil meistens das Bild komplett neu gezeichnetwird. Oft ergibt sich nicht die Situation, eine Kopie eines Bildschirmteils erstellen zumüssen, wenn man die Motive einfach noch einmal zeichnen kann.

Ein sinnvoller Einsatzzweck ist das manuelle Vergrößern und Verkleinern von Bildern.Die Bordmittel von Blitz Basic, ScaleImage und ResizeImage, arbeiten sehr langsam.Daher ist es eine Überlegung wert, ein eigenes Verfahren zu programmieren. Derschnellste Weg: Das Bild wird über zwei Berechnungsstufen in der Größe geändert. Zu-erst strecken oder stauchen Sie die X-Achse, anschließend die Y-Achse. Die Berech-nung erfolgt in For-Schleifen. Sie schneiden das Bild mit CopyRect aus und kopieren essofort. Ein Beispiel finden Sie im Quelltext VERKLEINERN.BB auf der Buch-CD, einzweites als GROESSE.BB. Dort ändern Sie die Größe eines Bilds stufenlos mit derMaus.

Page 125: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

125

Transparenz j e t z t l e r n e i c h

8.9 Transparenz

Schauen Sie sich noch einmal das Bild der Kuh an:

Graphics 640, 480bild = LoadImage("cow.bmp")DrawImage bild, 100, 100WaitKey

Und jetzt erneut, aber mit weißem Hintergrund:

; TRANSPARENZ1.BBGraphics 640, 480SetBuffer BackBuffer()ClsColor 255, 255, 255Clsbild = LoadImage("cow.bmp")DrawImage bild, 100, 100FlipWaitKey

Das Bild der Kuh hat ein rechteckiges Format. Trotzdem wird offenbar nur die Kuhselbst gemalt, weil kein Rahmen sichtbar ist. Sie könnten das Beispiel mit den verschie-densten Farben ausprobieren – jedes Mal nimmt der Hintergrund der Kuh den Hinter-grund des gesamten Bildschirms an, als ob er durchsichtig wäre. Das ganze Geheimnis:Er ist es.

Das Bild der Kuh hat in Wirklichkeit einen schwarzen Rand und das Schwarz zeigt BlitzBasic nicht an, es ist »unsichtbar« oder besser »durchsichtig«. Man nennt dieses Verhal-ten Transparenz. Dieses Verfahren ermöglicht es, dass ein Bild wie »ausgeschnitten«wirkt und damit gut auf jede Art von Hintergrund passt, egal ob dort Himmel, Waldoder Meer gezeichnet ist. Transparenz kommt nicht nur in Spielen vor, sondern wirdhäufig auch in Webseiten eingesetzt, damit ein Bild wie angegossen auf jeden Unter-grund passt.

Das Transparenzverhalten eines Bilds ändern Sie auf zwei Arten:

� Statt Schwarz wählen Sie eine beliebige andere Farbe, die durchsichtig erscheinensoll.

� Wahlweise schalten Sie die Transparenz ganz ab, so dass ein Bild tatsächlich als»Block« gezeichnet wird.

8.9.1 Transparenzfarbe ändernUm eine andere Farbe »durchsichtig« erscheinen zu lassen, nennen Sie dem BefehlMaskImage das gewünschte Bild und den RGB-Wert der transparenten Farbe:

MaskImage bild, rot, grün, blau

Page 126: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

126

Bilder8j e t z t l e r n e i c h

8.9.2 Ohne Transparenz zeichnenUm ein Bild ohne Transparenz zu zeichnen, verwenden Sie statt des BefehlspaarsDrawImage und DrawImageRect die Geschwister DrawBlock und DrawBlockRect. Um dieKuh mit schwarzem Rand zu zeichnen (was natürlich nur sichtbar ist, wenn der restli-che Untergrund nicht schwarz ist), ersetzen Sie einfach DrawImage durch DrawBlock:

; TRANSPARENZ2.BBGraphics 640, 480SetBuffer BackBuffer()ClsColor 255, 255, 255Clsbild = LoadImage("cow.bmp")DrawBlock bild, 100, 100FlipWaitKey

Auch TileImage hat mit TileBlock einen nicht transparenten Gegenpart. Diese Block-befehle arbeiten etwas schneller als Image-Befehle, weil sie den ursprünglichen Hinter-grund nicht erhalten müssen. Im Regelfall werden Sie aber dennoch transparent zeich-nen, wenn sich Ihre Figuren über verschiedene Untergrundmotive bewegen sollen.

8.10 Bildpuffer

Neben dem Backbuffer und dem Frontbuffer gibt es einen dritten Puffer. Er speichertein Bild Ihrer Wahl und wird daher Bildpuffer oder Imagebuffer genannt. Der Sinn:Sie zeichnen in ein Bild. Dazu stehen Ihnen zwei Wege offen:

� Sie laden ein vorhandenes Bild von der Festplatte und verändern es.

� Sie weisen Blitz Basic an, ein Leerbild zu erzeugen, das Sie nach Belieben füllen.

8.10.1 Bild verändernDie erste Methode wird selten verwendet. Üblicherweise ändert man Bilder mit einemGrafikprogramm und legt alle Varianten des Motivs (wie Beschädigungsgrade einesRaumschiffs) bei. Aber wenn ein großes Objekt im Spiel ist, das sich an vielen Stellenbeschießen lässt, ist es sinnvoll, die Einschlagstelle in den Bildpuffer zu lassen, einSchussloch zu zeichnen und das Ergebnis künftig statt des Originalbilds darzustellen.

Mit SetBuffer ImageBuffer(bild) zeichnen Sie direkt in ein Bild. Ich verpasse der Kuheine andere Nase und bilde sie fünfmal ab:

Reiner Prokein, www.reinerstileset.de: »Achten Sie darauf, dass sich nicht ein zugroßer Rahmen mit transparenter Farbe um das eigentliche Bild herum befindet. Derwird zwar im Spiel nicht angezeigt, aber berechnet werden muss er trotzdem. Manch-mal lässt sich das beim Erschaffen der Motive nicht vermeiden. Ich erstelle zum Bei-spiel meine Bilder in einer Größe von 96x96 Punkten, damit ein geschwungenesSchwert nicht einfach abgeschnitten wird. Danach schaue ich mir das Ergebnis anund schneide den überflüssigen Bereich mit der transparenten Farbe wieder weg, sodass das Ergebnis etwa nur 30 x 60 Punkte groß ist. Das verkleinert auch die Dateig-röße.«

Page 127: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

127

Bildpuffer j e t z t l e r n e i c h

; KUH8.BBGraphics 640,480bild = LoadImage("cow.bmp")SetBuffer ImageBuffer(bild)Oval 46,35,11,13;SetBuffer BackBuffer()ClsFor I=0 To 4 DrawImage bild, I*100, I*100NextFlipWaitKey

28.10.2 Ausschnitt in Bild kopierenAnstatt »per Hand« in ein Bild zu zeichnen, können Sie einen Ausschnitt vom Bild-schirm (genauer: vom aktuellen Puffer) in ein Bild kopieren. Wie groß der Ausschnittist, hängt von der Größe des Bilds ab. Füllen Sie den Bildschirm mit Sternen:

; AUSSCHNITT4.BBGraphics 640,480SetBuffer BackBuffer()Clssterne = LoadImage("stars.bmp")TileImage sterne

Laden Sie ein beliebiges Bild:

bild = LoadImage("cow.bmp")

Ersetzen Sie den Inhalt des Bilds durch einen Teil des Bildschirms:

GrabImage bild, 100, 100

Und schauen Sie sich das Ergebnis an:

ClsDrawImage bild, 100, 100FlipWaitKey

8.10.3 Bild kopierenWie sieht es aus, wenn Sie von einem Bild eine veränderte Version erstellen, die Urver-sion aber behalten wollen? Die einfachste Möglichkeit: das Bild einfach zweimal laden:

bild1 = LoadImage("cow.bmp")bild2 = LoadImage("cow.bmp")

Alternativ kann man in Blitz Basic mit CopyImage() ein geladenes Bild kopieren:

bild1 = LoadImage("cow.bmp")bild2 = CopyImage(bild1)

Diese Variante ist etwas schneller.

Vergessen Sie nicht, nach der Arbeit mit dem Imagebuffer wieder den Back- oderFrontbuffer einzustellen, um wieder auf den Bildschirm zu zeichnen.

Page 128: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

128

Bilder8j e t z t l e r n e i c h

8.10.4 Bild erzeugenMit CreateImage() erstellen Sie ein »leeres« Bild, einen Rahmen, in den Sie zeichnen.Der Befehl erwartet die Breite und die Höhe.

bild = CreateImage()

Oft werden Sie den Befehl nicht brauchen. Im Notfall erstellen Sie damit kleinere Gra-fiken, die Sie abspeichern und später im Spiel als fertige Bilder laden – aber ich rate Ih-nen davon ab, diese Grafiken erst während des Spielablaufs zu erzeugen.

Der Befehl ist außerdem dabei behilflich, einen Ausschnitt einer Grafik auszuschneidenund als eigenständige Datei abzuspeichern. Auf diese Weise lassen sich Einschuss-löcher in einem Spielstand ablegen. Wie das funktioniert, zeige ich Ihnen anhand derDatei INVADER2.BMP. Sie enthält eine Reihe von Objekten, und wir werden uns darauseine Rakete entnehmen. Die Position der Rakete innerhalb des Bilds (Koordinaten35,240) und seine Größe (34 Punkte breit, 31 lang) erfahren Sie leicht mit einem Gra-fikprogramm – ansonsten durch Probieren.

; BILD_ERZEUGEN.BBGraphics 640,480bild = LoadImage("invader2.bmp")bild2 = CreateImage(34,31)SetBuffer ImageBuffer(bild2)DrawImageRect bild, 0, 0, 35,240,34,31

Nun haben wir ein Bild (bild2), das nur die Rakete enthält:

SetBuffer BackBuffer()For I=480 To 0 Step -1 Cls DrawImage bild2, 305, I FlipNext

8.10.5 Bild speichernMit SaveImage speichern Sie ein Bild als Grafikdatei (.BMP) auf die Festplatte. Dasfunktioniert mit jeder Art von Bild, macht aber freilich nur Sinn mit Bildern, die Sie erstwährend der Laufzeit des Programms erzeugt oder verändert haben. Probieren wir esgleich mit unserer ausgeschnittenen Rakete aus:

; BILD_SPEICHERN.BBGraphics 640,480bild = LoadImage("invader2.bmp")bild2 = CreateImage(34,31)SetBuffer ImageBuffer(bild2)DrawImageRect bild, 0, 0, 35,240,34,31;SaveImage bild2, "rakete.bmp"

Mit diesem Programm wird sie dauerhaft als RAKETE.BMP abgelegt.

1 SaveImage() als Funktion liefert Ihnen den Wert 0, wenn die Datei nicht gespeichertwerden konnte, weil die Festplatte voll ist oder in ein Verzeichnis auf CD geschriebenwerden soll.

Page 129: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

129

Puffer abspeichern j e t z t l e r n e i c h

8.10.6 Bild in Puffer ladenMit LoadBuffer laden Sie ein Bild so in einen Puffer, dass es ihn ausfüllt. Dabei wird esnotfalls vergrößert oder auch verkleinert. Der Befehl eignet sich dazu, um Titelbilder,Abspann-Bildschirme und Ähnliches darzustellen:

Graphics 640, 480LoadBuffer FrontBuffer(), "cow.bmp"WaitKey

Da Blitz Plus das direkte Schreiben in den Frontbuffer nicht mehr unterstützt, müssenSie das Bild in den Backbuffer kopieren und dann umschalten.

Graphics 640, 480LoadBuffer BackBuffer(), "cow.bmp"FlipWaitKey

Freilich könnten Sie dazu normalerweise DrawImage verwenden. Sinnvoller ist LoadBuf-fer in Zusammenhang mit dem Bildpuffer. Leicht kopieren Sie ein ganzes Bild oder ei-nen Teil davon in ein neues Bild:

; BILDPUFFER1.BBGraphics 640,480bild1 = LoadImage("cow.bmp")bild2 = CreateImage(50,50)SetBuffer ImageBuffer(bild2)DrawImage bild1, 0,0SetBuffer BackBuffer()ClsDrawImage bild2, 100, 100FlipWaitKey

8.11 Puffer abspeichern

Ein Puffer lässt sich als Grafikdatei (.BMP) auf der Festplatte ablegen. Für den Front-und den Backbuffer wäre das ein Screenshot, ein Foto des ganzen Bildschirms. ZumEinsatz kommt dabei der Befehl SaveBuffer, dem Sie den gewünschten Puffer und denNamen der zu erstellenden Datei übergeben:

SaveBuffer FrontBuffer(),"screenshot.bmp"

1Der Bildpuffer lässt sich ebenfalls als Datei ablegen. Genau genommen handelt es sichdabei um eine etwas umständlichere Alternative zu SaveImage:

SaveBuffer() als Funktion liefert Ihnen den Wert 0, wenn die Datei nicht gespeichertwerden konnte – weil die Festplatte voll ist oder in ein Verzeichnis auf CD geschrie-ben werden soll.

Page 130: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

130

Bilder8j e t z t l e r n e i c h

; BILDPUFFER2.BBGraphics 640,480bild = LoadImage("invader2.bmp")bild2 = CreateImage(34,31)SetBuffer ImageBuffer(bild2)DrawImageRect bild, 0, 0, 35,240,34,31SaveBuffer ImageBuffer(bild2),"rakete.bmp"

8.12 Aufgabe

1. Erstellen Sie ein Bild in der Größe 640x480. Als Motiv verwenden Sie 100 zufälligplatzierte Kuhköpfe vor einem grünen Hintergrund. Speichern Sie das Bild alsBitmap-Datei auf der Festplatte ab.

Page 131: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

131

jetz

t le

rne

ich

KAPITEL 9

Sichtfenster und Aufsätze

Häufig nimmt das Spielgeschehen nicht den gesamten Bildschirm ein. Oft ist das Spiel-feld umzäunt, so dass oben und unten Platz für allerlei Anzeigen bleibt. Blitz Basic er-laubt es Ihnen, einen Rahmen festzulegen, ein Sichtfenster, auf das die Grafikausgabebeschränkt wird. Egal, was und wo Sie zeichnen wollen: Blitz Basic malt nur in dem Be-reich innerhalb des Rahmens. Grafiken außerhalb des Rahmens werden ausgeblendet.Diese Begrenzung wird ViewPort genannt und genauso heißt der Befehl, der ihn fest-legt:

ViewPort 100,100,150,150

Genau wie beim Befehl Rect legen Sie die Startkoordinaten sowie die Länge des Rah-mens fest. Wiederholen wir unser Beispiel mit den bunten Ovalen, beschränken jedochdie Ausgabe auf ein Fenster:

; VIEWPORT.BBGraphics 640,480SetBuffer BackBuffer()ClsViewport 100,100,439,279SeedRnd MilliSecs()For I=1 To 1000 Color Rand(255), Rand(255), Rand(255) Oval Rand(640), Rand(480), Rand(50), Rand(50)NextFlipWaitKey

Dieser einfache Befehl eröffnet eine Vielzahl von Erleichterungen und Möglichkeiten.Als Programmierer eines Spiels müssen Sie nicht darauf achten, ob etwa der Begren-zungsrahmen versehentlich übermalt wird. Unterstützend kommt hinzu, dass Sie denViewPort jederzeit ändern können. So schalten Sie blitzschnell vom Spielfeld auf einenoberen Rahmen, um dort zum Beispiel die Punktzahl zu aktualisieren. Meist ist es je-doch einfacher, selbst darauf zu achten, dass nur in einem bestimmten Fenster gezeich-net wird.

Page 132: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

132

Sichtfenster und Aufsätze9j e t z t l e r n e i c h

Einen kleinen Nachteil hat ein ViewPort. Arbeiten Sie im Vollbildmodus, hat der Punktlinks oben die Koordinaten 0,0. Verwenden Sie einen ViewPort, ist der Startpunkt desRahmens nicht 0,0, sondern vielleicht 100,100, und Sie müssen nach unten und zurSeite immer 100 Punkte addieren, um relativ vom Startpunkt des ViewPort zu eineranderen Stelle zu gelangen: Beginnt der ViewPort ab 100,100, dann sind die Vollbild-koordinaten 150,150 gleichzusetzen mit den Koordinaten 50,50 innerhalb des View-Port. Damit lässt sich leben, aber es erschwert die Arbeit ein wenig. Besser wäre es,wenn der Startpunkt eines ViewPort die Koordinaten 0,0 hätte.

Zu diesem Zweck gibt es den Befehl Origin. Er versetzt die Koordinaten 0,0 um einevon Ihnen vorgegebene Punktzahl. Wenn Sie etwa:

Origin 100,100Plot 0,0

angeben, dann wird der Punkt an die Stelle 100,100 gesetzt. Origin macht nichts an-deres, als zu allen verwendeten Koordinaten einen festen Wert zu addieren, einen sogenannten Offset.

Ein sinnvoller Einsatzpunkt von ViewPorts sind Multiplayer-Spiele an einem Monitor,bei denen der Bildschirm geteilt wird. Bei diesen so genannten Split-Screen-Spielenhat jeder Teilnehmer eine eigene Darstellung der Spielsicht. Der Origin-Befehl erleich-tert dabei das mehrfache Zeichnen. Es muss lediglich der Offset geändert werden, dieeigentlichen Zeichenbefehle sind für jede Darstellung gleich. Ich habe unser kleinesHaus-Beispiel entsprechend angepasst:

; HAUS2.BBGraphics 640,480SetBuffer BackBuffer()ClsColor 0,0,255ClsFor X=0 To 1 For Y=0 To 1 Origin X*320, Y*240

; Wiese Color 0,255,0 Rect 0,220,320,20,1

; Sonne Color 255,255,0 Oval 250,50,25,25

; Haus Color 0,0,127 Rect 50,145,100,75,1

; 2 Bäume Color 50,0,0 Rect 225,160,7,60 Rect 260,165,7,55 Color 0,200,0 Oval 216,140,25,30 Oval 251,145,25,30 NextNextFlipWaitKey

Page 133: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

133

Aufgabe j e t z t l e r n e i c h

Abb. 9.1:Gleiche Koordi-naten, aber vier verschiedene Positionen dank Offsets.

Mein Ziel war es, das Bild gleich viermal auf den Monitor zu bannen. Dazu habe ich eszunächst auf ein Viertel der ursprünglichen Größe gestaucht, indem ich die Längen-und Breitenangaben der Vierecke und Ovale halbierte. Mithilfe von zwei verschachtel-ten For-Schleifen, die jeweils zweimal ausgeführt werden, wird das Bild an vier ver-schiedenen Stellen gemalt.

1

9.1 Aufgabe

1. Teilen Sie den Bildschirm durch eine Mittellinie in zwei gleich große Bereiche. Fül-len Sie jeden Teilbereich mit einem (riesigen) Kuhkopf aus.

SetBuffer setzt Origin und ViewPort des angegebenen Puffers auf ihre Standardwer-te. Das heißt, der Aufsatz wird in die linke obere Ecke (0,0) zurückbeordert und derAnzeigerahmen ist so groß wie der gesamte Bildschirm. Origin hat keinen Einflussauf die Koordinaten, die von Mausbefehlen zurückgegeben werden. Deren X- undY-Werte beziehen sich immer auf den gesamten Bildschirm.

Page 134: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 135: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

135

jetz

t le

rne

ich

KAPITEL 10

APixeleien

Dieser Abschnitt beschreibt das Lesen und Schreiben einzelner Bildpunkte. Für diemeisten Spiele wird dieses Wissen nicht notwendig sein. Fortgeschrittene können al-lerdings eigene Funktionen zum schnellen Kopieren von Bildschirminhalten program-mieren.

10.1 Rot, Grün, Blau

Jede Farbe besteht aus je einem Anteil Rot, Grün und Blau. Mit Color legen Sie die Zei-chenfarbe fest und zeichnen damit Bildpunkte. Nicht immer ist später bekannt, welcherBildpunkt welche Farbe hat. Um das zu ermitteln, müssten Sie beim Zeichnen die Far-be gleichzeitig in ein Datenfeld eintragen, um sie später auszulesen. Blitz Basic erleich-tert Ihnen das durch eine kleine Gruppe von Befehlen, mit denen Sie erfahren, welcheFarbe ein beliebiger Bildpunkt auf dem Bildschirm hat.

GetColor fragt die Farbe eines Bildpunkts ab und stellt die Zeichenfarbe danach ein:

GetColor 100,100

Der Befehl arbeitet damit ähnlich wie Color, nur dass Sie nicht die Farbe direkt fest-legen, sondern auf einen Punkt auf dem Monitor zeigen und sagen: »So will ich eshaben.«

Welche Farbe das ist, wissen wir noch nicht. Aber wir finden es heraus. Mit dem TrioColorRed(), ColorGreen() und ColorBlue() erfragen Sie die Anteile an Rot, Grün undBlau der aktuellen Zeichenfarbe:

; RGB1.BBGraphics 640,480SetBuffer BackBuffer()ClsSeedRnd MilliSecs()

Page 136: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

136

Pixeleien10j e t z t l e r n e i c h

Color Rand(255), Rand(255), Rand(255)Plot 100,100;GetColor 100,100Text 200,200, "Die Farb-Anteile des Punktes:"Text 200,220, "Rot: " + ColorRed()Text 200,240, "Grün: " + ColorGreen()Text 200,260, "Blau: " + ColorBlue()FlipWaitKey

GetColor arbeitet recht langsam. Wenn Sie den Farbwert von Punkten vielfach erfra-gen, sollten Sie stattdessen ReadPixel() verwenden. Dieser Befehl ist schneller und bie-tet dazu einen Vorteil: Der Farbwert wird in einer Variable gespeichert, muss also nichtnoch mit ColorRed() usw. ermittelt werden.

farbe = ReadPixel (100,100)

Wie bekommt man drei Anteile in einer Variablen, fragen Sie sich? Nun, die RGB-An-teile nehmen einen Wert zwischen 0 und 255 ein, passen damit in ein Byte. Eine nor-male Variable ist aber vier Byte lang. Blitz Basic speichert alle drei Teile in einer Vari-ablen:

1. Byte: 255 (für Profis: in Blitz Basic 3D wird dort der Alpha-Wert abgelegt)

2. Byte: Rotwert

3. Byte: Grünwert

4: Byte: Blauwert

Mit Kenntnis von Hexzahlen und mithilfe von And, mit dem Sie bestimmte Bytes aus-blenden, ermitteln Sie die einzelnen RGB-Werte:

RGB = ReadPixel(X,Y)R = (RGB And $FF0000) / $10000G = (RGB And $FF00) / $100B = RGB And $FF

Oder raffinierter:

RGB = ReadPixel (X,Y)R = (RGB Shr 16) And $FFG = (RGB Shr 8) And $FFB = RGB And $FF

Sie brauchen diese Umrechnung nicht unbedingt, weil es mit WritePixel einen Befehlgibt, der wie Plot einen Bildpunkt zeichnet – mit dem Unterschied, dass Sie zusätzlichdie gewünschte Farbe übergeben, und das in der gleichen Form, wie ReadPixel() dieFarbe ausliest:

RGB = ReadPixel(100,100)WritePixel 200,200, RGB

2Beachten Sie dabei, dass sich die geschriebenen RGB-Werte von den gelesenen un-terscheiden, wenn Sie eine Farbtiefe von weniger als 24 Bit verwenden.

Page 137: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

137

Puffer und Punkte j e t z t l e r n e i c h

Umgekehrt ist es natürlich genauso möglich, aus drei RGB-Werten eine Vier-Byte-Zahlzu errechnen:

RGB = $FF000000 + R * $10000 + G * $100 + B

110.2 Puffer und Punkte

Die Funktionen ReadPixel() und WritePixel dürfen durch die Angabe des Puffers er-gänzt werden:

RGB = ReadPixel(100,100,BackBuffer())

Um einen Punkt schnell von einem Ort zum anderen zu kopieren, verwenden Sie statt

RGB = ReadPixel(100,100)WritePixel 200,200, RGB

kürzer CopyPixel. Da Sie hier zwingend jeweils den Puffer für den Quell- und Zielpunktangeben, lassen sich auf diese Weise einfach Bildpunkte von einem Puffer in den an-deren kopieren:

CopyPixel 100,100,BackBuffer(), 100,100, FrontBuffer()

10.3 Puffer sperren

Die Befehle ReadPixel(), WritePixel und CopyPixel haben die Pendants ReadPixel-Fast(), WritePixelFast und CopyPixelFast, die schneller arbeiten.

Um sie zu benutzen, frieren Sie vorher mit dem Befehl LockBuffer den Puffer ein, aufden der jeweilige Befehl angewandt wird. Als Parameter übergeben Sie den (bzw. beiCopyPixelFast die) zu sperrenden Puffer:

LockBuffer BackBuffer()

Fehlt der Parameter, verwendet Blitz Basic den aktuellen (also mit SetBuffer eingestell-ten) Puffer. Am Ende Ihrer Aktivitäten geben Sie den Puffer mit UnlockBuffer wiederfrei:

UnlockBuffer BackBuffer()

2

Parallel zu WritePixel und ReadPixel() gibt es das Paar WritePixelFast und Read-PixelFast(), zu dem wir später kommen.

Mit den Sperrbefehlen friert Blitz Basic die Zugriffe auf die Puffer ein. Dadurch ent-fallen Sicherheitsabfragen, so dass die Bildpunktbefehle schneller sind. Die Koordi-naten für die Bildpunkte müssen innerhalb des sichtbaren Bereichs liegen. Da BlitzBasic bei den »Fast«-Befehlen nicht die Plausibilität der Koordinaten überprüft, kannes sonst zu Abstürzen kommen. Beachten Sie, dass Sie bei CopyPixelFast notfalls bei-de Puffer sperren müssen. Schnell genug für das flinke Übertragen ganzer Bilder sinddie Befehle übrigens nicht.

Page 138: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

138

Pixeleien10j e t z t l e r n e i c h

1

10.4 Aufgabe

1. Schreiben Sie ein Programm, das in eine Hälfte des Bildschirms zufällig erzeugtebunte Vierecke malt. Erzeugen Sie mithilfe der Pixelbefehle danach eine Kopie derAusgabe auf der anderen Hälfte des Schirms.

In Blitz Plus sind weitere Pixel-Befehle zum Lösen anspruchsvoller Kopieraufgabenhinzugekommen: LockedFormat() ermittelt die Farbtiefe eines Puffers. LockedPitch()nennt die Größe einer Grafikzeile in Byte. Mit LockedPixels() lässt sich der Videos-peicher als Speicherbank frei lesen und beschreiben.

Page 139: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

139

jetz

t le

rne

ich

KAPITEL 11

Text und Fonts

Mit Print und Write zeigen Sie einen Text an. Besonders komfortabel sind die Anwei-sungen nicht: Sie dürfen weder Größe und Ausrichtung noch Ausgabeort oder garSchriftart festlegen. Im Grafikmodus stehen Ihnen viel mehr Befehle zur Verfügung.

11.1 Text

Wesentlich besser geeignet zum Ausgeben von Zeichenketten und Zahlen ist der Be-fehl Text. Er wurde speziell für den Grafikmodus entwickelt und erwartet neben demText auch die Koordinaten, wohin geschrieben werden soll:

Text 80,240, "Dieser Text erscheint in der Mitte des Bildschirms."

Dadurch lassen sich Ausgaben punktgenau steuern, etwa in einen Kasten stecken:

; TEXT.BBGraphics 640,480SetBuffer BackBuffer()ClsText 80,240, "Voila! Dieser Text erscheint in der Mitte des Bildschirms."Rect 74,234,470,23,0FlipWaitKey

Mit der Koordinate geben Sie die linke obere Ecke des Textes an. Alternativ legen Siefest, dass der Text waagerecht oder senkrecht um einen Punkt gemittelt (zentriert) wird.Geben Sie dazu zwei zusätzliche Parameter an, nämlich jeweils für die waagerechteund die senkrechte Achse, ob der Text an ihr gemittelt (1) werden soll oder nicht (0):

Text 200,200, "Um Position 200,200 gemittelt",1,1

Also: Ohne Zentrierungsparameter entsprechen die Koordinaten der linken oberenEcke des Textes. Mit Zentrierungsparametern wird der Text um die Koordinaten ge-mittelt – wahlweise senkrecht und/oder waagerecht.

Page 140: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

140

Text und Fonts11j e t z t l e r n e i c h

Folgendes Beispiel druckt ein kurzes Gedicht auf den Bildschirm, wobei jede Zeile umdie Mittelachse (Pixelspalte 320) zentriert wird:

; ZWÖLFELF.BBGraphics 640,480SetBuffer BackBuffer()ClsColor 0,0,255ClsFor I=1 To 10 Read A$ Text 320, 30*I + 50, A$, 1, 0NextFlipWaitKey;Data "Das Problem"Data "von"Data "Christian Morgenstern"Data ""Data "Der Zwölf-Elf kam auf sein Problem"Data "und sprach: 'Ich heiße unbequem."Data "Als hieß ich etwa Drei-Vier"Data "statt Sieben - Gott verzeih mir!'"Data "Und siehe da, der Zwölf-Elf nannte sich"Data "von jenem Tag an Dreiundzwanzig."

Abb. 11.1:Der Text-Befehl

platziert Zei-chen an jede

Stelle des Bild-schirms.

2Mit Blitz Plus lassen sich Print und Write nicht mehr sinnvoll einsetzen. Ebenfalls»Schnee von gestern« ist der Befehl Locate. Er positioniert den Cursor für Print undWrite, wird aber von Blitz Plus nicht mehr unterstützt und könnte auch in zukünftigenVersionen von Blitz Basic 3D entfallen. Nutzen Sie für den Grafikmodus Text.

Page 141: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

141

Fonts j e t z t l e r n e i c h

11.2 Fonts

Wenn Sie nichts anderes angeben, verwendet Text die Standardschrift. Sie können je-doch eine andere Schriftart verwenden. Voraussetzung ist, dass sie als TTF-Datei vor-liegt. TTF steht für True Type Font und bezeichnet das Format, in dem Windows-Pro-gramme ihre Schriftarten ablegen. Sie werden normalerweise im Windows-OrdnerFONTS abgelegt.

Windows selbst bietet eine Reihe von Fonts, die sich für Spiele eignen. Eine gute Über-sicht liefert Ihnen das Programm Zeichentabelle. Es gehört zum Lieferumfang vonWindows, wird aber standardmäßig nicht eingerichtet. Sie können es von der Win-dows-CD leicht nachträglich installieren. Wählen Sie START/AUSFÜHREN und tippen SieCHARMAP ein, um schnell an das Programm zu gelangen.

Abb. 11.2:Die Zeichen-tabelle von Windows gibt Aufschluss über verfügbare Fonts und das Aussehen aller Zeichen.

1Natürlich lassen sich exotische Schriftarten verwenden. In diesem Fall müssen Sie dieTTF-Datei Ihrem Spiel beilegen, bevor Sie es weitergeben. Beachten Sie dabei, dassFonts urheberrechtlich geschützt sein können; manches Unternehmen lebt allein vomVerkauf hochwertiger Schriftarten. Es gibt zahlreiche Fonteditoren, mit deren Hilfe Sieeigene Fonts erstellen. Im Internet finden Sie Abertausende von kostenlosen Schrift-arten, etwa auf www.grsites.com.

Um Blitz Basic anzuweisen, einen bestimmten Font zu laden, verwenden Sie den Be-fehl LoadFont. Sie erhalten eine Kennziffer zurück. Diese Nummer benötigt der BefehlSetFont. Er stellt den Font ein, der von Text verwendet wird. Also:

1. Einen oder mehrere Fonts mit LoadFont in den Speicher laden.

2. Mit SetFont den Font einstellen, der im Moment verwendet werden soll.

3. Mit Text den Text in der gewünschten Schriftart ausgeben.

11.2.1 Font ladenDem Befehl LoadFont teilen Sie den Namen des Fonts mit, der geladen werden soll.Fontnamen werden in der Auswahlliste der Zeichentabelle und von Textprogrammen

Auch mit Office-Programmen wie Word verschaffen Sie sich einen Eindruck über ver-fügbare Schriften. Übrigens: Word zeigt nur dann alle möglichen Schriften an, wennSie einen Drucker installiert haben.

Page 142: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

142

Text und Fonts11j e t z t l e r n e i c h

wie Word angezeigt. Sie sind nicht unbedingt identisch mit den Namen der TTF-Datei,in der sie gespeichert sind.

0Weil Sie die übergebene Nummer an SetFont weiterleiten müssen, sollten Sie LoadFontmit einer Variablenzuweisung versehen.

2Mit einem zweiten Parameter legen Sie die Schriftgröße fest.

Drei weitere, freiwillige Angaben bestimmen den Schriftschnitt. Mit 1 (für »ein«) und0 (für »aus«) wählen Sie eine Kombination der Erscheinungsformen fett, schräg (kur-siv) und unterstrichen:

Font = LoadFont("Times New Roman",20,1,0,0)

1

Lassen Sie die Parameter für den Schriftschnitt weg, wird der Font »normal« geladen:

Font = LoadFont("Times New Roman",20,1,0,0)

11.2.2 Font verwendenDie Variable Font zeigen Sie SetFont:

SetFont Font

Alle Ausgaben durch Text, Print und Write verwenden nun die Schriftart, die Sie mitSetFont festgelegt haben. Der Text wird in der Farbe gedruckt, die Sie zuvor mit Colorfestgelegt haben.

Ein Beispiel soll die Arbeit mit Schriftarten demonstrieren. Dabei wird zweimal derFont Times New Roman, einmal fett (Font1), einmal normal (Font2), geladen, der Bild-schirm gefärbt und ein Gedicht ausgedruckt. Die Überschrift erscheint fett und blau,der Text normal und rot:

Die Namen der Schriftarten im Windows-Ordner FONTS erfahren Sie, wenn Sie inder Windows-Systemsteuerung das Symbol »Schriftarten« anklicken. Achtung: BlitzBasic kann keine Symbol-Fonts wie WingDings und WebDings laden.

Sollte das Laden des Fonts fehlschlagen, wird ein Standardfont geladen. Da trotzdemeine Kennziffer übergeben wird, können Sie nicht auslesen, ob das Laden funktio-niert hat.

Die Größe der Schrift geben Sie, wie üblich, in Punkt an. Diese Maßeinheit stammtaus dem Schriftsatz. Ein Punkt sind 0,376 Millimeter. Blitz Basic verwendet für Fontskeine Kantenglättung (Antialiasing). Je größer Sie eine Schrift drucken, desto auf-fälliger sind hässliche Treppeneffekte. Meistens verwenden Spiele daher keine True-Type-Fonts, sondern Bitmap-Fonts, bei denen die Buchstaben in Grafikdateien ge-speichert sind. Auf diese Weise sind vielfältige Effekte wie Schatten und 3D möglich.Im Abschnitt Menüs gestalten kommen wir auf Bitmap-Fonts kurz zurück.

Page 143: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

143

Fontgröße ermitteln j e t z t l e r n e i c h

; WIESEL.BBGraphics 640,480SetBuffer BackBuffer()Font1 = LoadFont("Times New Roman",35,1,0,0)Font2 = LoadFont("Times New Roman",30,0,0,0)ClsColor 255,255,0ClsColor 0,0,255SetFont Font1Text 320,50,"Das ästhetische Wiesel",1,0Text 320,100,"von Christian Morgenstern",1,0Color 255,0,0SetFont Font2Text 320,200,"Ein Wiesel saß auf einem Kiesel inmitten Bachgeriesel.",1,0Text 320,250,"Wisst Ihr weshalb?",1,0Text 320,300,"Das Mondkalb verriet es mir im Stillen:",1,0Text 320,350,"Das raffinierte Tier tat’s um des Reimes willen.",1,0FlipWaitKey

Abb. 11.3:Fonts lassen sich in belie-bigen Größen und Farben darstellen.

11.3 Fontgröße ermitteln

Oftmals muss ein Text innerhalb bestimmter Maße liegen. Wenn Sie ihn umrahmenwollen, müssen Sie vorher bestimmen, welche Ausmaße er annimmt. Blitz Basic stelltIhnen dazu zwei Funktionen zur Verfügung.

FontHeight() nennt Ihnen die Höhe des Fonts (genauer: des höchsten Zeichens) inBildpunkten:

Print "Ein Zeichen ist höchstens " + FontHeight() + " Pixel hoch."

Page 144: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

144

Text und Fonts11j e t z t l e r n e i c h

Die Funktion StringWidth(Zeichenkette) ermittelt die Breite einer angegebenen Zei-chenkette, wiederum in Pixeln:

Print "Hausaufgabenheft"Print "Breite in Pixeln: " + StringWidth("Hausaufgabenheft")

Während Ihnen FontHeight() eher im Entwicklungsstadium hilft, um den Platzbedarfvon Texten herauszufinden, unterstützt Sie StringWidth() bei der Automatisierung vonTextausgaben, die einen festgelegten Rahmen nicht überschreiten dürfen. Hierbei sindZeichenkettenbefehle nützlich, um den Text in Häppchen zu unterteilen: Zunächst prü-fen Sie, wie viele Zeichen maximal in eine Zeile passen. Danach gehen Sie bis zumnächsten Leerzeichen zurück, um eine Trennung nicht innerhalb eines Wortes vorzu-nehmen. Nun springen Sie in die nächste Zeile und fahren genauso fort. Alternativ hilftIhnen vor allem StringWidth(), um Zeichenketten verschiedener Längen automatischmit einem passenden (und damit unterschiedlich großen) Rahmen zu versehen.

1

11.4 Font löschen

Falls Sie einen Font nicht mehr benötigen, können Sie ihn wieder »entladen«. Dadurchwird der in Beschlag genommene Speicher freigegeben. Notwendig ist das nicht –heutzutage, wo PCs teilweise über 512 Mbyte Arbeitsspeicher und mehr regieren,dürfte ein Blitz-Basic-Spiel nur einen Bruchteil der verfügbaren Ressourcen beanspru-chen. Der guten Ordnung halber will ich Ihnen dennoch sagen, dass Sie mit FreeFonteinen Font aus dem Speicher löschen:

FreeFont Font

Wie bei SetFont übergeben Sie die Fontnummer als Parameter.

11.5 Aufgabe

1. Schreiben Sie ein Programm, das einen kreisförmigen Text auf den Bildschirmzaubert. Oberer Teil: »Mit diesem Buch«. Unterer Teil: »habe ich viel gelernt!«

Zusätzlich gibt es die Funktionen FontWidth(), um die maximale Breite eines Zei-chens des Fonts auszugeben, und StringHeight(), um die Höhe einer Zeichenkettemitzuteilen. Sie entfielen in der ersten Fassung von Blitz Plus (Version 1.10, ent-spricht der Demo auf der Buch-CD), sind aber aufgrund von Klagen der Nutzer mitdem ersten Update wieder aufgenommen worden. Notwendig sind die Funktionenfreilich nicht: Im Regelfall möchte man ja die Breite eines genau festgelegten Texteserfahren; dabei hilft StringWidth(). Und die Höhe einer Zeichenkette ermitteltFontHeight() genauso gut.

Page 145: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

145

jetz

t le

rne

ich

KAPITEL 12

Maus abfragen

Bisher habe ich die Möglichkeiten der Dateneingabe recht stiefmütterlich behandelt:Mit Input() lassen Sie eine ganze Zeile eingeben; WaitKey wartet auf eine Taste,WaitMouse auf einen Klick. Doch wie fragt man die Maus »richtig« ab?

Die meisten Spiele werden mit der Maus bedient. Lediglich bei einigen Genres ist sieunpraktisch, etwa bei Arcade- und Plattformspielen oder bei Autorennen. Aber auchhier erwartet der Spieler eine Mausbedienung im Hauptmenü und in Einstellungsfens-tern.

Für Sie ist das Einbinden einer Maussteuerung mit etwas Aufwand verbunden. Immer-hin müssen Sie mehrere Posten abarbeiten:

� Herausfinden, an welcher Position sich die Maus befindet

� den Mauszeiger an die aktuelle Stelle setzen

� Abfragen, ob eine Maustaste gedrückt wurde

� Prüfen, ob die Maustaste über einer spielrelevanten Stelle gedrückt wurde, und dieentsprechenden Handlungen ausführen (zum Beispiel: Menüpunkt ausgewählt)

112.1 Drücken von Maustasten ermitteln

WaitMouse wartet nicht nur auf einen Mausklick, sondern teilt Ihnen auch mit, welcheTaste gedrückt wurde. Dazu verwenden Sie den Befehl als Funktion:

Print WaitMouse()

Blitz Basic stellt Ihnen keinen Mauszeiger zur Verfügung; Sie müssen selbst einenzeichnen. Der Mauszeiger von Windows, der zu sehen ist, wenn Ihre Programme imFenstermodus ablaufen, lässt sich nicht steuern.

Page 146: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

146

Maus abfragen12j e t z t l e r n e i c h

Sie gibt den Wert

1 beim Drücken der linken Taste

2 beim Drücken der rechten Taste

3 beim Drücken der mittleren Taste

zurück.

1WaitMouse() wartet so lange, bis eine Taste gedrückt wird. Das ganze Programm wirdso lange angehalten. Für ein Spiel ist dieses Verhalten natürlich selten erwünscht. Da-her wird meistens auf eine andere Funktion zurückgegriffen: GetMouse() liefert Ihnendie Taste zurück, die gerade gedrückt wird. Sie wartet nicht auf Klicks und weiß nicht,was kurz vor ihrem Aufruf gedrückt wurde:

; MAUS1.BBGraphics 640,480SetBuffer BackBuffer()Repeat Cls A = GetMouse() If A = 1 Then Oval 100,200,50,50,1 If A = 2 Then Oval 490,200,50,50,1 If A = 3 Then Oval 295,200,50,50,1 FlipUntil KeyHit(1)

Beim Drücken einer Maustaste wird ein Kreis gezeichnet.

Außerdem können Sie gezielt abfragen, ob gerade eine bestimmte Taste gedrücktwird. Dazu übergeben Sie MouseDown() als Parameter die Taste:

; MAUS2.BBGraphics 640,480SetBuffer BackBuffer()ClsColor 0,255,0ClsFlipRepeatCls If MouseDown(1) Then Rect Rand(0,590), Rand(0,430),50,50,1 Flip EndIf

If MouseDown(2) Then Oval Rand(0,590), Rand(0,430),50,50,1 Flip EndIfUntil KeyHit(1)

Das Beispiel zeichnet an zufälliger Position ein Quadrat, wenn Sie die linke Maustastedrücken – oder einen Kreis, wenn Sie rechts klicken. Halten Sie die jeweilige Taste ge-drückt, um eine ganze Reihe von Formen zu erstellen.

Statt WaitMouse() dürfen Sie auch MouseWait() schreiben. Warum es für diesen Be-fehl zwei Namen gibt – keine Ahnung.

Page 147: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

147

Mausklicks zählen j e t z t l e r n e i c h

212.2 Mausklicks zählen

Mithilfe einer weiteren, seltener benutzten Funktion zählen Sie Tastendrücke.MouseHit() sagt Ihnen, wie oft die angegebene Taste seit dem letzten Aufruf der Funk-tion betätigt wurde. Das folgende Beispiel misst, wie oft die linke Maustaste innerhalbvon fünf Sekunden gedrückt wurde:

; MAUS3.BBGraphics 640,480SetBuffer BackBuffer()ClsDelay 2000Text 200,200, "Los!"FlipA = MouseHit(1)Delay 5000Text 200,200, MouseHit(1) + " Mausclicks in 5 Sekunden"FlipWaitKey

(Mehr als dreißig Mal sollten Sie schon schaffen! :-)

12.3 Mauspuffer löschen

Nach einer solchen Klickorgie ist es möglich, dass Tastendrücke mit in andere Menüsübernommen werden: Der Spieler wechselt etwa mit È ins Menü, wo noch nicht be-arbeitete Klicks aus dem Spiel fälschlich interpretiert werden. Um das zu verhindern,löschen Sie mit FlushMouse den Zwischenspeicher für Mausklicks.

12.4 Mausrad abfragen

Immer mehr Plastiknager haben die mittlere Taste um ein Rad erweitert. In Spielenwird sie gern verwendet, um zum Beispiel Waffen oder andere Gegenstände auszuwäh-len: Mit dem Rad scrollen Sie durch das Inventar.

Die Funktion MouseZ() teilt Ihnen die Position des Scrollrads mit. Die Standardstellungist 0. Jedes Mal, wenn Sie das Rad um eine Stellung nach vorn (in Richtung Monitor)drehen, erhöht sich der Wert (auf 1, 2, 3 ...). Wenn Sie es zurückdrehen, wird er gerin-ger, bis er wieder 0 erreicht und dann ins Negative geht (-1, -2, -3 ...):

; MAUS4.BBGraphics 640,480SetBuffer BackBuffer()Repeat Cls Rect 270,190 - (MouseZ() * 20), 100,100 FlipUntil KeyHit(1) Or MouseDown(1)

Nicht verwechseln: GetMouse() liefert die gedrückte Taste. MouseDown() liefert 1, wenneine bestimmte Taste gedrückt wird.

Page 148: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

148

Maus abfragen12j e t z t l e r n e i c h

Wenn es weniger ausgefeilt sein soll, verwenden Sie MouseZSpeed(). Die Funktion in-formiert Sie nur über die Richtung seit der letzten Änderung:

1 für vorwärts

-1 für rückwärts

0 für keine Bewegung

Damit erfahren Sie, wie das Rad gedreht wurde, nicht wie weit.

2

12.5 Mausposition ermitteln

Das Abfragen der Mausposition ist ebenfalls sehr einfach. Blitz Basic stellt dazu zweiFunktionen zur Verfügung. MouseX() und MouseY() geben die waagerechte und senk-rechte Position der Maus zurück.

1

Folgendes Miniprogramm zeichnet jeweils an der aktuellen Mausposition einen Maus-zeiger. Das Programm wird mit der rechten Maustaste beendet:

; MAUS6.BBGraphics 640,480SetBuffer BackBuffer()maus = LoadImage("pointer.bmp")Repeat Cls X = MouseX() Y = MouseY() DrawImage maus, X, Y FlipUntil GetMouse() = 2

Hm, ein bisschen mehr Pep könnte das Programm vertragen. Wie wäre es, wenn beimDrücken der linken Maustaste etwas passieren würde? Wir wollen (ganz kurz) einenKreis an die Stelle des Mauspunkts zeichnen lassen, wenn die linke Taste gedrücktwird. Dazu fügen wir in das Beispiel folgende Zeile ein:

If GetMouse() = 1 Then Oval X-10, Y-10, 20, 20, 1

In der Version 1.10 von Blitz Plus gibt es ein interessantes Phänomen: Die Funktio-nen MouseZ() und MouseZSpeed() funktionieren nur, wenn im Quelltext auch Mouse-Hit() oder MouseDown() verwendet werden. Vermutlich wurde vergessen, alle Maus-befehle unabhängig voneinander zu initialisieren. Der Bug wurde im ersten Updatekorrigiert.

Die Koordinaten der Maus sind abhängig von der gewählten Auflösung. So ist bei640 x 480 der Mittelpunkt bei 320,240. Bei 1024 x 768 liegt er hingegen bei512,384. Origin hat auf die Werte keinen Einfluss. 0,0 ist also immer die linke obereEcke des Bildschirms.

Page 149: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

149

Mausposition festlegen j e t z t l e r n e i c h

Wir erinnern uns: Oval zeichnet einen Kreis oder ein Oval ausgehend von der linkenoberen Ecke, nicht etwa vom Mittelpunkt aus (wie es in anderen Programmiersprachenüblich ist). Daher habe ich die Startkoordinaten um den halben Durchmesser nach linksund oben korrigiert.

1

12.6 Mausposition festlegen

Der Befehl MoveMouse X,Y verschiebt die Maus an die angegebene Position. Nach demGraphics-Befehl ist die Mausposition auf 0,0, also links oben. Es empfiehlt sich, sie indie Mitte zu verschieben, damit sie sofort gesehen wird:

MoveMouse 320,240

Auch nach dem Öffnen von Fenstern während des Spiels sollten Sie die Maus an einenpassenden Ort versetzen.

A12.7 Mausbewegung feststellen

Die Funktionen MouseX() und MouseY() informieren Sie über die Position der Maus aufdem Bildschirm. Mit zwei ähnlichen Funktionen, MouseXSpeed() und MouseYSpeed(),fragen Sie nicht die tatsächliche Position der Maus ab, sondern ihre Veränderungseit ihrem letzten Aufruf.

MouseXSpeed() liefert Ihnen:

� 0, wenn es keine seitliche Bewegung gab

� einen negativen Wert, wenn sie nach links geschoben wurde

� einen positiven Wert, wenn sie nach rechts geschoben wurde

MouseYSpeed() liefert Ihnen:

� 0, wenn es keine senkrechte Bewegung gab

� einen negativen Wert, wenn sie nach oben geschoben wurde

� einen positiven Wert, wenn sie nach unten geschoben wurde

1

Wenn Sie ein Programm im Fenstermodus ausführen, bleibt der Windows-Mauszei-ger sichtbar. Mit dem Befehl HidePointer machen Sie ihn unsichtbar. ShowPointerstellt ihn wieder dar. Im Vollbildmodus ist der Windows-Zeiger grundsätzlich unsicht-bar.

Unter Windows können Sie einen Beschleunigungswert des Mauszeigers einstellen:Er bewegt sich überdurchschnittlich schnell, wenn Sie die Maus rasch bewegen. Diefestgelegte Strecke auf dem Mauspad ist geringer als die des Zeigers auf dem Bild-schirm. Eine Beschleunigung hat in Blitz Basic keine Wirkung, doch Sie können na-türlich eine programmieren.

Page 150: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

150

Maus abfragen12j e t z t l e r n e i c h

12.8 Aufgabe

1. Schreiben Sie ein kleines Spiel, das für anderthalb Sekunden ein Quadrat entwederin der linken oder in der rechten Hälfte des Bildschirms erscheinen lässt. Der Spie-ler bekommt einen Punkt, wenn er in der Zeit, in der das Quadrat sichtbar ist, fürdas Erscheinen in der linken Hälfte die linke und das Erscheinen in der rechtenHälfte die rechte Maustaste drückt – bzw. einen Minuspunkt, wenn er zu spät oderfalsch klickt.

Page 151: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

151

jetz

t le

rne

ich

KAPITEL 13

Tastatur abfragen

Maus hin oder her, die Tastatur bleibt das wichtigste Eingabegerät für Spiele. Selbst beirein mausbasierten Spielen sollten Sie eine Tastatursteuerung einbauen. So könnte einBallerspiel à la »Moorhuhnjagd« auch mit den Pfeiltasten und der Leertaste bedientwerden.

13.1 Zeichen von der Tastatur einlesen

Bereits am Anfang dieses Buchs haben Sie den Befehl WaitKey kennen gelernt. Er war-tet so lange, bis eine Taste gedrückt wurde, und ist damit ein praktisches Hilfsmittel,um das Programm in den Pausemodus zu versetzen.

Unterschlagen habe ich dabei, dass WaitKey eine Funktion ist, die einen Wert zurück-gibt – nämlich den des Zeichens, das durch den Tastendruck erzeugt wurde. Der Zei-chenwert ist der (8 Bit große) ASCII-Code (American Standard Code for InformationInterchange). Er stellt sicher, dass Buchstaben mit der gleichen Bitfolge verschlüsseltwerden. Das erleichtert den Austausch von Texten.

Einige ASCII-Codes sind keinem Zeichen zugeordnet, sondern einer Funktion, etwa»nächste Zeile« oder »eine Spalte nach links«. Diese Funktionscodes heißen Steuer-zeichen.

In der Online-Hilfe finden Sie eine ASCII-Tabelle. Es kann trotzdem nicht schaden, sichdie wichtigsten Zeichen einzuprägen:

Zeichen ASCII-Code(s)

0 bis 9 48 bis 57

A bis Z 65 bis 90

a bis z 97 bis 122

Page 152: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

152

Tastatur abfragen13j e t z t l e r n e i c h

Statt der ASCII-Codes unterstützt Blitz Plus eine erweiterte Fassung davon: Wide-Chars, die auf dem Unicode (www.unicode.org) basieren. Der Unicode bietet mit bis-her 16 und neuerdings sogar 32 Bit Breite vier Milliarden Variationen, mit denen jedesnur denkbare Zeichen jeder Sprache einen festen Code erhält. Während sich im ASCII-Code hinter den Codes von Land zu Land verschiedene Zeichen verbergen, vor allemsprachspezifische Sonderzeichen, ist im Unicode jedes Zeichen gleich kodiert, egal inwelcher Sprache oder auf welchem System.

2

Mit einem kleinen Programm probieren Sie die Zeichencodes aus. Es endet, indem SieÈ drücken.

; ASCII.BBGraphics 640,480SetBuffer BackBuffer()Repeat Cls A = WaitKey() Text 200,200, "ASCII-Code: " + A FlipUntil A=27

2Natürlich ist eine Funktion, die das ganze Programm anhält, um auf einen Tastendruckzu warten, für ein Action-Spiel nicht zu gebrauchen. Die Funktion GetKey() arbeitet aufähnliche Weise, wartet jedoch nicht. Schreiben wir damit etwas Anspruchsvolleres, einProgramm, das Cursortasten abfragt und damit die Position einer Kiste beeinflusst:

; GETKEY.BBGraphics 640,480SetBuffer BackBuffer()X = 220Y = 140

|, ~, } und { 28 bis 31 (oder 63232 bis 63235 bei Blitz Plus)

¢Leertaste£ 32

Æ 13

È 27

Zeichen ASCII-Code(s)

Der ASCII-Code bildet eine Untermenge der WideChars. Daher lassen sind die meis-ten Codes sowohl für Blitz Plus wie für Blitz Basic 2D/3D verwenden. Unterschiedegibt es vor allem bei den Funktionstasten und unglücklicherweise bei den vier Pfeil-tasten. Das heißt: Ein Programm für Blitz Basic 2D, das den ASCII-Code für die Cur-sortasten abfragt, funktioniert nicht unter Blitz Plus. Dort haben die Tasten nicht dieCodes 28 bis 31, sondern 63232 bis 63235. Zwei Lösungen gibt es für diesesDilemma: Sie fragen für jede dieser vier Tasten einfach beide Codes ab. Oder Sie tes-ten nicht den ASCII-Code, sondern den Scancode, zu dem wir gleich kommen.

Vergessen Sie nicht, dass WaitKey() als Funktion mit Klammern geschrieben werdenmuss, wenn das Ergebnis einer Variablen zugewiesen werden soll.

Page 153: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

153

Scancode ermitteln j e t z t l e r n e i c h

Repeat Cls A = GetKey() If A=28 Then Y = Y – 10 ; ASCII-Codes für Blitz 2D/3D If A=29 Then Y = Y + 10 If A=30 Then X = X + 10 If A=31 Then X = X - 10 If A=63232 Then Y = Y – 10 ; Widechars für Blitz Plus If A=63233 Then Y = Y + 10 If A=63234 Then X = X + 10 If A=63235 Then X = X - 10

Rect X,Y, 100,100 FlipUntil A=27

Ganz befriedigend ist das Ergebnis nicht. Durchgängige Bewegungen sind nicht mög-lich. Sie müssen die Taste immer wieder loslassen. Gedrückt halten gilt nicht. (In BlitzPlus wurde dieses Verhalten geändert, aber eine Verzögerung gibt es dennoch.)

Bevor wir das Problem lösen, wiederhole ich zwei nützliche Funktionen. Asc() liefertIhnen den ASCII-Code eines Zeichens. Chr$() wiederum erwartet einen ASCII-Codeund gibt das passende Zeichen zurück:

Print Asc("A")Print Chr$(65)

Chr$() ist auch nützlich beim Ausgeben von Zeichen, die sich nicht direkt über die Tas-tatur eingeben lassen. Ein Sonderfall dabei ist das Anführungszeichen. Da es eine Zei-chenkette begrenzt, kann es nicht direkt ausgegeben werden. Die Schreibweise """,wie sie einige Programmiersprachen erlauben, ist nicht möglich. Die Lösung:

Print Chr$(34)

13.2 Scancode ermitteln

Das Abfragen des ASCII-Codes hat einen Nachteil: Nicht jeder Taste ist ein ASCII-Code zugeordnet. Steuerungstasten wie Ÿ, Ç oder die Funktionstasten habenkeinen ASCII-Code.

Um alle Tasten zu erwischen, fragen Sie den Scancode ab, den Code der Taste selbst.Der Scancode einer Taste ist völlig verschieden von dem ASCII-Code des Zeichens, dasauf der Taste liegt. Scancodes kann man sich schlechter merken, da sie nicht auf derReihenfolge der Zeichen basieren (so dass die Codes von A bis Z aufeinander fol-gen), sondern anhand ihres Auftretens auf der Tastatur nummeriert sind. So hat Aden Scancode 30, während S den Scancode 31 hat, D 32 usw.

Tasten, die doppelt auf der Tastatur vorkommen, etwa Ÿ, haben verschiedeneScancodes. So können Sie die linke und die rechte Ÿ-Taste mit verschiedenenFunktionen versehen.

Page 154: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

154

Tastatur abfragen13j e t z t l e r n e i c h

Wichtige Scancodes sind:

Die komplette Liste finden Sie wiederum in der Online-Hilfe. Um das lästige Nach-schlagen zu umgehen, definieren Sie häufige oder alle Tasten als Konstanten. EinenQuelltext, der nur aus diesen Konstantenzuweisungen besteht, finden Sie als SCAN-CODES.BB auf der Buch-CD. Sie binden ihn mit Include "scancodes.bb" in Ihr Pro-gramm ein. (Mehr zu Include finden Sie im Abschnitt »Verteilte Quelltexte«.)

2

Die Funktion KeyDown() informiert Sie darüber, ob eine bestimmte Taste gerade ge-drückt wird. Als Parameter nennen Sie den Scancode der Taste, die Sie interessiert.Unser kleines Kisten-Programm ist mit KeyDown() etwas länger, ...

; SCANCODE.BBGraphics 640,480SetBuffer BackBuffer()X = 320Y = 240

Repeat Cls Rect X,Y, 100,100 Flip If KeyDown(200) = 1 Then Y = Y - 1 If KeyDown(208) = 1 Then Y = Y + 1 If KeyDown(205) = 1 Then X = X + 1 If KeyDown(203) = 1 Then X = X - 1Until KeyDown(1) = 1

Taste Scancode

{ 203

} 205

| 200

~ 208

¢Leertaste£ 57

È 1

Ç 56

Ÿ links 29

Ÿ rechts 157

Á links 42

Á rechts 54

Å 15

Æ 28

Vergessen Sie nicht den Unterschied: Der Scancode ist der Code einer Taste. DerASCII-Code ist der Code eines Zeichens, das entweder einer Taste zugeordnet oderTeil einer Zeichenkette ist. Der Scancode für die È-Taste ist 1. Der ASCII-Code desSteuerzeichens »Esc«, das auf der È-Taste liegt, ist 27.

Page 155: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

155

Tastendrücke zählen j e t z t l e r n e i c h

... hat aber zwei Vorteile: Zum einen können Sie die Tasten gedrückt halten. Zum an-deren fragen Sie jede Taste einzeln ab, auch wenn mehrere gleichzeitig gedrückt wer-den. Für unser Programm heißt das, dass Sie { und | gleichzeitig drücken, um dieKiste schräg zu bewegen. Für Action-Spiele, bei denen mehrere Tasten zur gleichenZeit in Aktion sein könnten, setzen Sie KeyDown() ein.

1

2

13.3 Tastendrücke zählen

Ähnlich wie Sie mit MouseHit() die Zahl der Klicks zählen, sagt Ihnen KeyHit(), wie ofteine bestimmte Taste gedrückt wurde – im Zeitraum zwischen dem jetzigen und demletzten Aufruf der Funktion. Als Parameter teilen Sie den Scancode der Taste mit:

; KEYHIT.BBGraphics 640,480SetBuffer BackBuffer()ClsDelay 2000Text 200,200, "Los!"FlipA = KeyHit(57)Delay 5000Text 200,200, KeyHit(57) + " Tastendrücke in 5 Sekunden"FlipWaitMouse

13.4 Tastenpuffer löschen

Auch für das Löschen des Tastenpuffers gibt es mit FlushKeys ein gleichwertiges Kom-mando zu FlushMouse. Mit dem Befehl verhindern Sie, dass noch nicht bearbeitete Tas-tendrücke aus dem Spiel fälschlicherweise etwa in einem Menü interpretiert werden.

0

Anders als beim ASCII-Code und WaitKey()/GetKey()gibt es keine Scancode-Funk-tion, die Ihnen mitteilt, welche Taste gerade gedrückt wird, weil mehrere Tastengleichzeitig gedrückt sein können.

Aufgrund technischer Beschränkungen erkennen manche Tastaturen bestimmteKombinationen von Tasten nicht. Das ist bauartbedingt und unterscheidet sich vonModell zu Modell. Probleme kann es bereits ab drei gleichzeitig gehaltenen Tasten ge-ben.

Soll ein Tastendruck an mehreren Stellen des Programms ausgewertet werden, spei-chern Sie den Wert in einer Variablen und arbeiten Sie damit. Nur so stellen Sie si-cher, dass jede Zeile den gleichen Tastendruck erhält – und nicht etwa Eingaben desSpielers »verschluckt« werden.

Page 156: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

156

Tastatur abfragen13j e t z t l e r n e i c h

13.5 Aufgabe

1. Schreiben Sie ein kleines Spiel, das alle paar Sekunden einen zufällig ausgewähltenBuchstaben auf dem Bildschirm erscheinen lässt. Alle Buchstaben addieren sich zueiner immer länger werdenden Zeichenkette. Der Spieler muss schnell die jeweili-gen Tasten drücken, um einen Buchstaben zu entfernen und die Schlange damit zuverkürzen.

Page 157: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

157

jetz

t le

rne

ich

KAPITEL 14

AJoystick abfragen

Der gute alte Steuerknüppel hatte seine Blütezeit in der Ära der Homecomputer, inden 80er Jahren. Für viele Genres, etwa Ego-Shooter und Simulationen, ist er unge-eignet. Dennoch bleiben Anwendungszwecke für Joysticks, wie auch das große Ange-bot an dieser Hardware zeigt. Neben Fahr- und Flugsimulationen dienen sie vor allemfür schnelle Arcade-Spiele als Steuerung. Sie können Ihre Spiele um eine Joystick-Ab-frage erweitern, doch ich rate Ihnen davon ab, die Möglichkeiten der Eingabe daraufzu beschränken.

14.1 Art des Joysticks ermitteln

Es gibt zwei Arten von Joysticks. Vor allem ältere Modelle arbeiten digital. Sie fragenvon ihnen nur die Richtung des Steuerknüppels ab, nicht die Stärke des Drucks. Beianalogen Joysticks lässt sich auch messen, wie stark der Knüppel in eine Richtung be-wegt wird.

Die Funktion JoyType() sagt Ihnen, was angeschlossen ist. Sie liefert:

� 0, wenn ein Joystick fehlt

� 1, wenn es sich um einen digitalen Joystick handelt

� 2, wenn es sich um einen analogen Joystick handelt

1Der Joystick-Port wird in der Regel über die Soundkarte zur Verfügung gestellt. EinigePCs haben jedoch direkt am Gehäuse eine eigene Joystick-Buchse. In diesem Fallkönnen Sie jeder Joystick-Funktion als Parameter übergeben, welcher der beidenPorts angesprochen werden soll (JoyWait(1)). Funktionen, die sowieso einen Para-meter haben, übergeben Sie den Port, durch ein Komma getrennt, als zweiten Para-meter (etwa JoyDown(1,1)).

Page 158: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

158

Joystick abfragen14j e t z t l e r n e i c h

14.2 Joystick-Tasten abfragen

Es gibt zahllose Arten von Joysticks, angefangen von einfachen Modellen mit einemFeuerknopf bis hin zu ausgefeilteren Ausgaben mit vier oder mehr Knöpfen. Sie kön-nen nicht ermitteln, wie viele Knöpfe ein angeschlossener Joystick hat. Daher solltenSie möglichst nur einen Knopf abfragen. Einige Knöpfe lassen sich bereits durch Be-wegungsabfragen ersetzen. So könnte zum Beispiel »Ducken« durch das Ziehen desSteuerknüppels nach hinten (zum Spieler hin) erreicht werden, »Springen« durch Be-wegung nach vorn oder vorn/rechts. Die Knöpfe sind nacheinander nummeriert; dererste Feuerknopf ist 1, der zweite 2 usw.

Die Funktionen zum Abfragen der Joystick-Knöpfe ähneln stark den Maus- und Tasta-turbefehlen. Daher liste ich sie nur kurz auf:

� JoyWait

Hält das Programm an und wartet auf das Drücken eines Knopfs.

� JoyWait()

Hält das Programm an und wartet auf das Drücken eines Knopfs. Der gedrückteKnopf wird übermittelt (z.B. 1 für den ersten Knopf).

� GetJoy()

Gibt zurück, welcher Knopf bei Aufruf der Funktion gedrückt wird.

� JoyDown(Knopf)

Liefert 1, wenn der angegebene Knopf beim Aufrufen der Funktion gedrückt wird.

� JoyHit(Knopf)

Liefert zurück, wie oft der angegebene Knopf seit dem letzten Aufruf der Funktiongedrückt wurde.

� FlushJoy

Löscht alle noch nicht abgerufenen Knopfdrücke aus dem Puffer.

114.3 Bewegung des Steuerknüppels feststellen

Durch die Unterteilung in digitale und analoge Joysticks gibt es zwei Gruppen vonBefehlen zum Abfragen der gedrückten Richtung des Steuerknüppels.

JoyXDir(), JoyYDir() und JoyZDir() sagen Ihnen nur die Richtung (englisch Direction)und eignen sich daher vor allem für digitale Joysticks.

JoyX(), JoyY(), JoyZ() liefern Ihnen in Zwischenwerten, wie weit der Steuerknüppel ineine Richtung gedrückt ist. Sie sollten vor allem bei analogen Joysticks zum Einsatzkommen. Damit die Messung genau erfolgt, sollte der Joystick vor der Abfrage ausge-richtet (kalibriert) werden. Windows bietet dafür in der Systemsteuerung eine entspre-chende Hilfe.

Für JoyWait() ist auch die Schreibweise WaitJoy() erlaubt. In Blitz Plus wurden dieFunktionen GetJoy(), JoyWait() und WaitJoy() entfernt – wegen »unsynchronen Ver-haltens«.

Page 159: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

159

Bewegung des Steuerknüppels feststellen j e t z t l e r n e i c h

Im Folgenden sind die sechs Funktionen aufgelistet:

� JoyXDir()

Liefert zurück, in welche waagerechte Richtung der Steuerknüppel bewegt wird:

-1 für Bewegung nach links

1 für Bewegung nach rechts

0 für Mittelstellung (keine Bewegung)

� JoyYDir()

Liefert zurück, in welche senkrechte Richtung der Steuerknüppel bewegt wird:

-1 für Bewegung nach vorn (Richtung Monitor)

1 für Bewegung nach hinten (Richtung Spieler)

0 für Mittelstellung (keine Bewegung)

� JoyZDir()

Liefert zurück, in welche Richtung der Z-Achse (hinauf/hinunter) der Steuerknüp-pel bewegt wird:

-1 für Bewegung nach oben

1 für Bewegung nach unten

0 für Mittelstellung (keine Bewegung)

� JoyX()

Liefert zurück, wie stark in waagerechter Richtung der Steuerknüppel bewegt wird;der Wert liegt dabei zwischen:

-1 für Ausschlag nach links

1 für Ausschlag nach rechts

0 für Mittelstellung (keine Bewegung)

� JoyY()

Liefert zurück, wie stark in senkrechter Richtung der Steuerknüppel bewegt wird:

-1 für Ausschlag nach vorn (Richtung Monitor)

1 für Ausschlag nach hinten (Richtung Spieler)

0 für Mittelstellung (keine Bewegung)

� JoyZ()

Liefert zurück, wie stark auf der Z-Achse (nach oben/nach unten) der Steuerknüp-pel bewegt wird:

-1 für Bewegung nach oben

1 für Bewegung nach unten

1Mit der Version 1.78 wurde eine Handvoll weiterer Joystick-Befehle eingeführt. Sienutzen die erweiterten Steuerungsmöglichkeiten von 3D-Joysticks. Mit ihnen fragenSie etwa die Drehung des Sticks ab. Detailliert sind sie in der Online-Hilfe beschrie-ben. Da Sie jedoch nicht prüfen können, wie der Joystick des Spielers ausgestattet ist(ein Mangel, den der Entwickler von Blitz Basic ebenfalls erkannt hat und der sicherirgendwann behoben wird), sollten Sie besser auf die Nutzung verzichten.

Page 160: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

160

Joystick abfragen14j e t z t l e r n e i c h

14.4 Aufgabe

1. Beschreiben Sie den Unterschied zwischen einem digitalen und einem analogenJoystick.

Page 161: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

161

jetz

t le

rne

ich

KAPITEL 15

Töne und Musik

Die Geräuschkulisse trägt zu einem großen Teil zur Atmosphäre bei. Hintergrundme-lodien und Toneffekte helfen dabei, dass der Spieler tiefer in das Geschehen eintau-chen kann, geben aber auch wichtige Hinweise.

Blitz Basic erzeugt keine Klänge, sondern spielt sie nur ab. Für eigene Kompositionennehmen Sie eines der vielen Musikprogramme, die sich aus dem Internet laden oderkäuflich erwerben lassen.

Thomas Köhre, www.lcm-network.info: »Für den richtigen Klang ist es nicht nurwichtig, dass eine gut klingende und nicht nervende Musik ertönt. Es müssen vieleschöne Soundeffekte zu hören sein. Wenn ein Raumschiff fliegt, sollte es ein Trieb-werksgeräusch haben. Wenn es mit seinem Laser schießt, sollte der nach Laser undnicht nach Topfdeckel klingen. Deswegen ist es wichtig, dass neben dem Spielprinzipund der Grafik dem Spieler auch ein guter Sound geboten wird. Die Soundeffekte be-stehen aus vielen kleinen Schnipseln und werden dann eingefügt, wenn eine be-stimmte Aktion geschieht. Wenn etwa die Spielfigur hüpft oder wenn ein paar Geg-ner auftauchen, muss ein solcher Sound abgespielt werden. Ebenso wichtig ist diepassende Musik.«

Josef »DJJUPP« Sejrek, www.budbrain.de: »Wenn Sie für Ihre Spiele kostenloseEffekte oder Musik suchen, sollten Sie bei www.homerecording.de vorbeischauen.Dort finden Sie neben Samples viele interessante Programme, um selbst Musik zu er-stellen. Sampling-CDs, also Ansammlungen von verschiedenen Sounds, können aufwww.samplepoolz.de/reviews/cd/ erworben werden.«

Page 162: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

162

Töne und Musik15j e t z t l e r n e i c h

15.1 Toneffekte

Blitz Basic spielt Tondateien ab, die in verbreiteten Formaten wie WAV, MP3 oderOGG vorliegen. Auch das neue Ogg Vorbis wird seit Version 1.72 unterstützt. DiesesVerfahren (www.xiph.org) bietet bei gleicher Samplingrate eine bessere Qualität alsMP3 und ist patentfrei. Es hat aber Schwierigkeiten, sich gegen seinen übermächtigenMitbewerber durchzusetzen.

Im Ordner SAMPLES\SOUNDS von Blitz Basic und Blitz Basic 3D finden Sie Klang-schnipsel, so genannte Samples, die Sie sofort verwenden können. Im Windows-Ord-ner MEDIA sind ebenfalls Tondateien enthalten.

Winfried Rothenberg, www.erwinmusik.de: »Es gibt drei Wege, um an Geräuschef-fekte zu gelangen. Die naheliegende Lösung ist das Internet. Auf unzähligen Seitengibt es Geräusche zum Download, etwa auf www.a1freesoundeffects.com,www.hoerspielbox.de oder www.echovibes.com. Auch Profi-Studios bieten Bei-spiele ihrer Arbeit kostenfrei an. Vor der Verwendung sollte geklärt werden, ob dieSounds wirklich frei verwendet werden dürfen. Das gilt vor allem für den Einsatz inkommerziellen Spielen. Zu beachten ist auch, dass die Musikstücke GEMA-frei sind.Die GEMA ist die Verwertungsgesellschaft für Musiker. Ist ein Musiker Mitglied derGEMA, müssen für die öffentliche Aufführung seiner Stücke (etwa im Radio) oder diemechanische Vervielfältigung (auf CD oder Tonband) Gebühren an die GEMA gezahltwerden. Hersteller von Geräusch-CDs sind meistens keine »Komponisten«, dieGEMA-Mitglied und damit GEMA-pflichtig sind. Daher können sie gegen eine mitdem Kauf erhobene Summe (oder natürlich auch gratis) eine befristete oder unbefris-tete Erlaubnis für die kommerzielle Verwendung erteilen.

Die bequemere, aber kostenpflichtige Variante dazu sind Geräusch-CDs. Sie werdenim Fachhandel angeboten und im Netz vertrieben. Für den professionellen Markt bie-tet etwa die BBC ein aus vierzig CDs bestehendes Archiv (www.soundfx.com/bbc.htm) mit Geräuschen zu den verschiedensten Themen wie Wetter, Babys, ver-schiedene Länder und Maschinenlärm an. Einzelne CDs verkauft The HollywoodEdge (www.hollywoodedge.com). Die Silberscheiben enthalten oft mehrere hundertGeräusche, sind aber mit Preisen von einigen hundert Euro sehr teuer. Zum Trost gibtes hundert Effekte zum Gratis-Download. Billiger geht es etwa bei www.tonarchiv-online.de: Dort werden Geräusch-CDs schon für 25 Euro verkauft.

Grundsätzlich gilt für mich aber: Selbermachen macht am meisten Spaß und bringtauch keine Nebeneffekte mit wie Urheberrechtsverletzung, Erwerben von Lizenzenund andere Fallstricke. Je nach Aufgabe bin ich selbst auf die Jagd nach Aufnahmengegangen. So habe ich mich, mit einem tragbaren DAT-Recorder und zwei Mikrofo-nen bewaffnet, zwischen zwei S-Bahnhöfe postiert, um »echte« Bahngeräusche zu er-halten. Auf diese Weise gelangt man leicht an die Klänge von klappenden Autotüren,knarrenden Haustüren, Autofahrten, Wasserrauschen, Tierstimmen und mehr. DerComputer kommt dabei freilich nicht zu kurz und hilft einerseits beim Bearbeiten vonGeräuschen und andererseits beim Entwerfen. Als Software für die Audiobearbeitungbenutze ich die Programme Nuendo und Wavelab von Steinberg. Das sind profes-sionelle Audio-Editoren, mit denen ich auch komplexe Hörspiele, Werbeproduk-tionen und Musikaufnahmen mache. Diese Programme beinhalten eine MengeEchtzeiteffekte wie Hall, Echo und Pitch (Verstimmung). Damit lassen sich fast alleSoundeffekte erzielen, einen entsprechenden Ursprungsklang vorausgesetzt.«

Page 163: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

163

Musik j e t z t l e r n e i c h

Mit der Funktion LoadSound() laden Sie eine Klangdatei in den Speicher. Sie gibt Ihneneine Kennziffer zurück, über die Sie den Toneffekt später ansprechen. Daher verwen-den Sie LoadSound() in Verbindung mit einer Variablenzuweisung:

ton = LoadSound("soundfx11.wav")

Falls die Datei nicht geladen werden konnte (oder der PC keine Soundkarte besitzt), er-hält die Variable den Wert 0. Sie sollten eine entsprechende Sicherheitsabfrage einbau-en. PlaySound spielt den Effekt ab:

PlaySound ton

Ja, das war’s schon. Nicht schwer, oder? Der Effekt wird einmal abgespielt. In einemSpiel werden Sie das Ausgeben eines Tons von einer Bedingung abhängig machen. Sowird für bestimmte Ereignisse, etwa das Auslösen eines Schusses, ein individueller Ef-fekt abgespielt. Dabei können mehrere Klänge gleichzeitig ertönen.

0

Ein Klang lässt sich unablässig wiederholen. Die sinnvollste Anwendung dafür ist eineHintergrundmusik. Um die Wiederholung einzuschalten, setzen Sie vor PlaySound denBefehl LoopSound:

; TON.BBton = LoadSound("soundfx11.wav")LoopSound tonPlaySound tonWaitKey

1

Wenn Sie einen Klang nicht mehr benötigen, geben Sie ihn wieder frei:

FreeSound ton

15.2 Musik

Für länger ablaufende Musik gibt es mit PlayMusic einen speziellen Befehl. Er spieltauch das weit verbreitete MIDI-Format ab. MIDI-Dateien (Musical Instrument DigitalInterface, Dateiendung MID) sind besonders platzsparend.

In seiner Anwendung unterscheidet sich PlayMusic in zwei Punkten von LoadSound.Zum einen wird die Musik sofort abgespielt; Laden und Abspielen sind ein Befehl:

PlayMusic("lied.wav")

Falls Sie nichts hören, kann es daran liegen, dass Ihr Programm bereits beendet ist,bevor der Ton beginnt. Blitz Basic scheint je nach Version unterschiedlich zu reagierenbei einem Programm, das nur aus dem Laden und Abspielen eines Klangs besteht.Blitz Basic (2D) spielt überhaupt nichts ab; Blitz Basic 3D und Blitz Plus spielen denTon, beenden aber gleichzeitig das Programm. Abhilfe schaffen WaitKey oder Delay.

In älteren Blitz-Basic-Versionen vor 1.36 hat LoopSound gleich das Abspielen über-nommen; PlaySound() war damit nicht notwendig. Die Musikbefehle haben seit die-ser Zeit eine Reihe von Veränderungen erfahren; einige Kommandos sind inzwischenungültig.

Page 164: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

164

Töne und Musik15j e t z t l e r n e i c h

Zum anderen gibt es keinen Befehl zur Wiederholung der Wiedergabe. Um eine Melo-die unablässig zu spielen, wiederholen Sie die Anweisung. (Wie Sie erfahren, ob dasStück schon zu Ende ist, zeige ich Ihnen einige Zeilen später.)

Bei Programmende reagiert PlayMusic genauso, wie ich es einige Zeilen weiter obenfür PlaySound beschrieben habe.

15.3 Audio-CDs

Das Abspielen von Audio-Tracks einer CD ist mit Blitz Basic kein Problem. Wenn SieIhr Spiel auf CD ausliefern, erfreuen Sie den Spieler mit hochwertigen Audiotiteln oderbieten ihm an, seine Lieblings-CD einzulegen. So einfach ist es, eine Musik-CD zumRotieren zu bringen:

PlayCDTrack(1)

Als Parameter geben Sie die Titelnummer (hier: 1) an. Mithilfe eines zweiten Parame-ters steuern Sie das Verhalten des CD-Players:

1 den gewählten Titel einmal abspielen (Standard, falls Parameter fehlt)

2 den gewählten Titel in einer Endlosschleife wiederholen

3 ab dem gewählten Titel bis zum Ende der CD spielen

Der Befehl PlayCDTrack(4,2) spielt damit den Titel 4 immer wieder ab.

1

Marc »DJ MACOMAR« Schömehl, www.budbrain.de: »Professionelle Musik-Soft-ware kann viel Geld kosten. Das Paket aus dem beliebten Cubase SX von Steinbergund einigen virtuellen Instrumenten wie Absynth, Waldorf Attack, Pro 53 und Rebirthals Ergänzung kostet mehr als 1000 Euro! Billiger, aber nicht so komfortabel in derBedienung, geht es mit den beliebten Trackern, die ihre Wurzeln im CommodoreAmiga haben. Sie sind nicht so leicht zu bedienen wie die Einsteigerprogramme inder Art des Music Makers, bieten aber mehr Freiheiten. Zu den besten dieser Pro-gramme gehört der »Impulse Tracker« (www.noisemusic.org/it/). Er ist kostenlos undkann Samples auf 64 Spuren mit bis zu 16 Bit und 48 kHz verarbeiten. Mit diesemWerkzeug lässt sich schon recht gute Musik erstellen, ohne viel Geld ausgeben zumüssen. Und man kann antesten, ob einem das Musizieren überhaupt liegt.«

Josef »DJJUPP« Sejrek, www.budbrain.de: »Für die Spieleprogrammierung würdeich dem MP3-Format den Vortritt geben. Das veraltete WAV-Format erzeugt viel zugroße Dateien. Ein Beispiel: Nimmt man ein Lied von 6 Minuten Länge auf, das mit44 kHz Stereo gesampelt wurde, dann ist die WAV-Datei 80 MB groß. Wandelt mandas Lied in eine MP3-Datei um (128 Kbit), sind es gerade 6 MB! Einen Qualitäts-unterschied hört man vor allem ab 192 Kbit kaum noch. Die Güte der Umwandlunghängt neben der Kbit-Zahl auch vom verwendeten Konverter ab.«

Um Musik aus dem PC-Lautsprecher zu hören, muss das CD-Laufwerk mit derSoundkarte verbunden sein. Nur bei wenigen Anwendern dürfte ein Lautsprecher di-rekt am Kopfhörerausgang des Laufwerks angeschlossen sein. Es ist nicht möglich,ein bestimmtes Laufwerk auszuwählen.

Page 165: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

165

Musikkanäle und Steuerbefehle j e t z t l e r n e i c h

15.4 Musikkanäle und Steuerbefehle

Blitz Basic stellt Ihnen ein kleines Mischpult bereit, mit dem Sie Klänge verändern:Lautstärke, Balance und Tonhöhe lassen sich einstellen. Außerdem gibt es eine Pause-und eine Stopp-Taste. Dabei ist zu berücksichtigen, dass mehrere Klänge gleichzeitigertönen können. Wie sagen Sie, welchen Sie meinen?

Klänge und Musik werden in so genannte Kanäle (Channels) eingeteilt. Die Funktio-nen PlaySound(), PlayMusic() und PlayCDTrack() geben Ihnen eine Kanalnummer zu-rück. Sie speichern sie in einer Variable, um damit später den Klang anzusprechen:

ton1 = LoadSound("soundfx11.wav")kanal1 = PlaySound(ton1)ton2 = LoadSound("soundfx16.wav")kanal2 = PlaySound(ton2)kanal3 = PlayCDTrack(1)

15.4.1 Kanal anhaltenDank der Kanalnummer stoppen Sie jederzeit die Wiedergabe, etwa wenn ein Spiel be-endet oder ein Level abgeschlossen wird:

StopChannel(kanal)

Manchmal soll das Aus nur vorübergehend erfolgen. Der Spieler wechselt etwa in einMenü oder drückt die Pause-Taste – in diesem Fall sollten Geräusche stoppen und spä-ter wieder an der gleichen Stelle fortgesetzt werden. Dafür gibt es das BefehlspaarPauseChannel() (um den Kanal anzuhalten) und ResumeChannel() (um ihn wieder fort-zusetzen):

PauseChannel(kanal); weitere BefehleResumeChannel(kanal)

Etwa so:

; CD-PLAYER.BBGraphics 640,480SetBuffer BackBuffer()Clskanal = PlayCDTrack(1)Text 100,100,"[1] = Pause"Text 100,120,"[2] = Weiter"Text 100,140,"[3] = Ende"Flip

Repeat A = GetKey() If A = 49 Then PauseChannel(kanal) If A = 50 Then ResumeChannel(kanal) If A = 51 Then StopChannel(kanal)Until A = 51

Wie bei den anderen Musikbefehlen gilt: Blitz Basic wartet nicht auf die Musik. EinProgramm, das nur aus dem Befehl PlayCDTrack() besteht, bleibt stumm, da esschneller beendet ist, als die Musik beginnen kann.

Page 166: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

166

Töne und Musik15j e t z t l e r n e i c h

Oft ist es hilfreich zu erfahren, ob ein Toneffekt oder ein Musikstück noch läuft. WennSie ein halbes Dutzend Titel haben, die nacheinander abgespielt werden sollen, dannmüssen Sie wissen, wann ein Titel zu Ende ist. Diese Information liefert Ihnen dieFunktion ChannelPlaying(). Sie gibt eine 1 zurück, wenn auf dem gewünschten Kanalnoch etwas los ist:

If ChannelPlaying(klang1) = 0 Then PlaySound(klang2)

15.4.2 Lautstärke regelnIn Musikdateien wird die Lautstärke zur Wiedergabe mitgeliefert. Auf diese Weise las-sen sich laute und leise Passagen realisieren, ohne dass ständig die Lautstärke manuellgeändert werden muss. Mit

ChannelVolume(kanal, lautstärke)

ändern Sie trotzdem die Lautstärke eines Kanals. Der Wert für »Lautstärke« liegt zwi-schen 0 (lautlos) und 1 (höchste Lautstärke):

; LAUTSTÄRKE.BBklang = LoadSound("soundfx11.wav")LoopSound klangkanal = PlaySound(klang)

For I# = 0 To 1.0 Step 0.2 ChannelVolume(kanal, I) Print I Delay 2000Next

Beachten Sie, dass Sie eine Variable mit # kennzeichnen müssen, damit sie einen re-ellen Wert speichert.

15.4.3 Balance einstellenSeit mehr als zehn Jahren sind Stereo-Soundkarten Standard und üblicherweise sindam PC mindestens zwei Lautsprecher angeschlossen. Sie erzeugen einen Stereoeffekt,indem Sie die Lautstärke beider Lautsprecher unterschiedlich balancieren. Mit Chan-nelPan() ändern Sie die Balance für links und rechts:

ChannelPan(kanal, 0.5)

Der Wert 0 bedeutet: Von beiden Seiten kommt die gleiche Lautstärke. -1 legt den Tonnur auf den linken Lautsprecher, 1 nur auf den rechten. Zwischenstufen sind möglich.

Mithilfe des Befehls verstärken Sie den Eindruck der Bewegung von einer Seite zur an-deren, indem Sie die Balance mit dem Objekt ändern. Wenn sich etwa eine Figur voneiner Seite zur anderen bewegt, dann geben Sie ihr in der Mitte des Bildschirms die Ba-lance 0 und ganz links die Balance -1. Dazu teilen Sie die Bildschirmbreite (zum Bei-spiel 640 bei 640 x 480) durch die Differenz aus Position und Breite. Mit dieser Rech-nung erhalten Sie passende Werte zwischen -1 und 1, je nach gewünschter Position:

; BALANCE.BBGraphics 640,480SetBuffer BackBuffer()ton = LoadSound("soundfx11.wav")LoopSound tonkanal = PlaySound(ton)

Page 167: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

167

Musikkanäle und Steuerbefehle j e t z t l e r n e i c h

For I=0 To 639 Cls Text 0,0, Float(I-320) / Float(320) Plot I,240 Flip ChannelPan(kanal, Float(I - 320) / Float(320) ) Delay 20Next StopChannel(kanal)

15.4.4 Frequenz ändernMit einem weiteren Befehl ändern Sie die Frequenz (Samplingrate) eines Klangs unddamit seine Höhe und Geschwindigkeit:

ChannelPitch(kanal, frequenz)

Thomas Köhre, www.lcm-network.info: »Nehmen wir ein Beispiel für den Einsatzvon Klängen in einem Spiel. Wir wollen, dass eine Möwe auftaucht und vom linkenBildschirmrand zum rechten fliegen soll. Dabei muss man Möwengeschrei hören. Ineinem bestimmten Moment lässt der Vogel etwas Unappetitliches fallen. Und das sollauch untermalt werden. Hierbei verwenden wir am besten drei Soundeffekte. Einmaldas Möwengeschrei, das Fallgeräusch und das Aufplatschen des Exkrements. Sie allekennen den Stereo-Effekt. Ein Ton besteht aus zwei Richtungsinformationen, demlinken und dem rechten Kanal. Ist ein Objekt links von uns, hören wir nun den linken,ist es rechts, nur den rechten. Alles was dazwischen ist, muss aus beiden Kanälenkombiniert werden.

Die Möwe fliegt also von links nach rechts. Zuerst müssen wir den Sound nur vonlinks hören, dann wird der linke Lautsprecher leiser und wir hören das Objekt auchauf dem rechten Lautsprecher. Zusammen muss die Lautstärke immer 100% betra-gen. Wir kombinieren einfach die Flugposition des Vogels auf dem Bildschirm von0% bis 100% mit der Tonerzeugung. Befindet sich die Möwe in der Mitte, sind beideLautsprecher zu 50% mit dem Geschrei belegt. Weiter nach rechts sind es dann zumBeispiel 40% links und 60% rechts ... und so weiter. Wenn die Möwe aus dem Bildverschwunden ist, muss das Möwengeschrei beendet werden. Man kann das Auftau-chen von Objekten auf dem Bildschirm auch mit einem gesamten Lautstärkewert ver-sehen und den Soundeffekt langsam einblenden. Dazu sollten Sie beim Auftauchendie Lautstärke des Sounds auf Null setzen und dann schnell auf 100% erhöhen. Beilangsamen Objekten kann das entsprechend schleichender vonstatten gehen. DasGeschrei an sich brauchen wir natürlich nur einmal als Geräusch. Denn wir könnenes in einer Endlosschleife, versehen mit den Positionswerten, immer wieder ab-spielen.

Das Fallobjekt lassen wir zwischendurch fallen. Bei einem Punkt x müssen wir dasFallgeräusch abspielen. Wir benötigen dazu die Fallzeit, die wir aus der Flughöhe undder Fallgeschwindigkeit berechnen. Wir lassen in diesem Moment nun das Fall-geräusch abspielen, versehen es mit einer Änderung der Tonhöhe von hoch nach tiefund spielen es einmal für einen bestimmten Zeitraum – der Falldauer – ab. Danachspielen wir einfach den Platschsound ab – natürlich versehen mit der richtigen Posi-tionsangabe für den Stereosound. Das Möwendreckprinzip ist uneingeschränkt auchfür alle anderen Objekte übertragbar. Aus der Kombination aller Möglichkeiten bauenSie sich eine stimmungsvolle Klangkulisse zusammen.«

Page 168: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

168

Töne und Musik15j e t z t l e r n e i c h

Üblicherweise haben Klangdateien eine Samplingrate von 11000, 22000 oder 44000Hz. Wählen Sie für den Frequenzparameter einen Bereich von 8000 bis 44100. Einkleines Beispiel demonstriert die Veränderung:

; FREQUENZ.BBklang = LoadSound("soundfx11.wav")LoopSound klangkanal = PlaySound(klang)For I=1000 To 20000 Step 500 ChannelPitch(kanal, I) Print I Delay 1000Next

1Mithilfe der Frequenzänderung erzielen Sie hübsche Effekte. Probieren Sie ruhig einwenig herum, um passende Verzerrungen zu erzielen. Empfehlenswert ist das Schrei-ben eines kleinen Programms, das die Frequenz per Tastendruck ändert. Freilich bietenspezielle Tonbearbeitungsprogramme erheblich bessere Möglichkeiten. Bereits mitSoftware, die Soundkarten gratis beiliegt, lässt sich einiges anstellen.

15.5 Aufgabe

1. Schreiben Sie ein Programm, das einen Klang fortlaufend abspielt. Per Tasten-druck kann der Nutzer Lautstärke, Tonhöhe und Balance ändern. Zeigen Sie dieWerte optisch – zum Beispiel mit einem Balken – auf dem Bildschirm an.

Der Befehl hat keine Wirkung bei Audio-CDs, die mit einer festen Frequenz von44000 Hertz abgespielt werden.

Winfried Rothenberg, www.erwinmusik.de: »Ein Chorus- oder Pitch-Effekt machteinen Sound breiter, ein Hall bringt Tiefe. Soll es lustig klingen, pitcht (stimmt) manden Sound eine Oktave höher. Ein Monster oder Fiesling spricht immer tiefer, alsoPitch nach unten. Stimmen aus dem »Off«, bei denen man den Sprecher nicht sieht,bekommen Echo-Effekte, die links und rechts unterschiedlich verzögert sind. Dadurchklingen diese wie »von überall«, sind also nicht ortbar. Traumstimmen oder verzauber-te Elfen werden mit einem Chorus-Effekt versehen. Diese verwaschen den Klang undlassen den Sound schweben. Ganz wichtig für die Natürlichkeit von Effekten undStimmen ist der Raumanteil, also der Nachhall. In einer Kirche klingt es anders als ineinem Wald. Befindet sich eine Figur im Freien, gibt es keinen Hall, sondern höchs-tens Echoeffekte von Mauern oder Wänden. Während dessen hallt es in einem Keller,Tunnel oder Saal stark. Im Tunnel muss der Hall aber dumpf klingen, in einer Säu-lenhalle mit viel Marmor eher spitz und scharf. Um Bewegung in die Atmosphäre zubekommen, sollte man viel mit Panorama-Bewegungen arbeiten: Wenn sich der Geg-ner von links nach rechts bewegt, muss auch der Sound von links nach rechts wan-dern. Kommt ein Fahrzeug von weit weg, ist der Ton erst leise und dumpf und wirdbeim Vorbeifahren dröhnend laut. Um einen kurzen Sound zu verlängern, benutztman auch den Hall. Beim Loopen (Wiederholen) von Geräuschen muss man auf Pe-gelsprünge achten, um bei der Wiederholung keine Knackser und Soundunterschiedezu bekommen.«

Page 169: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

169

jetz

t le

rne

ich

KAPITEL 16

AVideos

Für Hobbyspiele sind aufwendige Videosequenzen sicher übertrieben. Doch eine klei-ne Videoanimation als Intro ist oft eine bessere Lösung, als sie mit Grafikbefehlenselbst zu generieren.

Blitz Basic spielt Videos ab, wie sie etwa in AVI-Dateien vorliegen, inklusive Ton, so-fern vorhanden. Das ist beinahe genauso einfach, wie ein Bild anzuzeigen.

1

0

16.1 Video öffnen

Zunächst öffnen Sie mit OpenMovie() eine Videodatei. Der Befehl liefert Ihnen eineKennung zurück, über die Sie das Video später ansprechen. Daher verwenden Sie ihnmit einer Variablenzuweisung:

Video = OpenMovie("intro.avi")

Gibt OpenMovie() den Wert 0 zurück, dann konnte Blitz Basic das Video nicht laden(weil zum Beispiel der Dateiname falsch ist).

Auf der Buch-CD finden Sie kleine Beispielvideos. Es gibt unzählige Programme, umeigene Videos zu erstellen, etwa der kostenlose Movie Maker von Microsoft(www.microsoft.com/windowsxp/moviemaker/, auf der Buch-CD). Er arrangiertFotos, Bilder und Filmsequenzen zu einem Video.

Der Videosupport wurde erst in der Version 1.71 von Blitz Basic aufgenommen. DieDemo von Blitz Basic 2D ist auf einem älteren Stand; daher lassen sich die Befehlenicht einsetzen. Blitz Basic greift auf die Abspielfunktionen von DirectX zurück, dahermüssen korrekte Treiber installiert sein.

Page 170: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

170

Videos16j e t z t l e r n e i c h

016.2 Abspielen eines Videos

Ein Video besteht aus einer Folge von Einzelbildern. Blitz Basic hat keinen Befehl, umein komplettes Video zu zeigen. DrawMovie() zeigt jeweils ein Einzelbild. Damit die Ein-zelbilder ein Video ergeben, führen Sie den Befehl in einer Schleife so lange aus, bisalle Einzelbilder abgearbeitet sind.

Sie übergeben dem Befehl die Kennziffer des Videos und die Stelle, an der das Bild dar-gestellt werden soll, als X- und Y-Koordinaten. Fehlt die Lage, wird die Position 0,0verwendet.

1Und wie erfahren Sie, ob das Ende erreicht ist, wann die Schleife also enden soll? DieFunktion MoviePlaying() sagt es Ihnen: Warten noch Einzelbilder auf ihre Anzeige, er-halten Sie eine 1. Ist das Video zu Ende, liefert die Funktion eine 0.

Eine Abspielschleife programmieren Sie also wie folgt:

; VIDEO1.BBGraphics 640,480SetBuffer BackBuffer()Video = OpenMovie("mann.avi")Repeat Cls DrawMovie(Video, 50, 50) FlipUntil MoviePlaying(Video) = 0

Klar, es wäre einfacher, wenn der Befehl gleich das gesamte Video abspielen würde.Dafür ermöglicht Ihnen die Vorgehensweise zwei Vorteile: Das Video lässt sich jeder-zeit abbrechen, sofern Sie einen entsprechenden Test ...

If KeyHit(1) Then Exit

... einbauen. Außerdem können nette Effekte eingebaut werden. Leicht ändern Sie diePosition jedes Einzelbilds:

; VIDEO2.BBGraphics 800,600SetBuffer BackBuffer()Video = OpenMovie("mann.avi")Repeat Cls I=I+1 DrawMovie(Video, I*2, I) FlipUntil MoviePlaying(Video) = 0

Übrigens spielt Blitz Basic auch animierte GIF-Dateien ab. Verwenden Sie die Grafikwie eine normale Video-Datei.

Im Gegensatz zu den Zeichen- und Bildfunktionen werden ViewPort und Origin nichtberücksichtigt; die Position 0,0 ist also immer links oben. Das Video muss vollständigauf den Bildschirm passen.

Page 171: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

171

Größe eines Videos ändern j e t z t l e r n e i c h

16.3 Größe eines Videos ändern

Das Video wird normalerweise in seiner Originalgröße angezeigt. Die FunktionenMovieWidth() und MovieHeight() nennen Ihnen die Breite und die Höhe eines Videos:

Print "Format: " + MovieWidth(Video) + "x" + MovieHeight(Video)

Sie sind aber nicht an das Format gebunden, sondern verkleinern oder vergrößern dasVideo nach Belieben. Dazu übergeben Sie DrawMovie() als zusätzliche Parameter dieBreite und Länge in Bildpunkten:

DrawMovie(Video, 100, 100, 200, 200)

Um ein Video zweimal so groß abzuspielen, verdoppeln Sie die Werte:

DrawMovie(Video, 50, 50, MovieWidth(Video)*2, MovieHeight(Video)*2)

1Mit veränderlichen Werten erzielen Sie raffinierte Resultate. Wenn Sie je Einzelbild dasFormat vergrößern, zoomt das Video langsam auf:

; VIDEO3.BBGraphics 640,480SetBuffer BackBuffer()Video = OpenMovie("mann.avi")Repeat Cls I=I+1 DrawMovie(Video, 50, 50, I*2, I*2) FlipUntil MoviePlaying(Video) = 0

Auch wenn Sie nur die Breite oder die Höhe ändern wollen, müssen Sie beide Para-meter angeben. Falls einer von ihnen der Originalgröße entsprechen soll, brauchen Sienicht MovieWidth() oder MovieHeight() zu verwenden. Der Parameter -1 tut es in die-sem Fall auch:

DrawMovie(Video, 50, 50, I, -1)

16.4 Video schließen

Am Ende schließen Sie das Video wieder, was seinen Speicherplatz freigibt:

CloseMovie Video

Das waren schon alle Videobefehle.

Beachten Sie dabei, dass die Größe auch abhängig ist von der Auflösung des Bild-schirms. Ein Video im Format 200 x 200 erscheint in einer Monitorauflösung von640 x 480 viel größer als etwa bei 1024 x 768.

Page 172: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

172

Videos16j e t z t l e r n e i c h

16.5 Wiederholtes Abspielen

Ein Video lässt sich nur einmal abspielen. Soll es mehrfach ablaufen, müssen Sie es mitCloseMovie zunächst schließen und dann mit OpenMovie() erneut öffnen.

16.6 Aufgabe

1. Schreiben Sie ein kleines Programm, das ein festgelegtes Video lädt und abspielt.Mit Tastendrücken kann das Video pausiert, fortgesetzt oder von vorn begonnenwerden.

Thomas Köhre, www.lcm-network.info: »Als in den frühen 90er Jahren die CD dasSpeichermedium Floppy-Disk ersetzte, kam die große Zeit der Filmsequenzen. Man-ches Computerspiel setzte Videos als spieldefinierendes Mittel ein. Titel wie »Phan-tasmagoria« oder »Wing Commander 3« erschienen auf einer Handvoll Silberschei-ben und bereiteten der CD-ROM den Durchbruch.

Doch zwei Jahre später gab es kaum noch Computerspiele, die sich mit großartigenVideosequenzen rühmen konnten. Die hohen Kosten zeigten die Grenzen des Video-wahns auf. Das künstlerische Mittel Video war recht schnell aufgebraucht. SchnelleGrafikkarten mit 3D-Unterstützung machten eine in Echtzeit berechnete realistischeSpielwelt möglich. Durch den nahtlosen Übergang von Spielwelt zu Zwischen-sequenz wurde die Synthese aus Spiel und Story perfekt.

Führende Spieledesigner sind dem Video weniger aufgeschlossen, als es der DVD-verwöhnte Spieler sich wünschen mag. Die Produktion einer Videosequenz muss vonDritten durchgeführt werden und schneidet den Spielentwickler von der Einflussnah-me ab, denn er ist kein Regisseur und Kameramann in einem. Die Filmsequenz störtoft auch den Spielablauf. So ist es heute das Maximum, Firmenlogo und Eingangs-sowie Finalsequenz in Videoform zu gestalten. Selbst die zwischen den Levels liegen-den Sequenzen gestaltet man lieber im Rahmen der Spielwelt, mit den Fähigkeitender Grafik-Engine.

Zu Beginn und zum Ende kann man aber gern stimmungsvolle Eingangsbilder spen-dieren. Zum Abschluss des Spiels sollte eine kleine oder größere Belohnung in Formeiner animierten Schlusssequenz und eines Abspann im Kinoformat belohnen. Weniglässt ein Spiel besser im Gedächtnis bleiben als eine fantastische Endsequenz, wennman sich schon stunden- oder tagelang durchs Spiel »gequält« hat.«

Page 173: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

173

jetz

t le

rne

ich

KAPITEL 17

Dateien

Größere Projekte verteilt man auf mehrere Dateien. Das hat viele Vorteile. Denken Siean Informationen über einzelne Levels. Es ist sehr bequem, sie in einzelnen Dateien zuspeichern. Sie erhöhen die Übersicht und nehmen Korrekturen an Levels vor, ohnedas Hauptprogramm zu verändern. Wenn jeder Level in einer eigenen Datei gespei-chert ist, fügen Sie mühelos neue Ebenen hinzu. Programmieren Sie die Levelverwal-tung so, dass sie automatisch erkennt, wie viele Levels das Spiel hat.

Das Arbeiten mit Dateien kann man in mehrere Bereiche unterteilen: Der Quelltextlässt sich auf mehrere Dateien aufteilen. Ein ganzer Satz an Befehlen ermittelt, wie vie-le und welche Dateien ein Verzeichnis enthält, erstellt und löscht Ordner, liest undschreibt Dateien.

17.1 Verteilte Quelltexte

Falls Ihr Quelltext zu lang und unübersichtlich geworden ist, teilen Sie ihn in mehrereDateien auf. So lassen sich Themengruppen wie verwandte Unterprogramme undFunktionen in separate Dateien verschieben. Mit dem Schlüsselwort Include informie-ren Sie Blitz Basic beim Übersetzen des Programms darüber, dass es weitere Teile inanderen Dateien berücksichtigen soll:

Include "Levels.bb"

Sie verwenden beliebig viele Include-Anweisungen, gefolgt von jeweils einer Quellda-tei. Blitz Basic wird daraus ein Programm erzeugen, als ob alle Befehle in einer Quell-datei stünden.

Neben dem Aufteilen eines größeren Projekts lässt sich das Verfahren auch dazu be-nutzen, um häufig verwendete Funktionen leicht in mehrere Spiele einzubinden. Den-ken Sie dabei an den Aufbau einer Bibliothek von Unterprogrammen, die Sie in allenSpielen nutzen wollen. Mit einem Include-Befehl stellen Sie sie in einem Programm

Page 174: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

174

Dateien17j e t z t l e r n e i c h

zur Verfügung. Anstatt für jedes Spiel das Rad neu zu erfinden, greifen Sie auf Altbe-währtes zurück und konzentrieren sich auf andere Dinge.

17.2 Lesen und Verändern von Verzeichnissen

Alte Hasen werden noch DOS-Befehle wie cd, copy und del kennen. Blitz Basic bietetIhnen ein ähnliches Set an Anweisungen, um Verzeichnisse zu erstellen bzw. zu lö-schen und um Dateien zu kopieren und zu löschen.

Diese Anweisungen unterscheiden sich von ähnlichen Befehlen anderer Programmier-sprachen darin, dass sie meist keine Rückmeldung über die erfolgreiche Ausführunggeben. Ein Beispiel: Sie benutzen einen Befehl, um eine Datei zu löschen (etwa einenSpielstand, den der Benutzer Ihres Spiels nicht mehr benötigt), erfahren aber hinterhernicht, ob die Datei tatsächlich gelöscht wurde. Um sicherzugehen, sollten Sie einen ge-eigneten Test vornehmen, etwa prüfen, ob die Datei noch vorhanden ist, und eine Feh-lermeldung ausgeben (»Datei konnte nicht gelöscht werden«).

Oft werden Sie diese Befehle nicht brauchen. Mir fällt in erster Linie ein Fenster ein,in dem Spieler einen Zielordner für Spielstände auswählen können, selbst einen, denes noch zu erstellen gilt. Bei einfachen Arcade-Spielen wollen freilich die Wenigstenvor eine solche Entscheidung gestellt werden. Ihnen genügt es, zum Beispiel auf Ëzu drücken, um zu speichern, und auf Ì, um zu laden.

17.2.1 Ordnernamen ermittelnDie Funktion CurrentDir$() liefert Ihnen den Namen des aktuellen Ordners:

Print CurrentDir$()

217.2.2 Ordner auslesenNicht so einfach erfahren Sie, welche Dateien ein Ordner enthält. Sie müssen dreiSchritte ausführen:

1. Ordner »öffnen« (ReadDir())

2. Nacheinander alle Dateinamen auslesen (NextFile())

3. Ordner schließen (CloseDir)

Mit ReadDir() sagen Sie Blitz Basic, um welchen Ordner es geht. Der Befehl liefert Ih-nen eine Kennzahl, die Sie sich (in einer Variable) merken. Über diese Kennzahl grei-fen Sie später auf den Ordner zu:

Ordner = ReadDir("c:\windows")

Nun lesen Sie Dateinamen aus. Jedes Mal, wenn Sie den Befehl NextFile verwenden,erhalten Sie einen weiteren Dateinamen als Zeichenkette:

Beachten Sie dabei, dass der Ordnername mit "\" endet. In frühen Blitz-Basic-Ver-sionen fehlte das Trennzeichen. Sie fügen damit direkt an den Ordnernamen einenDateinamen an.

Page 175: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

175

Lesen und Verändern von Verzeichnissen j e t z t l e r n e i c h

Datei1 = NextFile(Ordner)Datei2 = NextFile(Ordner)Datei3 = NextFile(Ordner)

Sobald keine weiteren Dateien übrig sind, meldet NextFile() Ihnen eine leere Zeichen-kette (""). Weil Sie nicht erfragen können, wie viele Dateien ein Ordner enthält, bietetes sich an, mithilfe einer Schleife alle Dateinamen in ein ausreichend großes Dim-Feldzu lesen – so lange, bis NextFile() »leer« ist – oder Types zu verwenden.

0Nach getaner Arbeit schließen Sie den Ordner wieder mit CloseDir:

CloseDir(Ordner)

Das folgende Beispiel listet alle Dateien eines Ordners auf:

; ORDNER1.BBOrdner$ = Input("Welcher Ordner? ")OrdnerNr = ReadDir(Ordner$)Repeat A$ = NextFile(OrdnerNr) If A$ <> "" Then Print A$Until A$ = ""CloseDir(OrdnerNr)WaitKey

0

Besonders komfortabel ist das nicht, aber es waren auch nur ein paar Zeilen. Mal se-hen, wie wir unseren Datei-Lister verbessern können, zum Beispiel durch die Angabeder Dateigröße. Mit FileSize() erfahren Sie die Größe einer Datei:

Print FileSize("c:\windows\win.ini")

0

Vielleicht ist Ihnen aufgefallen, dass NextFile() nicht nur Dateien findet, sondern auchVerzeichnisse, die sich im gewünschten Ordner befinden. Das liegt daran, dass die Na-men von Dateien und Verzeichnissen auf der Festplatte auf die gleiche Weise gespei-chert werden. Lediglich eine zusätzliche Kennung weist auf den Unterschied hin. DieFunktion FileType() liefert Ihnen die Kennung:

Print FileType("c:\windows\win.ini")

Mit Blitz Plus geht das einfacher: Mit der – derzeit »geheimen« – Funktion MoreFiles()ermitteln Sie die Anzahl der Dateien, die noch mit NextFile() ausgelesen werdenkönnen.

Vielleicht kommen Ihnen die Ordner "." und ".." merkwürdig vor, die sich in jedemVerzeichnis befinden. Dabei handelt es sich nicht etwa um Fehler: Es sind Platzhalter,die das Betriebssystem nutzt, um das aktuelle und das übergeordnete Verzeichnis fest-zulegen.

FileSize() verlangt den vollständigen Dateinamen mit Pfad. NextFile() liefert je-doch den Namen ohne Pfad. Sie stellen daher dem Dateinamen den Pfad, also dasVerzeichnis, gefolgt von "\", voran, bevor Sie eine durch NextFile() übergebene Da-tei an FileSize() weiterleiten.

Page 176: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

176

Dateien17j e t z t l e r n e i c h

Sie erhalten:

� 0, wenn die Datei nicht gefunden wurde

� 1, wenn es sich um eine Datei handelt

� 2, wenn es sich um ein Verzeichnis handelt

Verbessern wir damit die Anzeige. Schreiben wir Verzeichnisse in Blockschrift, Datei-namen in Kleinschrift. Fügen wir hinter den Namen die Kennung "<Verzeichnis>"oder die Dateigröße an:

; ORDNER2.BBOrdner$ = Input("Welcher Ordner? ")OrdnerNr = ReadDir(Ordner$)Repeat A$ = NextFile(OrdnerNr) If A$ <> "" Then If FileType(Ordner$ + "\" + A$) = 1 Then Print LSet$(Lower(A$),30) + " " + FileSize(Ordner$ + "\" + A$) + " Byte" Else Print LSet$(Upper(A$),30) + " <Verzeichnis>" EndIf EndIfUntil A$ = ""CloseDir(OrdnerNr)WaitKey

Noch schöner wäre eine Sortierung, jeweils separat Verzeichnisse und Dateien. Dazumüssten Sie alle Dateien zunächst in ein Feld (oder eine dynamische Type-Liste) einle-sen. Eine weitere Spalte könnte die Kennung (Datei oder Verzeichnis) aufnehmen.Leicht geben Sie damit nacheinander erst alle Verzeichnisse, anschließend alle Dateienaus. Falls Sie auf eine Sortierung verzichten, wäre eine Alternative möglich: Sie öffnendas Verzeichnis zweimal hintereinander und geben über eine If-Einschränkung beimersten Mal nur die Verzeichnisse, beim zweiten Mal nur die Dateien aus.

117.2.3 Ordner wechselnMit ChangeDir wechseln Sie in den angegebenen Ordner:

ChangeDir "c:\windows"

Der Befehl arbeitet ähnlich wie der DOS-Befehl cd. Neben absoluten (vollständigen)Pfadangaben sind auch relative Verweise in der Art

ChangeDir ".."ChangeDir "\windows"ChangeDir "..\tools\source"

erlaubt. Die beiden Punkte stehen dabei als Platzhalter für das übergeordnete Verzeich-nis. Von c:\windows\fonts wechseln Sie mit .. daher nach c:\windows.

0

Das Erfragen von Dateiattributen wie »schreibgeschützt« und des Datums der letztenÄnderung ist mit Blitz Basic nicht möglich.

Falls der Zielordner nicht existiert, findet kein Wechsel statt. Mit CurrentDir$() über-prüfen Sie, ob der Wechsel erfolgreich war.

Page 177: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

177

Öffnen von Dateien j e t z t l e r n e i c h

17.2.4 Ordner erstellenDer Befehl CreateDir erstellt einen neuen Ordner:

CreateDir "c:\savegames"CreateDir "saves"

17.2.5 Ordner löschenSein Gegenstück heißt DeleteDir. Der Befehl löscht einen leeren Ordner:

DeleteDir "c:\savegames"DeleteDir "saves"

Wenn Sie den Befehl auf einen Ordner anwenden, der Dateien enthält, passiert nichts.

17.2.6 Datei löschenDer Befehl DeleteFile löscht eine Datei:

DeleteFile "c:\savegames.dat"

Die Datei wird nicht gelöscht, wenn sie mit dem Attribut »schreibgeschützt« versehenist oder gerade durch ein anderes Programm verwendet wird.

17.2.7 Datei kopierenMit CopyFile kopieren Sie eine Datei in einen anderen Ordner. Sie geben dazu den Na-men der zu kopierenden Datei (Quelle) sowie den Namen der Zieldatei an:

CopyFile "c:\savegames.dat", "c:\savegames.bak"CopyFile "c:\savegames.dat", "c:\bak\savegames.dat"

1

17.3 Öffnen von Dateien

Sie können Daten aus Dateien lesen und Daten in eine Datei schreiben. Je nachdem,ob Sie lesen, schreiben oder beides möchten, verwenden Sie einen der folgenden Be-fehle, um die Datei zu öffnen:

� OpenFile() zum Lesen und Schreiben; Datei muss vorhanden sein

� ReadFile() zum Lesen; Datei muss vorhanden sein

� WriteFile() zum Schreiben; Datei wird notfalls erstellt

Jeder Befehl liefert eine Kennung zurück, über die Sie die Datei später ansprechen.Daher verwenden Sie den Befehl zusammen mit einer Variablenzuweisung:

datei = OpenFile("c:\autoexec.bat")

Der Name der Zieldatei darf nicht fehlen. Es genügt nicht, nur einen Zielordner an-zugeben. Falls die Zieldatei bereits existiert, wird sie durch das Kopieren überschrie-ben. Der Name der Zieldatei muss nicht mit der Quelldatei identisch sein. Sie könnensie daher während des Kopierens umbenennen. Wenn Sie die Zieldatei nach dem Ko-pieren mit DeleteFile löschen, haben Sie sie in zwei Schritten verschoben.

Page 178: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

178

Dateien17j e t z t l e r n e i c h

Hat die Kennung den Wert 0, dann konnte die Datei nicht geöffnet werden. Der Grundist meistens, dass sie nicht existiert:

datei = OpenFile("c:\blabla.txt")If datei = 0 Then Print "Datei nicht gefunden."

OpenFile() und WriteFile() reagieren unterschiedlich auf das Öffnen einer nicht vor-handenen Datei: OpenFile() liefert die Kennung 0. WriteFile() erzeugt eine Datei mitdem angegebenen Namen. Daher können Sie mit WriteFile() eine Datei erstellen,etwa einen Spielstand.

Die Kennung ist ebenfalls 0, wenn ein Schreibzugriff (OpenFile(), WriteFile()) ge-wünscht wird, die Datei aber das Attribut »schreibgeschützt« hat.

Ist die Arbeit mit der Datei abgeschlossen, schließen Sie sie wieder. Damit haben Sie ei-nen weiteren Einsatz der Kennungsvariable erfahren:

CloseFile datei

17.3.1 Lesen und Schreiben von DatenEine Datei ist eine Ansammlung von Bytes, Dateneinheiten, die jeweils einen Wert zwi-schen 0 und 255 annehmen. Bytes werden als Zahlen, als Teil von Zahlen, als Buch-stabe oder als Teil eines Befehlscodes interpretiert.

In Blitz Basic verwenden Sie drei Datentypen:

� ganze Zahlen (Integer)

� reelle Zahlen (Float)

� Zeichenketten (Strings)

Jeden dieser Datentypen können Sie in eine Datei schreiben und aus einer Datei lesen.Für ganze Zahlen und Zeichenketten gibt es darüber hinaus Abstufungen.

Normalerweise wird eine ganze Zahl in vier Byte gespeichert. Sie nimmt einen Bereichvon +/– 2 Milliarden ein. Wenn Ihre Zahlen in kleineren Bereichen liegen, lassen siesich auf platzsparendere Weise in einer Datei ablegen, wie folgende Tabelle zeigt.

Das lohnt sich, wenn Sie besonders viele Daten verwenden. Nehmen wir an, Ihr Spielhat 50 Levels und der Aufbau jedes Levels wird in 4000 Zahlen gespeichert. Das wä-ren normalerweise 50 x 4000 x 4 = 800.000 Byte. Als Datentyp »Byte« verringert sichdie Größe auf ein Viertel.

Typ Wertebereich Platzverbrauch

Integer –2147483648 bis +2147483647 4 Byte

Short Integer 0 bis 65535 2 Byte

Byte 0 bis 255 1 Byte

Page 179: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

179

Öffnen von Dateien j e t z t l e r n e i c h

1

Zeichenketten lassen sich wahlweise als ganze Zeilen lesen und schreiben. Dieses Ver-fahren bietet sich an, wenn Sie normale Textdateien einlesen oder erzeugen wollen.Normalerweise schreibt Blitz Basic Zeichenketten in eine Datei auf eine Weise, die sichmit einem normalen Texteditor schwer ansehen lässt.

Für all diese Arten von Daten gibt es jeweils einen Befehl zum Auslesen aus einer Dateiund zum Schreiben in eine Datei (siehe folgende Tabelle).

Keine Angst: Es ist weniger wild, als es aussieht.

Der Lesebefehl benötigt als Parameter die Kennung der geöffneten Datei. Was er Ih-nen übergibt, weisen Sie entweder einer Variable zu oder drucken es mit Print sofortauf den Bildschirm:

Print ReadLine(datei)

Der Schreibbefehl erwartet als Parameter die Dateikennung und die Daten, die ge-schrieben werden sollen:

WriteLine datei, "Diese Zeile wird in eine Datei geschrieben."

Das war es schon. Probieren wir, eine Textdatei zu erzeugen ...

; SCHREIBEN1.BBdatei = WriteFile("c:\blabla.txt")WriteLine datei, "Ein Ring, sie zu knechten."CloseFile dateiWaitKey

... und ihren Inhalt wieder auszulesen:

; LESEN1.BBdatei = ReadFile("c:\blabla.txt")Print ReadLine(datei)CloseFile dateiWaitKey

Dieses Sparprogramm funktioniert nur in Extradateien. Egal, ob Integer, Short Inte-ger oder Byte: Im Arbeitsspeicher werden alle Zahlen in normalen 4 Byte großen In-teger-Variablen abgelegt. Die Ausnahme sind Speicherbänke, zu denen wir einigeSeiten später kommen. Mit ihnen verwalten Sie große Datenmengen im Arbeitsspei-cher genauso platzsparend wie in einer Datei.

Datentyp Byte Lesebefehl Schreibbefehl

Ganze Zahl (Integer) 4 ReadInt() WriteInt

Ganze Zahl (Short Integer) 2 ReadShort() WriteShort

Ganze Zahl (Byte) 1 ReadByte() WriteByte

Reelle Zahl 4 ReadFloat() WriteFloat

Zeichenkette 4 + Länge ReadString() WriteString

Zeile Länge ReadLine() WriteLine

Page 180: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

180

Dateien17j e t z t l e r n e i c h

So einfach ist das! Für einzelne Zeichenketten verwenden Sie besser WriteString():

; SCHREIBEN2.BBData "Krummbein", "Hedwig", "Krätze"datei = WriteFile("c:\blabla.txt")For I=1 To 3 Read A$ WriteString datei, A$NextCloseFile dateiWaitKey

Die drei Zeichenketten lesen Sie auf umgekehrtem Weg aus:

; LESEN2.BBdatei = ReadFile("c:\blabla.txt")For I=1 To 3 Print ReadString(datei)NextCloseFile dateiWaitKey

Ähnlich funktioniert es mit Zahlen:

; SCHREIBEN3.BBData 145, 783, 10367, 13, 7datei = WriteFile("c:\blabla.txt")For I=1 To 5 Read A WriteShort datei, ANextCloseFile dateiWaitKey

Und so lesen wir die fünf Zeilen aus der Datei wieder heraus:

; LESEN3.BBdatei = ReadFile("c:\blabla.txt")For I=1 To 5 Print ReadShort(datei)NextCloseFile dateiWaitKey

Beachten Sie dabei, dass Blitz Basic nicht weiß, welche Datentypen Sie in der Datei ab-gelegt haben. Wenn Sie eine Zahl vom Typ Short Integer in die Datei schreiben, dannmüssen Sie an der gleichen Stelle denselben Typ auslesen, um den richtigen Wert zuerhalten. Und nicht nur das: Sämtliche Folgewerte wären damit auch falsch. Die Zah-len werden in jeweils einer, zwei oder vier Speicherstellen abgelegt. Wenn Sie aus einerSpeicherstelle, die eine vier Byte große Zahl enthält, nur zwei Byte auslesen, erhaltenSie nicht nur eine falsche Zahl. Auch der nächste Lesevorgang wird ab dem drittenByte der Zahl beginnen. Ist die Position einmal aus dem Tritt geraten, werden Sie fort-laufend falsche Werte einlesen. Ersetzen Sie im vorigen Beispiel ReadShort() durchReadByte() und führen Sie das Programm noch einmal aus, um zu sehen, was ichmeine.

Page 181: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

181

Öffnen von Dateien j e t z t l e r n e i c h

A17.3.2 Little Endian FormatBeim Speichern von Zahlen kann Ihnen eine Besonderheit Kopfzerbrechen bereiten.Die 4-Byte-Zahl 100.000 ergibt 186A0H in hexadezimaler (H!) Notation und damitdie vier einzelnen Bytes 00 01 86 A0, die in je eine Speicherzelle geschrieben werden.Es wäre vernünftig zu denken, dass dies nacheinander geschieht. Aber Computer ha-ben ihren eigenen Willen. Die Reihenfolge ist nämlich A0 86 01 00: Die beiden äußerenBytes werden miteinander vertauscht, dann die beiden inneren (bei 2-Byte-Werten fin-det nur ein Tausch statt). Der Programmierer nennt diese Eigenheit Little Endian For-mat. Normalerweise müssen Sie darüber nichts wissen, weil der Computer von alleindarauf achtet.

Wenn Sie jedoch die 4-Byte-Zahl 000186A0H in eine Datei (oder eine Speicherbank)schreiben und an der gleichen Stelle eine 2-Byte-Zahl auslesen, dann erhalten Sie nichtetwa die Bytes 00 01, sondern A0 86 (was 86A0H = 34464 dezimal ergibt).

; LITTLE_ENDIAN.BBdatei = WriteFile("c:\blabla.txt")WriteInt datei, 100000CloseFile datei;datei = ReadFile("c:\blabla.txt")Print ReadShort(datei)CloseFile dateiWaitKey

17.3.3 Eof()Für das Lesen und Schreiben vieler Daten verwenden Sie am besten eine For-Schleife.Sie nutzt aber nur, wenn die Menge der Daten bekannt ist. Wenn Sie ein Programmschreiben, das eine beliebige Textdatei einliest und Zeile für Zeile auf dem Bildschirmausdruckt, wäre es hilfreich zu wissen, wie viele Zeilen die Datei hat. Nun, sagen kannIhnen das Blitz Basic nicht. Es beantwortet Ihnen nur die Frage, ob das Dateiende be-reits erreicht ist. Im Normalfall reicht dieses Wissen auch aus: Sie lesen eben so langeZeile für Zeile, bis Blitz Basic sagt: Ende.

Dafür gibt es die Funktion Eof(), die Abkürzung für End of File, Dateiende. Sie lieferteine 1, falls Sie aus der Datei keine weiteren Daten mehr lesen können, ansonsten eine0:

; EOF.BBdatei = ReadFile("c:\autoexec.bat")Repeat Print ReadLine(datei)Until Eof(datei) = 1CloseFile dateiWaitKey

17.3.4 Dateizeiger ändernÄhnlich wie bei Read/Data lesen und schreiben Sie Daten hintereinander weg. Jedochkönnen Sie die aktuelle Position erfragen und festlegen. Dazu dienen die Befehle Fil-ePos() und SeekFile.

Page 182: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

182

Dateien17j e t z t l e r n e i c h

FilePos() übermittelt Ihnen die aktuelle Lese- oder Schreibstelle. Als Parameter gebenSie die Dateikennung an. Die Maßeinheit sind Speicherstellen, also Bytes. Die ersteSchreibstelle ist 0. Das Beispiel ...

; FILEPOS.BBdatei = ReadFile("c:\blabla.txt")For I=1 To 4 Print ReadShort(datei)NextPrint "Lesepostion:"Print FilePos(datei)CloseFile dateiWaitKey

... ergibt die Position 8: Viermal wird eine Zahl vom Typ Short Integer, 2 Byte lang,ausgelesen. Insgesamt werden also 8 Byte ausgelesen, die Positionen 0 bis 7. Dienächste Position ist damit 8.

SeekFile ist der Gegenpart: Er benötigt die Dateikennung sowie eine neue Position inBytes. Ab dieser Stelle greift der nächste Lese- oder Schreibbefehl:

; SEEKFILE.BBdatei = ReadFile("c:\blabla.txt")SeekFile datei, 2Print ReadShort(datei)CloseFile dateiWaitKey

Wenn Sie mit Daten gleicher Länge arbeiten, greifen Sie mit SeekFile schnell auf be-stimmte Werte zu. Sie multiplizieren nur die Nummer des gewünschten Datensatzesmit seiner Länge. (Na ja, ganz so einfach ist es nicht: 100 Datensätze je 4 Byte ergeben400 Byte Gesamtmenge für alle Datensätze. Der 100. Datensatz beginnt ab der 397.Position. Weil die Zählung ab 0 beginnt, ist das eigentlich Position 396.)

Ans Dateiende gelangen Sie schnell, indem Sie den Zeiger auf den Wert setzen, den Ih-nen FileSize() liefert.

1

A17.4 Speicherbänke

Während Sie Zahlen in einer Datei wahlweise in einem, zwei oder vier Byte ablegen,weist Blitz Basic jeder Zahl im Arbeitsspeicher vier Byte zu. Neben einfachen Variab-len, Feldern und Typen stellt Ihnen Blitz Basic mit Speicherbänken eine Alternative zurVerfügung, mit der Sie große Datenmengen auf ähnliche Weise wie in einer Datei de-ponieren. Genau wie in einer Datei speichern Sie beliebig Zahlen verschiedener Byte-Größen und sparen damit viel Platz.

WriteString speichert zuerst die Länge der Zeichenkette in einer vier Byte langenZahl und danach die Zeichenkette selbst. Daher verbraucht eine Zeichenkette immervier Byte mehr, als sie Zeichen lang ist.

Page 183: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

183

Speicherbänke j e t z t l e r n e i c h

Die drei hauptsächlichen Unterschiede zur Datei:

� Eine Datei wird auf Festplatte gespeichert, während eine Speicherbank im Arbeits-speicher liegt.

� Während Sie eine Datei hintereinander lesen und schreiben, können Sie immerjede Position einer Speicherbank erreichen, ohne den Zeiger erst positionieren zumüssen.

� Eine Speicherbank eignet sich nur für Zahlen, nicht für Zeichenketten.

Da sich sehr leicht Daten zwischen Speicherbänken und Dateien austauschen lassen,lohnt sich die Kooperation vor allem dann, wenn große Datenmengen, etwa Level-daten, von einer Datei in den Arbeitsspeicher geladen werden sollen.

117.4.1 Speicherbank erstellenMit CreateBank() erzeugen Sie eine Bank. Als Parameter übergeben Sie die Größe inByte. Sie ist abhängig von der Anzahl und Byte-Größe der zu speichernden Zahlen:Wenn Sie 200 Zahlen mit vier Byte Größe speichern wollen, wählen Sie etwa 8000.Wie bei einer Datei liefert Ihnen die Funktion eine Kennziffer, über die Sie die Bankspäter ansprechen:

bank = CreateBank(8000)

Sie können die Größe einer Speicherbank nachträglich ändern:

ResizeBank bank, 10000

Die Daten bleiben dabei erhalten. Bei einer Verkleinerung wird ein Teil allerdings ab-geschnitten und verfällt. Bei einer Vergrößerung wird mit Nullwerten aufgefüllt.

Wenn Sie die Dienste der Bank nicht mehr benötigen, geben Sie den in Beschlag ge-nommenen Speicher wieder frei:

FreeBank bank

0

17.4.2 Speicherbank beschreiben und auslesenBlitz Basic bietet jeweils vier Funktionen zum Lesen und vier Befehle zum Schreibenvon Werten in eine Bank. Sie sind in ihrer Handhabung sehr ähnlich und unterschei-den sich nur in der Byte-Größe.

Eine ganze Zahl schreiben Sie mit PokeInt bank, position, zahl. Sie lesen sie spätermit zahl = PeekInt(bank, position) aus. Die anderen drei Kommandopaare funktio-nieren genauso.

Allerdings verläuft das Lesen und Schreiben bei Speicherbänken erheblich langsamerals bei einem Dim-Feld. Daher taugen Speicherbänke eher zum Aufbau eines Spielsals zum Verlauf.

Mit der Funktion LockedPixels() lässt sich unter Blitz Plus der Videospeicher alsSpeicherbank ansprechen. Er kann damit frei gelesen und beschrieben werden. EinBeispiel finden Sie in der Online-Hilfe. Eine detaillierte Beschreibung anspruchsvollerPixel-Manipulationen würde hier zu weit führen.

Page 184: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

184

Dateien17j e t z t l e r n e i c h

Ein kleines Beispiel soll Ihnen das Verwenden einer Speicherbank verdeutlichen. Icherzeuge eine 2000 Byte große Bank, erstelle 1000 Zufallszahlen und speichere sie als2-Byte-Werte in die Bank. Im zweiten Schritt werden die ersten 10 Zahlen aus derBank gelesen und ausgedruckt:

; BANK1.BBbank = CreateBank(2000)SeedRnd MilliSecs()For I=0 To 999 PokeShort bank, I*2, Rand(32000)NextFor I=0 To 20 Step 2 Print PeekShort(bank, I)NextWaitKey

217.4.3 Datenaustausch zwischen zwei SpeicherbänkenSehr einfach kopieren Sie Daten von einer Speicherbank in eine andere. Sie verwen-den dazu CopyBank. Dem Befehl übergeben Sie folgende Parameter:

� Kennung der Quellbank

� Startposition der Quellbank

� Kennung der Zielbank

� Startposition der Zielbank

� Anzahl der zu kopierenden Bytes

Sehr häufig werden Sie den Befehl nicht benötigen; ich spare mir deswegen ein schlau-es Beispiel. Interessant zu wissen ist allerdings, dass Sie mit CopyBank innerhalb einerBank Daten kopieren können. Achten Sie in diesem Fall darauf, dass sich Quell- undZieldaten nicht überlappen.

17.4.4 Datenaustausch zwischen Datei und SpeicherbankNicht umsonst befindet sich der Abschnitt über Speicherbänke im Kapitel über Datei-en. Die Arbeit mit Speicherbänken und Dateien ähnelt sich nicht nur sehr, Sie könnenzwischen beiden Lagerplätzen direkt Daten austauschen.

Datentyp Byte Lesebefehl Schreibbefehl

Ganze Zahl (Integer) 4 PeekInt() PokeInt

Ganze Zahl (Short Integer) 1 PeekShort() PokeShort

Ganze Zahl (Byte) 1 PeekByte() PokeByte

Reelle Zahl 4 PeekFloat() PokeFloat

Anders als bei einem Dim-Feld können Sie nicht davon ausgehen, dass beim Erstelleneiner Speicherbank alle Speicherzellen gelöscht, also mit 0 gefüllt werden.

Page 185: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

185

Patch programmieren j e t z t l e r n e i c h

Hierbei wird nicht zwischen Zahlentypen unterschieden; es werden einfach nur Bytesübertragen. Wie viele, das müssen Sie selbst errechnen: 500 Zahlen je vier Byte etwasind 2000 Byte.

Zunächst öffnen Sie Datei und Speicherbank:

; BANK2.BBdatei = WriteFile("c:\blabla.dat")bank = CreateBank(2000)

Mangels Inhalt füllen wir die Bank mit Zufallszahlen:

For I=0 To 999 PokeShort bank, I*2, Rand(32000)Next

Mit nur einem Befehl kopieren Sie alle 2000 Byte, angefangen von Bankposition 0, indie Datei:

WriteBytes(bank, datei, 0, 2000)

Das war’s schon. Zum Schluss schließen Sie die Datei. Wenn Sie die Speicherbanknicht mehr benötigen, geben Sie den Platz frei:

CloseFile dateiFreeBank bank

Der umgekehrte Weg ist ebenso unspektakulär. ReadBytes liest Werte von einer Dateiin eine Speicherbank; die Parameter sind die gleichen:

; BANK3.BBdatei = ReadFile("c:\blabla.dat")bank = CreateBank(2000)ReadBytes(bank, datei, 0, 2000)CloseFile dateiFor I=0 to 9 Step 2 Print PeekShort(bank, I)NextWaitKey

1

A17.5 Patch programmieren

Das Patchen bezeichnet das Verändern einer Datei, z.B. im Falle von Lese- oderSchreibfehlern: Wir laden eine Datei komplett in den Arbeitspeicher, suchen einenWert, verändern ihn und schreiben die Datei zurück auf die Festplatte. Für diese Auf-gabe eignet sich eine Speicherbank sehr gut. Anhand der Dateigröße, die wir mit File-Size() ermitteln, legen wir die Größe der Bank fest.

Auf den ersten Seiten dieses Buchs wurde ein Problem geschildert, das Ihnen mögli-cherweise selbst schon begegnet ist: Starten Sie ein Blitz-Basic-Programm aus dem

ReadBytes() und WriteBytes übergeben als Rückgabewert die Zahl der gelesenenoder geschriebenen Bytes. Diese Information ist im Regelfall nutzlos, weil Sie ja fest-legen, wie viele Bytes Sie lesen oder schreiben möchten. Allerdings erfahren Sie da-mit, ob ein Fehler vorliegt, ob zum Beispiel weniger Daten gelesen werden konnten,als Sie beabsichtigt hatten (weil die Datei weniger Daten enthält). WriteBytes schrei-ben Sie in diesem Fall als Funktion, mit den Parametern in Klammern.

Page 186: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

186

Dateien17j e t z t l e r n e i c h

Editor heraus, ohne den Quelltext abzuspeichern, wird in jüngeren Versionen automa-tisch ein Backup TMP\TMP.BB erstellt. Das ist fürsorglich, aber dann problematisch,wenn das Programm weitere Dateien wie Grafiken benötigt. Fehlen Pfadangaben,sucht das Programm sie nämlich im Ordner TMP – und wird dort nichts finden. Die Si-cherung von Blitz Basic ist hilfreich, aber ideal wäre sie, wenn sie nicht in einem Extra-Ordner, sondern im Hauptverzeichnis von Blitz Basic vorgenommen würde.

Das Problem lösen wir, indem wir einfach den Dateinamen verändern. Der Editor ver-birgt sich in der Datei BIN\IDE.EXE. Sie vergibt den Namen TMP\TMP.BB unddaher liegt es nahe, dass die EXE-Datei diese Zeichenkette enthält. (Mit einem Hex-Editor, zum Beispiel »WinHex«, www.winhex.de, lässt sich das leicht überprüfen.)

Unser Plan: Finden und Ersetzen der Zeichenkette. Dabei darf sich die Länge nicht än-dern. Wir können ja nicht einfach in einer Programmdatei Code verändern. UnserProblemkind ist das Backslash-Zeichen, das in den anderen Ordner führt. Wir brau-chen es nur zu entfernen und Blitz Basic speichert die Temp-Datei künftig im Haupt-ordner. Dazu ersetzen wir »\« durch »-«: Statt TMP\TMP.BB heißt die Zieldatei nunTMP-TMP.BB. (Wir hätten auch mehr als ein Zeichen ersetzen können, aber mir fielkein schlauerer Name ein.)

Wir sind dazu angehalten, ohne Zeichenketten zu arbeiten. Binärdateien lassen sichfehlerfrei nur byteweise auslesen und Speicherbänke unterstützen überhaupt keine Zei-chenketten. Daher betrachten wir die ASCII-Codes der Zeichenkette »TMP\« als 4-Byte-Zahl und erhalten unter Berücksichtigung des Little-Endian-Formats den Wert1550871924. Zuvor haben wir uns vergewissert, dass die Zeichenkette nur einmal in derEXE-Datei enthalten ist (wiederum mit einem Hex-Editor oder, falls keiner zur Handist, mit einem selbst geschriebenen Programm). An der Fundstelle ersetzen wir die Zei-chenkette. Genauer: Wir zählen von der Fundstelle drei Speicheradressen weiter undtragen dort 45 ein, den ASCII-Code für »-«.

Am Schluss schreiben wir alle Daten wieder zurück auf die Festplatte. Bei dem geplan-ten Patch gilt es eine Besonderheit zu beachten: Wir können unser Blitz-Basic-Pro-gramm nicht aus dem Editor heraus starten. Denn in diesem Fall wäre ja genau dieDatei IDE.EXE aktiv, die wir verändern wollen. Das erlaubt Windows nicht. Also:Quelltext zu einer EXE-Datei kompilieren, Editor schließen, Programm starten. Freilichentfällt der Aufwand, wenn Sie einen alternativen Editor verwenden, etwa »BlitzView«.

So oder so erstellen wir von der Datei, die wir patchen, eine Sicherheitskopie – fallsetwas schief geht. Um das Programm zum Laufen zu bringen, müssen Sie die Pfade zurQuelldatei und Sicherheitskopie anpassen.

; PATCH.BB; Dieses Programm kann nicht vom BB-Editor aus gestartet werden.; Erst EXE-Datei kompilieren und nur diese aufrufen.

; Vorbereitungenquelldatei$ = "c:\basic\bin\ide.exe" ; <--- anpassenzieldatei$ = quelldatei$kopie$ = "c:\basic\bin\ide.ori" ; <--- anpassen

groesse = FileSize(quelldatei$) - 1lesen = ReadFile(quelldatei$)bank = CreateBank(groesse+4)

Page 187: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

187

Patch programmieren j e t z t l e r n e i c h

; Sicherheitskopie erstellenPrint "Sicherheitskopie " + kopie + " erstellen."CopyFile quelldatei, kopie

; Datei in Speicherbank kopierenWrite "Datei " + quelldatei$ + " einlesen ... "For I=0 To groesse A = ReadByte(lesen) PokeByte bank, I, ANextCloseFile lesenPrint "Ok"

; Zeichenkette suchenPrint "Zeichenkette suchen ..."For I=0 To groesse If PeekInt(bank, I) = 1550871924 Then Print "Gefunden bei Offset " + I Exit EndIfNextIf I = groesse + 1 Then Print "Wert nicht gefunden! Abbruch!" WaitKey EndEndIf

; Wert ändernWrite "Wert patchen ... "PokeByte bank, I + 3, 45 ; 45 = Ascii-Wert von "-"Print "Ok"

; Datei schreibenWrite "Datei " + zieldatei$ + " schreiben ... "schreiben = WriteFile(zieldatei$)For I=0 To groesse A = PeekByte(bank, I) WriteByte schreiben, ANextCloseFile schreibenPrint "Ok"

WaitKey

Der Patch wurde erfolgreich mit Version 1.80 von Blitz Basic getestet und sollte mit al-len Versionen funktionieren, die eine TMP-Datei speichern.

Abschließend – sonderlich effektiv ist unser Patch nicht. Wir verändern nur ein Byte,speichern aber die ganze Datei noch einmal. Sinnvoller wäre es gewesen, die Ziel-adresse anzusteuern und den neuen Wert zu schreiben. Die eigentliche Suche nach derZieladresse darf hingegen nicht entfallen, will man sichergehen, dass der Patch mit ver-schiedenen Programmversionen funktioniert, bei denen die gesuchte Zeichenkette anverschiedenen Stellen steht.

Page 188: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

188

Dateien17j e t z t l e r n e i c h

A17.6 Ordner des Betriebssystems erfragen

Normalerweise wird ein Spielstand im gleichen Ordner abgelegt, in dem das Spiel in-stalliert ist, oder in einem ihm untergeordneten Verzeichnis. Das geht meistens in Ord-nung. Wenn ein Spiel allerdings direkt von CD ausgeführt werden soll, ohne es aufFestplatte zu installieren, dann müssen die Spielstände und temporäre Dateien (mitDaten, die nur während des Spiels notwendig sind und bei Spielende gelöscht werden)gezielt auf Festplatte geschrieben werden. Eine einfache, aber nicht sehr eleganteLösung ist es, dem Dateinamen "C:\" voranzustellen, damit die Dateien ins Wurzel-verzeichnis von C: gelangen.

Besser ist es, den Spielstand im Windows-Ordner abzulegen und temporäre Dateien imTEMP-Ordner. Die Pfade dorthin sind aber von PC zu PC verschieden. Der eine nenntseinen Windows-Ordner C:\WIN, der andere C:\WINDOWS und der dritteC:\WIN2K. Sie müssen nicht rätseln: Die richtige Antwort gibt Ihnen die FunktionSystemProperty(). Sie erwartet einen der folgenden Parameter:

Um eine Datei etwa im TEMP-Verzeichnis abzulegen, übergeben Sie dem Kommandozum Öffnen eine Zeichenkette wie SystemProperty("TEMPDIR") + "MONSTER.DAT". Be-achten Sie dabei, dass der Trenner "\" bereits Teil des zurückgegebenen Ordners ist.

Als Namen des Betriebssystems gibt Blitz Basic nur den Oberbegriff zurück, also »Win-dows 98« auch bei »Windows 98 – Zweite Ausgabe« oder »Windows XP« sowohl bei derHome- wie bei der Pro-Edition.

Der Name des Ordners ist das Verzeichnis, aus dem heraus das Blitz-Basic-Programmgestartet wird.

A17.7 Andere Programme ausführen

Innerhalb eines Blitz-Basic-Programms können Sie ein beliebiges anderes Programmaufrufen und starten. In den meisten Fällen wird das eine EXE-Datei sein. Sie nennendazu dem Befehl ExecFile die gewünschte Datei, gegebenenfalls ergänzt um den kom-pletten Pfad und Parameter – und zwar als Zeichenkettenvariable oder als Zeichenkettein Anführungszeichen:

ExecFile "programm.exe"

Die Möglichkeiten dafür sind mannigfaltig. Durch das Einbinden eines Fremdpro-gramms erweitern Sie die Fähigkeiten Ihres Programms, etwa um Pack-Werkzeuge,die ZIP-Archive entfalten, oder um Abspieler für Videodateien.

Parameter Ergebnis

"WINDOWSDIR" Name des Windows-Ordners, etwa »C:\WINDOWS\«

"TEMPDIR" Name des TEMP-Ordners von Windows

"SYSTEMDIR" Name des SYSTEM-Ordners von Windows

"APPDIR" Name des Ordners

"OS" Name des Betriebssystems

Page 189: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

189

DLLs ausführen j e t z t l e r n e i c h

2

Schließlich lassen sich alle Windows-eigenen Programme aufrufen, etwa der Exploreroder Hilfsmittel wie WINIPCFG. Programme wie RunDLL32.exe enthalten eine Viel-zahl von Funktionen, die als Parameter übergeben werden. Die folgende Zeile etwa öff-net ein Einstellungsfenster von Windows:

; DLL1.BBExecFile("Rundll32 shell32.dll,Control_RunDLL joy.cpl,,0 ")

1Und drittens können Sie Ihr Spiel in mehrere Einzelteile aufsplitten, die jeweils in einerEXE-Datei abgelegt sind. Ein Basisprogramm würde nacheinander die Einzelteile auf-rufen:

ExecFile "Teil1.exe"ExecFile "Teil2.exe"ExecFile "Teil3.exe"

Betriebssystemtypisch ist es möglich, statt eines ausführbaren Programms eine Daten-datei aufzurufen. Windows wird dann das dazugehörige Programm automatisch laden.Das funktioniert ebenfalls bei WWW-Adressen. Die Zeile

ExecFile "http://www.eastereggs.de"

ruft den Standard-Browser auf und lädt die Website, sofern eine Internetverbindung be-steht.

2

A17.8 DLLs ausführen

Blitz Basic erlaubt es, Funktionen aufzurufen, die sich in anderen ausführbaren Dateienbefinden. Diese Dateien heißen DLL, Dynamic Link Library. Da Blitz Basic nur sehreingeschränkt auf Funktionen des Betriebssystem zugreifen lässt (etwa das Öffnen derCD-Schublade), ergänzen DLLs die Fähigkeiten der Sprache. So bietet die frei verfüg-bare BlitzSys.DLL Zugriff auf eine Reihe von Windows-Ressourcen, während Blitz-Bass.DLL 3D-Sound unterstützt. (Beide Erweiterungen finden Sie auch auf der Buch-CD.) DLL-Dateien werden meist in C++ programmiert.

Zumindest in den derzeitigen Versionen von Blitz Basic hat ExecFile einen Bug: Wirddas Programm inklusive Pfadnamen angegeben, so darf das Verzeichnis kein Leer-zeichen enthalten (z.B. »C:\Eigene Dateien\Test.exe«). Notlösung: Wechseln Sie mitChangeDir in den fraglichen Ordner und rufen Sie das Programm ohne Pfad auf.

Im Netz finden Sie auf unzähligen Seiten detaillierte Beschreibungen vonRunDLL32.exe, etwa auf www.winfaq.de/faq_html/tip0564.htm.

Beachten Sie dabei, dass Blitz Basic nach dem Aufruf von ExecFile die Befehlszeilenweiter fortsetzt, ohne darauf zu achten, ob das externe Programm beendet wurde.

Page 190: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

190

Dateien17j e t z t l e r n e i c h

17.8.1 CallDLLDie einfache Fassung ist der Befehl CallDLL. Er ruft eine DLL-Datei auf:

CallDLL$(DLL-Name$, Funktionsname)

Umständlich ist das Übergeben und Empfangen von Daten. Dazu muss eine Speicher-bank verwendet werden. Als zusätzliche Parameter geben Sie den Namen der Eingabe-und den Namen der Ausgabebank an. Blitz Basic übergibt an die DLL den Zeiger zurSpeicherbank sowie ihre Größe – und erwartet diese Daten zurück. Daher lassen sichin der Regel nur DLLs verwenden, die Handlungen ohne Parameteraustausch vorneh-men oder speziell an Blitz Basic angepasst sind.

17.8.2 UserLibsDer DLL-Aufruf wurde durch die so genannten Userlibs (»Nutzerbibliotheken«) deutlicherweitert. In Blitz Basic 3D seit Version 1.81 und in Blitz Plus (aber nicht in Blitz Basic2D!) ist es möglich, den Befehlssatz von Blitz Basic durch externe Funktionen zu er-weitern. Dazu sind zwei Angaben nötig:

� die DLL-Datei mit den externen Funktionen

� eine Beschreibung dieser Funktionen in einer Textdatei

Beides gehört in den Blitz-Basic-Ordner Userlibs. Die Beschreibungsdatei muss die En-dung .decls aufweisen und folgenden Inhalt haben:

; eventuelle Kommentarzeilen.lib "Name der DLL-Datei"Blitz-FunktionsName1 (Parameter1, Parameter2,...) : "Dll-FunktionsName1")Blitz-FunktionsName2 (Parameter1, Parameter2,...) : "Dll-FunktionsName2")...

Die Kennung .lib wartet auf den Namen der DLL-Datei. Diese muss sich im gleichenOrdner befinden. Danach folgt eine Liste mit Funktionsnamen inklusive Parameter-liste. Diese Funktionen lassen sich dank dieser Vereinbarung in Blitz Basic wie normaleBefehle benutzen; sie werden sogar im Editor farblich hervorgehoben. Hinter demDoppelpunkt steht der Name der DLL-Funktion, die tatsächlich aufgerufen wird.

Ein Beispiel: Wir wollen aus einem Blitz-Basic-Programm heraus das Standard-Info-fenster von Windows-Programmen öffnen. Das führt die Funktion ShellAboutA derDLL Shell32.DLL aus. Zunächst benötigen wir die korrekten Parameter dieser Funk-tion. Dabei helfen Nachschlagewerke wie der API-Katalog auf www.activevb.de oderdie API Calls auf www.pbdr.com/pbtips.

Dank dieser Angaben erzeugen wir im Ordner Userlibs eine Datei namens Test.decls.Sie enthält folgende zwei Zeilen:

; TEST.DECLS.lib "shell32.dll"Copyright(hWnd%,szApp$,szOtherStuff$,hIcon%) : "ShellAboutA"

Darin vereinbaren wir die neue Blitz-Basic-Funktion Copyright (). Der Aufruf dieserFunktion erfolgt mit den Parametern, welche die DLL-Funktion erwartet:

Copyright(0,"","",0)

Verwenden wir diese Funktion in einem Programm, wird das Infofenster aufgerufen.Wir können statt der leeren Zeichenketten individuellen Text eintragen. Die erste er-

Page 191: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

191

Parameter übergeben j e t z t l e r n e i c h

wartet den Programmnamen, der im Titel des Fensters und noch einmal im Fensterselbst erscheint. Enthält die Kette eine Raute (#), dann erscheint nur der Text vor derRaute im Titel und der Text nach der Raute im Fenster. Die zweite Zeichenkette enthältText, der nach der Copyright-Zeile ausgedruckt wird.

; DLL2.BBCopyright(0,"Blitz Basic Test#DLL-Test","Das ist ein Testprogramm",0)

Der Name der .decls-Datei ist egal.

Abb. 17.1:Aufruf einer Windows-Funk-tion – hier das Anzeigen des Copyright-Fensters – mit einem Blitz-Basic-Programm.

A17.9 Parameter übergeben

In DOS-Zeiten, als Programme noch über eine Eingabeaufforderung wie:

c:\>

aufgerufen wurden, war es üblich, dem Programm zusätzliche Informationen direktbeim Start zu übergeben. Anstatt etwa eine Textverarbeitung allein durch Angabe ihresNamens zu starten:

c:\word> word.exe

konnte man gleich den Namen eines zu ladenden Dokuments nennen:

c:\word> word.exe brief.doc

Diesen Zusatz bezeichnet man als Kommandozeilenparameter oder kurz Parameter.Er ist in Windows-Zeiten selten geworden, aber immer noch existent.

Sie übergeben einem Programm einen Parameter, indem Sie es in Windows überSTART/AUSFÜHREN aufrufen. Beim Start über ein Icon oder das Startmenü klicken Siesein Symbol mit der rechten Maustaste an und fügen der Programmdatei in den Eigen-schaften in der Zielzeile einen Parameter hinzu. Für Ihre Programme, die Sie aus demEditor von Blitz Basic heraus aufrufen, tragen Sie den Parameter im Menü PROGRAM/PROGRAM COMMAND LINE... ein.

Page 192: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

192

Dateien17j e t z t l e r n e i c h

Die Funktion CommandLine() übergibt Ihnen alles, was nach der Programmdatei einge-ben wurde, als Zeichenkette. Bei

spiel.exe 1024x768 nointro

wäre der Inhalt von CommandLine() eben "1024x768 nointro".

0Eine beliebte Anwendung von Parametern in Spielen ist die Übergabe eines Code-worts, um einen Cheatmodus zu aktivieren, in dem der Spieler zum Beispiel unver-wundbar ist. Das hat Vorteile, weil der Cheat nicht immer während des Spiels einge-geben werden muss. Eine ganze Reihe von Ego-Shootern verfährt auf diese Weise.

Abb. 17.2:Kommando-zeilen-Para-

meter, ein Reliktaus der DOS-Zeit, werden

noch heute voneinigen Pro-

grammen ver-wendet. Sie

ermöglichendas Übergeben

speziellerDaten bereits

zum Start.

Mithilfe eines Parameters bauen Sie sehr einfach einen Cheatmodus in Ihr Spiel ein.Sie fragen ein bestimmtes Codewort ab, etwa "legolas". Ist es Teil des Parameters,setzen Sie eine Variable wie Cheatmodus auf 1.

If InStr(CommandLine(), "legolas", 1) <> 0 Then Cheatmodus=1

Oder eleganter:

Cheatmodus = InStr(CommandLine(), "legolas", 1)

Soll der Cheat für Unverwundbarkeit sorgen, dann ziehen Sie die Lebensenergie ...

If Treffer=1 Then Energie = Energie-10

... nur ab, wenn der Cheatmodus ausgeschaltet ist:

If Cheatmodus = 0 Then If Treffer=1 Then Energie = Energie-10EndIf

Mit der Funktion InStr() durchsuchen Sie die Zeichenkette nach Schlüsselwörtern.

Page 193: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

193

Fehlermeldung erzeugen j e t z t l e r n e i c h

0

A17.10 Fehlermeldung erzeugen

Mit End beenden Sie ein Programm sofort. Manchmal bietet es sich an, das Programm-ende mit einer Fehlermeldung zu verbinden – weil sich beispielsweise die Grafik, dieSie verwenden wollen, nicht laden lässt, da sie nicht am vorgesehenen Ort ist. Der Be-fehl RuntimeError beendet ein Programm, indem eine Windows-Box mit einer Mel-dung Ihrer Wahl erscheint:

RuntimeError "Datei LEVEL2.DAT fehlt!"

117.11 Aufgaben

1. Schreiben Sie ein Programm, das alle Ordnernamen im Windows-Verzeichnis aus-liest und in eine Datei auf der Festplatte speichert.

2. Schreiben Sie ein kleines Quiz. Die Fragen und Antworten sollen aus einer Text-datei gelesen werden. Sie können die Datei QUIZ.TXT nutzen, die sich auf derBuch-CD befindet. Sie enthält einige Quizfragen rund um die Welt des Kinos. Kei-ne Frage soll zweimal gestellt werden.

Eine weitere Möglichkeit, Daten von außen zu erhalten, bieten die so genannten Um-gebungsvariablen. Das sind vom Betriebssystem genutzte Variablen (etwa PATH,PROMPT und TEMP), die von der DOS-Eingabeaufforderung aus mit dem BefehlSET gelesen und erzeugt werden. Mit der Funktion GetEnv() lesen Sie eine Umge-bungsvariable aus. Mit SetEnv erzeugen Sie eine Variable, die aber nur so lange gültigist, wie Ihr Programm läuft.

Runtime Error ist eine typische Bezeichnung für einen Fehler, der erst während desAblaufs eines Programms (und nicht wie ein Syntaxfehler beim Übersetzen des Pro-gramms) auftritt.

Page 194: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 195: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

195

jetz

t le

rne

ich

KAPITEL 18

ADatenaustausch im Netzwerk

Gibt es eine schönere Beschäftigung, als gegen den Computer zu spielen? Ja! Mit einerHandvoll Gleichgesinnter sich zu einem spannenden Spiel treffen. Der Adrenalinstoßsetzt bereits ein, wenn man sich zu zweit gegenübersitzt; ideal ist jedoch eine Vierer-oder noch größere Runde.

Warum es viel mehr Spaß macht, gegen Menschen als gegen Computer zu spielen, istleicht erklärt: Computer zeigen keine Emotionen. Computer reagieren sehr viel schnel-ler als wir. Und Computer sind dumm. Schauen Sie sich ein typisches Strategiespiel an:Der Computer baut wesentlich schneller, schafft sich schneller eine kleine Armee. Hin-gegen wird er kaum ausgefeilte Strategien entwickeln. Spiele, die dem Computer einekünstliche Intelligenz einzuflößen scheinen, kann man an einer Hand abzählen. Nichtselten hat der Computer schnellere und geeignetere Algorithmen, um eine Handlungauszuführen. Der maschinelle Gegner hält damit vor allem bei hohem Schwierigkeits-grad meist die besseren Karten in der Hand. Spielt er bereits im niedrigen Schwierig-keitsgrad zu gut, verlieren Sie schnell die Freude am Spiel. Schließlich wollen Sie aucheinmal gewinnen. Besitzt das Spiel dagegen zusätzlich eine Mehrspieleroption, sokann man sich einen ebenbürtigen menschlichen Gegner suchen. Die Chance zu ge-winnen, ist damit sicherlich höher.

Es ist leicht, ein Spiel so zu gestalten, dass mehrere Personen gegeneinander an einemPC antreten können – hintereinander (»Hot Seat«), etwa bei einem Brettspiel, oder ne-beneinander, wie z.B. bei einem rasanten Geschicklichkeitsspiel. Die Königsklasse istaber das Spielen im Netz. Blitz Basic liefert eine komplette Unterstützung für das Spie-len in einem Netzwerk (wozu auch das Internet zählt).

Page 196: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

196

Datenaustausch im Netzwerk18j e t z t l e r n e i c h

1

Drei Schritte sind notwendig, um in Blitz Basic Daten von einem PC zu einem anderenzu schicken:

1. Ein PC öffnet ein Netzwerkspiel, er dient als Host. Andere PCs nehmen alsClients an diesem Spiel teil.

2. Jeder teilnehmende PC erstellt einen virtuellen Spieler. Der Spieler erhält eine ein-deutige Kennziffer, über die er später angesprochen wird.

3. Jeder virtuelle Spieler kann nun an andere Spieler Daten senden.

18.1 Netzwerkspiel einrichten

Ein Netzwerkspiel richten Sie einfach mit dem Befehl StartNetGame() ein. Dieser lieferteinen Wert ...

0 = Netzwerkspiel konnte nicht gestartet werden

1 = Netzwerkspiel als Client gestartet

2 = Netzwerkspiel als Host gestartet

... zurück, so dass Sie ihn mit einer Variablenzuweisung verbinden sollten:

Netzspiel = StartNetGame()

Abb. 18.1:Dialog zum

Erstellen einesNetzwerkspiels

über DirectPlay.

Wir besprechen hauptsächlich das Starten eines Netzwerkspiels und das Austauschenvon Daten zwischen den Spielern über DirectX-Funktionen (genauer: über Direct-Play). Das sind einerseits Bewegungen und Aktionen einer Partei, die den anderenmitgeteilt werden, andererseits normale Nachrichten (»Chat«). Schneller ist das UDP-Protokoll, das wir am Schluss des Kapitels behandeln. Die Bibliothek BlitzPlay(www.blitzcoder.com/blitzplay/, auf der Buch-CD) bietet eine Reihe von Funktionenzum Entwickeln von Netzwerkspielen via UDP.

Es entfallen spezielle Befehle für das TCP-Protokoll, die ebenfalls für Spiele geeignetsind, mit denen Sie aber auch Webseiten lesen und Ihr E-Mail-Postfach öffnen kön-nen. Sie ähneln UDP stark, so dass die Einarbeitung leicht fällt. Eine hilfreiche Hin-tergrundlektüre ist das Multiplayer-Kapitel von Robs Blitz-Basic Kurs 2 (www.rob-site.de), der sich auf der Buch-CD befindet.

Page 197: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

197

Netzwerkspiel einrichten j e t z t l e r n e i c h

Dieser Befehl öffnet ein vorgefertigtes Fenster, in dem der Spieler die Verbindungsart(TCP/IP oder IPX für Netzwerkspiel) auswählt. Danach erscheint die Liste der laufen-den Spielsitzungen. Findet Blitz Basic keine Spiele, fragt ein Minifenster nach demComputernamen (wie er auch in der Windows-Netzwerkumgebung erscheint) oder derIP-Adresse des Host-PCs. Auf diese Weise lassen sich beliebige Teilnehmer erreichen,sofern sie »online« sind.

1

Lässt man das Eingabefeld leer und klickt nur auf OK, kann man ein Spiel erstellen, alsoeinen Host einrichten. Dazu gibt man einen beliebigen Namen, zum Beispiel »MartinsSpiel«, ein und klickt auf CREATE NEW GAME.

Also: Ein PC erstellt ein Spiel (Host); danach treten alle anderen als Clients diesemSpiel bei. Das ist jederzeit möglich, solange das Netzwerkspiel läuft.

Der Befehl StartNetGame() nimmt Ihnen allerhand Programmierarbeit ab, verwendetdazu aber ein Standardfenster, wodurch Ihr eigentliches Spiel vom Vollbildmodus vor-übergehend in den Hintergrund geschaltet wird. Um das zu vermeiden, verwenden Siealternativ den Befehl HostNetGame() zum Hosten und JoinNetGame() zum Beitreten ei-nes Spiels. Beide Befehle müssen den Namen der Spielsitzung wissen. Sie erfragen ihndaher vorher. JoinNetGame() übergeben Sie außerdem die IP-Adresse des Host-PCs:

; NETZ1.BBPrint "Drücken Sie [1], um ein Spiel zu erstellen."Print "Drücken Sie [2], um an einem Spiel teilzunehmen."Wahl = Input("Ihre Wahl: ")Name$ = Input("Name der Spielsitzung:")If Wahl=2 Then IP$ = Input("IP-Adresse des Hosts:")If Wahl=1 Then Spiel = HostNetGame(Name$)If Wahl=2 Then Spiel = JoinNetGame(Name$, IP$)If Spiel=0 Then Print("Fehler beim Starten eines Netzwerkspiels!")If Spiel=1 Then Print("Spiel als Client gestartet.")If Spiel=2 Then Print("Spiel als Host gestartet.")WaitKey

Jeder Computer, der mit dem Internet verbunden ist, bekommt vom Provider eine in-dividuelle Kennnummer zugeteilt, die IP-Adresse (IP = Internet Protocol). Über dieseAdresse ist er eindeutig zu identifizieren und anzusprechen, ähnlich einer Telefon-nummer. Üblicherweise wird Ihnen für jede Online-Sitzung eine andere IP-Adresse(»dynamisch«) zugeteilt. Damit ein Client-PC an einem Netzwerkspiel teilnehmenkann, muss er die aktuelle IP-Adresse des Host-PCs kennen.

Bei Windows 95/98 nennt Ihnen das Programm WINIPCFG.EXE die IP-AdresseIhres PCs, zum Beispiel 213.6.151.163. Bei Windows XP, 2000 und NT ist es IP-CONFIG.EXE. Um die Ausgaben von IPCONFIG.EXE zu lesen, öffnen Sie zu-nächst ein DOS-Fenster (START/AUSFÜHREN, COMMAND eintippen). Rufen Sie dort dasProgramm auf.

Beachten Sie dabei, dass sich die IP-Adresse nach außen von der IP-Adresse inner-halb eines lokalen Netzes unterscheidet. Wenn Ihr PC gleichzeitig online und in ei-nem lokalen Netz ist, hat er zwei IP-Adressen. Üblicherweise steht die IP-Adresse fürdas Internet unter »PPP-Adapter«. Die Nummer für den heimischen Rechnerverbundist hingegen unter dem Namen des Netzwerktreibers (z.B. »The PCI Fast EthernetAdapter« oder »Ethernetadapter LAN-Verbindung« aufgeführt.

Page 198: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

198

Datenaustausch im Netzwerk18j e t z t l e r n e i c h

0

Am Ende schließen Sie die Netzverbindung durch den Befehl:

StopNetGame

18.2 Spieler erstellen

Wenn die Verbindung steht, erstellen Sie mit CreateNewPlayer() einen virtuellen Mit-spieler. Als Parameter übergeben Sie den Namen des Spielers, zum Beispiel "Georg".Angesprochen wird der Spieler nur über seine Spielernummer, die der Befehl zurück-gibt. Daher sollten Sie ihn nur in Verbindung mit einer Variablenzuweisung verwenden:

SpielerNr = CreateNewPlayer("Georg")

Wird ein Spieler nicht mehr benötigt, löschen Sie ihn unter Angabe seiner Nummer:

DeleteNetPlayer SpielerNr

Das waren bereits alle Vorbereitungen.

18.3 Nachricht versenden

Um miteinander Daten auszutauschen, versenden Spieler einander Nachrichten. JederSpieler schickt entweder an alle oder gezielt an einen Spieler beliebig oft eine Nach-richt (genauer: eine Zeichenkette). Ähnlich wie bei einem Stapel Briefe werden dieNachrichten hintereinander gereiht und nacheinander abgerufen – die älteste zuerst,die jüngste zuletzt. Um eine Nachricht zu verschicken, benötigen Sie:

� die Spielernummer des Senders (geliefert von CreateNetPlayer())

� die Spielernummer des Empfängers (0 sendet Nachricht an alle)

� die Nachricht selbst

� eine Codenummer von 1 bis 99

Die Codenummer ist frei wählbar. Sie sollten darin die Art der Nachricht speichern,zum Beispiel:

Sie benötigen nicht unbedingt mehrere miteinander vernetzte PCs, um die Beispieleauszuprobieren. Es genügt, wenn Sie ein Windows-Netzwerk und das Protokoll TCP/IP installiert haben. Starten Sie das Programm gleichzeitig mehrfach auf einem PC.Als IP-Adresse des Host können Sie dabei 127.0.0.1 angeben. Das ist, einfach ge-sagt, die IP-Adresse des eigenen PCs.

Grundsätzlich funktioniert die Verbindung über das Internet zu einem beliebigen PC,dessen IP-Adresse bekannt ist. In der Praxis können der Provider oder die Schutz-mechanismen des Betriebssystems (Firewall) diese Bestrebungen einschränken, in-dem der verwendete Port gesperrt ist. Mit CreateTCPServer() bauen Sie eine Inter-netverbindung auf, bei der Sie den Port angeben. Dieses Verfahren wird in diesemBuch nicht besprochen.

Page 199: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

199

Nachricht empfangen j e t z t l e r n e i c h

1 – Textmitteilung, die auf dem Bildschirm erscheinen soll (Chat)

2 – neue Koordinaten des Spielers

3 – Lebensenergie des Spielers ändert sich

4 – Spieler kauft eine Ware

...

Folgerichtig lautet der Befehl:

SendNetMsg Code, Nachricht, Sender, Empfaenger

Ein Beispiel:

NachrichtAn$ = Input$("Nachricht eingeben: ")SendNetMsg 1, NachrichtAn$, SpielerNr, 0

118.4 Nachricht empfangen

Zu einem zünftigen Sender gehört eine Antenne, die empfängt. Nachrichten treffennacheinander im Ziel ein. Und nacheinander werden sie auch gelesen. Das Lesen ver-läuft in zwei Schritten:

1. Mit RecvNetMsg() testen Sie, ob eine neue Nachricht eingetroffen ist, und holen siegleichzeitig ab.

2. Mit NetMsgData$() lesen Sie die Nachricht.

In Blitz-Basic-Deutsch heißt das:

If RecvNetMsg() = 1 Then NachrichtVon$ = NetMsgData$()Print NachrichtVon$

2Liefert Ihnen RecvNetMsg() eine 0, ist das Postfach leer. Erhalten Sie eine 1, wartet min-destens eine Nachricht auf Sie. Die Nachricht selbst erhalten Sie als Zeichenkette vonNetMsgData$().

Mit diesem Wissen ausgestattet, können wir bereits ein kleines Programm schreiben,das wie ein Chat arbeitet, also Zeilen entgegennimmt und sie an alle anderen Spielerschickt. Ergänzen wir unser vorheriges Beispiel um das Erstellen eines Spielers ...

Spieler$ = Input$("Spielername: ")SpielerNr = CreateNetPlayer(Spieler$)Print "Spielernummer: " + SpielerNr

Meistens werden Sie eine Nachricht an alle Spieler schicken und damit die Sender-nummer 0 verwenden. Nur für private Chats zwischen zwei Teilnehmern bietet sichdas gezielte Senden an einen Spieler an.

Beachten Sie, dass NetMsgData$() nur eine Nachricht ausgibt, die Sie zuvor mit Recv-NetMsg() abgeholt haben. Beide Befehle machen allein in der Kombination Sinn.

Page 200: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

200

Datenaustausch im Netzwerk18j e t z t l e r n e i c h

... und um eine Schleife, die jeweils eine Zeile entgegennimmt und eine empfangeneausdruckt, so lange, bis die Eingabe "Ende" lautet:

RepeatNachrichtAn$ = Input("Nachricht eingeben: ")SendNetMsg 1, NachrichtAn$, SpielerNr, 0If RecvNetMsg() = 1 Then Print NetMsgData$()Until NachrichtAn$ = "Ende"

18.5 Systemnachrichten

Seltsamerweise kommen unsere Nachrichten mit Verzögerung beim Empfänger an.Ich habe Ihnen ein Detail unterschlagen: SendNetMsg() ist nicht die einzige Quelle füreine Mitteilung. Blitz Basic selbst sendet automatisch eine Nachricht, wenn es etwasWichtiges zu sagen gibt, wenn etwa ein neuer Spieler eingetreten ist oder ein Spielerdas Spiel verlassen hat. Für solche »offiziellen« Zwecke wurden folgende Codenum-mern reserviert:

Weil bereits die Nachricht eingegangen ist, dass ein Spieler hinzukam, hinkt die Aus-gabe immer einen Schleifenlauf hinterher.

Was uns helfen würde, wäre ein Befehl, der die Codenummer einer Nachricht erfragt.Anhand der Nummer könnten wir testen, ob es eine normale Nachricht (Codenummerzwischen 1 und 99) oder eine Systemmeldung (Codenummer > 100) ist.

18.6 Details einer Nachricht erfragen

Zum Auslesen der Codenummer einer Nachricht und ihres Absenders gibt es gleichmehrere Funktionen:

100 Ein neuer Spieler ist dem Spiel beigetreten.

101 Ein Spieler hat das Netzwerkspiel verlassen.

102 Der Host hat das Spiel verlassen; der Empfänger ist nun der Host.

200 Das Netzwerkspiel wurde abgebrochen.

NetMsgType() liefert den Code der Nachricht

NetMsgFrom() liefert die Spielernummer des Absenders

NetMsgTo() liefert die Spielernummer des Empfängers (0 = Nach-richt geht an alle)

NetPlayerName$(Spielernummer) liefert den Spielernamen anhand der Spielernummer

NetPlayerLocal(Spielernummer) liefert 1, wenn sich der angegebene Spieler auf dem gleichen PC befindet

Page 201: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

201

Details einer Nachricht erfragen j e t z t l e r n e i c h

Die Funktion NetPlayerName$() ist das Gegenstück zu CreateNewPlayer(). CreateNew-Player() nimmt den Namen und liefert die Spielernummer. NetPlayerName$() nimmtdie Spielernummer und liefert den Namen:

Print NetPlayerName$(SpielerNr)

Falls die Nachricht an alle Teilnehmer geht, ist das Resultat die Zeichenkette "<all">;wenn die Spielernummer unbekannt ist, bekommen Sie "<unknown>" zurück.

0Mit diesen neuen Befehlen gestalten wir ein komfortableres Beispiel. Der erste Teil istnahezu identisch mit dem vorherigen Beispiel. Ich habe lediglich den Namen des Spielsfestgelegt ("test"), so dass dessen Eingabe entfällt. Der Teil, in dem Nachrichten ge-sendet und empfangen werden, wurde ausgebaut:

� Der Empfänger erfährt, von wem die Nachricht kommt (NetPlayerName$(NetMsg-From())).

� Gleichzeitig werden nun mehrere Nachrichten abgeholt (While/Wend).

� Es wird ausgewertet, ob die Nachricht von einem anderen Spieler oder vom Sys-tem kommt. Ist es eine Systemnachricht, wird sie anhand der Codenummer ent-schlüsselt (Select/Case).

; NETZ2.BBPrint "Drücken Sie [1], um ein Spiel zu erstellen."Print "Drücken Sie [2], um an einem Spiel teilzunehmen."Wahl = Input("Ihre Wahl: ")Name$ = "test"If Wahl=2 Then IP$ = Input("IP-Adresse des Hosts:")If Wahl=1 Then Spiel = HostNetGame(Name$)If Wahl=2 Then Spiel = JoinNetGame(Name$, IP$)If Spiel=0 Then Print("Fehler beim Starten eines Netzwerk-Spiels!")If Spiel=1 Then Print("Spiel als Client gestartet.")If Spiel=2 Then Print("Spiel als Host gestartet.");Spieler$ = Input$("Spielername: ")SpielerNr = CreateNetPlayer(Spieler$);Repeat NachrichtAn$ = Input("Nachricht eingeben: ") SendNetMsg 1, NachrichtAn$, SpielerNr, 0 While RecvNetMsg() = 1 Select NetMsgType() Case 100 Print "Spieler " + NetPlayerName$(NetMsgFrom()) + " beigetreten" Case 101 Print "Spieler " + NetPlayerName$(NetMsgFrom()) + " ausgetreten" Case 102 Print "Host ausgetreten" Case 200 Print "Verbindung abgebrochen" Default Print "Nachricht von " + NetPlayerName$(NetMsgFrom()) + ": " + NetMsgData$() End Select WendUntil NachrichtAn$ = "Ende"

Die Spielernummer eines anderen Teilnehmers erfahren Sie durch das Auswerten ei-ner Nachricht von ihm.

Page 202: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

202

Datenaustausch im Netzwerk18j e t z t l e r n e i c h

Das ist schon recht ordentlich, aber immer noch nicht das Gelbe vom Ei. Inputblockiert das Empfangen einer Nachricht so lange, bis selbst eine abgeschickt wurde.Um es perfekt zu machen, müssten wir Zeichen für Zeichen von der Tastatur einlesenund für Eingabe und Ausgabe getrennte Bereiche einführen. Probieren Sie es doch ein-mal! :-)

0

18.7 Nachricht interpretieren

Üblicherweise ist der Chat in einem Netzwerkspiel nur nettes Beiwerk. Vor allem dientdie Datenübermittlung dazu, Eingaben eines Spielers an die anderen weiterzuleiten.Wie Sie das machen, bleibt Ihrer Phantasie überlassen. Hauptsache, Sie fassen allenotwendigen Angaben in eine Zeichenkette. Nutzen Sie die Codenummer, um dort dieArt der Nachricht zu übermitteln; Beispiele dazu finden Sie im Abschnitt »Nachrichtversenden«.

Sie müssen für Ihr Programm einen Weg finden, einerseits so rasch wie möglich Än-derungen mitzuteilen, andererseits aber nur so viele Nachrichten wie notwendig zu ver-wenden. Zeitgleiche Aktionen sollten Sie in einer Nachricht verschicken, eine Positi-onsangabe etwa wie folgt:

"100,345"

Mit den Zeichenkettenbefehlen trennen Sie die beiden Zahlen voneinander und wan-deln sie in echte Zahlen um. Die erste Zahl knacken Sie ganz einfach:

Int("100,345")

liefert Ihnen die Zeichenkette als Zahl zurück, macht aber beim ersten ungültigen Zei-chen (",") Halt. Das Ergebnis ist die Zahl 100. Für die zweite Zahl fragen Sie die Posi-tion des Kommas ab und wandeln den Teilstring nach dem Komma in eine Zahl um:

Int( Mid$("100,345", Instr("100,345",",") +1) )

Ich will Ihnen an einem Beispiel zeigen, wie Bewegungsdaten über das Netzwerk über-tragen werden. Im Abschnitt über die Abfrage der Maustasten haben Sie erfahren, wieman mit der Maus einen roten Punkt auf dem Bildschirm bewegt:

; NETZ3.BBGraphics 640,480SetBuffer BackBuffer()Color 255,0,0;Repeat Cls X = MouseX() Y = MouseY() Oval X,Y, 10,10 FlipUntil KeyHit(1)

Wenn Sie Ihre Multiplayer-Spiele bei Ihnen zu Hause testen und ein bestimmter PCimmer Host und der andere Client ist, dann sollten Sie die IP-Adresse direkt ins Pro-gramm schreiben (zum Beispiel IP$="192.168.1.30"), um sie nicht immer mühsameintippen zu müssen.

Page 203: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

203

Nachricht interpretieren j e t z t l e r n e i c h

Erweitern Sie das Programm doch, indem Sie an einem PC die Maus bewegen, denPunkt aber nicht nur auf dem eigenen PC zeichnen, sondern auf allen Monitoren, diesich im Netzwerkspiel befinden – diesmal in Blau. Um nur so viele Daten wie notwen-dig zu übertragen, wird eine Netznachricht nur gesandt, wenn sich die Position desMauszeigers geändert hat. Für das Zeichnen von blauen Punkten durch »fremde« Mäu-se muss dafür nicht mehr getestet werden, ob die Position neu ist – trifft eine Nachrichtein, ist die Position neu und der Punkt wird daher auf jeden Fall neu gezeichnet.

Der Bequemlichkeit halber muss man keinen Spielernamen mehr eingeben – das Pro-gramm ermittelt eine (quasi) zufällige Zahl und nimmt sie als Namen. Bevor der Gra-fikmodus aktiviert wird, holen wir die Netzwerknachricht ab, die das Eintreten einesSpielers übermittelt. Sie würde sonst als Positionsnachricht interpretiert.

; NETZ4.BBPrint "Drücken Sie [1], um ein Spiel zu erstellen."Print "Drücken Sie [2], um an einem Spiel teilzunehmen."Wahl = Input("Ihre Wahl: ")Name$ = "test"If Wahl=2 Then IP$ = Input("IP-Adresse des Hosts:")If Wahl=1 Then Spiel = HostNetGame(Name$)If Wahl=2 Then Spiel = JoinNetGame(Name$, IP$)If Spiel=0 Then Print("Fehler beim Starten eines Netzwerk-Spiels!")If Spiel=1 Then Print("Spiel als Client gestartet.")If Spiel=2 Then Print("Spiel als Host gestartet.")SpielerNr = CreateNetPlayer(Str$(MilliSecs()))If RecvNetMsg() = 1 Then Position$ = NetMsgData$();Graphics 640,480SetBuffer BackBuffer()Repeat Cls X2 = MouseX() Y2 = MouseY() If (X2 <> X1) Or (Y2 <> Y1) Then Position$ = Str$(X2) + "," + Str$(Y2) SendNetMsg 1, Position , SpielerNr, 0 X1=X2 Y1=Y2 EndIf

If RecvNetMsg() = 1 Then Position$ = NetMsgData$() X0 = Int(Position$) Y0 = Int( Mid$(Position$, Instr(Position,",") +1) ) EndIf

Color 0,0,255 Oval X0,Y0, 10,10 Color 255,0,0 Oval X2,Y2, 10,10

FlipUntil KeyHit(1)

Page 204: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

204

Datenaustausch im Netzwerk18j e t z t l e r n e i c h

18.8 Netzwerkverbindungen mit UDP

Alternativ zu DirectPlay bauen Sie eine Netzwerkverbindung mit UDP auf. Das UserDatagram Protocol versendet Daten schneller und ist somit vorzuziehen, wenn zweiSpiele viele Informationen miteinander austauschen. Der Grund ist seine einfacheStruktur: Es ist nicht notwendig, erst eine Verbindung aufzubauen, und das Protokollwartet nicht auf eine Bestätigung, dass Daten vollständig angekommen sind. Allerdingsfällt damit auch eine Kontrollmöglichkeit weg.

1UDP arbeitet mit Datenströmen. Für das Senden und das Empfangen wird je ein Strom(Stream) aufgebaut:

senden = CreateUDPStream()empfangen = CreateUDPStream()

Als Parameter übergeben Sie gegebenenfalls einen Port, der für den Austausch genutztwerden soll.

Grundsätzlich kann Senden und Empfangen mit nur einem Strom realisiert werden.Dann muss der Datenaustausch synchronisiert werden: Bevor Sie eine Nachricht ver-senden, müssen Sie sicherstellen, dass sich keine Mitteilung im Posteingang befindet.

Am Ende des Nachrichtenaustauschs schließen Sie mit CloseUDPStream die Verbindungwieder.

Robert Gerlach, www.robsite.de: »Besteht eine Verbindung zu einem anderen Spiel,kommt es vor allem auf Geschwindigkeit an. Sie haben minimal nur 7 Kbyte pro Se-kunde (bei einem 56K-Modem) zur Verfügung. Zur Auswahl stehen die ProtokolleTCP, DirectPlay und UDP. TCP ist zu langsam. DirectPlay ist besonders einfach zuverwenden. UDP bietet dafür mehr Möglichkeiten. Wenn Sie sich dafür interessieren:Auf www.blitzbasic.com finden Sie hilfreiche Funktionen. Ebenfalls wichtig ist derverwendete Datentyp. Eine Integerzahl verbraucht 4 Byte. Wenn Sie nicht unbedingtWerte bis zur Größe von 4 Milliarden übertragen wollen, nehmen Sie den Short-Typ(bis 65536 mit 2 Byte) oder noch besser ein einzelnes Byte, das allerdings nur Wertebis 255 annehmen kann. Sie sollten nicht jedes Mal, wenn das Spiel die Hauptschlei-fe durchläuft, alle Daten senden. Senden Sie nur dann Daten, wenn sich die eigeneRichtung und Geschwindigkeit verändert. Oft verbraucht es weniger Platz, statt derneuen Koordinaten nur Angaben wie Richtung und Geschwindigkeit zu übertragen.Die tatsächliche Position errechnet dann der Empfänger. Bei Programmen, die »nor-mal« aufs Internet zugreifen, gibt es das Problem der Geschwindigkeit nicht. Hier sindnur die verschiedenen Protokolle zu beachten. In den RFC-Dokumenten (www.rfc-editor.org) sind alle verbreiteten Netzwerkprotokolle detailliert beschrieben. Sehr de-tailliert sogar – jede Einzelheit steht darin, wodurch die englischen Texte nicht unbe-dingt leicht zu lesen sind.«

Die UDP-Befehle wurden erst mit Version 1.65 in den Befehlsvorrat aufgenommen.Sie funktionieren nicht mit der Demo von Blitz Basic 2D, die auf einem älteren Standist.

Page 205: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

205

Netzwerkverbindungen mit UDP j e t z t l e r n e i c h

1

18.8.1 Nachricht empfangen und lesenRecvUDPMsg() testet, ob eine Nachricht eingetroffen ist, und empfängt sie gleich. Nunmuss sie gelesen werden. Das läuft ganz ähnlich ab wie bei Dateien – Sie verwendenFunktionen wie ReadByte() und ReadString(). Statt der Dateikennung übergeben Siedie Kennziffer des Datenstroms. Sie müssen das Senden und Empfangen so koordinie-ren, dass Sie immer Bescheid wissen, wie welche Daten empfangen werden. Die Men-ge der im Postausgang wartenden Bytes lässt sich immerhin mit ReadAvail() erfragen.

18.8.2 Empfänger ermittelnNoch ist unbekannt, wer die Nachricht geschickt hat. RecvUDPMsg() übergibt die IP-Adresse des Senders als Parameter:

IP = RecvUDPMsg(strom)

Sie erhalten die IP-Adresse in Form einer kodierten 4-Byte-Zahl. Um sie in das uns ver-traute Format aaa.bbb.ccc.ddd zu verwandeln, hilft Ihnen die Funktion DottedIP$().

Mit UDPMsgIP() erfahren Sie nachträglich die IP-Adresse des Senders.

18.8.3 Nachricht sendenUm Daten zu verschicken, verwenden Sie die von den Dateibefehlen her bekanntenAnweisungen wie WriteByte, WriteShort oder WriteString. Das eigentliche Versendenübernimmt SendUDPMsg:

WriteShort senden, X1SendUDPMsg senden, IP, sendeport

Beim Senden müssen Sie die IP-Adresse des Empfängers angeben, in Form einer ko-dierten Zahl. Wenn Sie die IP-Adresse nur in der gebräuchlichen 4-Punkt-Form ken-nen, müssen Sie sie erst umrechnen. Das ist ein recht aufwendiger Vorgang:

; INTEGERIP.BBFunction IntegerIP(IP$) A1 = Int(Left(IP$,Instr(IP$,".")-1)) : IP$ = Right(IP$,Len(IP$)-Instr(IP$,".")) A2 = Int(Left(IP$,Instr(IP$,".")-1)) : IP$ = Right(IP$,Len(IP$)-Instr(IP$,".")) A3 = Int(Left(IP$,Instr(IP$,".")-1)) : IP$ = Right(IP$,Len(IP$)-Instr(IP$,".")) A4 = Int(IP$) Return (A1 Shl 24) + (A2 Shl 16) + (A3 Shl 8 ) + A4End Function

Bei UDP gibt es keine direkten Host- oder Client-Befehle. Beide PCs bauen die Ver-bindungen auf die gleiche Weise auf. Ein PC muss allerdings die IP-Adresse seinesPartners kennen, um Nachrichten zu verschicken. Anhand der empfangenen Nach-richt kann der zweite PC die IP-Adresse des ersten ermitteln und damit ebenfallsNachrichten versenden.

Es empfiehlt sich eine Port-Angabe. Nehmen Sie für den ersten PC etwa 8000 zumSenden und 8001 zum Empfangen. Den zweiten PC lassen Sie über Port 8001 sendenund über Port 8000 empfangen.

Page 206: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

206

Datenaustausch im Netzwerk18j e t z t l e r n e i c h

18.8.4 BeispielEin Programm soll den Datenaustausch zwischen zwei PCs verdeutlichen. In den Quell-text des einen PCs (Client) muss die IP-Adresse des zweiten PCs (Host) eingetragenwerden. Steht die Verbindung, lässt sich mit der Maus ein roter Kreis auf dem Bild-schirm bewegen. Der Kreis wird parallel in blauer Farbe auf dem jeweils anderen PCdargestellt. Der Host-PC erkennt die Verbindung erst bei einem Dateneingang. BeimClient sollte daher die Maus probehalber bewegt werden.

; UDP.BB; Host oder Client?Hostmodus = 1

sendeport = 8000empfangsport = 8001

If Hostmodus = 0 Then sendeport = 8001 empfangsport = 8000EndIf senden = CreateUDPStream(sendeport)empfangen = CreateUDPStream(empfangsport)

; Hier IP-Adresse des Hosts eintragen:If Hostmodus = 0 Then IP = IntegerIP("192.168.0.1")Else Print "Warten auf anderen PC ..." Repeat IP = RecvUDPMsg(empfangen) If KeyHit(1) Then End Until IP <> 0 Print "Verbindung steht. Print "IP-Adresse des Senders: " + DottedIP(IP) Print "<Taste drücken>" WaitKeyEndIf

Graphics 640,480SetBuffer BackBuffer()

Repeat Cls ; Remote-Kreis If RecvUDPMsg(empfangen) Then X2 = ReadShort(empfangen) Y2 = ReadShort(empfangen) EndIf

If Hostmodus = 1 Then Color 255,0,0 Else Color 0,0,255 EndIf

Oval X2,Y2, 30, 30, 1

Page 207: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

207

Aufgabe j e t z t l e r n e i c h

; Lokaler Kreis X1Alt = X1 Y1Alt = Y1 X1 = MouseX() Y1 = MouseY() If X1 <> X1Alt And Y1 <> Y1Alt Then WriteShort senden, X1 WriteShort senden, Y1 SendUDPMsg senden, IP, sendeport EndIf

If Hostmodus = 1 Then Color 0,0,255 Else Color 255,0,0 EndIf

Oval X1,Y1, 30, 30, 1 FlipUntil KeyHit(1)

CloseUDPStream sendenCloseUDPStream empfangen

Function IntegerIP(IP$) A1 = Int(Left(IP$,Instr(IP$,".")-1)) : IP$ = Right(IP$,Len(IP$)-Instr(IP$,".")) A2 = Int(Left(IP$,Instr(IP$,".")-1)) : IP$ = Right(IP$,Len(IP$)-Instr(IP$,".")) A3 = Int(Left(IP$,Instr(IP$,".")-1)) : IP$ = Right(IP$,Len(IP$)-Instr(IP$,".")) A4 = Int(IP$) Return (A1 Shl 24) + (A2 Shl 16) + (A3 Shl 8 ) + A4End Function

18.9 Aufgabe

1. Schreiben Sie ein Chat-Programm für zwei Personen. Jeder sieht seinen Text aufeiner Hälfte des Bildschirms und den Text des Partners auf der anderen Seite.

Peter »DC« Schauß, www.unrealsoftware.de.vu: »Es gibt keine Garantie dafür, dassUDP-Daten wirklich ankommen. Sie werden einmal gesendet; wenn sie nicht denEmpfänger erreichen, werden sie nicht noch einmal verschickt. Allerdings habe ichnoch nicht erlebt, dass Daten ihren Empfänger nicht erreicht hätten. Wenn Sie einSpiel hosten und einen Router oder eine Firewall benutzen, werden andere Teilneh-mer Ihrem Spiel nicht beitreten können. Versuchen Sie, den Router und die Firewallumzustellen und den verwendeten Port freizugeben. Unproblematisch sollte es sein,wenn Sie einem Spiel selbst beitreten.«

Page 208: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 209: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

209

jetz

t le

rne

ich

KAPITEL 19

Grafikseminare

Die Theorie ist so weit geschafft, die Themen Grundlagen, Grafik und Eingaben solltenIhnen geläufig sein. Für dieses große Kapitel habe ich eine Vielzahl von Einzelthemenherausgesucht, um alles miteinander zu verknüpfen. Einiges davon sind grafische Spie-lereien, anderes, wie die Kollisionsabfrage, bildet die Voraussetzung für Spiele. Die Ab-schnitte sollen Ihnen ein Aha-Gefühl vermitteln, welche einfachen Strukturen hinterEffekten wie Laufschrift stecken, und den Umgang mit Blitz Basic festigen.

19.1 Animationen

Aktion in einem Film vermittelt den Eindruck einer kontinuierlichen, wirklichen Bewe-gung. Tatsächlich besteht ein Film aus Einzelbildern, die in schneller Folge nacheinan-der abgespielt werden. Das Auge wird getäuscht und nimmt die Einzelbilder als eineBewegung, als Animation wahr. Genauso funktioniert es bei einem Spiel.

Einfache Bewegungen haben wir bereits simuliert, indem wir eine Kuh über den Bild-schirm wandern ließen. Das i-Tüpfelchen sind mehrere Bewegungsschritte: Das Objektsoll sein Aussehen verändern. Es genügt nicht, eine Spielfigur wie einen Pöppel auf derKarte eines Brettspiels von einem Ort zum anderen zu transportieren. Seine Arme undseine Beine müssen sich dabei so bewegen, dass der Betrachter an eine tatsächlicheBewegung glaubt. Die Entwickler geben sich immense Mühe, Spielfiguren lebensechtdarzustellen. In Kampfsportspielen, wo die Bewegung maßgeblicher Inhalt ist, werdendie Bewegungen von Menschen aufgezeichnet und digitalisiert (»Motion Capturing«).Auf ihnen basieren Computerfiguren. Wir begnügen uns mit einigen Nummern klei-ner. Häufig genügen zwei bis sechs Bewegungsschritte. Nacheinander werden die Ein-zelbilder oder Frames dargestellt.

Page 210: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

210

Grafikseminare19j e t z t l e r n e i c h

19.1.1 Figur animierenBequemerweise lädt man dazu nicht mehrere einzelne Dateien, sondern setzt mehrereTeilbilder in einer Bilddatei nebeneinander. Blitz Basic unterstützt diese Bemühungen,indem es Arbeiten mit Frames erleichtert. Enthält eine Bilddatei mehrere Bewegungs-schritte, sollten Sie sie nicht mit LoadImage(), sondern mit LoadAnimImage() laden. Zu-sätzlich zum Dateinamen geben Sie Folgendes an:

� Breite und Höhe des Einzelbilds

� bei welchem Einzelbild begonnen werden soll (normalerweise dem ersten, 0)

� wie viele Einzelbilder vorhanden sind:

bild = LoadAnimImage("Surfer_32by32.bmp", 32,32, 0,16)

Daraus ergibt sich, dass jedes Einzelbild die gleiche Größe haben und exakt an das vor-hergehende Bild anschließen muss.

Abb. 19.1:Animations-stufen einer

Figur.

Beim Darstellen eines Einzelbilds geben Sie zusätzlich an, welcher Frame dargestelltwird:

DrawImage bild, 100, 100, 3

Eine Animation stellen Sie mit einer For-Schleife dar:

Graphics 640,480SetBuffer BackBuffer()bild = LoadAnimImage("Surfer_32by32.bmp", 32,32, 0,16)For I=0 To 15 Cls DrawImage bild, 100, 100, I Flip Delay 200NextWaitKey

Und nun noch einmal, mit etwas mehr Raffinesse:

; SURFER.BBGraphics 640,480SetBuffer BackBuffer()bild = LoadAnimImage("Surfer_32by32.bmp", 32,32, 0,16)For I=0 To 15 Cls DrawImage bild, MouseX(), MouseY(), I Flip Delay 200 If I=15 Then I=0 If KeyHit(1) Then I=15NextWaitKey

Page 211: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

211

Animationen j e t z t l e r n e i c h

Ideal ist das Programm allerdings nicht: Die Bewegungen sind ruckelnd, weil sie imGleichklang mit dem Animationsschritt laufen. Verringern Sie den Delay-Wert, läuftdas Programm flüssiger, aber der Surfer bekommt einen Drehwurm.

19.1.2 Figur animieren IIEmpfehlenswert ist folgendes Vorgehen: Überlegen Sie, wie lange jedes Einzelbild an-gezeigt werden soll. Nutzen Sie MilliSecs()dazu, um festzulegen, wann welches Ein-zelbild an der Reihe ist. Dadurch trennen Sie die Geschwindigkeit des Spiels von denAnimationsstufen.

Schauen wir uns das an einem Beispiel an. Aus der Fülle der Beispielbilder habe ich ei-nen Tiger mit sechs Animationsstufen gewählt. LoadAnimImage() lässt sich hier nichtverwenden, weil die Teilbilder nicht exakt die gleichen Abstände haben, sondern auchuntereinander. In diesem Fall bietet es sich an, die Positionen der Teilbilder in einemDim-Feld zu speichern.

Dim Frames(5,1)Frames(0,0) = 0 : Frames(0,1) = 0Frames(1,0) = 128 : Frames(1,1) = 0Frames(2,0) = 256 : Frames(2,1) = 0Frames(3,0) = 384 : Frames(3,1) = 0Frames(4,0) = 0 : Frames(4,1) = 128Frames(5,0) = 128 : Frames(5,1) = 128

Abb. 19.2:Vor allem bei Animationen lohnt sich das Aufnehmen aller Schritte in eine Grafik. Dabei sollten die Schritte jedoch neben-einander und nicht – wie hier – in meh-reren Reihen abgespeichert werden.

Damit kennen wir etwa die Position des fünften Tigerbilds bei Frames(4,0), Fra-mes(4,1). Bei der Zeitsteuerung hilft uns MilliSecs(). Jedes Teilbild soll eine festgeleg-te Anzahl Millisekunden sichtbar sein, etwa 150. Dazu speichern wir MilliSecs() inder Zwischenvariable ZaehlStart. Bei jedem Durchlauf überprüfen wir, ob die Lebens-dauer eines Teilbilds beendet ist. In diesem Fall setzen wir die Zwischenvariable wiederauf MilliSecs() und den Teilbildzähler auf 0.

Page 212: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

212

Grafikseminare19j e t z t l e r n e i c h

If ZaehlStart + 10 < MilliSecs() Then Frame = Frame + 1 If Frame = 6 Then Frame = 0 ZaehlStart = MilliSecs()EndIf

Auf diese Weise erhalten wir einen rennenden Tiger:

; TIGER.BBGraphics 640, 480SetBuffer BackBuffer()hinter = LoadImage("stars.bmp")tiger = LoadImage ("char9.bmp")Color 0, 200, 0

Dim Frames(5,1)Frames(0,0) = 0 : Frames(0,1) = 0Frames(1,0) = 128 : Frames(1,1) = 0Frames(2,0) = 256 : Frames(2,1) = 0Frames(3,0) = 384 : Frames(3,1) = 0Frames(4,0) = 0 : Frames(4,1) = 130Frames(5,0) = 128 : Frames(5,1) = 130

Repeat H = H-1 If H=200 Then H=0 TileBlock hinter,H,0 Rect 0, 300, 639, 279 ; Zeit = MilliSecs() If ZaehlStart + 150 < MilliSecs() Then Frame = Frame + 1 If Frame = 6 Then Frame = 0 ZaehlStart = MilliSecs() EndIf

DrawImageRect tiger, 250, 172, Frames(Frame,0), Frames(Frame,1), 128, 128 FlipUntil KeyHit(1)

Abb. 19.3:Obwohl derTiger seine

Position nichtverändert,

scheint er sichzu bewegen.

Page 213: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

213

Animationen j e t z t l e r n e i c h

19.1.3 ExplosionenHäufig werden Animationen nicht endlos abgespielt, sondern durch ein Ereignis ge-steuert. Ein Beispiel: Bei der Explosion eines Raumschiffs wird seine Grafik ersetztdurch die Teilbilder einer Animation. Das Raumschiff fliegt ahnungslos durch das weiteAll, bis es ein Druck auf die Leertaste zerstört. Ab diesem Zeitpunkt bis zum Ende derZerstörung setzen wir eine Variable (Explodiert) auf 1. Sie hilft uns auszuwählen, obwir das Schiff zeichnen oder die Explosionsanimation. Vermeiden Sie bei solchen Fest-legungen das Einstellen eines Zustands, der bereits existiert. Mit einem Test ...

If KeyDown(57) And (Explodiert=0) Then ...

... verhindern Sie, dass die Explosion erneut beginnt, wenn der Spieler während derAnimation noch einmal die Leertaste drückt.

Abb. 19.4:Animations-schritte einer Explosion.

Ähnlich wie beim Tiger im vorigen Beispiel, verwenden wir MilliSecs(), um dieLebensdauer einer Animationsphase zu bestimmen. Zusätzlich zeichnen wir eine roteLinie als »Laserstrahl«.

; EXPLOSION.BBGraphics 640, 480SetBuffer BackBuffer()

hinter = LoadImage("stars.bmp")schiff = LoadImage("spaceship2.bmp")explosion = LoadAnimImage("kaboom.bmp", 60,46, 0,6)Color 255,0,0X = 300Y = 240

Repeat ; Hintergrund zeichnen H = H+1 If H=200 Then H=0 TileBlock hinter,0,H

; Leertaste gedrückt? If KeyDown(57) And (Explodiert=0) Then Explodiert = 1 ZaehlStart = MilliSecs() EndIf

If Explodiert = 0 Then ; Schiff zeichnen DrawImage schiff, X,Y Else ; Explosion If ZaehlStart + 100 < MilliSecs() Then Frame = Frame + 1 ZaehlStart = MilliSecs() If Frame = 6 Then Frame = 0 Explodiert = 0

Page 214: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

214

Grafikseminare19j e t z t l e r n e i c h

X = Rand(50,570) Y = Rand(50,410) EndIf EndIf DrawImage explosion, X,Y, Frame Line 0,0,X,Y ; Laserstrahl :-) EndIf FlipUntil KeyHit(1)

19.2 Kollisionen

Viele Spiele basieren auf zwei grundlegenden Funktionen: dem Erstellen von Bewe-gungen und dem Abfragen von Zusammenstößen. Ein Zusammenstoß kann vielessein:

� das Erreichen des Bildschirmrands

� das Stoßen an eine Mauer

� der Zusammenstoß der Spielfigur mit einem Objekt oder einem Gegner

Zusammenstöße nennt man auch Kollisionen und der Test, ob ein Zusammenstoß er-folgt ist, heißt Kollisionsabfrage. Bei jeder Bewegung einer Figur, ob vom Spieler odervom Computer gesteuert, muss sie erfolgen.

Grundsätzlich lässt sich eine Kollisionsabfrage leicht selbst programmieren. Sie müssennur testen, ob sich zwei Bilder (deren Position und Maße Ihnen ja bekannt sind) berüh-ren oder gar überschneiden. Da eine Kollisionsabfrage aber ein wichtiger Bestandteilvieler Spiele ist, stellt Ihnen Blitz Basic vorgefertigte Befehle zur Verfügung. Mit ihrerHilfe ermitteln Sie leicht, ob Bild A und Bild B miteinander kollidieren.

19.2.1 Rand testenOb ein Objekt den Rand erreicht hat, testen Sie einfach anhand seiner Koordinaten;besondere Befehle sind nicht notwendig.

Nehmen wir einen Ball, der sich auf einem Feld bewegt. Solange er freie Bahn hat, istalles in Ordnung: Sie erhöhen oder verringern in einer For-Schleife einfach seine Ko-ordinaten. Bei jedem Bewegungsschritt fragen Sie viermal ab, ob der Ball an den Randstößt – links, rechts, oben oder unten. Nickt der Computer, brauchen Sie eine Regel,was passieren soll: Der Ball prallt ab, ändert also seine Richtung. Und damit der Ballnicht langweilig von links nach rechts hin- und herwandert, probieren wir es schräg.Das ist nicht schwieriger zu programmieren, sieht aber netter aus. Damit es noch net-ter aussieht, habe ich gleich drei Bälle genommen. In einem Feld werden ihre Datenabgelegt. (I,1) und (I,2) enthalten ihre derzeitige Position; (I,3) und (I,4) ihrewaagerechte und senkrechte Richtung (-1 für oben/links; +1 für unten/rechts). BeimÄndern der Koordinaten wird der Richtungswert hinzugefügt – was bei -1 eine Verrin-gerung bedeutet.

Page 215: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

215

Kollisionen j e t z t l e r n e i c h

; KOLLISION1.BBGraphics 640,480SetBuffer BackBuffer();; Startdaten für die BälleData 100,100,1,1Data 200,200,1,-1Data 300,300,-1,1Dim Ball(3,4); Startdaten einlesenFor I=1 To 3 For J=1 To 4 Read Ball(I,J) NextNext; HauptschleifeRepeat ClsColor 200,200,0 Cls Color 220,220,0 Rect 50,50,540,380,1

For I=1 To 3 ; Randtest If Ball(I,1)=50 Then Ball(I,3) = +1 If Ball(I,1)=555 Then Ball(I,3) = -1 If Ball(I,2)=50 Then Ball(I,4) = +1 If Ball(I,2)=395 Then Ball(I,4) = -1 ; Position ändern Ball(I,1) = Ball(I,1) + Ball(I,3) Ball(I,2) = Ball(I,2) + Ball(I,4)

Color 0,0,255 Oval Ball(I,1),Ball(I,2),36,36,0 Next Flip Delay 1Until KeyHit(1)WaitKey

(Wenn Sie mögen, ändern Sie das Programm so ab, dass der Ball nicht zurückprallt,sondern an der entgegengesetzten Seite des Bildschirms wieder erscheint. Das war zueinfach? Dann lassen Sie die Bälle sich mit verschiedenen Geschwindigkeiten bewe-gen.)

Page 216: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

216

Grafikseminare19j e t z t l e r n e i c h

Abb. 19.5:Einfacher Kolli-sionstest durch

Vergleich derKoordinaten

mit dem Spiel-rand.

19.2.2 Überlappung von zwei BereichenOb sich zwei rechteckige Bereiche berühren, testen Sie am schnellsten mit RectsOver-lap(). Die Funktion erwartet als Parameter:

� die Koordinaten der oberen linken Ecke des ersten Rechtecks

� Breite und Höhe des ersten Rechtecks

� die Koordinaten der oberen linken Ecke des zweiten Rechtecks

� Breite und Höhe des zweiten Rechtecks

und liefert das Ergebnis 1, wenn sich die Rechtecke überlagern oder berühren.

Probieren wir es aus, indem wir an zufälliger Stelle jeweils ein Paar Quadrate zeichnen– und wenn sie sich berühren, lassen wir einen Klang ertönen:

; KOLLISION2.BBGraphics 640,480ton = LoadSound("soundfx11.wav")SetBuffer BackBuffer()Repeat Cls X1 = Rand(570) Y1 = Rand(410) X2 = Rand(570) Y2 = Rand(410) Color Rand(255), Rand(255), Rand(255) Rect X1,Y1, 70,70,1 Delay 200 Color Rand(255), Rand(255), Rand(255)

Page 217: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

217

Kollisionen j e t z t l e r n e i c h

Rect X2,Y2, 70,70,1 Flip If RectsOverlap(X1,Y1,70,70, X2,Y2,70,70) Then PlaySound(ton) EndIf Delay 300Until KeyHit(1)

19.2.3 Kollision eines Bilds mit einem BereichMit der Funktion ImageRectCollide() testen Sie, ob ein Bild mit einem festgelegtenrechteckigen Bereich kollidiert. Diese Funktion erwartet als Parameter:

� den Namen des Bilds

� die Koordinaten des Bilds

� das Einzelbild einer Animation (normal: 0)

� die Koordinaten des Rechtecks

� Breite und Höhe des Ausschnitts

Um das an einem netten Beispiel auszuprobieren, habe ich das Ball-Beispiel etwas ver-ändert:

� Statt der gemalten Kreise bewegen sich drei Discs (DISC.BMP).

� Auf dem Bildschirm werden zehn rote Quadrate verteilt.

� Wenn eine Disc ein Quadrat berührt, wird es entfernt und ein Geräusch ertönt.

� Entfernte Quadrate werden durch neue Quadrate ersetzt.

; KOLLISION3.BBGraphics 640,480SetBuffer BackBuffer()

disc = LoadImage("disc.bmp")ton = LoadSound("soundfx11.wav")Dim Quadrat(10,3);; Startdaten für die BälleData 100,100,1,1Data 200,200,1,-1Data 300,300,-1,1Dim Ball(3,4); Startdaten für Bälle einlesenFor I=1 To 3 For J=1 To 4 Read Ball(I,J) NextNext;; Hauptschleife;Repeat ClsColor 200,200,0 Cls Color 220,220,0 Rect 50,50,540,380,1

Page 218: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

218

Grafikseminare19j e t z t l e r n e i c h

; Quadrate "ausdenken" For I=1 To 10 If Quadrat(I,0) = 0 Then Quadrat(I,0) = 1 ; = vorhanden Quadrat(I,1) = Rand(520) + 50 Quadrat(I,2) = Rand(360) + 50 EndIf Next

; Quadrate zeichnen Color 255,0,0 For I=1 To 10 If Quadrat(I,0) = 1 Then Rect Quadrat(I,1),Quadrat(I,2),20,20,1 Next

For I=1 To 3 ; Randtest If Ball(I,1)=50 Then Ball(I,3) = +1 If Ball(I,1)=527 Then Ball(I,3) = -1 If Ball(I,2)=50 Then Ball(I,4) = +1 If Ball(I,2)=366 Then Ball(I,4) = -1 ; Position Bälle ändern Ball(I,1) = Ball(I,1) + Ball(I,3) Ball(I,2) = Ball(I,2) + Ball(I,4)

DrawImage disc, Ball(I,1),Ball(I,2)

; Zusammenstoß mit Quadraten testen For J=1 To 10 If Quadrat(J,0) = 1 Then If ImageRectCollide (disc,Ball(I,1),Ball(I,2),0, Quadrat(J,1),Quadrat(J,2),20,20) Then Quadrat(J,0) = 0 PlaySound(ton) EndIf EndIf Next

Next Flip Delay 1Until KeyHit(1)WaitKey

Natürlich hätten wir keine Quadrate zeichnen müssen. Der Funktion ImageRect-Collide() ist es egal, ob überhaupt etwas gezeichnet ist. Es wird nur geprüft, ob einBild einen Bereich berührt. Dabei kann es sich um einen Rand, einen Balken oder so-gar ein anderes Bild handeln. Die Prüfung ist dabei pixelgenau: Obwohl das Disc-Bildrechteckig ist, wird ein Quadrat nur gelöscht, wenn es den Rand tatsächlich berührt.Der Hintergrund ist also transparent.

Falls es Ihnen nicht darauf ankommt, die genaue Umrandung des Bilds zu prüfen, neh-men Sie stattdessen die schnellere Funktion ImageRectOverlap(). Sie ignoriert dietransparente Farbe. Da die Größe eines Bilds bekannt ist, sollten Sie in diesem Fall bes-ser die noch simplere Funktion RectOverlap() nutzen.

Page 219: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

219

Kollisionen j e t z t l e r n e i c h

Abb. 19.6:Kollision zwi-schen einer Grafik und einem Bild-schirm-ausschnitt (Quadrat).

19.2.4 Kollision zweier BilderÄhnlich einfach prüfen Sie den Zusammenstoß zweier Bilder. Auch hier gibt es zweiFunktionen: ImagesCollide() beachtet den transparenten Hintergrund, misst alsopunktgenau die Umrisse der Bilder. ImagesOverlap() prüft hingegen nur die rechtecki-gen Bereiche, den die beiden Bilder einnehmen. Die Parameter:

� das erste Bild

� die Koordinaten des ersten Bilds

� das Einzelbild der Animation (normal: 0)

� das zweite Bild

� die Koordinaten des zweiten Bilds

� das Einzelbild der Animation (normal: 0)

1Da ImagesCollide() langsamer arbeitet als ImagesOverlap(), sollten Sie die Funktionnur dann einsetzen, wenn sie wirklich notwendig ist. Es ist ratsam, zunächst nur eineRechteck-Prüfung vorzunehmen. Erst wenn dabei eine Kollision auftritt, prüfen Siepixelgenau mit ImagesCollide().

Page 220: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

220

Grafikseminare19j e t z t l e r n e i c h

Erweitern wir doch unser Disc-Beispiel um Zusammenstöße der Bälle: Wenn zwei Ku-geln aneinander geraten, stoßen sie einander ab. Da es nur drei Bälle gibt, brauchenSie nur drei Abfragen:

� Stößt Ball 1 an Ball 2?

� Stößt Ball 1 an Ball 3?

� Stößt Ball 2 an Ball 3?

Aufwendiger sind die Regeln, was bei einem Zusammenstoß passieren soll: Der Ballsoll zurückprallen und daher muss berücksichtigt werden, aus welcher Richtung der an-dere Ball kommt. Wir machen es uns sehr einfach und tauschen einfach die Richtungs-daten zweier zusammenstoßender Bälle:

; KOLLISION4.BB; Zusammenstoß zweier Bälle prüfen If ImagesCollide(disc,Ball(1,1),Ball(1,2),0,disc,Ball(2,1),Ball(2,2),0) Then X = Ball(1,3) Y = Ball(1,4) Ball(1,3) = Ball(2,3) Ball(1,4) = Ball(2,4) Ball(2,3) = X Ball(2,4) = Y PlaySound(discton) EndIf If ImagesCollide(disc,Ball(1,1),Ball(1,2),0,disc,Ball(3,1),Ball(3,2),0) Then X = Ball(1,3) Y = Ball(1,4) Ball(1,3) = Ball(3,3) Ball(1,4) = Ball(3,4) Ball(3,3) = X Ball(3,4) = Y PlaySound(discton) EndIf If ImagesCollide(disc,Ball(2,1),Ball(2,2),0,disc,Ball(3,1),Ball(3,2),0) Then X = Ball(2,3) Y = Ball(2,4) Ball(2,3) = Ball(3,3) Ball(2,4) = Ball(3,4) Ball(3,3) = X Ball(3,4) = Y PlaySound(discton) EndIf

Damit ein Zusammenstoß auch akustisch quittiert wird, habe ich am Anfang eine zwei-te Klangdatei geladen ...

discton = LoadSound("soundfx20.wav")

... und lasse sie abspielen.

19.2.5 Programmieren von SchalternEine besondere Form des Zusammenstoßens von Objekten sind grafische Menüs. Obder Bediener eines Programms gerade auf eine Schaltfläche klickt, erfragen Sie, indemSie die Kollision des Mauszeigers (POINTER.BMP) mit den Maßen des Schalters unddem Drücken der Maustaste überprüfen.

Page 221: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

221

Kollisionen j e t z t l e r n e i c h

Sie sollten das Anklicken eines Schalters akustisch und optisch kennzeichnen, indemSie einen Klang abspielen und die Farbe des Schalters ändern. Selbst dann, wenn perMausklick auf eine andere Menüseite gewechselt werden soll, empfehle ich Ihnen einUmfärben des Menüpunkts, eine kleine Pause von einer Drittelsekunde und erst danneinen Seitenwechsel.

Soll mit dem Schalten das Wechseln einer Eigenschaft verbunden werden, etwa dasEin- und Ausschalten der Hintergrundmusik, speichern Sie den Zustand in einer Vari-ablen und fragen Sie ihn an passender Stelle ab.

Lassen wir an zufälligen Stellen des Bildschirms zehn Quadrate zeichnen. Wenn Sie einQuadrat anklicken, verfärbt es sich. Nach drei Sekunden erhält es seine ursprünglicheFarbe zurück. Auf ähnliche Weise verwenden Sie Text-Menüpunkte oder grafischeSchalter.

; SCHALTER.BBGraphics 640,480SetBuffer BackBuffer()maus = LoadImage("pointer.bmp")sound = LoadSound("soundfx20.wav")Dim Quadrate(10,2)

For I=1 To 10 Quadrate(I,1) = 60 * I-1 Quadrate(I,2) = Rand(410) Quadrate(I,0) = 0Next

Repeat ClsColor 255,0,0 Cls X = MouseX() Y = MouseY() For I=1 To 10 If ImageRectOverlap (maus, X,Y, Quadrate(I,1), Quadrate(I,2), 50, 50) And MouseDown(1) And Quadrate(I,0) = 0 Then Quadrate(I,0) = MilliSecs() PlaySound sound EndIf If MilliSecs() - 3000 > Quadrate(I,0) Then Quadrate(I,0) = 0 Color 0,255,0 If Quadrate(I,0) = 0 Then Color 0,0,255 Rect Quadrate(I,1), Quadrate(I,2),50,50,1 Next DrawImage maus, X, Y FlipUntil KeyHit(1)

(Spielen Sie so lange, bis alle Quadrate grün sind! ;-)

1Statt mit Grafiken funktioniert das Verfahren auch mit Text. Ein einfaches Menü lässtsich mit einer netten Schriftart und einem Rechteck erstellen. Ob sich die Maus in-nerhalb eines Rechtecks befindet, erfragen Sie mit ImageRectCollide().

Page 222: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

222

Grafikseminare19j e t z t l e r n e i c h

19.2.6 Eigene Berechnung der KollisionDie Kollisionsabfrage wird meist für Aufgaben »missbraucht«, für die sie gar nicht vor-gesehen ist. Versuchen Sie, auf die langsamen Kollisionsbefehle zu verzichten. Meistgenügt es, die Koordinaten zu überprüfen. Auch Tests, ob ein Rechteck, ein Kreis odereine Ellipse angeklickt wurde, sind mit einfachen Berechnungen möglich:

19.3 Frame-Rate berechnen

Ein beliebtes Messinstrument ist die so genannte Frame-Rate, die Anzahl der gezeich-neten Bilder je Sekunde. Sie wird oft kurz als FPS bezeichnet – Frames per Second. Siesehen anhand dieser Zahl leicht, ob Änderungen am Quelltext förderlich für die Spiel-geschwindigkeit sind oder nicht. Wenn Sie Ihr Programm an Freunde weitergeben, er-fahren Sie über die ermittelte Frame-Rate, wie schnell Ihr Spiel auf anderen PCs läuft.

Um die Frame-Rate zu errechnen, müssen Sie zählen, wie oft Flip je Sekunde ausge-führt wird. Dazu bietet sich eine Funktion an:

; FPS.BBFunction FPS() Frames = Frames + 1

If ZaehlStart + 1001 < MilliSecs() Then FramesJeSekunde = Frames Frames = 0 ZaehlStart = MilliSecs() EndIf

Text 10, 10, FramesJeSekunde + " FPS"End Function

Um den Sekundentakt zu erreichen, versorgen wir die Variable ZaehlStart mit Milli-Secs(). Ist eine Sekunde verstrichen, setzen wir sie wieder auf 0. Die Anzahl derDurchläufe in dieser Zeit ist die Frame-Rate. Wir übergeben sie an eine weitere Vari-able FramesJeSekunde, um im Sekundentakt eine konstante Zahl auszudrucken und da-mit die Variable Frames wieder für die nächste Sekunde zählen kann. Ein praktischesBeispiel finden Sie im Quelltext KUH10.BB abgelegt.

0

Form Kollisionstest

Rechteck If X=>X1 And Y=>Y1 And X<=X2 And Y<=Y2 Then...

Kreis If Sqr((X-MitteX)^2+(Y-MitteY)^2) >= Radius Then...

Ellipse(RadiusY= RadiusX/2)

If Sqr((X-MitteX)^2+((Y-MitteY)*2)^2) >= Radius Then...

Es gibt externe Werkzeuge, die nebenbei mitlaufen und die Frame-Rate mitzählen.Fraps (www.fraps.com, auf der Buch-CD) ist eines davon. Das Besondere: Es mel-det sich nur im Grafikmodus und ist ansonsten still. Und es bietet gleichzeitig eineScreenshot-Funktion, erzeugt also auf Tastendruck Schnappschüsse des Bildschirm-inhalts.

Page 223: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

223

Sternenhimmel j e t z t l e r n e i c h

Je nach Rechenaufwand kann sich die Frame-Rate stark ändern. Bei grafisch sehr auf-wendigen Spielen wie Ego-Shootern ist die Darstellungsdichte in kleinen Innenräumenoft viel höher als in großen Außenarealen. Allgemein sagt man, dass 25 Frames je Se-kunde für eine flüssige Darstellung genügen. Der tatsächliche Akzeptanzwert ist aberbei jedem unterschiedlich. Und was der eine als flüssig ansieht, mag für den anderenruckeln.

19.4 Sternenhimmel

Überlegen wir, wie man einen einzelnen Punkt auf effektvolle Weise vermehren kann.Ein Punkt ist langweilig, doch viele Punkte ergeben auf einem schwarzen Hintergrundeinen Sternenhimmel:

; STERNE1.BBGraphics 640, 480SetBuffer BackBuffer()Color 0,0,255SeedRnd MilliSecs()

Repeat Cls For I=1 To 200 Plot Rand(1, 640), Rand(1, 480) Next Flip Delay 2000Until KeyHit(1)

Das Beispiel zeichnet im Abstand von zwei Sekunden jeweils 200 weitere »Sterne« aufden Schirm. Die Punkte werden dichter und dichter – bis die È-Taste alles zerstört.

Probieren wir eine kleine Abwandlung: Das Bild soll in kurzen Abständen zwischenzwei Sternenkonstellationen hin- und herschwenken. Wir erstellen zufällig zwei Grup-pen von Sternenanordnungen, die wir im Wechsel zeichnen. Ihre Positionen merkenwir uns in je einem Feld:

; STERNE2.BBGraphics 640, 480SetBuffer BackBuffer()SeedRnd MilliSecs()

; 2 Gruppen von Sternen merkenDim Sterne1(400, 1)Dim Sterne2(400, 1)

Reiner Prokein, www.reinerstileset.de: »Bauen Sie während der Testphase einesProgramms unbedingt einen Frame-Zähler ein. Damit haben Sie immer eine Kon-trolle, wo Optimierungen nötig sind. Denken Sie dabei an Besitzer langsamerer Com-puter. Wohl sollten nur die eigenen Maßstäbe die Grenze für Ihre Spiele sein. DochSie haben nichts von der Freiheit, wenn Ihr Werk so überladen ist, dass nur noch zweiBilder je Sekunde berechnet werden können. :-)«

Page 224: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

224

Grafikseminare19j e t z t l e r n e i c h

For I=1 To 400 Sterne1(I, 0) = Rand(0,640) Sterne1(I, 1) = Rand(0,480) Sterne2(I, 0) = Rand(0,640) Sterne2(I, 1) = Rand(0,480)Next

Repeat ; Gruppe 1 zeichnen Cls Color 255,0,0 For I=1 To 400 Plot Sterne1(I, 0), Sterne1(I, 1) Next Flip Delay 500

; Gruppe 2 zeichnen Cls Color 0,0,255 For I=1 To 400 Plot Sterne2(I, 0), Sterne2(I, 1) Next Flip Delay 500Until KeyHit(1)

Erhöhen wir die Herausforderung etwas: Jeder Stern soll eine bestimmte Lebensdauerhaben. Danach verglüht er und ein neuer Stern wird an eine andere Stelle versetzt.Dazu benötigen wir neben den Koordinaten des Punkts eine dritte Angabe – die Le-bensdauer. Wir zählen bei jedem Stern einfach bis 1000. Ist die Zahl erreicht, versetzenwir die Koordinaten des Sterns:

If Sterne(I, 0) < 1000 Then Sterne(I, 0) = Sterne(I, 0) + 1Else Sterne(I, 0) = Rand(0,1000) Sterne(I, 1) = Rand(0,640) Sterne(I, 2) = Rand(0,480)EndIf

Zu Beginn erhält jeder Stern eine zufällige Lebensdauer, sonst würden alle Sterne zurgleichen Zeit »sterben«:

Sterne(I, 0) = Rand(0,1000)

Das komplette Programm:

; STERNE3.BBGraphics 640, 480SetBuffer BackBuffer()Color 0,0,255SeedRnd MilliSecs()

; Sterne merkenDim Sterne(400, 2)For I=1 To 400 Sterne(I, 0) = Rand(0,1000) ; Lebensdauer Sterne(I, 1) = Rand(0,640) Sterne(I, 2) = Rand(0,480)Next

Page 225: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

225

Sternenhimmel j e t z t l e r n e i c h

Repeat Cls For I=1 To 400

If Sterne(I, 0) < 1000 Then Sterne(I, 0) = Sterne(I, 0) + 1 Else Sterne(I, 0) = Rand(0,1000) Sterne(I, 1) = Rand(0,640) Sterne(I, 2) = Rand(0,480) EndIf

Plot Sterne(I, 1), Sterne(I, 2)

Next FlipUntil KeyHit(1)

Effektvoll kann auch ein Sternenhimmel sein, der sich bewegt. Bei einem Weltraum-Shooter lässt sich auf zwei Arten eine Bewegung des Raumschiffs simulieren: Man ver-ändert die Position des Raumschiffs – oder man verschiebt den Hintergrund. Um dasumzusetzen, merken wir uns wiederum die Position von 400 Sternen in einem Feld.Bei jedem Schleifendurchlauf verringern wir die Y-Koordinate um 1, damit jeder Sterneinen Punkt nach oben wandert. Ist er oben angelangt, wird er ersetzt durch einen neu-en Stern (eigentlich wird nur die Position des alten geändert), der an der Grundlinie(Sterne(I, 1) = 479) erstellt wird:

; STERNE4.BBGraphics 640, 480SetBuffer BackBuffer()Color 0,0,255SeedRnd MilliSecs()

; Sterne merkenDim Sterne(400, 1)For I=1 To 400 Sterne(I, 0) = Rand(0,640) Sterne(I, 1) = Rand(0,480)Next

Repeat Cls For I=1 To 400

If Sterne(I, 1) <> 0 Sterne(I, 1) = Sterne(I, 1) - 1 Else Sterne(I, 0) = Rand(0,640) Sterne(I, 1) = 479 EndIf

Plot Sterne(I, 0), Sterne(I, 1)

Next FlipUntil KeyHit(1)

Hübscher wäre ein Hintergrund aus »echten« gezeichneten Sternen. Wie das aussehenkann, das sehen Sie wenige Seiten später.

Page 226: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

226

Grafikseminare19j e t z t l e r n e i c h

19.5 Bunte Linien

Tauschen wir 400 Sterne gegen 399 bunte Linien! Ich gebe zu, das Beispiel ist nichtsonderlich originell, aber es ist nett anzusehen – mindestens 20 Sekunden lang. InAnlehnung an das vorherige Beispiel sind Anfangs- und Endpunkt nicht ganz zufälliggewählt: Eine neue Linie beginnt immer dort, wo die vorherige endete. Daher sind alleLinien miteinander verbunden.

; LINIEN.BBGraphics 640, 480SetBuffer BackBuffer()ClsColor 255,255,255SeedRnd MilliSecs()Dim Punkte(400, 1)

Repeat Cls ; Punkte merken For I=1 To 400 Punkte(I, 0) = Rand(0,640) Punkte(I, 1) = Rand(0,480) Next

; Linien zeichnen For I=1 To 399 Color Rand(255), Rand(255), Rand(255) Line Punkte(I, 0), Punkte(I, 1), Punkte(I+1, 0), Punkte(I+1, 1) Next FlipUntil KeyHit(1)

Die È-Taste wird nur im Abstand von einigen Sekunden abgefragt – bei aufwendi-geren Demos sollte die Tastatur innerhalb der For-Schleife abgefragt werden.

Abb. 19.7:Bunte Linien,

erzeugt miteiner For-

Schleife undZufallszahlen.

Page 227: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

227

Sinuskurve j e t z t l e r n e i c h

19.6 Sinuskurve

Besonders raffinierte Effekte erzielen Sie unter Zuhilfenahme mathematischer For-meln. Der Verlauf einer Sinuskurve lässt sich mit Punkten einfach nachbilden:

; SINUSKURVE1.BBGraphics 640,480SetBuffer BackBuffer()ClsFor I=1 To 360 Plot I, Sin(I) * 100 + 100NextFlipWaitKey

Na gut, das sieht noch ein wenig bieder aus. Spielen wir mit den Parametern, dann er-halten wir rasch schönere Ergebnisse:

; SINUSKURVE2.BBGraphics 640,480SetBuffer BackBuffer()ClsFor I=1 To 760 Plot I, Sin(I) * 100 + 100 Plot I, Sin(I) * 100 + 100 + I / 2 Plot I, Sin(I) * 100 + 100 + I Plot I, Sin(I) * 100 + 100 + I * 2NextFlipWaitKey

Abb. 19.8:Eine Sinuskurve lässt sich durch das Variieren der Parameter stark ver-ändern.

Page 228: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

228

Grafikseminare19j e t z t l e r n e i c h

19.7 Flugbahnen

Die Sinus-Kurve eignet sich aufgrund ihres harmonischen Erscheinungsbilds gut alsFlugbahn. So wirkt ein Space-Shooter schicker, wenn computergesteuerte Raumschif-fe nicht senkrecht nach unten fliegen, sondern elegant nachschwingen. Das lässt sichleicht umsetzen. Die Zeile wird normal erhöht. Für die Spalte verwenden wir einen Si-nus-Wert. Je größer die Zahl ist, mit der wir das Ergebnis (das immer zwischen –1 und1 liegt) multiplizieren, desto mehr schlägt die Schlängellinie aus. Freilich lässt sich dieBahn beschränken auf einen Teil der Kurve. Wenn Sie das Zeichnen oder Löschen desHintergrunds in der Schleife entfernen, vollziehen Sie die Flugbahn genau nach.

; FLUGBAHN.BBGraphics 640,480SetBuffer BackBuffer()

hinter = LoadImage ("stars.bmp")schiff = LoadImage ("spaceship2.bmp")RotateImage schiff, 180

Repeat TileBlock hinter ; evt. auskommentieren Y = Y + 1 If Y = 480 Then Y = 0 X1 = 320 + Sin(Y) * 150 X2 = 320 + Sin(Y) * 100

DrawImage schiff, X1,Y-20 DrawImage schiff, X2,Y+20

Flip Until KeyHit(1)

A19.8 Drehung um die eigene Achse

Eine Spielfigur lässt sich leicht nach links, rechts, oben und unten bewegen. Ändernwir gleichzeitig die vertikale und horizontale Position, sind vier weitere Richtungenmöglich. Das genügt nicht immer. In einigen Spielen dreht sich die Figur stufenlos umdie eigene Achse, etwa bei Weltraum-Shootern, wo die Gegner aus allen Richtungenkommen. Oder bei Spielen aus der Vogelperspektive, wie die beiden ersten Teile von»Grand Theft Auto«.

1Wir müssen dazu zwei Teilaufgaben umsetzen. Da sich die Figur in jede Richtung – qua-si im Kreis – drehen soll, benötigen wir Grafiken in jede Richtung. Bei einem Vollwinkelvon 360 Grad benötigen wir 360 Einzelbilder. Oftmals genügen freilich weniger Ab-stufungen, zum Beispiel 16. Es bietet sich an, diese Einzelbilder vorher zu erstellen undin einem Feld zu speichern. Wir laden das Bild einmal in den Hauptspeicher, ziehen mitCopyImage() 360 Kopien davon und drehen diese Kopien um jeweils ein Grad mehr.

Dieser Abschnitt entstand in Zusammenarbeit mit Raffael »Inpac« Hannemann, demBetreiber der Seite www.inpacproducts.de.vu.

Page 229: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

229

Drehung um die eigene Achse j e t z t l e r n e i c h

Moderne PCs sind schnell genug, um diese Vorbereitungen während der Laufzeit einesSpiels vorzunehmen. Mit RotateImage gibt es einen passenden Befehl dazu. So haltenwir es auch. Um Bildverfälschungen zu vermeiden (und gleichzeitig die Geschwindig-keit zu erhöhen), schalten wir vorher den binlinearen Filter (TFormFilter) ab. Da sichdas Bild um sich selbst dreht, zentrieren wir den Bezugspunkt.

Zu berücksichtigen ist dabei die Grundausrichtung des Objekts. Ist es nach links ausge-richtet, drehen wir das Bild jeweils um den korrekten Winkel. Schaut es nach oben, wiebei unserer Grafik, ziehen wir jeweils 90 Grad ab. Schaut es nach rechts, 180 usw.

Dim Alien(359)TFormFilter 0bild = LoadImage("alien.bmp")

For Winkel = 0 To 359 Alien(Winkel) = CopyImage(bild) RotateImage Alien(Winkel), Winkel - 90 MidHandle Alien(Winkel)Next

Damit haben wir 360 Einzelbilder und können unser Alien stufenlos um sich selbst dre-hen lassen:

; VOLLDREHUNG1.BBGraphics 640,480SetBuffer BackBuffer()

Dim Alien(359)TFormFilter 0bild = LoadImage("alien.bmp")

For Winkel = 0 To 359 Alien(Winkel) = CopyImage(bild) RotateImage Alien(Winkel), Winkel - 90 MidHandle Alien(Winkel)Next

Repeat Cls Winkel = Winkel + 5 If Winkel > 359 Then Winkel = 0 DrawImage Alien(Winkel), 200,200 FlipUntil KeyHit(1)

Das heißt: Indem Sie den Winkel erhöhen oder verringern, drehen Sie das Objekt inAbhängigkeit von seiner derzeitigen Position. Sie müssen lediglich berücksichtigen,dass 360 Grad gleichzeitig 0 Grad sind, der Winkel von 360 also auf 1 Grad springt.

Etwas kniffliger ist die Fortbewegung des Objekts. Bei Spielen mit Volldrehung wirdmeistens das Objekt mit { und } gedreht, während es sich mit | in die Richtung be-wegt, in die es gerade schaut. Es soll sich damit in jede beliebige Richtung steuern las-sen, nicht nur waagerecht und senkrecht. Wir müssen also für jeden Winkel in Erfah-rung bringen, wie weit sich das Objekt auf der X- und auf der Y-Achse bewegt. Und dassagen uns die Sinus- und Cosinus-Funktionen.

X# = X - Cos(Winkel)Y# = Y - Sin(Winkel)

Page 230: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

230

Grafikseminare19j e t z t l e r n e i c h

Wir können das Ergebnis der Funktionen mit einer Konstante multiplizieren, um dieGeschwindigkeit zu erhöhen:

X# = X - Cos(Winkel) * GeschwindigkeitY# = Y - Sin(Winkel) * Geschwindigkeit

Setzen wir alles zu einem Beispiel zusammen. Das Alien bewegt sich vorwärts undrückwärts im Verhältnis zu der Richtung, in die es schaut. Mit { und } dreht es sichum seine eigene Achse.

; VOLLDREHUNG2.BBGraphics 640,480SetBuffer BackBuffer()

Dim Alien(359)TFormFilter 0bild = LoadImage("alien.bmp")

For Winkel = 0 To 359 Alien(Winkel) = CopyImage(bild) RotateImage Alien(Winkel), Winkel - 90 MidHandle Alien(Winkel)Next

Geschwindigkeit = 3X# = 300Y# = 220

Repeat Cls If KeyDown(203) Then Winkel= Winkel - 1 ; Links - Winkel wird verkleinert If KeyDown(205) Then Winkel= Winkel + 1 ; Rechts - Winkel wird erhöht If Winkel > 359 Then Winkel = 0 If Winkel < 0 Then Winkel = 359 If KeyDown(200) Then ; Hoch X = X - Cos(Winkel) * Geschwindigkeit Y = Y - Sin(Winkel) * Geschwindigkeit EndIf If KeyDown(208) Then ; Runter X = X + Cos(Winkel) * Geschwindigkeit Y = Y + Sin(Winkel) * Geschwindigkeit EndIf DrawImage Alien(Winkel),X,Y FlipUntil KeyHit(1)

19.9 Eingabefunktion

Mit Input() gibt der Spieler Texte, beispielsweise seinen Namen, über die Tastatur ein.Doch diese Funktion hat auch Nachteile. Das komplette Programm hält so lange an,bis Æ gedrückt wurde. Es ist nicht möglich, etwa währenddessen eine Animation ab-zuspielen. Auch Effekte wie das akustische Quittieren eines Tastendrucks oder das pa-rallele Darstellen des jeweiligen Zeichens als Grafikdatei sind nicht möglich. Unter BlitzPlus wird Input() im Grafikmodus gar nicht mehr unterstützt.

Leicht schreiben Sie sich eine eigene Eingabefunktion. Sie wartet in einer Schleife aufeinen Tastendruck und gibt ihn aus. Æ beendet sie. Auch die Ã-Taste zum Lö-

Page 231: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

231

Laufschrift j e t z t l e r n e i c h

schen eines Buchstabens muss unterstützt werden, falls sich der Spieler vertippt. EineSchreibmarke ist nicht notwendig, doch sie schafft ein vertrautes Bild. Mit ein bisschenAufwand lassen wir sie sogar blinken.

; EINGABE.BBGraphics 640,480SetBuffer BackBuffer()

Repeat Cls Text 100,100, "Name: " A = GetKey() If A > 31 Then Name$ = Name$ + Chr$(A) If (A = 8) And Len(Name$) > 0 Then Name$ = Left$(Name$, Len(Name$) - 1) Text 150,100, Name$ + "_" FlipUntil (Len(Name$) > 0) And KeyHit(28)

19.10 Laufschrift

Genau wie Punkte und Linien können wir auch Schrift bewegen, um Laufschrift zu er-zeugen, einen gern genutzten Effekt. Vorab sei gesagt – richtig überzeugend kann dasnur aussehen mit Spezialfonts, die aus Grafikdateien gebildet werden. Die normalen,mit Windows mitgelieferten Fonts kranken schon daran, dass Blitz Basic sie ohne Kan-tenglättung darstellt. So bilden sich hässliche Treppeneffekte.

Lassen wir zunächst ein Wort waagerecht hin- und herlaufen. Dazu verändern wir nurdie waagerechte Position. In einer Variable (Richtung) merken wir uns, in welche Rich-tung der Text gerade läuft. Ist eine bestimmte linke oder rechte Grenze erreicht, dannändern wir die Richtung.

; LAUFSCHRIFT1.BBGraphics 640, 480SetBuffer BackBuffer()font = LoadFont("Times",30)SetFont fontRichtung = 0

Repeat If Richtung = 0 Then I = I + 1 If Richtung = 1 Then I = I - 1 If I = 200 Then Richtung = 1 If I = 100 Then Richtung = 0

Cls Text I,100, "Fang mich!" FlipUntil KeyHit(1)

Das war billig. Nur – wie stellen wir es an, dass der Text auf der einen Seite aus demBildschirm verschwindet und auf der anderen Seite wieder auftaucht? Dazu nutzen wirdie Tatsache, dass wir in Blitz Basic über den Bildschirm hinaus malen können. Wennwir die Anfangsposition auf der waagerechten Achse immer mehr verringern oder er-höhen, verschwindet der Text langsam aus dem Bild. Soll sich der Text unermüdlichwiederholen, muss er auf der anderen Seite auftauchen. Das läßt sich im einfachstenFall wie folgt umsetzen:

Page 232: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

232

Grafikseminare19j e t z t l e r n e i c h

; LAUFSCHRIFT2.BBGraphics 640, 480SetBuffer BackBuffer()font = LoadFont("Times",30)SetFont fontZeile$ = "Wenn die DARKness kommt und ein BLITZ vor Dir einschlägt und Dir der PURE Angstschweiß im Gesicht steht. Dann ist Basic rulez. ;)"Geschwindigkeit=5

Repeat Cls I = I - Geschwindigkeit Text I,100, Zeile$ If Abs(I) > StringWidth(Zeile$) Then I=640 FlipUntil KeyHit(1)

Wir fragen also, ob der gesamte Text bereits außerhalb des Bildschirms ist. Wenn ja,dann wissen wir, dass der Textdurchlauf wieder von vorn beginnt. Je mehr Pixel jeDurchlauf versetzt werden, desto schneller läuft die Schrift. Das speichern wir in derVariable Geschwindigkeit.

Wenn wir den Text nicht immer auf die gleiche Höhe setzen, sondern etwa im Takt ei-ner Sinus-Kurve verändern, tanzt er auf dem Bildschirm:

Text I,Sin(I) * 100 + 200, Zeile$

Freilich könnten wir auf die gleiche Weise stetig die Farbe wechseln.

Für eine lückenlose Wiederholung bieten sich mehrere Verfahren an. Zum Beispiel:Wir vervielfältigen die Zeichenkette so oft, daß sie den gesamten Bildschirm ausfüllt.Dabei berücksichtigen wir, daß wir mit dem Schreiben außerhalb des sichtbaren Be-reichs beginnen, und vergrößern die Zeichenkette auf doppelte Bildschirmlänge:

; LAUFSCHRIFT3.BBBildschirmBreit = 640BildschirmHoch = 480Graphics BildschirmBreit, BildschirmHochSetBuffer BackBuffer()font = LoadFont("Times",60)SetFont fontZeile$ = "Blitzschnell +++ "Geschwindigkeit = 5

While StringWidth(Lauftext$) < BildschirmBreit + Bildschirmbreit Lauftext$ = Lauftext$ + Zeile$Wend

Repeat Cls I = I - Geschwindigkeit Text I,100, Lauftext$ If Abs(I) > StringWidth(Zeile$) Then I=0 FlipUntil KeyHit(1)

Auf ähnliche Weise lassen wir den Text senkrecht laufen. Netter sieht es aus, wenn jedeZeile zentriert ist. Dazu ermitteln wir die jeweilige X-Koordinate durch folgende Formel:

(640 - StringWidth(Zeilen$(I))) / 2

Page 233: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

233

Schreibmaschineneffekt j e t z t l e r n e i c h

Wir ziehen die Breite der Zeile von der Breite des Bildschirms ab und teilen das Ergeb-nis durch 2.

; LAUFSCHRIFT4.BBGraphics 640, 480SetBuffer BackBuffer()font = LoadFont("Times",30)SetFont font

Dim Zeilen$(7)For I=1 To 7 Read Zeilen$(I)NextA = 480

Data "Listen!"Data "Do you want to know a secret?"Data "Move with me inside the strange world of a 12 Inch."Data "Where nothing is as it seems,"Data "where everything has it's place,"Data "And there's a place for everything."Data "And anything can happen...";Repeat Cls A = A – 1 If A = -400 Then A=480 For I=1 To 7 Text (640 - StringWidth(Zeilen$(I))) / 2, (I*50) + A, Zeilen$(I) Next FlipUntil KeyHit(1)

19.11 Schreibmaschineneffekt

Um das Auge besser auf den Text zu lenken, verwenden manche Entwickler einenSchreibmaschineneffekt: Statt Zeile für Zeile werden die Buchstaben einzeln gemalt,mit einer zeitlichen Verzögerung. Um das umzusetzen, müssen wir genauso vorgehen:Wir lesen die Zeichen einer Zeichenkette nacheinander aus und zeichnen sie. Das isteine leichte Aufgabe:

; SCHREIBMASCHINE1.BBSpruch$ = "Der satanarchäolügenialkohöllische Wunschpunsch"For I=1 To Len(Spruch$) Write Mid$(Spruch$, I, 1) Delay 200NextWaitKey

Etwas aufwendiger wird es, wenn wir mit mehreren Zeilen arbeiten und mit Doppel-pufferung. Denn dann sollten wir einerseits den gesamten bisherigen Text immer wie-der schreiben und dennoch den Effekt behalten. Das erreichen wir, indem wir beijedem Durchlauf immer ein Zeichen mehr schreiben als beim letzten Mal. Der Zeilen-umbruch wird erleichtert, wenn wir jede Zeile in einem Dim-Feld speichern. Dann er-rechnen wir die Pixelzeile aus der Spruchzeile.

Page 234: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

234

Grafikseminare19j e t z t l e r n e i c h

; SCHREIBMASCHINE2.BBGraphics 640,480SetBuffer BackBuffer()ClsColor 255,255,255Color 50,50,50font = LoadFont("Courier",20)SetFont font;Dim Spruch$(6)Spruch$(1) = "Ein Meister allen Jüngern riet"Spruch$(2) = "Nur das zu glauben, was man sieht."Spruch$(3) = "Und doch - der Einwand sei erlaubt,Spruch$(4) = "Daß mancher das sieht, was er glaubt."Spruch$(5) =""Spruch$(6) ="(Eugen Roth)"X = 100Y = 50;For J=1 To 6 For I=1 To Len(Spruch$(J)) Cls ; alle vorigen Zeilen For K = 1 To J-1 Text X, Y + K*50, Spruch$(K) Next ; aktuelle Zeile Text X, Y + J*50, Mid$(Spruch$(J),1,I) Flip Delay 70 NextNextWaitKey

Das Beispiel ist freilich recht einfach gehalten. Für eine häufigere Nutzung sollte eineuniverselle Funktion geschrieben werden. Ein Anschlagton erhöht den Effekt. Über-treiben sollten Sie es jedoch nicht: Manche Menschen lesen schneller, als Sie erwarten,und das Warten auf den nächsten Text ist nervig. Ein Vorschlag: Vervollständigen Siebei einem Tastendruck den Text komplett.

19.12 Zeilenumbruch erzwingen

Oftmals wird Text in Kästen mit festgelegter Größe angezeigt. Damit er hineinpasst,muss vor dem rechten Rand umgebrochen, also in die nächste Zeile gewechselt wer-den. Wir könnten dazu in den Text ein Trennzeichen einfügen oder den Text Zeile fürZeile fertig aus einem Feld lesen. Eleganter ist es jedoch, den Zeilenumbruch automa-tisch durchzuführen, indem wir immer nur so viel Text ausgeben, wie in eine Zeilepasst. Die Herausforderung ist dabei, dass natürlich nicht mitten im Wort ein Zeilen-umbruch erfolgen darf.

; UMBRUCH.BBText$ = "Dieser lange Text soll jeweils nach 20 Zeichen umgebrochen werden."Umbruch = 20

Repeat Ausgabe$ = Left$(Text$, Umbruch) For I=1 To Umbruch

Page 235: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

235

Beweglicher Hintergrund j e t z t l e r n e i c h

If Right$(Ausgabe$, 1) <> " " Then Ausgabe$ = Left$(Ausgabe$, Umbruch-I) Else Text$= Right(Text$, Len(Text$) - Umbruch -1 +i) I=Umbruch EndIf Next Print Ausgabe$Until Len(Text$) < Umbruch + 1Print Text$WaitKey

Die Ausschrift:

Dieser lange Textsoll jeweils nach20 Zeichenumgebrochen werden.

Das einfache Beispiel arbeitet mit der Anzahl der Zeichen, nicht mit der tatsächlichenBreite. Bei den meisten Schriftarten sind jedoch die einzelnen Buchstaben unterschied-lich groß (»proportional«). Und es scheitert an Wörtern, die länger als 20 Zeichen sind.Aber die wären ja ohnehin verboten. Für eine größere Anzahl an Texten ist es emp-fehlenswert, innerhalb längerer Wörter ein Zeichen für die Silbentrennung zu verein-baren, zum Beispiel eine Raute. So müsste ein Wort wie Ritterburg nicht komplettumgebrochen werden, sondern es könnte dank einer Speicherung als Ritter#burg imKasten als

... Ritter-burg ...

erscheinen.

19.13 Beweglicher Hintergrund

Bilder dienen nicht nur zur Darstellung von Spielfiguren. Auch der Hintergrund ist ausBildern zusammengesetzt. Häufig verwendet man zum Darstellen des Hintergrundsuniverselle Grafikblöcke, die man nebeneinander stellt. Dieses Verfahren eignet sichvor allem zum Darstellen von Mauern, Felsen oder Strand.

Ich habe Ihnen den Befehl TileBlock bereits kurz vorgestellt. Er zeichnet ein Bildso lange, bis der gesamte Bildschirm gefüllt ist:

; HINTERGRUND1.BBGraphics 640, 480Setbuffer BackBuffer()bild = LoadImage("stars.bmp")TileBlock bildFlipWaitKey

1TileBlock arbeitet nicht transparent. Das ist bei einem Hintergrund auch sinnvoll –man verwendet ja eine »unsichtbare« Farbe gerade deshalb, damit der Hintergrunddurchscheint. Sollten Sie dennoch mit einer transparenten Farbe arbeiten wollen, soverwenden Sie TileImage statt TileBlock. Wenn Sie mit TileBlock den Bildschirm fül-len, können Sie auf ein vorangestelltes Cls freilich verzichten.

Page 236: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

236

Grafikseminare19j e t z t l e r n e i c h

Lebensechter als eine starre Tapete ist ein Hintergrund, der sich bewegt. Das ist nichtschwer: Sie müssen Ihr Hintergrundmotiv jeweils um einige Punkte versetzen. Dazuverwenden Sie zwei zusätzliche Parameter: die waagerechte und die senkrechte Ver-schiebung in Punkten. Obwohl die Rakete immer wieder an die gleiche Stelle gezeich-net wird, hat man den Eindruck, sie würde durch das All fliegen:

; HINTERGRUND2.BBGraphics 640, 480SetBuffer BackBuffer()hinter = LoadImage("stars.bmp")rakete = LoadImage("spaceship2.bmp")Repeat I = I+1 If I=200 Then I=0 TileBlock hinter,0,I DrawImage rakete,310,400 FlipUntil KeyHit(1)

Natürlich geht das Ganze auch seitwärts:

TileBlock hinter,I,0

Abb. 19.9:Bildschirm-

füllender Hin-tergrund, dersich mit weni-gen Befehlenzum Scrollenbringen lässt.

0Auf der Buch-CD finden Sie eine Reihe von Texturen, die sich als Hintergrundbildeignen. Millionen weitere können Sie sich aus dem Internet laden. Auf unzähligenSeiten warten sie darauf, herunter geladen zu werden. Füttern Sie Google einfach mitBegriffen wie download textures games free. Eine schöne Anlaufstelle ist www.gr-sites.com mit mehr als 4000 Hintergrundtexturen. Die Site www.texturengalerie.dehat sogar ihren Bestand für die Buch-CD spendiert. Mit etwas Geduld finden Sie auchkleinere, aber lohnenswerte Archive. So bietet www.indiaeye.com eine Reihe vonTexturen mit fernöstlichen Motiven. Achten Sie darauf, dass die Bilder kachelbarsind. Wenn Sie sie wie Fließen nebeneinander setzen, müssen die Muster nahtlos in-einander übergehen.

Page 237: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

237

Übergänge gestalten j e t z t l e r n e i c h

19.14 Übergänge gestalten

Üblicherweise erreichen Sie einen Seitenwechsel, indem Sie den Bildschirm löschenund neu zeichnen. So gelangt der Spieler vom Titelbild zum Hauptmenü, vom Menüzum Spiel, vom Spiel zum Ende-Bildschirm ... Es bietet sich an, den Übergang nichtabrupt zu gestalten, sondern mit grafischen Effekten zu versehen. Das geht ganz leicht.

Wir können das »alte« Bild hinausschieben und das neue Motiv hereinfahren lassen,indem wir in einer Schleife die Startpunkte versetzen und somit einen Teil des Bildsaußerhalb des sichtbaren Bereichs zeichnen.

; UEBERGANG1.BBGraphics 640,480SetBuffer BackBuffer()bild = LoadImage("racetrack.bmp")ResizeImage bild, 640,480

Repeat For I=0 To 640 Step 10 Cls DrawImage bild, I,0 Flip Next

For I=480 To 0 Step -5 Cls DrawImage bild, 0,I Flip NextUntil KeyHit (1)

Auch mit ViewPort lässt sich der sichtbare Bereich in einer Schleife treffend verändern,um das Überblenden zu bewirken. Das Bild wird immer kleiner, bis nichts mehr zu se-hen ist. Im zweiten Schritt lassen wir vom Mittelpunkt aus die Ansicht des neuen Bildsimmer größer werden.

; UEBERGANG2.BBGraphics 640,480SetBuffer BackBuffer()bild = LoadImage("racetrack.bmp")ResizeImage bild, 640,480

Repeat For I=0 To 240 Step 2 Viewport 0,0, 640,480 Cls Viewport I,I, 640-I*2, 480-I*2 DrawImage bild, 0,0 Flip Next

For I=240 To 0 Step -10 Viewport 0,0, 640,480 Cls Viewport I,I, 640-I*2, 480-I*2 DrawImage bild, 0,0 Flip NextUntil KeyHit(1)

Page 238: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

238

Grafikseminare19j e t z t l e r n e i c h

Dabei muss sich die Verkleinerung nicht auf das Zentrum konzentrieren; das Bild kannsich auch in eine der vier Ecken zusammenziehen:

; UEBERGANG3.BBGraphics 640,480SetBuffer BackBuffer()bild = LoadImage("racetrack.bmp")ResizeImage bild, 640,480

Repeat For I=0 To 480 Step 5 Viewport 0,0, 640,480 Cls Viewport I*1.3,I, 640-I*1.3, 480-I DrawImage bild, 0,0 Flip Next

For I=0 To 480 Step 5 Viewport 0,0, 640,480 Cls Viewport 0,0, I*1.3,I DrawImage bild, 0,0 Flip NextUntil KeyHit(1)

Eine weitere Möglichkeit, das Bild effektvoll zu verbergen, ist das Überzeichnen mitFlächen, etwa Quadraten:

; UEBERGANG4.BBGraphics 640,480SetBuffer BackBuffer()bild = LoadImage("racetrack.bmp")ResizeImage bild, 640,480Color 0,0,0

Repeat For J=0 To 640 Step 32 DrawImage bild, 0,0 For I=0 To 480 Step 40 Rect 0,I,J,20 Rect 640-J, 480-I+20, 640, 20 Next Delay 50 Flip NextUntil KeyHit (1)

Leicht lässt sich das Prinzip ausbauen, etwa mit dem zufallsartigen Füllen des Bild-schirms mit Quadraten, bis alle Flächen bedeckt sind.

Page 239: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

239

Bildschirm »wackeln« lassen j e t z t l e r n e i c h

Abb. 19.10:Für das Über-blenden zwi-schen zwei Bild-schirmen lassen sich mit einfa-chen Mitteln interessante Effekte er-zeugen.

19.15 Bildschirm »wackeln« lassen

Ein ähnlicher Effekt ist das schnelle »Wackeln« des gesamten Bildschirms. Das istweniger als Übergang geeignet, es sei denn, man macht sich die Mühe, die einzelnenPixel so zusammenzuschütten, dass das Bild dauerhaft zerstört wird und im zweitenSchritt ein neues Bild entsteht. Sie können den Effekt verwenden, um große Explo-sionen zu untermalen.

; WACKELN.BBGraphics 640,480SetBuffer BackBuffer()bild = LoadImage("racetrack.bmp")ResizeImage bild, 640,480

Repeat DrawImage bild, Rand(-20,20), Rand(-20,20) FlipUntil KeyHit(1)

A19.16 Gamma-Wert ändern

Die Farbe jedes Bildpunkts ergibt sich durch eine Mischung von Rot, Grün und Blau.Jede dieser Farben hat eine Intensität von 0 bis 255. Je niedriger der Wert ist, destodunkler ist der jeweilige Farbanteil. So bildet sich Schwarz aus 0 Anteilen Rot, 0 An-teilen Grün und 0 Anteilen Blau. Weiß hingegen hat die Werte 255, 255, 255. Durch

Page 240: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

240

Grafikseminare19j e t z t l e r n e i c h

die Intensitätsstufen erzielen wir ein mehr oder weniger kräftiges Rot. Nennen wir sieeinfach Rot-30, Rot-100 oder Rot-255:

; GAMMA1.BBGraphics 640,480SetBuffer BackBuffer()Cls;Color 30,0,0Rect 50,100,100,100,1;Color 100,0,0Rect 250,100,100,100,1;Color 255,0,0Rect 450,100,100,100,1;FlipWaitKey

Mit SetGamma verändern Sie die Intensität eines Anteils, den so genannten Gamma-Wert. Sie stellen damit ein, dass etwa Rot-30 nicht so intensiv ist wie Rot-100, son-dern zum Beispiel wie Rot-255. Der Sinn des Ganzen: Sie können eine Grafik aufhel-len oder verdunkeln, sie invertieren oder einzelne Anteile komplett herauslöschen.

Der Befehl erwartet für eine »fertige« RGB-Farbe die neue Gamma-Intensität. Die Zeile

SetGamma 0,0,255, 255,0,0

zeigt das satte Blau so an, als ob es Rot wäre. Um in einem Bild nur die Rottöne zu be-halten, löschen Sie mit einer For-Schleife alle Anteile Grün und Blau, für jede Intensitätvon 0 bis 255. Nur die von Rot bleibt erhalten:

For I=0 To 255 SetGamma I,I,I, I,0,0Next

Der Gamma-Befehl lässt sich jederzeit einsetzen. Er funktioniert auch mit Grafiken, diebereits auf dem Bildschirm zu sehen sind. Um die Änderungen wirksam werden zu las-sen, benötigen Sie allerdings einen zweiten Befehl: UpdateGamma. Damit stellen Sie si-cher, dass alle Gamma-Korrekturen auf einen Schlag aktualisiert werden.

1

Lassen wir eine Grafik anzeigen – zunächst normal, dann nur ihre Rot-Anteile, ihreGrün-Anteile und zum Schluss nur Blau:

; GAMMA2.BBGraphics 640,480SetBuffer BackBuffer()bild = LoadImage("racetrack.bmp")

Die Gamma-Befehle sind erst seit Version 1.80 verfügbar und funktionieren nur imVollbildmodus, nicht jedoch im Windows-Fenster. Verwechseln Sie die Gamma-Inten-sität nicht mit dem Alpha-Wert, der angibt, wie durchsichtig eine Farbe ist. Damit las-sen sich zum Beispiel Wassereffekte erzeugen. Der Alpha-Wert lässt sich nur mit BlitzBasic 3D verändern.

Page 241: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

241

Gamma-Wert ändern j e t z t l e r n e i c h

; NormalClsDrawImage bild, 30,50 FlipWaitKey

; Nur RotClsDrawImage bild, 30,50 For I=0 To 255 SetGamma I,I,I, I,0,0Next UpdateGamma FlipWaitKey

; Nur GrünClsDrawImage bild, 30,50 For I=0 To 255 SetGamma I,I,I, 0,I,0Next UpdateGamma FlipWaitKey

; Nur BlauClsDrawImage bild, 30,50 For I=0 To 255 SetGamma I,I,I, 0,0,INext UpdateGamma FlipWaitKey

Wir können auch das Bild langsam löschen, indem wir jeden Farbanteil entfernen, bisnichts mehr übrig ist:

; GAMMA3.BBGraphics 640,480SetBuffer BackBuffer()Clsbild = LoadImage("racetrack.bmp")DrawImage bild, 30,50Flip

For I=0 To 255 SetGamma I,I,I, I,I,0 UpdateGamma Delay 10Next

For I=0 To 255 SetGamma I,I,I, I,0,0 UpdateGamma Delay 10Next

Page 242: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

242

Grafikseminare19j e t z t l e r n e i c h

For I=0 To 255 SetGamma I,I,I, 0,0,0 UpdateGamma Delay 10Next

Um ein Bild aufzuhellen, erhöhen wir die Intensität jedes Anteils, um es zu verdunkeln,verringern wir ihn. Auf diese Weise löschen wir ein Bild elegant aus. Oder wir ändernjede Intensität zufällig und schaffen ein wirres Kunterbunt:

; GAMMA4.BBGraphics 640,480bild = LoadImage("racetrack.bmp")DrawImage bild, 30,50

For I=1 To 1000 SetGamma Rand(1,255),Rand(1,255),Rand(1,255), Rand(1,255),Rand(1,255),Rand(1,255) UpdateGamma Delay 10Next

Mit dem Befehlstrio GammaRed(), GammaGreen() und GammaBlue() ermitteln Sie den der-zeitigen Gamma-Wert jedes RGB-Anteils. GammaRed(50) sagt Ihnen etwa, wie intensivRot-50 tatsächlich angezeigt wird.

Sie sehen: Es ist wirklich einfach, mit den Gamma-Befehlen zu arbeiten, und es führtrasch zu unterhaltsamen Effekten.

19.17 Energiebalken

Bei Ego-Shootern zeigt man die Lebensenergie in Prozent an: 100% sind der Ideal-wert, 0% bedeuten den Tod. Arcade-Spiele bereiten den Wert optisch auf: Oftmalswird das aktuelle Leben in Form einer grafischen Leiste angezeigt. Je mehr Energieverloren geht, desto kleiner wird der Balken.

Wir wollen überlegen, wie sich ein solcher Balken umsetzen lässt. Bleiben wir bei100% als Idealwert. Das Reduzieren könnte stufenlos oder in Schritten erfolgen. Letz-teres Verfahren ist häufiger: Meistens genügen drei bis zehn Treffer und die Spielfigurist hinüber. Oft weist nicht nur die Länge des Balkens auf das verbliebene Leben hin,sondern auch ihre Farbe: Grün steht für gesund, Gelb für angegriffen und Rot für kri-tisch. Dabei ändert zum Teil der gesamte Balken seine Farbe; mitunter ist der Balkenin verschiedenfarbige Segmente unterteilt.

19.17.1 Balken aus zehn TeilenLosgelöst von einem Spiel wollen wir einen Energiebalken programmieren, dessenGröße sich per Tastendruck steuern lässt. Wir setzen einen Balken ein, der aus zehnTeilen besteht. Je nachdem, ob 10%, 50% oder 100% Leben übrig sind, zeichnen wirein Segment, die Hälfte oder den ganzen Balken.

Page 243: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

243

Energiebalken j e t z t l e r n e i c h

Zunächst legen wir die Farben für jedes Segment fest:

Dazu erzeugen wir ein Dim-Feld, in das wir für jeden Prozentwert die passende Farbeeinlesen:

Data 51,255,0 ; 100%Data 51,255,0 ; 90%Data 51,255,0 ; 80%Data 51,255,0 ; 70%Data 51,255,0 ; 60%Data 255,255,0 ; 50%Data 255,255,0 ; 40%Data 255,190,0 ; 30%Data 255,130,0 ; 20%Data 255,51,0 ; 10%

Dim Balken(100,3)For I=100 To 10 Step -10 Read Balken(I,1), Balken(I,2), Balken(I,3)Next

Unser Verfahren erlaubt es, den Balken später leicht zu erweitern: Wir könnten nichtnur für jeden Zehnerschritt eine eigene Farbe festlegen, sondern für jeden Wert von 1bis 100.

Nun zeichnen wir den Balken. Je nach Wunsch erhält jedes Segment seine eigeneFarbe ...

For I = 10 To Leben Step 10 Color Balken(I,1), Balken(I,2), Balken(I,3) Rect 20 + (I*5), 200, 50, 40, 1Next

... oder wir zeichnen den gesamten Balken in der Farbe des aktuellen Segments, alsoetwa Gelb bei 40%:

For I = 10 To Leben Step 10 Color Balken(Leben,1), Balken(Leben,2), Balken(Leben,3) Rect 20 + (I*5), 200, 50, 40, 1Next

60% bis 100% Grün

40% bis 50% Gelb

30% Ocker

20% Orange

10% Rot

Page 244: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

244

Grafikseminare19j e t z t l e r n e i c h

Abb. 19.11:Energiebalken

mit Farb-abstufungen.

Nun benötigen wir noch eine kleine Tastatursteuerung, mit deren Hilfe wir die Anzahlder Lebenspunkte und damit die Größe des Balkens verändern. Im fertigen Programmsind beide Balkenarten möglich. Mit den Tasten 1 und 2 wechseln wir zwischen»buntem« und einfarbigem Balken.

; ENERGIEBALKEN1.BBGraphics 640,480SetBuffer BackBuffer()

Data 51,255,0 ; 100%Data 51,255,0 ; 90%Data 51,255,0 ; 80%Data 51,255,0 ; 70%Data 51,255,0 ; 60%Data 255,255,0 ; 50%Data 255,255,0 ; 40%Data 255,190,0 ; 30%Data 255,130,0 ; 20%Data 255,51,0 ; 10%

Dim Balken(100,3)For I=100 To 10 Step -10 Read Balken(I,1), Balken(I,2), Balken(I,3)Next

Leben = 100Modus = 1

Repeat Cls

Page 245: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

245

Energiebalken j e t z t l e r n e i c h

If KeyDown(203) And ( Leben <> 10 ) Then Leben = Leben - 10 ; Links If KeyDown(205) And ( Leben <> 100 ) Then Leben = Leben + 10 ; Rechts

If KeyDown(2) Then Modus = 1 ; [1] If KeyDown(3) Then Modus = 2 ; [2]

For I = 10 To Leben Step 10 If Modus = 1 Then Color Balken(I,1), Balken(I,2), Balken(I,3) If Modus = 2 Then Color Balken(Leben,1), Balken(Leben,2), Balken(Leben,3) Rect 20 + (I*5), 200, 50, 40, 1 Next

Delay 50 FlipUntil KeyHit(1)

Der zweite Modus mit einfarbigem Balken wirkt harmonischer; die abgehackten Farb-abstufungen entfallen.

19.17.2 Balken mit stufenloser FarbänderungFreilich lässt sich das Zeichnen des Balkens verfeinern, indem wir innerhalb eines Seg-ments Farbabstufungen vornehmen:

; ENERGIEBALKEN2.BBGraphics 640,480SetBuffer BackBuffer()Stand = 0

Repeat Cls If KeyDown(203) And ( Stand <> 0 ) Then Stand = Stand - 1 ; Links If KeyDown(205) And ( Stand <> 255 ) Then Stand = Stand + 1 ; Rechts

Color Stand,127,127

For I=1 To 10 Line 100, 100 + I, 100 + Stand, 100 + I Next

Flip Delay 10Until KeyHit(1)

Die Farben passen nicht zu einem Energiebalken. Wir müssten für jede Position denpassenden Farbcode festlegen.

19.17.3 Balken aus einer GrafikNoch einfacher gelangen wir zu unserem flexiblen Balken, wenn wir eine fertige Grafikverwenden und von ihr einen prozentualen Ausschnitt zeigen. Bestens eignet sich dazuder Befehl DrawBlockRect (bzw. DrawImageRect für transparente Bilder). Er zeichnet einBild in beliebigen Ausmaßen, egal wie groß es tatsächlich ist. Damit schneiden wirleicht Teile ab. Wir müssen nur die Prozentzahl mit der Breite des Bilds ins Verhältnissetzen. Ist das Bild 575 Pixel breit, wie in unserem Beispiel, so entspricht das 100%.

Page 246: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

246

Grafikseminare19j e t z t l e r n e i c h

Abb. 19.12:Energiebalkenals Grafik mitveränderlicher

Größe.

; ENERGIEBALKEN3.BBGraphics 640,480bild = LoadImage("racetrack.bmp")SetBuffer BackBuffer()Breite = 575

Repeat Cls DrawBlockRect bild, 30,100, 0,0, Breite, 287 Text 500,0, Int(Breite / 5.75) + " Prozent"

If KeyDown(203) And ( Breite > 9) Then Breite = Breite - 10 ; Links If KeyDown(205) And ( Breite < 574) Then Breite = Breite + 10 ; Rechts

Delay 20 FlipUntil KeyHit(1)

Das Programm wird ebenfalls mit den waagerechten Pfeiltasten bedient. Damit frisst esTeile des Bilds auf, vom rechten Rand beginnend. Freilich ließe sich das Programmleicht anpassen, so dass es senkrecht arbeitet, also von oben nach unten mit dem Ver-schlingen beginnt.

Page 247: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

247

Ablaufsteuerung j e t z t l e r n e i c h

A19.18 Ablaufsteuerung

Ein Spiel läuft automatisch ab. Auch wenn der Spieler nicht in das Geschehen ein-greift, ertönt Musik, laufen Gegner hin und her, schwebt ein Fahrstuhl. Die Steuerungdieser Bewegungen erfolgt

� zufällig,

� durch ein Regelwerk oder

� durch eine automatische Steuerung, ein »Programm im Programm«.

Zufällig bedeutet: Bei jedem Schritt oder bei jeder Kreuzung wird zufällig eine neueRichtung ausgewählt. Ein Regelwerk legt genauer fest, wie sich ein Objekt bewegensoll, wie es auf die Umgebung reagiert. So kann sich ein Gegner etwa bevorzugt derSpielfigur nähern. Sollen Bewegungen gesteuert, aber dennoch unabhängig vom Restdes Spielgeschehens ablaufen, bietet sich ein Programm an, eine Liste mit Anweisun-gen. Diese Liste legt fest, welche Schritte nacheinander ausgeführt werden und gege-benenfalls, wie lange ein Schritt dauern soll. Dadurch lassen sich Bewegungsschrittevon Objekten programmieren, etwa der Weg einer computergesteuerten Spielfigurvon A nach B festlegen.

Es gibt zahlreiche Einsatzzwecke für derartige Anweisungslisten, etwa nach welchemSchema Power-ups und Extra-Waffen erscheinen oder wie sich das Wetter ändert. Einbesonders plastisches Beispiel sind die Farbphasen einer Ampel: Nach einem bestimm-ten Schema und in festgelegten Zeiträumen ändert sich die Farbe. Lassen Sie uns ein-mal eine Ampelsteuerung praktisch umsetzen.

Eine Ampel hat drei Leuchten: Rot, Gelb und Grün. Sie kann vier Zustände einneh-men: Rot, Rot/Gelb, Gelb und Grün. Schreiben wir ein Programm, das eine Ampelzeichnet. Sie soll zunächst per Hand, auf Tastendruck, eine bestimmte Farbe anneh-men:

Etwa so:

; AMPEL1.BBGraphics 640,480SetBuffer BackBuffer()

Repeat Cls ; Tasten abfragen Select GetKey() Case 49 Farbe = 1 ; "1" = Rot Case 50 Farbe = 2 ; "2" = Rot / Gelb Case 51 Farbe = 3 ; "3" = Grün Case 52 Farbe = 4 ; "4" = Grün End Select

Rot 1

Rot/Gelb 2

Gelb 3

Grün 4

Page 248: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

248

Grafikseminare19j e t z t l e r n e i c h

; Leerampel zeichnen Color 255, 255, 255 Oval 100, 100, 100, 100, 0 Oval 250, 100, 100, 100, 0 Oval 400, 100, 100, 100, 0

; aktuelle Ampelfarbe zeichnen Select Farbe Case 1 ; Rot Color 255, 0, 0 Oval 100, 100, 100, 100, 1 Case 2 ; Rot/Gelb Color 255, 0, 0 Oval 100, 100, 100, 100, 1 Color 255, 255, 0 Oval 250, 100, 100, 100, 1 Case 3 ; Gelb Color 255, 255, 0 Oval 250, 100, 100, 100, 1 Case 4 ; Grün Color 0, 255, 0 Oval 400, 100, 100, 100, 1 End Select FlipUntil KeyHit(1)

19.18.1 Ampel steuernÜberlegen wir uns nun eine Steuerung für die Ampel, eine Festlegung der Ampelpha-sen, also in welcher Reihenfolge und wie lange jedes Licht leuchten soll. Vielleicht so:

Diese vier Schritte sollen fortlaufend ausgeführt werden; nach Gelb kommt also wiederSchritt 1, Rot.

Für die Umsetzung in einem Programm verwenden wir am besten ein Feld, das sich fürjeden Schritt die Dauer in Sekunden merkt:

Dim Ampel(4)Ampel(1) = 3 ; RotAmpel(2) = 1 ; Rot / GelbAmpel(3) = 3 ; GrünAmpel(4) = 2 ; Gelb

Statt der Tastenabfrage im vorherigen Beispiel lassen wir jetzt den Computer die Lich-terfolge automatisch steuern. Damit jede Farbe die vorgegebene Anzahl Sekunden zusehen ist, benötigen wir zwei Variablen zur Zeitmessung. Immer wenn eine Farbe ge-wechselt wird, erhält die Variable Beginn die aktuelle Zeit:

Beginn = MilliSecs()

Rot 3 Sekunden Phase 1

Rot/Gelb 1 Sekunde Phase 2

Grün 3 Sekunden Phase 3

Gelb 2 Sekunden Phase 4

Page 249: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

249

Ablaufsteuerung j e t z t l e r n e i c h

Bei jedem Durchlauf wird der Variable Dauer die Differenz aus der aktuellen Zeit unddem Beginn zugewiesen.

Dauer = MilliSecs() - Beginn

Sie weiß damit, wie viele Millisekunden die aktuelle Farbe zu sehen ist. Als Drittes be-nötigen wir einen Test, ob die Zeit für die aktuelle Farbe abgelaufen ist:

If Dauer > Ampel(Farbe) * 1000 Then

In diesem Fall wird die Farbe gewechselt. Das ganze Programm wechselt nun selbstän-dig im vorgegebenen Rhythmus die Ampelfarben.

; AMPEL2.BBGraphics 640,480SetBuffer BackBuffer()

; Steuerung festlegenDim Ampel(4)Ampel(1) = 3 ; RotAmpel(2) = 1 ; Rot / GelbAmpel(3) = 3 ; GrünAmpel(4) = 2 ; GelbFarbe = 2Beginn = MilliSecs()

Repeat ; Test, ob Farbe gewechselt wird Dauer = MilliSecs() - Beginn If Dauer > Ampel(Farbe) * 1000 Then Farbe = Farbe + 1 If Farbe = 5 Then Farbe = 1 Beginn = MilliSecs() EndIf

; Leerampel zeichnen Cls Color 255, 255, 255 Oval 100, 100, 100, 100, 0 Oval 250, 100, 100, 100, 0 Oval 400, 100, 100, 100, 0

; aktuelle Ampelfarbe zeichnen Select Farbe Case 1 ; Rot Color 255, 0, 0 Oval 100, 100, 100, 100, 1 Case 2 ; Rot / Gelb Color 255, 0, 0 Oval 100, 100, 100, 100, 1 Color 255, 255, 0 Oval 250, 100, 100, 100, 1 Case 3 ; Grün Color 0, 255, 0 Oval 400, 100, 100, 100, 1 Case 4 ; Gelb Color 255, 255, 0 Oval 250, 100, 100, 100, 1 End Select FlipUntil KeyHit(1)

Page 250: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

250

Grafikseminare19j e t z t l e r n e i c h

19.18.2 Ampel programmierenDie Ampel macht, was wir wollen. Doch besonders flexibel ist unsere Lösung nicht.Was ist, wenn wir die Leuchtreihenfolge ändern wollen? Dann müssten wir die Zahlendirekt im Dim-Feld ändern. Für mehrere Leuchtprogramme eignet sich unser Beispielnicht.

Um in die Ampelsteuerung verschiedene Programme einzuspeisen, müssten wir unseine Kodierung überlegen und die Möglichkeit schaffen, dass die Ampel die Kodierungliest und interpretiert.

Für eine Ampel eignet sich eine fortlaufende Beschreibung von zwei Werten als Pro-grammierung:

� welche Lampe aktiv ist

� und wie lange sie leuchten soll

So könnte 143243 bedeuten: Phase 1 (= Rot) vier Sekunden, Phase 3 zwei Sekunden,Phase 4 drei Sekunden.

Damit lassen sich aber keine halben Sekunden festlegen. Besser wäre statt der Sekun-denangabe ein Wert in Millisekunden. Damit würde die Angabe 3000 drei Sekundenentsprechen. Ein ganzes Programm sähe damit ungefähr wie folgt aus:

140003200043000

Der Nachteil: Bei einer längeren Folge von Ampelphasen ist das Programm für unsMenschen sehr schlecht lesbar. Da wir die Programme selbst schreiben, sollten wir unseine Erleichterung schaffen, indem wir die Werte durch zusätzliche Zeichen voneinan-der trennen:

1=4000,3=2000,4=3000

Damit sieht auch das menschliche Auge sofort, dass Phase 1 vier Sekunden lang dauertusw.

Damit wir unserer Ampel verschiedene Programme übermitteln können, gliedern wirsie in eine Funktion aus. Um in die Ampel ein neues Ablaufschema einzuspeisen, rufenwir einfach die Funktion auf und übergeben ihr das gewünschte Programm als Para-meter:

Ampel("1=4000,3=2000,4=3000")

Einen guten Teil des vorherigen Beispiels übernehmen wir 1:1 für unsere Funktion.Das Malen der Leerampeln sowie der aktuellen Farbe bleibt erhalten. Wir müssen nursicherstellen, dass die Variable Farbe den richtigen Wert enthält.

Die Funktion bekommt das Ampelprogramm als Zeichenkette Code$. Wir legen zweiweitere Variablen fest: Stelle merkt sich die aktuelle Position, die gerade im ProgrammCode$ abgearbeitet wird, also das erste Zeichen der Ampelphase. Für das Messen derLeuchtdauer füttern wir Beginn mit MilliSecs().

Nun beginnen wir die Abarbeitungsschleife. Für jede Phase lesen wir sieben Zeichenaus:

� Das erste Zeichen enthält die gewünschte Farbe, die wir in der Variablen Farbespeichern.

� Das zweite Zeichen (»=«) überspringen wir.

Page 251: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

251

Ablaufsteuerung j e t z t l e r n e i c h

� Die Zeichen 3 bis 6 enthalten die Dauer, die wir in der Variablen Dauer speichern.

� Zeichen 7 (»,«) überspringen wir.

Die gewünschte Farbe und ihre Dauer erhalten wir wie folgt:

Farbe = Mid$(Code$, Stelle, 1)Farbdauer = Mid$(Code$, Stelle+2, 4)

Beim Programmieren der Ampel müssen wir darauf achten, dass die Farbdauer immervier Zeichen lang ist. Bei Werten unter einer Sekunde muss dem Wert eine Null voran-gestellt werden (0500). Zeitabschnitte von zehn Sekunden und mehr sind nicht möglich.Freilich lässt sich das leicht realisieren; wir verwenden für die Dauer eben fünf statt vierZeichen. Doch in diesem Beispiel bleiben wir bei vier und damit maximal 9999 Milli-sekunden.

Ähnlich wie im vorherigen Beispiel prüfen wir, ob die derzeitige Ampelfarbe ihre fest-gelegte Dauer überschritten hat. In diesem Fall versetzen wir Stelle auf die nächsteFarbe und aktualisieren den Inhalt von Beginn, um die Dauer für die nächste Farbe zumessen.

Dauer = MilliSecs() - BeginnIf Dauer > Farbdauer Then Stelle = Stelle + 7 Beginn = MilliSecs()EndIf

Nun zeichnen wir die Ampeln sowie die aktuelle Ampelfarbe.

Wenn das Programm abgelaufen ist, endet die Funktion. Um es zu wiederholen, rufenwir die Funktion unablässig auf:

Repeat Ampel("1=4000,3=2000,4=3000")Forever

Eine Alternative dazu besteht darin, die Wiederholung in die Funktion einzubauen. Ambesten wäre es, man könnte sich heraussuchen, ob das Programm nur einmal oder un-endlich ablaufen soll. Wir könnten der Funktion einen zweiten Parameter übergeben,der klärt, ob das Programm wiederholt wird. Dafür bietet sich eine 1 an:

Ampel("1=4000,3=2000,4=3000", 1)

Die Funktion erhält vom Hauptprogramm nicht nur die Ampelsteuerung, sondernauch den Wiederholenstatus:

Function Ampel(Code$, Wiederholen)

Besonders komfortabel wäre der Aufruf, wenn wir den zweiten Parameter nur schrei-ben müssten, wenn wir die Wiederholung wirklich wollen. Dazu geben wir der VariableWiederholen den voreingestellten Wert 0. Den bekommt sie dann, wenn die Funktionmit nur einem Parameter aufgerufen wird:

Function Ampel(Code$, Wiederholen=0)

Die ganze Funktion auf einen Blick:

; AMPEL3.BBFunction Ampel(Code$, Wiederholen=0) Stelle = 1 Farbe = 0 Farbdauer = 0 Beginn = MilliSecs()

Page 252: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

252

Grafikseminare19j e t z t l e r n e i c h

Repeat ; Farbe + Dauer auslesen Farbe = Mid$(Code$, Stelle, 1) Farbdauer = Mid$(Code$, Stelle+2, 4)

; Test, ob Farbe gewechselt wird Dauer = MilliSecs() - Beginn If Dauer > Farbdauer Then Stelle = Stelle + 7 If ( Stelle > Len(Code$) ) And (Wiederholen = 1) Then Stelle = 1 Beginn = MilliSecs() EndIf

; Leerampel zeichnen Cls Color 255, 255, 255 Oval 100, 100, 100, 100, 0 Oval 250, 100, 100, 100, 0 Oval 400, 100, 100, 100, 0

; Zustandsbeschreibung; kann entfallen Text 50,50, Code$ Text 50,70, "Stelle: " + Stelle + " Farbe: " + Farbe + " Farbdauer: " + Farbdauer + " Dauer: " + Dauer

; aktuelle Ampelfarbe zeichnen Select Farbe Case 1 ; Rot Color 255, 0, 0 Oval 100, 100, 100, 100, 1 Case 2 ; Rot / Gelb Color 255, 0, 0 Oval 100, 100, 100, 100, 1 Color 255, 255, 0 Oval 250, 100, 100, 100, 1 Case 3 ; Grün Color 0, 255, 0 Oval 400, 100, 100, 100, 1 Case 4 ; Gelb Color 255, 255, 0 Oval 250, 100, 100, 100, 1 End Select Flip Until Stelle > Len(Code$) Or KeyHit(1)End Function

Das dazugehörige Hauptprogramm initialisiert den Grafikmodus, schaltet auf denBackbuffer um (was auch innerhalb der Funktion möglich wäre) und kann danach dieAmpelfunktion mit beliebigen Steuerungsfolgen aufrufen:

; AMPEL3.BBGraphics 640,480SetBuffer BackBuffer()

Ampel("1=3000,3=3000,4=3000")Ampel("1=1500,2=0500,3=2000,4=0500",1)

Page 253: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

253

Ballphysik j e t z t l e r n e i c h

Falls die Ampel nicht wie vorgesehen läuft, wurde sie falsch programmiert. In der Vor-bereitungsphase bietet es sich an, den Status der Schlüsselvariablen mit Text auf demBildschirm auszugeben (so wie es im Listing bereits geschehen ist).

Diese Art der vorbestimmten Steuerung lässt sich leicht auf Teilbereiche eines Spielsübertragen.

Abb. 19.13:Eine Ampel-steuerung als Beispiel für programmierte Abläufe.

A19.19 Ballphysik

Nicht immer sollen sich Objekte mit gleichmäßiger Geschwindigkeit bewegen. DenkenSie etwa an einen Ball, der auf- und abprallt: Nach und nach verliert er an Geschwin-digkeit und Höhe. Im Netz habe ich ein schönes Beispiel für Ballphysik gefunden, des-sen Aufbau ich überarbeitet habe. Es zeigt, was mit einem Ball passiert, der an eine zu-fällige Stelle in den Raum geworfen wird: das Wirken der Schwerkraft. Das Listing istkurz und gut dokumentiert, so dass es sich rasch erfassen lässt.

; PHYSIK.BB; nach einer Vorlage von Mario Sasse, www.cyber-nbg.de

Graphics 640,480SetBuffer BackBuffer()ClsColor 255,255,0Color 0,0,200

Y = 500 ; um Balleinwurf zu erzwingen

Page 254: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

254

Grafikseminare19j e t z t l e r n e i c h

Repeat

If ((Abs(W) < .2) And (Y >= 450)) Then ; ist der Ball langsam und unten = neuen Ball einwerfen ; Startkoordinaten des Balls SeedRnd MilliSecs() X = Rand(600) Y = Rand(100) V = Rnd(1) * 30 - 15 ; waagerechte Geschwindigkeit W = Rnd(1) * (-20) ; senkrechte Geschwindigkeit EndIf

Cls

If X < 8 Then V = Abs(V) * (1) ; Abprall links - langsamer If X > 590 Then V = Abs(V) * (-1) ; Abprall recht - langsamer If Y < 10 Then W = Abs(W) * (0.1) ; Abprall oben - langsamer If Y > 420 Then W = Abs(W) * (-1) ; Abprall unten - langsamer

W = W + 0.51 ; schwere Beschleunigung nach unten X = X + V ; waagerechte Geschwindigkeit zu X Y = Y + W ; senkrechte Geschwindigkeit zu Y

Oval X,Y,30,30,1

FlipUntil KeyHit(1)

Page 255: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

255

jetz

t le

rne

ich

KAPITEL 20

Programmieren wir ein Spiel!

Wann geht es denn endlich los, mögen Sie sich bereits ungeduldig gefragt haben.Wann endlich erklärt er, wie man ein Spiel schreibt? Nun: Es wurde von der ersten Sei-te an erklärt. Es steckt nichts Neues, Geheimnisvolles dahinter. Ein Spiel besteht aus allden Bausteinen, die ich Ihnen beschrieben und erklärt habe. Wie das Spiel im Detailaufgebaut ist, unterscheidet sich freilich von Genre zu Genre. Dennoch gibt es Sche-mata, die vielfach gleich bleiben.

Auf den folgenden Seiten erkläre ich Ihnen einige Gerüste für funktionsfähige Spiele.Sie lassen sich einerseits ausbauen und geben Ihnen andererseits Anregungen für ei-gene Versuche. Ich habe die Programme bewusst kurz und übersichtlich gehalten. Sosind sie leicht nachzuvollziehen. Wie in allen Beispielen zuvor verwende ich nur Grafi-ken und Klänge, die mit Blitz Basic mitgeliefert wurden. Das bedeutet Einschränkun-gen in der Vielfalt und in der Wirkung auf den Betrachter. Mit hochwertigen eigenenGrafiken (z.B. erstellt mit dem Tile Studio, http://tilestudio.sourceforge.net, auf derBuch-CD) erzielen Sie rasch schöne Ergebnisse.

2Sie sollten mit diesem Kapitel nicht zu früh beginnen. Sammeln Sie erst Erfahrungenmit kleinen Programmen und Beispielen, ehe Sie sich an ein richtiges Projekt wagen.Die auf den folgenden Seiten vorgestellten Spielegerüste sollen Ihnen helfen, ein Ver-ständnis zu erlangen, wie Spiele funktionieren. Sie sollten nicht als Grundlage fürIhre Spiele dienen. Einen vorhandenen Quelltext zu nehmen und leicht abzuändern,das ist kein Programmieren. Arbeiten Sie mit dem Kapitel, ändern Sie getrost Zeilen– und beginnen Sie dann mit einem leeren Editorfenster. So sammeln Sie am bestenErfahrung.

Page 256: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

256

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

20.1 Menüs gestalten

Jedes Spiel sollte ein Hauptmenü haben. In diesem Bildschirm wählt der Spieler zwi-schen den Programmteilen. Es bietet eine Auswahl aus folgenden Punkten:

� Spielen (oder Start)

� Einstellungen (oder Optionen)

� Passwort (oder Levelcode) eingeben

� (Spielstand) Laden

� (Spielstand) Speichern

� Bestenliste

� Ende

Abgesehen von einem eventuellen Titelbild oder Vorspann, ist das Hauptmenü das Ers-te, was der Spieler zu Gesicht bekommt. Es sollte daher mit der gleichen Mühe gestal-tet werden wie das Spiel selbst. Ein Vorschlag: Verwenden Sie für das Titelbild und dasHauptmenü das gleiche Spiel-Logo, in der gleichen Größe und am gleichen Platz – imoberen Drittel des Bildschirms.

0

Ein Menü soll intuitiv zu bedienen sein. Grafiksymbole zum Anklicken ohne Textbe-schreibung kommen daher nicht in Frage. Ob das Menü mit der Maus und/oder derTastatur bedient wird, hängt vom Genre ab. Arcade-Spiele werden in der Regel mit derTastatur gespielt, entsprechend genügt für das Menü eine Tastenabfrage. Halten Siesich an die Konventionen: Das Menü wird mit den Pfeiltasten navigiert, Æ und dieLeertaste bestätigen die Auswahl, È beendet das Spiel.

Vom Hauptmenü aus unterteilt sich das Programm in die einzelnen Teilbereiche wie ei-gentliches Spielgeschehen, Lade-Bildschirm, Einstellungen. Es bietet sich an, von derMenüschleife aus alle Bereiche als Funktion aufzurufen. So finden Sie am Ende leichtzum Menü zurück.

Sie sollten zunächst das eigentliche Spiel programmieren und sich dann um das Menükümmern. Oft genug haben Programmierer ihre ganze Energie in Titelbild, Menü,Abspann und andere Gimmicks investiert und dann die Motivation verloren, den auf-wendigeren Hauptteil anzugehen.

Reiner Prokein, www.reinerstileset.de: »Eine schön anzusehende Menüführungwertet ein Spiel auf. Achten Sie auf strukturierte Menüs, die übersichtlich und gut les-bar gestaltet und vor allem einfach zu bedienen sind. Wenn der Spieler unzählige Vor-spänne und Logos und danach eine fette Bedienungsanleitung wegklicken muss odergar einen Lageplan der Tasten benötigt, bis er tatsächlich loslegen kann, dann läuftetwas falsch. Dies ist einer der Punkte, wo sich Programmierung und Grafikdesignüberschneiden. Es kommt natürlich auch darauf an, um was für eine Art von Spiel essich handelt. Ein Menü mit vielen Unterpunkten und Querverweisen macht für einBallerspiel à la »Moorhuhn« wenig Sinn. Bei solchen Spielen will man sich nicht erstdurch ein Monstermenü hangeln, sondern zocken.«

Page 257: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

257

Menüs gestalten j e t z t l e r n e i c h

Für die Menüeinträge verwenden Sie entweder reine Schrift oder nett gestaltete Gra-fiken mit Schriftzügen.

0

Da wir für unsere Beispiele Grafiken verwenden, die mit Blitz Basic mitgeliefert wer-den, müssen wir tief in die Trickkiste greifen, um Schalter zu ergattern. Aus der Gra-fikdatei BLOCKS1.BMP nehmen wir uns ein Quadrat, kopieren den Ausschnitt in eineneue Grafik, verdoppeln ihn in seiner Höhe und verachtfachen ihn in seiner Breite.Damit erhalten wir einen 256x64 Punkt großen Schalter.

tiles = LoadImage ("blocks1.bmp")stein = CreateImage(32,32)SetBuffer ImageBuffer(stein)DrawImageRect tiles, 0, 0, 444, 308, 32, 32ScaleImage stein, 8, 2

Unser Menü soll drei Schaltflächen haben (START, EINSTELLUNGEN, ENDE) und sich mitder Maus bedienen lassen. Der Spieler fährt mit der Maus auf dem Bildschirm umherund wenn sie auf einem Schalter ruht, klickt er, um das entsprechende Menü zu akti-vieren. Dabei bietet es sich an, die Schaltfläche zu färben, wenn die Maus sie berührt.So erhält der Spieler eine optische Bestätigung über den ausgewählten Menüpunkt undkann beruhigt klicken. Daher erzeugen wir auf die gleiche Weise einen zweiten Schal-ter (aktivstein) mit einer anderen Farbe. Die Namen der Menüpunkte, mit denen wirdie Schalter beschriften, und ihre Zeilenposition speichern wir in zwei Dim-Feldern. Inder Menüschleife führen wir drei Aufgaben aus:

1. Wir fragen die Mausposition ab und zeichnen einen Mauszeiger, aber erst nach denSchaltern, damit der Pfeil darüber liegt.

X = MouseX()Y = MouseY()...DrawImage maus, X,Y

2. Wir testen, ob der Mauspfeil einen der Schalter berührt. Tut er das, wird er in eineranderen Farbe gezeichnet. Außerdem füttern wir die Variable Menu mit der Nummerdes hervorgehobenen Menüpunkts:

For I=1 To 3 If ImageRectOverlap (maus, X, Y, 192, 100*I, 256, 64) Then DrawImage aktivstein, 192, I * 100 Menu = I Else DrawImage stein, 192, I * 100 EndIf Text (640 - StringWidth( MenuName$(I) )) / 2, I*100 + 12, MenuName$(I)Next

Schöne Fonts finden Sie unter anderem auf www.fontfreak.com. Da Blitz Basic kei-ne Kantenglättung bei Fonts bietet, sehen die Texte etwas unbeholfen aus. Profes-sioneller wirken hier spezielle Schalter. Allgemein wirken Bitmap-Fonts, bei denenjeder Buchstabe in einer Grafikdatei abgelegt ist, professioneller. Mit Programmenwie Bitmap Font Builder (www.lmnopc.com/bitmapfontbuilder) und FONText(www.marina.cybermog.co.uk/fontext, beide auf der CD) wandeln Sie die Zeicheneines Fonts in eine BMP-Datei um, was als Grundlage für eigene Anreicherungen mitEffekten dienen kann. Achten Sie auch hier auf fremde Rechte und benutzen Sie nurFreeware-Fonts.

Page 258: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

258

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

3. Wird die linke Maustaste gedrückt, testen wir anhand dieser Variable, ob ein Menü-punkt aktiv ist. Falls ja, rufen wir die entsprechende Funktion auf.

If MouseHit(1) Then If Menu = 1 Then Start() If Menu = 2 Then Einstellungen() If Menu = 3 Then Ende()EndIf

Abb. 20.1:Das Haupt-menü sollte

ansprechend ge-staltet, aber vorallem übersicht-

lich sein.

Sind die Funktionen wie Einstellungen() beendet, kehren sie automatisch zum Haupt-programm und damit zum Menü zurück. Nur die Auswahl Ende() sollte das Programmbeenden. Eine zusätzliche Sicherheitsabfrage sollte nicht unbedingt erfolgen. Im Regel-fall hat der Spieler ja bewusst eine Auswahl angeklickt und weiß Bescheid über die Kon-sequenzen.

; HAUPTMENU.BBGraphics 640,480tiles = LoadImage ("blocks1.bmp")maus = LoadImage ("pointer.bmp")font = LoadFont("Times New Roman", 40, 1, 0, 0)SetFont font

; Grafik für Menüpunkt erzeugen

stein = CreateImage(32,32)SetBuffer ImageBuffer(stein)DrawImageRect tiles, 0, 0, 444, 308, 32, 32ScaleImage stein, 8, 2

Page 259: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

259

Menüs gestalten j e t z t l e r n e i c h

; Grafik für aktiven Spielstein erzeugen

aktivstein = CreateImage(32,32)SetBuffer ImageBuffer(aktivstein)DrawImageRect tiles, 0, 0, 2, 342, 32, 32ScaleImage aktivstein, 8, 2

; Menü definieren

Dim MenuZeile(3) : Dim MenuName$(3)MenuZeile(1) = 100 : MenuName$(1) = "Start"MenuZeile(2) = 200 : MenuName$(2) = "Einstellungen"MenuZeile(3) = 300 : MenuName$(3) = "Ende"

;; Hauptmenü-Schleife;SetBuffer BackBuffer()Repeat Cls Menu = 0 X = MouseX() Y = MouseY()

For I=1 To 3 If ImageRectOverlap (maus, X, Y, 192, 100*I, 256, 64) Then DrawImage aktivstein, 192, I * 100 Menu = I Else DrawImage stein, 192, I * 100 EndIf Text (640 - StringWidth( MenuName$(I) )) / 2, I*100 + 12, MenuName$(I) Next

DrawImage maus, X,Y Flip

If MouseHit(1) Then If Menu = 1 Then Start() If Menu = 2 Then Einstellungen() If Menu = 3 Then Ende() EndIf Until KeyHit(1)End

;; Funktionen für Menüpunkte;

Function Start() Repeat Cls Text 100,100, "Spielstart" Flip Until KeyHit(1)End Function

Page 260: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

260

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Function Einstellungen() Repeat Cls Text 100,100, "Einstellungen" Flip Until KeyHit(1)End Function

Function Ende() Repeat Cls Text 100,100, "Ende" Flip Until KeyHit(1) Or KeyHit(57) EndEnd Function

20.2 Spielschleife und Timing

Jedes Spiel läuft in einer Hauptschleife ab, in einer schnöden Repeat/Until-Bedin-gung. Dort werden fortlaufend drei Aktionen ausgeführt:

� Zeichnen des Bildschirms

� Abfrage der Spielereingaben

� Auswerten der Eingaben

Robert Hierl, www.meinmurks.de: »Neben dem Hauptmenü haben viele Spieleeine Optionen-Seite. Hier lassen sich Eigenschaften wie Auflösung und Schwierig-keitsgrad einstellen. Überlegen Sie, welche Regler zweckmäßig sind. Zu viele Optio-nen verwirren den Anwender und können bei falscher Einstellung zu Inkompatibilitä-ten mit der Hardware führen. Wenn etwa die Auswahl einer Auflösung angebotenwird, sollte sie sich auf 640x480, 800x600 und 1024x768 beschränken, da z.B.TFT-Monitore bei anderen Auflösungen Probleme bereiten können. Die Einstellmög-lichkeiten hängen natürlich stark von der Komplexität des Spiels ab. Wenn ein Spielkomplett über die Pfeiltasten und eine oder zwei Zusatztasten gesteuert wird, machtes keinen Sinn, die Steuerung einstellbar zu gestalten.

Die Auswahl der Sprache ist nur dann sinnvoll, wenn das Spiel auch außerhalbDeutschlands gespielt werden soll und es auch genügend Text (wie Story, Erklärun-gen, Anweisungen für jeden Level) gibt. Wer sein Spiel auf international verständlicheBegriffe wie Highscore, Points, Hits, Start Game und Exit beschränkt, kann sichdie Übersetzung sparen. Unter Umständen ist es empfehlenswert, eine internationale(englische) und eine deutsche Version zum Download anzubieten.

Grafikeffekte sollten nur dann angepasst werden können, wenn sie wirklich Einflussauf die Spielgeschwindigkeit haben. Oftmals gibt es so viele »sinnlose« Einstellmög-lichkeiten, dass man die Optionen, die wirklich zu einer Verbesserung der Perfor-mance führen, gar nicht so leicht findet. Auch der Grad der Spieleinstellungen solltenicht übertrieben werden. Eine pauschale Auswahl Leicht – Mittel – Schwer ist oft-mals besser, als jeden Parameter einzeln einstellen zu lassen.«

Page 261: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

261

Spielschleife und Timing j e t z t l e r n e i c h

Die Schleife endet meistens, wenn eine von drei Bedingungen erfüllt ist:

Meistens ist diese Schleife viel zu schnell abgearbeitet. Die Figuren rasen über den Bild-schirm. Eine Bremse muss her.

20.2.1 TaktfrequenzDer Befehl Flip gleicht den Seitenwechsel an den Bildaufbau des Monitors an. DerMonitor baut das Computerbild unermüdlich neu auf, in der Regel 60 bis 120 Mal inder Sekunde. Man nennt diesen Takt Bildwiederholrate oder (horizontale) Frequenz.Flip orientiert sich an dieser Frequenz.

1

Setzen Sie in Ihrer Hauptschleife Flip ein, dann läuft das Spiel genauso schnell ab, wiedie Taktfrequenz des Monitors ist – etwa 100 Mal je Sekunde. Das heißt: höchstens.Wenn das Abarbeiten der Schleife länger dauert als ein Taktzyklus, wird das Spiel ent-sprechend langsamer ausgeführt.

1Das Orientieren an der Bildwiederholrate (der Fachbegriff ist Frame-Sync) ist ein bes-serer Richtwert, als sich auf die Taktfrequenz des PCs zu verlassen. Denn dort ist von300 bis weit über 3000 MHz alles vertreten. Je schneller der PC, desto schneller läuftdann das Spiel ab. (Einige ältere DOS-Programme zeigen diesen Effekt. Sie laufen heu-te viel zu schnell. Mit einem Werkzeug wie MoSlo müssen Sie den PC abbremsen, ummit den Spielen vernünftig umzugehen.)

Ende-Bedingung Weiterleitung zu

Abbruch-Taste gedrückt Hauptmenü

Spiel verloren Verloren-Bildschirm, dann Hauptmenü

Spiel gewonnen nächster Level oder Sieg-Bildschirm, dann Hauptmenü

Frank Neumann, www.silizium-net.de: »Die Spielschleife sollte klein sein. LagernSie alle Zeilen zum Darstellen des Bildschirms in eine Funktion. Dann ist die Haupt-schleife im besten Fall keine zehn Zeilen lang. Diese Vorgehensweise dient der Über-sichtlichkeit, die sich wiederum positiv auf die Fehlerrate auswirkt.«

Der Monitor baut mithilfe eines waagerechten Elektronenstrahls das Bild Zeile für Zei-le auf. Ist der Strahl unten angelangt, wandert er schräg nach oben und beginnt wie-der von vorn. Diese Rückkehr bezeichnet man als vertikalen Strahlenrücklauf. Indieser Zeit wird kein Bild gezeichnet. Die Anzahl der Rückläufe je Sekunde entsprichtder Bildwiederholfrequenz. Flip nutzt den Augenblick, um die Puffer miteinander zuvertauschen und das Bild auszuwechseln, ohne dass der Strahl mittendrin die Ansichtaktualisiert.

Wenn Sie Flip mit dem Parameter 0 verwenden (Flip 0), wird der Pufferwechsel so-fort ausgeführt. Das ist schneller, sorgt aber für ein unruhiges Bild.

Page 262: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

262

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Optimal ist das Verfahren allerdings nicht: Auch bei der Bildfrequenz gibt es große Un-terschiede. Sie hängt von der verwendeten Auflösung, der Grafikkarte, dem Monitorund den Einstellungen ab. Die Grafikkarte kann noch so leistungsfähig sein: WennWindows nicht der verwendete Monitor mitgeteilt wird, wird sie nicht ausgereizt. DieAnzeigefrequenz soll so schnell sein, dass das Bild nicht mehr flimmert. Das ist jedocheine sehr subjektive Größe. Manche empfinden 75 Hz flimmerfrei, andere sind erst mit100 zufrieden.

20.2.2 Takt programmierenDie Hauptschleife Ihres Spiels wird gleichmäßig durchlaufen, indem Sie einen Taktfestlegen und den Beginn des nächsten Durchlaufs daran ausrichten. Mit der FunktionMilliSecs() stellen Sie einen Rhythmus ein. Sollen etwa 30 Bilder je Sekunde gezeich-net werden, pausieren Sie vor Flip so:

Repeat Until MilliSecs() Mod 33 = 0

(33 mal 30 sind 999 Millisekunden und damit beinahe eine Sekunde.)

20.2.3 Timer-BefehleBlitz Basic stellt Ihnen alternativ ein spezielles Set an Befehlen zur Verfügung, mit de-nen Sie das Timing Ihres Spiels an eine festgelegte Anzahl von Bildern je Sekunde an-passen. Mit CreateTimer() erzeugen Sie einen Zeitgeber. Als Parameter übergeben Siedie gewünschte Anzahl an Durchläufen je Sekunde, etwa 30. Die Funktion koppeln Siemit einer Variablenzuweisung:

takt = CreateTimer(30)

Damit erzeugt CreateTimer() 30 Mal je Sekunde einen Taktimpuls. Der Befehl Wait-Timer veranlasst Blitz Basic, mit der Programmausführung so lange zu warten, bis dernächste Taktzyklus beginnt:

WaitTimer takt

Üblicherweise setzen Sie diesen Befehl direkt vor Flip.

1Eine Spielschleife sieht unter Verwendung eines Zeitgebers ungefähr so aus:

takt = CreateTimer()Repeat ... WaitTimer takt FlipUntil KeyHit(1)

Wenn Sie WaitTimer als Funktion verwenden und ihr Ergebnis in einer Variable spei-chern, erfahren Sie, wie viele Taktzyklen seit dem letzten Aufruf vergangen sind:

Anzahl = WaitTimer(takt)

CreateTimer() klatscht im regelmäßigen Rhythmus, etwa 30 Mal je Sekunde, in dieHände. WaitTimer wartet so lange, bis das nächste Klatschen ertönt. Auf diese Weiseläuft das Spiel in konstanter Geschwindigkeit.

Page 263: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

263

Gerüst für einen Weltraum-Shooter j e t z t l e r n e i c h

Je mehr Zyklen es sind, desto langsamer ist der verwendete PC. Sollten Sie die Dienstedes Taktgebers nicht mehr benötigen, stoppen Sie ihn wieder:

FreeTimer takt

1

20.2.4 DelayDie einfachste Methode ist das Verzögern mithilfe von Delay. Sie ist bei vielen Entwick-lern verpönt, da damit das komplette Programm angehalten wird, statt die Rechenzeitanderweitig zu nutzen. Außerdem erzeugt Delay keine tatsächliche Synchronisation, daes nicht berücksichtigt, dass jeder Schleifendurchgang je nach Ereignissen unterschied-lich viel Zeit benötigt. Für einfache Programme erfüllt Delay mit einer Verzögerung un-terhalb von 200 oder besser 100 Millisekunden durchaus seinen Zweck.

20.3 Gerüst für einen Weltraum-Shooter

Ein Weltraum-Shooter gehört zu den einfachsten Spielideen. Ein Raumschiff, böseAlien-Schiffe – das genügt im einfachsten Fall. Einen spacigen Hintergrund nehmenwir als Vorlage. Dazu setzen wir unser Raumschiff ins Bild:

; SHOOTER1.BBGraphics 640, 480SetBuffer BackBuffer()hinter = LoadImage("stars.bmp")schiff = LoadImage("spaceship2.bmp")X = 305Y = 420;Repeat H = H+1 If H=200 Then H=0 TileBlock hinter,0,H DrawImage schiff, X,Y FlipUntil KeyHit(1)

Es gibt verschiedene Ansichten darüber, ob die Timer-Funktionen oder das Program-mieren eines eigenen Timers mit MilliSecs() die bessere Methode für die Steuerungder Spielgeschwindigkeit sind. In der ersten Version von Blitz Plus (auf der die Demobasiert), ist WaitTimer weggefallen: Die Synchronisation muss manuell programmiertwerden oder läuft ereignisbezogen mit WaitEvent. Nach Protesten, vor allem in Be-zug auf die Rückwärtskompatibilität, wurde mit dem ersten Update (Version 1.34)WaitTimer wieder aufgenommen.

Frank Neumann, www.silizium-net.de: »Bremsen Sie Ihr Spiel nicht mit Delay aus.Programmieren Sie Frame-unabhängig, indem Sie Ereignisse zeitgesteuert ablaufenzu lassen. Wenn man etwa alle 0,2 Sekunden einen Schuss abfeuert, anstatt alle 10Frames, macht es keinen Unterschied mehr, ob der Spieler 20 oder 100 FPS hat.«

Page 264: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

264

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

20.3.1 Schiff steuernAls Nächstes kümmern wir uns um die Steuerung für unser Schiff. Wir fragen also dievier Pfeiltasten ab und verändern entsprechend die Werte für X und Y, die als Koordi-naten für den Zeichenbefehl dienen. Weil unser Schiff sich schneller seitwärts als senk-recht bewegen soll, verändern wir X jeweils um den Wert 2 statt 1:

If KeyDown(200) = 1 Then Y = Y - 1If KeyDown(208) = 1 Then Y = Y + 1If KeyDown(205) = 1 Then X = X + 2If KeyDown(203) = 1 Then X = X - 2

Fügen wir diese wenigen Zeilen hinzu, bewegt sich unser Raumschiff nach unserenWünschen.

20.3.2 Rand einrichtenNoch kann sich das Gefährt aus dem sichtbaren Bereich heraus verirren. Um das zuverhindern, fragen wir nach der Veränderung X und Y ab, ob sie im erlaubten Rahmensind:

; SHOOTER2.BBIf X < 0 Then X = 0If X > 605 Then X = 605If Y < 0 Then Y = 0If Y > 451 Then Y = 451

Nun verlässt das Schiff nie den Bildschirm.

20.3.3 SchüsseEin Raumschiff ohne Raketen ist wie ein Regenwurm ohne Schwanz. Unser Schiff-chen soll Geschosse abgeben, wenn wir die Leertaste drücken. Das stellt eine kleineHerausforderung dar, weil sich das Geschoss unabhängig von dem Schiff bewegen soll.Wir laden dazu am Anfang zusätzlich die Grafik einer Rakete:

rakete = LoadImage("bullet.bmp")

In die Hauptschleife setzen wir zunächst einen Testbefehl:

If KeyDown(57)= 1 Then DrawImage rakete, X+10, Y-19

Der ist nicht übel für den Anfang: Solange wir die Leertaste drücken, erscheint vor demBug des Schiffs eine kleine Rakete.

Damit es »echt« aussieht

� muss sich die Rakete einige Sekunden lang vom Raumschiff wegbewegen,

� muss aber das Schiff weiterhin steuerbar sein,

� muss es möglich sein, mehrere Schüsse kurze Zeit nacheinander abzugeben.

Wie stellen wir das an? Die Rakete muss sich über mehrere Schleifendurchläufe hinwegbewegen und wir müssen uns die Position mehrerer Raketen merken.

Wir erzeugen dazu zunächst ein Feld:

Dim Rak(100,2)

Page 265: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

265

Gerüst für einen Weltraum-Shooter j e t z t l e r n e i c h

Für je 100 Raketen merken wir uns damit:

� ob sie gerade aktiviert ist

� die X-Position

� die Y-Position

Nach der hundertsten ausgelösten Rakete springt der Zähler wieder auf 1. Fällt einSchuss, wird das registriert und die Startposition der Rakete gespeichert:

If KeyHit(57) Then Schuss = Schuss + 1 If Schuss = 21 Then Schuss = 1 Rak(Schuss,0) = 1 Rak(Schuss,1) = X+10 Rak(Schuss,2) = Y-19EndIf

Die Raketen sollten nicht im Dauerfeuer möglich sein; daher wählen wir KeyHit(). MitKeyDown() könnte der Spieler die Taste gedrückt halten.

Der Schuss soll von einem Klang untermalt werden. Also laden wir am Anfang des Pro-gramms einen Sound ...

schusston = LoadSound("soundfx11.wav")

... den wir innerhalb der If-Bedingung abspielen lassen:

PlaySound(schusston)

Das ist bereits die halbe Miete. Nun müssen wir für jede Rakete die Position ändern.Die waagerechte Koordinate bleibt dabei gleich – die Munition schießt pfeilgerade nachoben. Ist die Rakete außer Sichtweite, wird sie gelöscht.

For I=1 To 100 If Rak(I,1) < 0 Then Rak(I,0) = 0 If Rak(I,0) = 1 Then DrawImage rakete, Rak(I,1), Rak(I,2) Rak(I,2) = Rak(I,2) - 10 EndIfNext

Damit es übersichtlich bleibt, liste ich Ihnen das ganze Programm an einem Stück auf.Das Raumschiff lässt sich bewegen und mittels Leertaste schießt es eine Rakete ab.

; SHOOTER3.BBGraphics 640, 480SetBuffer BackBuffer()hinter = LoadImage("stars.bmp")schiff = LoadImage("spaceship2.bmp")rakete = LoadImage("bullet.bmp")schusston = LoadSound("soundfx11.wav")Dim Rak(100,2)X = 305Y = 420;Repeat

; Hintergrund H = H+1 If H=200 Then H=0

Page 266: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

266

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

TileBlock hinter,0,H DrawImage schiff, X,Y

; Schusstest If KeyHit(57) Then Schuss = Schuss + 1 If Schuss = 100 Then Schuss = 1 Rak(Schuss,0) = 1 Rak(Schuss,1) = X+10 Rak(Schuss,2) = Y-19 PlaySound(schusston) EndIf

; Raketen bewegen For I=1 To 100 If Rak(I,1) < 0 Then Rak(I,0) = 0 If Rak(I,0) = 1 Then DrawImage rakete, Rak(I,1), Rak(I,2) Rak(I,2) = Rak(I,2) - 10 EndIf Next

; Tastendrücke abfragen If KeyDown(200) = 1 Then Y = Y - 1 If KeyDown(208) = 1 Then Y = Y + 1 If KeyDown(205) = 1 Then X = X + 2 If KeyDown(203) = 1 Then X = X - 2

; Randtest If X < 0 Then X = 0 If X > 609 Then X = 609 If Y < 0 Then Y = 0 If Y > 449 Then Y = 449 FlipUntil KeyDown(1)

20.3.4 GegnerWohin bzw. auf wen schießen unsere Raketen? Außer dem Schiff ist weit und breit nie-mand zu sehen. Wir brauchen daher feindlich gesinnte Alien-Raumschiffe. Sie werdennatürlich nicht mit den Pfeiltasten gesteuert, sondern bewegen sich selbstständig.

Da es im Regelfall mehrere Gegner gibt, bietet sich wieder ein Feld an:

Dim Alien(5,2)

Ähnlich wie bei den Raketen speichern wir wieder drei Informationen:

� Existiert der Gegner (noch)?

� X-Position des Gegners

� Y-Position des Gegners

Für das Bewegen der Gegner gibt es zwei grundsätzliche Vorgehensweisen. Entwederbewegen sich die Alien-Schiffe zufällig oder nach einem festgelegten Muster.

Page 267: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

267

Gerüst für einen Weltraum-Shooter j e t z t l e r n e i c h

Das zufällige Bewegen lösen wir mit Zufallszahlen. Dabei bauen wir Wahrscheinlichkei-ten ein. Einige Bewegungen kommen also häufiger vor als andere. Das Alien-Schiffkönnte etwa waagerecht

� in erster Linie stehen bleiben (70%)

� manchmal in Richtung unseres Schiffs schwenken (20%)

� und seltener in die entgegengesetzte Richtung schweben (10%)

und senkrecht

� sich eher nach unten bewegen (30%)

� in erster Linie aber auf der derzeitigen Höhe stehen bleiben (70%)

� nie ein Stück nach oben steigen (0%)

Dazu fragen wir am besten für die waagerechte und senkrechte Bewegung eine Zufalls-zahl von 1–10 ab. Entsprechend ihres Werts manövrieren wir das Schiff waagerechtund senkrecht. Zu vermeiden sind ständige Minibewegungen, die für Zittern sorgen.Lösung: Ein Schiff muss sich eine bestimmte Anzahl Pixel in eine Richtung bewegen.Dazu speichern wir zusätzlich die letzte Richtung (1 = links, 2 = rechts ...) sowie die An-zahl der bereits erfolgten Bewegungen in diese Richtung. Ob das eine optimale Fest-legung ist, finden wir nur durch Ausprobieren heraus. Es ist durchaus sinnvoll, solcheGegnerbewegungen eine längere Zeit ungebremst zu beobachten.

Eine bessere Methode ist das Verwenden vorgefertigter Bewegungsmuster, die nach-einander abgearbeitet werden. Dabei sollten sich die Gegner durch ihr Aussehen undihr Verhalten voneinander unterscheiden. Manche sind schneller, andere langsamer.Einige verschwinden rasch wieder, andere sind hartnäckiger.

Abb. 20.2:Bereits ein-fache Formeln genügen, um »interessante« Bewegungen von Gegnern zu generieren.

Page 268: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

268

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Wir wollen ein einfaches Bewegungsmuster anhand der Sinus-Kurve verwenden.Dabei greifen wir auf unser Flugbahnbeispiel (FLUGBAHN.BB) zurück. Für jedes Alienlegen wir fest: Größe der Kurve, Startwert X und Startwert Y:

For I=1 To 5 If Alien(I,0) = 0 Then ; Alien vorhanden? Alien(I,0) = Rand(100,400) ; Größe der Sinus-Kurve Alien(I,1) = Rand(-20,640) ; Startwert X Alien(I,2) = Rand(-100,0) ; Startwert Y EndIf

(Wir benutzen daher den Feldindex (I,0) doppelt – wir merken uns, ob das Alien exis-tiert, und wir speichern die Kurvengröße. Das lässt sich gut vereinbaren, denn wennder eine Wert größer als 0 ist, dann ist es der andere auch.)

Bei jedem Schleifendurchlauf verändern wir die Position der Aliens:

Alien(I,2) = Alien(I,2) + 1 Alien(I,1) = 320 + Sin( Alien(I,2) ) * Alien(I,0)

Ist ein Alien unten aus dem Bildschirm verschwunden, wird beim nächsten Durchlaufein neues erstellt:

If Alien(I,2) > 480 Then Alien(I,0) = 0

Am Schluss wird es gezeichnet:

DrawImage alienbild, Alien(I,1),Alien(I,2)

Wir haben mit diesem Programmteil gleich zwei Voraussetzungen erfüllt:

� Sind weniger Alien-Schiffe als vorgesehen aktiv, müssen neue erschaffen werden.

� Wenn ein Alien-Schiff abgeschossen wird oder vom Bildschirm verschwindet, er-folgt eine Markierung im Datenfeld.

Der ganze Alien-Abschnitt:

; SHOOTER4.BB; Alien-SteuerungFor I=1 To 5 If Alien(I,0) = 0 Then Alien(I,0) = Rand(100,400) Alien(I,1) = Rand(-20,640) Alien(I,2) = Rand(-100,0) EndIf

Alien(I,2) = Alien(I,2) + 1 Alien(I,1) = 320 + Sin( Alien(I,2) ) * Alien(I,0)

If Alien(I,2) > 480 Then Alien(I,0) = 0 DrawImage alienbild, Alien(I,1),Alien(I,2)Next

Page 269: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

269

Gerüst für einen Weltraum-Shooter j e t z t l e r n e i c h

20.3.5 KollisionWas passiert, wenn unser Held mit einem Alien-Schiff zusammenstößt? Nichts. Wenneine Rakete ein Schiff trifft? Nichts. Das lässt sich ändern. Wir müssen für jede Raketeerfragen, ob sie mit einem Gegner zusammenstößt.

; Kollision testenFor I=1 To 100 If Rak(I,0) <> 0 Then For J=1 To 5 If ImagesOverlap(alienbild, Alien(J,1), Alien(J,2), rakete, Rak(I,1),Rak(I,2)) Then PlaySound(trefferton) Alien(J,0) = -1 EndIf Next EndIfNext

In einem zweiten Schritt spielen wir die Explosionsanimation aus unserem BeispielEXPLOSION.BB ab. Dazu verwenden wir ein zweites Feld AlienExplodiert(), dasden aktuellen Frame der Animation und die verstrichene Zeit für den jeweiligen Ani-mationsschritt speichert.

; Explosion Alien zeichnenFor I=1 To 5 If Alien(I,0) = -1 Then If AlienExplodiert(I,1) + 100 < MilliSecs() Then AlienExplodiert(I,0) = AlienExplodiert(I,0) + 1 AlienExplodiert(I,1) = MilliSecs()

If AlienExplodiert(I,0) = 6 Then AlienExplodiert(I,0) = 0 AlienExplodiert(I,1) = 0 Alien(I,0) = 0 EndIf EndIf DrawImage explosion, Alien(I,1), Alien(I,2), AlienExplodiert(I,0) EndIfNext

Nun müssen wir noch sicherstellen, dass das Alien-Schiff nur gezeichnet wird, wennkeine Explosion erfolgt.

Dabei gehen wir davon aus, dass ein Treffer den Gegner sofort zerstört. Leicht ließesich Lebensenergie hinzufügen, die erst nach einigen Treffern verbraucht ist. Wirmüssten dazu in einer zusätzlichen Spalte einfach 100 (= volle Lebensenergie) eintra-gen. Bei einem Treffer ändert sich der Wert nicht in 0 (= zerstört), sondern es wird (zumBeispiel) der Wert 35 subtrahiert. Erst wenn er 0 ergibt, ist das Objekt tatsächlich zer-stört. Wir sollten dazu für jeden »Lebensabschnitt« eine unterschiedliche Grafik zumDarstellen der Beschädigungen verwenden.

Ähnlich gehen wir bei unserem Raumschiff vor: Die Gegner müssen regelmäßig schie-ßen. Der Zusammenstoß mit einem Alien-Schiff muss mit einer Explosion beiderKontrahenten verbunden sein. Hier bietet sich ein Balken für die verbliebene Lebens-energie an.

Page 270: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

270

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Abb. 20.3:Explosion:

Beim Trefferwird eine

Animationabgespielt.

Das ganze Programm:

; SHOOTER5.BBGraphics 640, 480SetBuffer BackBuffer()hinter = LoadImage("stars.bmp")schiff = LoadImage("spaceship2.bmp")alienbild = LoadImage("player.bmp")rakete = LoadImage("bullet.bmp")explosion = LoadAnimImage("kaboom.bmp", 60,46, 0,6)schusston = LoadSound("soundfx11.wav")trefferton = LoadSound("soundfx16.wav")

Dim Rak(100,2)Dim Alien(5,2)Dim AlienExplodiert(5,1)X = 305Y = 420

;; Hauptschleife;

Repeat Cls H = H+1 If H=200 Then H=0 TileBlock hinter,0,H DrawImage schiff, X,Y

; Schuß-Test If KeyHit(57) Then Schuss = Schuss + 1 If Schuss = 101 Then Schuss = 1

Page 271: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

271

Gerüst für einen Weltraum-Shooter j e t z t l e r n e i c h

Rak(Schuss,0) = 1 Rak(Schuss,1) = X+10 Rak(Schuss,2) = Y-19 PlaySound(schusston) EndIf

; ggf. Raketen zeichnen For I=1 To 100 If Rak(I,0) = 1 Then DrawImage rakete, Rak(I,1), Rak(I,2) Rak(I,2) = Rak(I,2) - 10 EndIf Next

; Pfeiltasten abfragen If KeyDown(200) = 1 Then Y = Y - 1 If KeyDown(208) = 1 Then Y = Y + 1 If KeyDown(205) = 1 Then X = X + 2 If KeyDown(203) = 1 Then X = X - 2

; Rand-Überschreitung verhindern If X < 0 Then X = 0 If X > 609 Then X = 609 If Y < 0 Then Y = 0 If Y > 449 Then Y = 449

; Kollision testen For I=1 To 100 If Rak(I,0) <> 0 Then For J=1 To 5 If ImagesOverlap(alienbild, Alien(J,1), Alien(J,2), rakete, Rak(I,1),Rak(I,2)) Then PlaySound(trefferton) Alien(J,0) = -1 EndIf Next EndIf Next

; Explosion Alien zeichnen For I=1 To 5 If Alien(I,0) = -1 Then If AlienExplodiert(I,1) + 100 < MilliSecs() Then AlienExplodiert(I,0) = AlienExplodiert(I,0) + 1 AlienExplodiert(I,1) = MilliSecs()

If AlienExplodiert(I,0) = 6 Then AlienExplodiert(I,0) = 0 AlienExplodiert(I,1) = 0 Alien(I,0) = 0 EndIf EndIf DrawImage explosion, Alien(I,1), Alien(I,2), AlienExplodiert(I,0) EndIf Next

; Alien-Steuerung For I=1 To 5 If Alien(I,0) = 0 Then Alien(I,0) = Rand(100,400) Alien(I,1) = Rand(-20,640)

Page 272: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

272

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Alien(I,2) = Rand(-100,0) EndIf

If Alien(I,0) <> -1 Then Alien(I,2) = Alien(I,2) + 1 Alien(I,1) = 320 + Sin( Alien(I,2) ) * Alien(I,0) EndIf

If Alien(I,2) > 480 Then Alien(I,0) = 0

If Alien(I,0) <> -1 Then DrawImage alienbild, Alien(I,1),Alien(I,2) Next

FlipUntil KeyDown(1)

20.3.6 AusblickeDas einfache Gerüst lässt sich vielfältig ausbauen: mehrere Levels, Aliens, die sich inFormation bewegen, Felsbrocken, die vorbeischweben, nützliche Dinge zum Einsam-meln – die Palette ist groß. Vor allem den Gegnern gebührt mehr Aufmerksamkeit, alsunser kleines Gerüst es zeigen konnte. Sie schießen nicht zurück und Zusammenstößezwischen Aliens und unserem Raumschiff werden bisher ignoriert.

20.4 Gerüst für Pac-Man & Co.

Ein Arcade-Spiel in der Art von »Pac-Man« unterscheidet sich von einem Shooter vorallem durch den Levelaufbau. Ein Level besteht in der Regel aus einer Vielzahl vonKacheln, quadratischen Einzelteilen (englisch: Tiles), die aneinander gereiht sind. Beikomplexeren Spielen werden mehrere Schichten (Layers) eingesetzt: So gäbe es etwaeine Hintergrundschicht (Gras), über die ein Objekt (Baum) gesetzt wird.

Bei 2D-Spielen verwendet man meistens ein Regelwerk bezüglich des Aufbaus einesLevels und für jeden Level eine eigene Schablone. Bewährt hat sich dabei, für jedesEinzelteil ein Zeichen zu vereinbaren: "1" ist eine Mauer, "2" ist eine Tür usw.; " " isteine freie Fläche. Jedes Zeichen steht dabei für ein Grafikrechteck gleicher Größe,etwa 32x32 Bildpunkte. Bei einer Auflösung von 640x480 Bildpunkten wären das20x15 Teile, sofern der Level die gesamte Fläche des Bildschirms ausfüllt. Auch dieStartplätze der Spielfigur ("S") und der Gegner ("G") passen in die Levelschablone.

111111111111111111111S 11 1 11 11 11 1111 111 1 11 11 11 1111 111 1 11 11 11 11 11 1111 11 11 11 11 11 1111 11 11 11 11111 11 11 1111 11111 11111 11 1111 11 11 11 11 11111 1111 11 11 11 11 11 1111 11 11 11 11 111111111111111111111

Page 273: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

273

Gerüst für Pac-Man & Co. j e t z t l e r n e i c h

Das hat einige Vorteile: Sie gestalten Ihre Levels, ohne ein spezielles Hilfsmittel pro-grammieren zu müssen. Ein Texteditor genügt. Auch das spätere Ändern von Levelsfällt leicht.

Abb. 20.4:2D-Levels wer-den meistens 1:1 aus einer Datei in ein Dim-Feld gelesen.

Der einfachste Weg ist, jeden Level in einer einzelnen Textdatei abzubilden. Der Nach-teil: Die Spieler können ebenso leicht Levels verändern. Wenn Ihnen das nicht gefällt,verschlüsseln Sie die Zeichen. So könnten Sie für ein Einzelbild nicht nur ein, sonderngleich mehrere Zeichen vereinbaren. Den Wert ändern Sie am Schluss mit Xor. Das Er-gebnis ist ein schwer durchschaubares Wirrwarr.

Die Textdatei dient nur zur dauerhaften Speicherung. Während des Spiels laden wir dieZeichen in den Arbeitsspeicher. Perfekt geeignet dafür ist ein Dim-Feld. Es bietet einenleichten Zugriff auf die Inhalte. Auch die Programmierung der Bewegungen wird er-leichtert. Wir benötigen keine grafische Kollisionsabfrage, sondern testen anhand derZeichen im Dim-Feld, ob eine gedrückte Pfeiltaste zu einer erlaubten Bewegung führtoder ob eine Mauer im Weg steht.

20.4.1 Level einlesenDas Einlesen der Leveldaten ist eine einfache Aufgabe. Wir erzeugen ein Dim-Feld, dasdie Informationen aufnimmt. Anschließend lesen wir den Level ein. Dabei beginnenwir die Zählung mit 0, was uns später Erleichterungen bringt.

; Level von Festplatte lesenDim Level$(14,19)leveldatei = ReadFile("pac1.dat")For Zeile=0 To 14 A$ = ReadLine(leveldatei)

Page 274: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

274

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

For Spalte=0 To 19 Level$(Zeile,Spalte) = Mid$(A$,Spalte+1,1) NextNextCloseFile leveldatei

20.4.2 Level zeichnenNun stellen wir den Level dar. In unserem Beispiel kommt die GrafikdateiBLOCKS1.BMP zum Einsatz. Sie besteht aus einer Vielzahl von Quadraten im Format32x32. Um vom Symbol auf die tatsächliche Grafik zu schließen, dafür gibt es mehrereWege. Wir wählen den einfachsten, eine If-Bedingung. (Eine Alternative wäre, einweiteres Feld zu erzeugen, das von jedem Zeichen die Koordinaten des Bildausschnittsenthält.)

; Level zeichnenGraphics 640,480SetBuffer BackBuffer()tiles = LoadImage("blocks1.bmp")For Zeile=0 To 14 For Spalte=0 To 19 Select Level$(Zeile,Spalte) Case "1" DrawImageRect tiles, Spalte*32, Zeile*32, 36, 36, 32, 32 Case " " DrawImageRect tiles, Spalte*32, Zeile*32, 70, 274, 32, 32 End Select NextNextFlip

Abb. 20.5:Elemente für

das Zusammen-stellen von2D-Karten

Page 275: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

275

Gerüst für Pac-Man & Co. j e t z t l e r n e i c h

20.4.3 Spielfigur darstellenNun brauchen wir Aktivität, eine Spielfigur! Um sie zu steuern, bedarf es weiterer Va-riablen, vor allem für ihre Position. Diese können wir, wie eben besprochen, gleich ausder Leveldatei lesen. Das hat mehrere Vorteile:

� Wir müssen die Startposition nicht separat angeben.

� Beim Zeichnen des Levels wird die Spielfigur mit dargestellt.

� Das Speichern der Spielfigur im Dim-Feld des Levels erleichtert das Programmierender Bewegung.

Wir laden daher die Figur ...

spieler = LoadImage("player.bmp")

.... und zeichnen die Spielfigur (sowie vorher ihren Untergrund) beim Levelaufbau mit,wobei wir uns gleich ihre Position merken:

Case "S" DrawImageRect tiles, Spalte*32, Zeile*32, 70, 274, 32, 32 DrawImageRect figuren, Spalte*32, Zeile*32, 481,142,32,26 SpielerS = Spalte SpielerZ = Zeile

20.4.4 Spielfigur bewegenIn der Hauptschleife lassen wir die Figur sich bewegen. Wir fragen dazu die Pfeiltastenab und ändern entsprechend die Position. Dabei prüfen wir, ob die gewünschte Rich-tung gültig ist, also nicht in eine Mauer ("1") führt.

; Spielfigur bewegen

If KeyDown(203) And ( Level$(SpielerZ,SpielerS-1) <> "1" ) Then Level$(SpielerZ, SpielerS) = " " SpielerS = SpielerS - 1 Level$(SpielerZ, SpielerS) = "S" EndIf

If KeyDown(205) And ( Level$(SpielerZ,SpielerS+1) <> "1" ) Then Level$(SpielerZ, SpielerS) = " " SpielerS = SpielerS + 1 Level$(SpielerZ, SpielerS) = "S" EndIf

If KeyDown(200) And ( Level$(SpielerZ-1,SpielerS) <> "1" ) Then Level$(SpielerZ, SpielerS) = " " SpielerZ = SpielerZ - 1 Level$(SpielerZ, SpielerS) = "S" EndIf

If KeyDown(208) And ( Level$(SpielerZ+1,SpielerS) <> "1" ) Then Level$(SpielerZ, SpielerS) = " " SpielerZ = SpielerZ + 1 Level$(SpielerZ, SpielerS) = "S" EndIf

Page 276: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

276

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

In der Datei PAC1.BB habe ich beide Teile zu einem lauffähigen Programm verbun-den: eine Spielfigur, die sich innerhalb erlaubter Bahnen mit den Pfeiltasten bewegenlässt.

1

20.4.5 GegnerWovor läuft die Spielfigur weg? Vor Gegnern. Diese bewegen sich selbstständig, teilszufällig und teils zielgerichtet. Wie das Regelwerk genau aussieht, kann nur ein aus-giebiger Test der Spielbalance ergeben. Es hängt auch davon ab, wie viele Gegner vor-handen sind und wie schnell sie sich bewegen. Gegner sollten höchstens so schnell wiedie Spielfigur selbst durch die Gänge huschen – sonst wäre es nicht fair. Reizvoll sindunterschiedliche Geschwindigkeiten: größere behäbigere und kleinere schnellere Geg-ner.

Für unser übersichtliches Spielfeld genügt uns ein Gegner. Wir merken uns zwei Eigen-schaften: die Koordinaten und die Richtung. Sonst verwende ich dazu gern ein Feld,doch bei gerade drei Einträgen sollten normale Variablen ausreichen.

Die Position des Gegners tragen wir in die Leveldatei ("G") ein. Um sie auszulesen, er-gänzen wir den Abschnitt »Level zeichnen« um eine weitere Bedingung:

Case "G" DrawImageRect tiles, Spalte*32, Zeile*32, 70, 274, 32, 32 DrawImageRect figuren, Spalte*32, Zeile*32, 379,140,32,28 GegnerS = Spalte GegnerZ = Zeile

Damit sich der Gegner natürlich bewegt, sollte er vorwiegend eine Richtung einschla-gen, sich in Geraden bewegen. Er sollte nicht auf der Hälfte der Strecke Halt machen,um dann wieder umzukehren. Zwingend eine neue Richtung einschlagen sollte er nurdann, wenn der Weg versperrt ist.

Da nur anhand der Positionsdaten nicht abzulesen ist, in welche Richtung sich der Geg-ner bewegt, speichern wir sie in einer zusätzlichen Variablen. Grundsätzlich versuchen

Die Figur wird bei jedem Schritt um eine Kachel bewegt. Sie überspringt bei jedemSchritt eine Reihe von Bildpunkten. Für eine geschmeidigere Bewegung bauen SieHalbschritte ein, bei denen sich die Figur um eine halbe Kachel bewegt. Sie benöti-gen dafür je Bewegungsschritt zwei Durchläufe der Spielschleife: beim ersten Durch-lauf die Bewegung um eine halbe Kachel; beim zweiten den nächsten Teilschritt, indem die Figur wieder auf einer ganzen Kachel steht. Erst dort sollten die Tasten wie-der abgefragt werden.

Frank Neumann, www.silizium-net.de: »Oftmals lässt sich mit wenigen If-Abfragenund programmierten Reaktionen auf die Bewegungen des Spielers eine KünstlicheIntelligenz vortäuschen. Überlegen Sie, wie Sie beim »Schiffe versenken« vorgehen:Sie schießen zunächst wahllos ins Blaue. Gab es einen Treffer, bombardieren Sienacheinander die Nachbarfelder. Solche Denkmuster lassen sich in wenigen Pro-grammzeilen umsetzen. Bei aufwendigeren Spielen täuschen Sie mit geskripteten(programmierten) Abläufen intelligentes Handeln vor, etwa bei Ausweich- und An-griffsmanövern.«

Page 277: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

277

Gerüst für Pac-Man & Co. j e t z t l e r n e i c h

wir, in der bisherigen Richtung weiterzulaufen. Ist dort eine Mauer ("1"), löschen wir dieRichtungsvariable.

If Richtung = 0 Then Richtung = Rand(4)Select Richtung Case 1 ; Links If Level$(GegnerZ,GegnerS-1) <> "1" Then Level$(GegnerZ,GegnerS) = " " GegnerS = GegnerS - 1 Level$(GegnerZ,GegnerS) = "G" Else Richtung = 0 EndIf Case 2 ; Rechts If Level$(GegnerZ,GegnerS+1) <> "1" Then Level$(GegnerZ,GegnerS) = " " GegnerS = GegnerS + 1 Level$(GegnerZ,GegnerS) = "G" Else Richtung = 0 EndIf Case 3 ; Hoch If Level$(GegnerZ-1,GegnerS) <> "1" Then Level$(GegnerZ,GegnerS) = " " GegnerZ = GegnerZ - 1 Level$(GegnerZ,GegnerS) = "G" Else Richtung = 0 EndIf Case 4 ; Runter If Level$(GegnerZ+1,GegnerS) <> "1" Then Level$(GegnerZ,GegnerS) = " " GegnerZ = GegnerZ + 1 Level$(GegnerZ,GegnerS) = "G" Else Richtung = 0 EndIfEnd Select

Das reicht allerdings nicht; der Gegner würde immer auf der gleichen Route bleiben.An jeder Kreuzung sollte zufällig die Richtung gewechselt werden. Wie prüft man, obder Gegner an einer Kreuzung steht? Theoretisch müssten wir für jede Richtung prü-fen, ob es jeweils nach links oder rechts geht: acht Prüfungen. Mit einem Trick verein-fachen wir die Programmierung: Wir zählen die Zahl der möglichen Nachbarfelder.Gibt es mehr als zwei (vor und zurück), steht die Figur an einer Kreuzung. In diesem Fallwird die Richtungsvariable ebenfalls gelöscht und zufällig neu gewählt. Es kann alsodurchaus sein, dass zufällig die gleiche Richtung beibehalten wird – aber das ist eher einVorteil.

Wahl = 0If Level$(GegnerZ, GegnerS-1) = " " Then Wahl = Wahl +1If Level$(GegnerZ, GegnerS+1) = " " Then Wahl = Wahl +1If Level$(GegnerZ-1, GegnerS) = " " Then Wahl = Wahl +1If Level$(GegnerZ+1, GegnerS) = " " Then Wahl = Wahl +1If ( Wahl > 2 ) Or ( Richtung = 0 ) Then Richtung = Rand(4)

Das lauffähige Programm ist unter dem Namen PAC2.BB abgespeichert. Sofern Siemehrere Gegner einsetzen, genügt die »Intelligenz« durchaus. Um es dem Spieler etwas

Page 278: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

278

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

schwerer zu machen, schubsen Sie die Gegner an Kreuzungen sanft (etwa mit einerWahrscheinlichkeit von 75%) in Richtung des Spielers.

1

Bisher passiert nichts, wenn die beiden Akteure aneinander geraten. Ja, der Gegnerkann unseren Helden sogar überschreiben. Im Folgenden behandeln wir daher die Zu-sammenstöße.

20.4.6 ZusammenstößeBei dieser Art von Spielen ist ein Zusammenstoß der Spielfigur oft mit dem Bildschirm-tod verbunden. Kollisionsbefehle brauchen wir nicht dazu – ein Zusammenstoß erfolgtgenau dann, wenn die Koordinaten des Gegners und der Spielfigur übereinstimmen:

If (GegnerZ = SpielerZ) And (GegnerS = SpielerS) Then ...

Wir lassen dabei einen Klang ("soundfx16.wav") abspielen, drucken einen Totenkopf(aus "pickups.bmp") und halten das Spiel für drei Sekunden an – ausnahmsweise mitDelay.

Dann versetzen wir die Spielfigur und den Gegner an ihre Anfangsposition. Diese wer-den beim Laden des Levels von der Festplatte in den Variablen SpielerStartZ undSpielerStartS sowie GegnerStartZ und GegnerStartS gespeichert:

If (GegnerZ = SpielerZ) And (GegnerS = SpielerS) Then PlaySound todsound Delay 2000 Leben = Leben - 1 If Leben = 0 Then Leben = 5 ; normalerweise: Spielende Level$(GegnerZ, GegnerS) = " " GegnerZ = GegnerStartZ GegnerS = GegnerStartS Level$(GegnerZ, GegnerS) = "G" SpielerZ = SpielerStartZ SpielerS = SpielerStartS Level$(SpielerZ, SpielerS) = "S"EndIf

Was passieren soll, wenn alle Leben verbraucht sind, wurde nicht programmiert (sinktdie Zahl der Leben auf 0, wird sie wieder auf 5 erhöht). Normalerweise würde ein Bild-schirm »Spielende« erscheinen. Damit wir sehen, wie weit wir davon entfernt sind,

Auf vielfältige Weise erhöhen Sie die Herausforderung für den Spieler:

1. Sie vergrößern die Anzahl der Gegner.

2. Sie erhöhen die Geschwindigkeit der Gegner.

3. Sie machen die Gegner schlauer, indem Sie sie eher in die Richtung der Spielfigurschicken.

Bei anderen Spiel-Genres gibt es eine vierte Möglichkeit: Sie erhöhen die Lebensen-ergie der Gegner – oder Sie verringern die der Spielfigur. Was am besten funktioniert,kann nur durch ausgiebiges Probieren ermittelt werden. Sie müssen die richtigeSpielbalance ermitteln, bei der es weder zu einfach und damit langweilig, noch zuschwer und damit unfair wird. Auf der sicheren Seite sind Sie, wenn Sie mehrereSchwierigkeitsstufen anbieten.

Page 279: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

279

Gerüst für Pac-Man & Co. j e t z t l e r n e i c h

zeichnen wir in die linke obere Ecke des Bildschirms so viele Herzen (wieder aus "pick-ups.bmp"), wie wir Leben haben:

For I=0 To Leben-1 DrawImage lebensstern, I*25,0Next

Abb. 20.6:Die Anzahl der Gegner sollte mit der Größe und Komplexi-tät des Levels abgestimmt werden.

Das ganze Programm:

; PAC3.BBGraphics 640,480SetBuffer BackBuffer()timer = CreateTimer(15)tiles = LoadImage("blocks1.bmp")tiles2 = LoadImage("pickups.bmp")figuren = LoadImage("invader2.bmp")todsound = LoadSound("soundfx16.wav")

; Level von Festplatte lesen

Dim Level$(15,20)leveldatei = ReadFile("pac2.dat")For Zeile=0 To 14 A$ = ReadLine(leveldatei) For Spalte=0 To 19 Level$(Zeile,Spalte) = Mid$(A$,Spalte+1,1)

If Level$(Zeile,Spalte) = "S" Then SpielerStartS = Spalte SpielerStartZ = Zeile EndIf

Page 280: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

280

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

If Level$(Zeile,Spalte) = "G" Then GegnerStartS = Spalte GegnerStartZ = Zeile EndIf

NextNextCloseFile leveldateileben = 5

Repeat

; Level zeichnen

For Zeile=0 To 14 For Spalte=0 To 19 Select Level$(Zeile,Spalte) Case " " DrawImageRect tiles, Spalte*32, Zeile*32, 36, 36, 32, 32 Case "1" DrawImageRect tiles, Spalte*32, Zeile*32, 70, 274, 32, 32 Case "S" DrawImageRect tiles, Spalte*32, Zeile*32, 36, 36, 32, 32 DrawImageRect figuren, Spalte*32, Zeile*32, 481,142,32,26 SpielerS = Spalte SpielerZ = Zeile Case "G" DrawImageRect tiles, Spalte*32, Zeile*32, 36, 36, 32, 32 DrawImageRect figuren, Spalte*32, Zeile*32, 379,140,32,28 GegnerS = Spalte GegnerZ = Zeile End Select Next Next

; Lebensherzen zeichnen

For I=0 To Leben-1 DrawImageRect tiles2, I*25,0, 178,19, 22,20 Next

; Zusammenstoß prüfen

If (GegnerZ = SpielerZ) And (GegnerS = SpielerS) Then DrawImageRect tiles2, SpielerS*32, SpielerZ*32, 428,231, 50,40 Flip PlaySound todsound Delay 3000 Leben = Leben - 1 If Leben = 0 Then Leben = 5 ; normalerweise: Spielende Level$(GegnerZ, GegnerS) = " " GegnerZ = GegnerStartZ GegnerS = GegnerStartS Level$(GegnerZ, GegnerS) = "G" SpielerZ = SpielerStartZ SpielerS = SpielerStartS Level$(SpielerZ, SpielerS) = "S" EndIf

Page 281: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

281

Gerüst für Pac-Man & Co. j e t z t l e r n e i c h

; Spielfigur bewegen

If KeyDown(203) And ( Level$(SpielerZ,SpielerS-1) <> "1" ) Then Level$(SpielerZ, SpielerS) = " " SpielerS = SpielerS - 1 Level$(SpielerZ, SpielerS) = "S" EndIf

If KeyDown(205) And ( Level$(SpielerZ,SpielerS+1) <> "1" ) Then Level$(SpielerZ, SpielerS) = " " SpielerS = SpielerS + 1 Level$(SpielerZ, SpielerS) = "S" EndIf

If KeyDown(200) And ( Level$(SpielerZ-1,SpielerS) <> "1" ) Then Level$(SpielerZ, SpielerS) = " " SpielerZ = SpielerZ - 1 Level$(SpielerZ, SpielerS) = "S" EndIf

If KeyDown(208) And ( Level$(SpielerZ+1,SpielerS) <> "1" ) Then Level$(SpielerZ, SpielerS) = " " SpielerZ = SpielerZ + 1 Level$(SpielerZ, SpielerS) = "S" EndIf

; Gegner bewegen

Wahl = 0 If Level$(GegnerZ, GegnerS-1) = " " Then Wahl = Wahl +1 If Level$(GegnerZ, GegnerS+1) = " " Then Wahl = Wahl +1 If Level$(GegnerZ-1, GegnerS) = " " Then Wahl = Wahl +1 If Level$(GegnerZ+1, GegnerS) = " " Then Wahl = Wahl +1 If ( Wahl > 2 ) Or ( Richtung = 0 ) Then Richtung = Rand(4)

Select Richtung Case 1 ; Links If Level$(GegnerZ,GegnerS-1) <> "1" Then Level$(GegnerZ,GegnerS) = " " GegnerS = GegnerS - 1 Level$(GegnerZ,GegnerS) = "G" Else Richtung = 0 EndIf Case 2 ; Rechts If Level$(GegnerZ,GegnerS+1) <> "1" Then Level$(GegnerZ,GegnerS) = " " GegnerS = GegnerS + 1 Level$(GegnerZ,GegnerS) = "G" Else Richtung = 0 EndIf Case 3 ; Hoch If Level$(GegnerZ-1,GegnerS) <> "1" Then Level$(GegnerZ,GegnerS) = " " GegnerZ = GegnerZ - 1 Level$(GegnerZ,GegnerS) = "G" Else Richtung = 0 EndIf

Page 282: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

282

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Case 4 ; Runter If Level$(GegnerZ+1,GegnerS) <> "1" Then Level$(GegnerZ,GegnerS) = " " GegnerZ = GegnerZ + 1 Level$(GegnerZ,GegnerS) = "G" Else Richtung = 0 EndIf End Select

WaitTimer timer FlipUntil KeyHit(1)

20.4.7 AusblickeDiese Grundlagen lassen sich zu einem »richtigen« Spiel mit mehreren Gegnern, mitObjekten zum Einsammeln, vielen Levels und einem vernünftigen Spielziel ausbauen.Eine nette Idee wäre, die Spielfigur in jedem Level an einen Eingang zu versetzen. Ein-zige Aufgabe: Den Ausgangspunkt erreichen – aber der Weg dorthin wird erschwertdurch Gegner und Fallen.

20.5 Gerüst für Sokoban

Leicht passen wir das vorige Beispiel so an, dass ein Tüftelspiel daraus wird. Bei demKlassiker »Sokoban« müssen Kisten an Zielorte geschoben werden. Das Tückische da-bei ist der geringe Platz, der geschickte Manöver erfordert.

Abb. 20.7:Das Original-

spiel von 1984wurde bisheretliche Male

»geklont«.

Page 283: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

283

Gerüst für Sokoban j e t z t l e r n e i c h

Das Programm PAC1.BB dient uns als Vorlage: Es lädt einen Level von der Festplatteund bewegt eine Spielfigur. Sie benötigt (als SOKOBAN1.BB) zunächst nur zwei Än-derungen: Neben einer Mauer ("M") und einer Spielfigur ("S") zeichnen wir Kisten ("K")und Zielorte ("Z"). Den Level speichern wir in der Datei SOKOBAN.DAT. Er stammtübrigens aus dem klassischen Sokoban-Spiel aus den frühen achtziger Jahren.

Die Bewegungssteuerung ist allerdings umfangreicher. Wir müssen uns merken, aufwelchem Untergrund sich Figuren und Kisten befinden. Denn neben den normalengrauen Gängen können sich die Objekte auch an den Zielorten aufhalten. Diese müs-sen – zumindest bei der Spielfigur – durchschimmern und beim Verlassen wieder voll-ständig gezeichnet werden. Im Feld Level$() können wir uns nicht merken, auf wel-chem Boden ein Objekt steht, da der Feldinhalt mit dem Objekt selbst beschriebenwird. Daher verwenden wir ein zweites Feld LevelBackup$(), dem wir entnehmen, obein Quadrat normalen Fußboden enthält oder ob es sich um ein Zielfeld handelt.

(Es gibt zu dieser Vorgehensweise zwei Alternativen: Wir hätten dem Feld eine weitereDimension zufügen können. Wir könnten auch jeder Kombination aus Objekt und Fuß-boden ein Zeichen zuordnen. Das ist freilich nur dann möglich, wenn es – wie hier –nur wenige Anordnungsmöglichkeiten gibt. )

Das Kistenschieben ist nicht sehr kompliziert. Wir müssen nur testen, ob das Feld leerist, auf das eine Kiste geschoben werden soll. Ist es leer, bewegen wir zunächst die Kisteund danach die Spielfigur auf das Nachbarfeld.

Da eine Kiste die Farbe des Zielfeldes vollständig überdeckt, haben die Kisten eine an-dere Farbe, wenn sie sich auf einem Zielfeld befinden.

Zu guter Letzt wird jede Bewegung mit einem Klang bestätigt.

20.5.1 AuswertungWoher weiß der Computer, wann der Level gelöst ist? Wenn alle Kisten auf den Ziel-feldern sind. Beim Laden des Levels zählen wir die Zielfelder:

If Level$(Zeile,Spalte) = "Z" Then ZielFelder = ZielFelder + 1

Bei jedem Zug zählen wir, wie viele Kisten auf Zielfeldern stehen. Das ist besonders ein-fach, da die Zielfelder sowieso eine andere Farbe haben und gesondert gezeichnet wer-den. Diesem If-Strang fügen wir einfach eine Zeile hinzu:

ImZiel = ImZiel + 1

Am Schluss vergleichen wir die Werte miteinander:

If ImZiel = ZieldFeld Then End ; hier Siegauswertung

Hier sollte nun ein Lob für den Sieg und der Sprung in den nächsten Level erfolgen;wir belassen es mit einem schnöden End.

Dieses Zählen ermöglicht es uns, jederzeit über den Fortschritt zu informieren. Ebensoleicht zählen wir die Anzahl der Schritte und Kistenbewegungen. In einem »richtigen«Spiel müsste das freilich aufgepeppt werden.

Page 284: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

284

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Abb. 20.8:Ebenso wie

»Pac-Man«, lässtsich ein Tüftel-

spiel wie »Soko-ban« relativschnell um-

setzen.

; SOKOBAN.BBGraphics 640,480SetBuffer BackBuffer()timer = CreateTimer(10)tiles = LoadImage("blocks1.bmp")figuren = LoadImage("invader2.bmp")sound1 = LoadSound("soundfx20.wav")sound2 = LoadSound("soundfx11.wav")

; Level von Festplatte lesen

Dim Level$(15,20)Dim LevelBackup$(15,20)

leveldatei = ReadFile("sokoban.dat")For Zeile= 0 To 14 A$ = ReadLine(leveldatei) For Spalte=0 To 19 B$ = Mid$(A$,Spalte+1,1) Level$(Zeile,Spalte) = B$ LevelBackup$(Zeile, Spalte) = Level$(Zeile,Spalte) If LevelBackup$(Zeile, Spalte) = "S" Then LevelBackUp$(Zeile, Spalte) = " " If LevelBackup$(Zeile, Spalte) = "K" Then LevelBackUp$(Zeile, Spalte) = " " If Level$(Zeile,Spalte) = "Z" Then ZielFelder = ZielFelder + 1 NextNextCloseFile leveldatei

Repeat

Page 285: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

285

Gerüst für Sokoban j e t z t l e r n e i c h

; Level zeichnen

ImZiel = 0 For Zeile=0 To 14 For Spalte=0 To 19 Select Level$(Zeile,Spalte) Case "M" ; Mauer DrawImageRect tiles, Spalte*32, Zeile*32, 172, 342, 32, 32 Case " " ; frei DrawImageRect tiles, Spalte*32, Zeile*32, 104, 274, 32, 32 Case "K" ; Kiste If LevelBackup$(Zeile, Spalte) = "Z" Then ImZiel = ImZiel + 1 DrawImageRect tiles, Spalte*32, Zeile*32, 2, 342, 32, 32 Else DrawImageRect tiles, Spalte*32, Zeile*32, 444, 308, 32, 32 EndIf Case "Z" ; Zielfeld DrawImageRect tiles, Spalte*32, Zeile*32, 444, 172, 32, 32 Case "S" ; Spielfigur If LevelBackup$(Zeile,Spalte) = "Z" Then DrawImageRect tiles, Spalte*32, Zeile*32, 444, 172, 32, 32 Else DrawImageRect tiles, Spalte*32, Zeile*32, 104, 274, 32, 32 EndIf DrawImageRect figuren, Spalte*32, Zeile*32, 481,142,32,26 SpielerS = Spalte SpielerZ = Zeile End Select Next Next Text 0,0, "Im Ziel: " + ImZiel + " von " + ZielFelder Text 0,25, "Schritte: " + Schritte Text 0,50, "Züge: " + Zuege

Flip

If ImZiel = ZielFelder Then End ; hier Siegauswertung

; Spielerbewegung

If KeyDown(203) And Level$(SpielerZ,SpielerS-1) <> "M" Then ; Links Ziel$ = Level$(SpielerZ,SpielerS-1) If ( Ziel$ = " " ) Or ( Ziel$ = "Z" ) Then Level$(SpielerZ, SpielerS) = LevelBackup$(SpielerZ, SpielerS) SpielerS = SpielerS - 1 Level$(SpielerZ, SpielerS) = "S" Schritte = Schritte + 1 PlaySound sound1 ElseIf ( Ziel$ = "K" ) And ( ( Level$(SpielerZ,SpielerS-2) = " " ) Or ( Level$(SpielerZ,SpielerS-2) = "Z" ) ) Then Level$(SpielerZ, SpielerS-2) = "K" Level$(SpielerZ, SpielerS) = LevelBackup$(SpielerZ, SpielerS) SpielerS = SpielerS - 1 Level$(SpielerZ, SpielerS) = "S" Zuege = Zuege + 1 PlaySound sound2 EndIf EndIf

Page 286: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

286

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

If KeyDown(205) And Level$(SpielerZ,SpielerS+1) <> "M" Then ; Rechts Ziel$ = Level$(SpielerZ,SpielerS+1) If ( Ziel$ = " " ) Or ( Ziel$ = "Z" ) Then Level$(SpielerZ, SpielerS) = LevelBackup$(SpielerZ, SpielerS) SpielerS = SpielerS + 1 Level$(SpielerZ, SpielerS) = "S" Schritte = Schritte + 1 PlaySound sound1 ElseIf ( Ziel$ = "K" ) And ( ( Level$(SpielerZ,SpielerS+2) = " " ) Or ( Level$(SpielerZ,SpielerS+2) = "Z" ) ) Then Level$(SpielerZ, SpielerS+2) = "K" Level$(SpielerZ, SpielerS) = LevelBackup$(SpielerZ, SpielerS) SpielerS = SpielerS + 1 Level$(SpielerZ, SpielerS) = "S" Zuege = Zuege + 1 PlaySound sound2 EndIf EndIf

If KeyDown(200) And Level$(SpielerZ-1,SpielerS) <> "M" Then ; Hoch Ziel$ = Level$(SpielerZ-1,SpielerS) If ( Ziel$ = " " ) Or ( Ziel$ = "Z" ) Then Level$(SpielerZ, SpielerS) = LevelBackup$(SpielerZ, SpielerS) SpielerZ = SpielerZ - 1 Level$(SpielerZ, SpielerS) = "S" Schritte = Schritte + 1 PlaySound sound1 ElseIf ( Ziel$ = "K" ) And ( ( Level$(SpielerZ-2,SpielerS) = " " ) Or ( Level$(SpielerZ-2,SpielerS) = "Z" ) ) Then Level$(SpielerZ-2, SpielerS) = "K" Level$(SpielerZ, SpielerS) = LevelBackup$(SpielerZ, SpielerS) SpielerZ = SpielerZ - 1 Level$(SpielerZ, SpielerS) = "S" Zuege = Zuege + 1 PlaySound sound2 EndIf EndIf

If KeyDown(208) And Level$(SpielerZ+1,SpielerS) <> "M" Then ; Runter Ziel$ = Level$(SpielerZ+1,SpielerS) If ( Ziel$ = " " ) Or ( Ziel$ = "Z" ) Then Level$(SpielerZ, SpielerS) = LevelBackup$(SpielerZ, SpielerS) SpielerZ = SpielerZ + 1 Level$(SpielerZ, SpielerS) = "S" Schritte = Schritte + 1 PlaySound sound1 ElseIf ( Ziel$ = "K" ) And ( ( Level$(SpielerZ+2,SpielerS) = " " ) Or ( Level$(SpielerZ+2,SpielerS) = "Z" ) ) Then Level$(SpielerZ+2, SpielerS) = "K" Level$(SpielerZ, SpielerS) = LevelBackup$(SpielerZ, SpielerS) SpielerZ = SpielerZ + 1 Level$(SpielerZ, SpielerS) = "S" Zuege = Zuege + 1 PlaySound sound2 EndIf EndIf

WaitTimer(timer)Until KeyHit(1)

Page 287: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

287

Gerüst für ein Verschiebe-Puzzle j e t z t l e r n e i c h

20.5.2 AusblickeDas Programm ist einfach und übersichtlich gehalten. Das geht zu Lasten des Kom-forts. Man kann keine Züge zurücknehmen und es gibt keine Siegauswertung. Wahl-weise könnte man, wie im Originalspiel, eine Zeitbegrenzung einbauen. Ja – und mehrals einen Level gibt es auch nicht. Die Idee lässt sich leicht in allerlei Richtungen aus-bauen, durch Fallen, Monster, Felder, die nur von einer Seite aus betreten werden kön-nen ...

20.6 Gerüst für ein Verschiebe-Puzzle

Schenken wir uns noch ein Puzzle, das dieses Mal mit der Maus bedient wird. Auf ei-nem fünf mal fünf Felder großen Spielfeld werden 24 nummerierte Steine zufällig an-geordnet. Sie müssen sortiert werden. Dabei kann immer nur ein Stein bewegt werden– auf die jeweils leere Stelle.

Für das Spielfeld eignet sich ein Dim-Feld bestens: Dim Feld(5,5). Darauf verteilen wirdie Spielsteine, genauer die Zahlen 1 bis 24. Und die 0 für das Leerfeld. Zwei Dingemüssen wir beachten:

Auf jedes Feld darf nur eine Nummer gelegt werden.

Jede Nummer ist nur einmal vorhanden.

Punkt 1 lässt sich einfach berücksichtigen: Wir grasen mit einer doppelten For-Schleifedas Spielfeld Zeile für Zeile ab und legen jeweils einen Stein drauf.

Punkt 2 ist eine Spur schwieriger. Wenn wir auf jedes Feld eine zufällig ermittelte Zahllegen, müssen wir sicherstellen, dass wir keine Zahlen doppelt verteilen. Wir schauenvor dem Auslegen, ob die aktuelle Zahl bereits vergeben wurde. Dazu könnten wir allebisherigen Felder abfragen, doch mir gefällt eine andere Vorgehensweise besser. Wirerstellen ein zweites Feld, das nur dazu dient, sich zu merken, ob eine Zahl bereits ver-geben wurde oder nicht.

Präsentiert uns der Computer für das aktuelle Feld etwa die Zufallszahl 4, so schauenwir uns den Inhalt von Mischen(4) an. Steht dort eine 0, wurde die Zahl noch nicht ver-geben. Wir setzen den Inhalt von Mischen(4) auf 1 und die 4 auf das Feld. Steht dorteine 1, so wurde die Zahl bereits vergeben und wir müssen uns eine neue Zahl ausden-ken. Diese Lösung lässt sich mit wenigen Zeilen umsetzen, auch wenn der Computervon Feld zu Feld immer mehr zu tun hat. Denn wenn der Computer das letzte der 25Felder erreicht hat, bleibt nur eine Zahl übrig, die er legen kann. Damit eine Zufallszahlgenau dieser Zahl entspricht, braucht er viele Versuche. Das soll uns aber nicht stören– das Auslegen der 24 Steine schafft er trotzdem in weniger als einer Sekunde:

; PUZZLE1.BBDim Feld(5,5)Dim Mischen(24)

; Spielsteine verteilenSeedRnd MilliSecs()For I=1 To 5 For J=1 To 5 Repeat A = Rand(0,24) Until Mischen(A) = 0

Page 288: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

288

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

; Mischen(A) = 1 Feld(I,J) = A NextNext

Schauen wir uns probehalber an, wie er sie belegt hat:

For I=1 To 5 For J=1 To 5 A = Feld(I,J) B$ = A If A < 10 Then B$ = "0" + B$ Write B$ + " " If J=5 Then Print NextNextWaitKey

Damit es netter aussieht, erhielten einstellige Zahlen eine führende 0. Das ergibt eineAusgabe wie:

08 18 07 10 1417 02 00 15 0305 16 24 13 0904 21 19 12 1123 22 20 01 06

20.6.1 Spielsteine druckenNatürlich wollen wir dem Spieler keine Zahlenwüste zumuten, sondern unsere Spiel-felder angemessen präsentieren. In der Grafikdatei BLOCKS1.BMP finden wir jedeMenge Quadrate, die sich zum Darstellen unserer Spielsteine eignen. Doch selbst inder Auflösung 640x480 nehmen die 25 Quadrate (in einer Größe von je 32x32 Punk-ten) nur einen Bruchteil der Oberfläche ein. Also verdoppeln wir trickreich ihre Größe,indem wir die Teilgrafik auslösen, in ein neues Bild (stein) kopieren und die Größe ver-doppeln.

stein = CreateImage(32,32)SetBuffer ImageBuffer(stein)DrawImageRect tiles, 0, 0, 444, 308, 32, 32ScaleImage stein, 2, 2SetBuffer FrontBuffer()

Das Ergebnis ist ein 64x64 Punkte großes Quadrat in der Farbe Beige. Schauen wiruns an, wie die 25 Felder auf dem Bildschirm aussehen:

For I=1 To 5 For J=1 To 5 DrawImage stein, 96 + I*64, 20 + J*64 Next Next

Wenn wir berücksichtigen, dass es ja ein leeres Feld gibt, das wir im Dim-Feld mit 0 ge-kennzeichnet haben, drucken wir nur 24 Spielsteine aus:

Page 289: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

289

Gerüst für ein Verschiebe-Puzzle j e t z t l e r n e i c h

For I=1 To 5 For J=1 To 5 If Feld(I,J) <> 0 Then DrawImage stein, 96 + I*64, 20 + J*64 NextNext

Fassen wir die drei Schritte in einem Listing zusammen:

� Wir erstellen eine 64x64 große Steingrafik.

� Wir erzeugen ein Dim-Feld und legen die Nummernsteine aus.

� Wir drucken die 24 Spielsteine probehalber auf dem Bildschirm aus.

Zusätzlich wählen wir einen netten Hintergrund und stellen auf Doppelpufferung undFlip um:

; PUZZLE2.BBGraphics 640,480

Dim Feld(5,5)Dim Mischen(24)

hinter = LoadImage ("space.jpg")tiles = LoadImage ("blocks1.bmp")

; Spielstein erzeugenstein = CreateImage(32,32)SetBuffer ImageBuffer(stein)DrawImageRect tiles, 0, 0, 444, 308, 32, 32ScaleImage stein, 2, 2SetBuffer BackBuffer()

; Spielsteine verteilenSeedRnd MilliSecs()For I=1 To 5 For J=1 To 5 Repeat A = Rand(0,24) Until Mischen(A) = 0 ; Mischen(A) = 1 Feld(I,J) = A NextNext

; Spielfeld zeichnenRepeat TileImage hinter ; For I=1 To 5 For J=1 To 5 If Feld(I,J) <> 0 Then DrawImage stein, 96 + I*64, 20 + J*64 Next Next FlipUntil KeyHit(1)

Page 290: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

290

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Abb. 20.9:Für das Verwal-

ten von Spiel-steinen eignen

sich Dim-Felderbestens.

Die Spielsteine brauchen eine Beschriftung. Für ein hochwertiges Ergebnis müsstenwir 24 einzelne Steine erzeugen und mit einer besonderen Beschriftung versehen. Inunserem Beispiel machen wir es uns einfacher. Wir laden eine Schriftart ...

font = LoadFont("Times New Roman", 40, 1, 0, 0)SetFont font

... und drucken die Zahl in Echtzeit auf jeden Stein:

Text 96 + 17 + I*64, 20 + 12 + J*64, Feld(I,J)

Dabei beachten wir, dass die Zahl 0 nicht gedruckt wird und dass einstellige Zahlen et-was weiter rechts positioniert werden, damit sie trotzdem in der Mitte des Spielsteinsliegen:

; PUZZLE3.BBIf Feld(I,J) <> 0 Then DrawImage stein, 96 + I*64, 20 + J*64If Feld(I,J) > 9 Then Text 96 + 17 + I*64, 20 + 12 + J*64, Feld(I,J)If (Feld(I,J) < 10) And (Feld(I,J) > 0) Then Text 96 + 25 + I*64, 20 + 12 + J*64, Feld(I,J)

20.6.2 Mauszeiger einzeichnenUnser Spiel wird mit der Maus bedient: Man setzt den Mauszeiger auf ein Spielfeld undklickt, um es zu verschieben. Die Mausbewegung lässt sich einfach einbauen. Wir ladeneine Mauszeigergrafik ...

maus = LoadImage("pointer.bmp")

Page 291: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

291

Gerüst für ein Verschiebe-Puzzle j e t z t l e r n e i c h

... und zeichnen den Mauszeiger innerhalb der Spielschleife:

X = MouseX()Y = MouseY()DrawImage maus, X, Y

20.6.3 Mausposition auswertenKlickt der Spieler auf die Maustaste, so möchte er das darunter liegende Feld verschie-ben. Das bedeutet drei Teilaufgaben für uns:

� Ermitteln, auf welchem Feld der Mauszeiger liegt, wenn ein Mausklick erfolgt

� Prüfen, ob der Stein verschoben werden kann (da das Leerfeld daneben liegt)

� Verschieben des Steins

Die Kollisionsbefehle sind für Punkt 1 weniger geeignet, da die Grafik des Mauszeigersgleichzeitig mehrere Steine berühren kann. Wir ermitteln daher nur, auf welchen Steindie Spitze des Mauszeigers zeigt. Dafür gibt es verschiedene Lösungen.

Das Spielfeld ist 5x5 Steine groß. Es wird in einem 5x5 großen Dim-Feld abgelegt. Mit-hilfe einer einfachen Formel haben wir von jedem Feld den Startpunkt auf dem Bild-schirm festgelegt. Auf umgekehrtem Weg schließen wir von der Position der Maus aufden Spielstein. Diese Methode ist allerdings aufwendiger: Zum Zeichnen benötigen wirnur die Startkoordinaten, also die linke obere Ecke jedes Spielsteins. Dahin wird derSpieler seinen Mauszeiger freilich nicht setzen; er wird ihn irgendwo innerhalb desSteins positionieren. Daher müssen wir nicht nur testen, ob die Maus mindestens dielinke obere Ecke eines Steins erreicht hat, sondern ob sie die rechte untere Ecke nichtüberschreitet. Das lässt sich auf diese Weise umsetzen:

For I=1 To 5 If X > 95 + I*64 Then X1 = X1+1Next

For J=1 To 5 If Y > 20 + J*64 Then Y1 = Y1+1Next

Als Ergebnis enthalten X1 und Y1 die Position des Steins im Dim-Feld. Oder anders:Feld(X1,Y1) ist der Stein, auf den die Mausspitze zeigt.

Beziehungsweise noch nicht ganz: Wenn die Maus nach rechts oder unten aus demSpielfeld hinausgeht, behalten X1 oder Y1 den Wert 5. Wir müssen die Koordinaten alsolöschen, wenn das Spielfeld überschritten wird. Für links und oben haben wir das be-reits automatisch gelöst, da wir nicht vor der ersten Reihe und Spalte zu zählen begin-nen. Wir könnten den Mauszeiger auf das Spielfeld begrenzen, wollen uns aber das An-klicken anderer Bildschirmbereiche (etwa ein »Ende«-Schalter) offen halten. Das lässtsich wie folgt lösen:

For I=1 To 6 If X > 95 + I*64 Then X1 = X1+1Next

For J=1 To 6 If Y > 20 + J*64 Then Y1 = Y1+1Next

Page 292: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

292

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

If X1 = 6 Then X1=0If Y1 = 6 Then Y1=0If X1 = 0 Then Y1=0If Y1 = 0 Then X1=0

Wir tun so, als ob das Spielfeld 6x6 Felder groß wäre. Wenn der Mauszeiger jedoch diesechste Zeile oder Spalte erreicht hat, werden beide Koordinaten auf 0 gesetzt.

Nicht nur außerhalb des Spielfelds ist ein Klicken »verboten«, auch das Klicken in dasLeerfeld macht keinen Sinn. Wenn wir bereits an dieser Stelle die Koordinaten desLeerfelds für ungültig erklären, also auf 0,0 setzen, erleichtern wir uns spätere Abfra-gen:

If Feld(X1,Y1) = 0 Then X1=0 : Y1 = 0

Vor den beiden For-Schleifen löschen wir natürlich den Inhalt der beiden Variablen:

X1 = 0Y1 = 0

Der geneigte Leser hat sicherlich festgestellt, dass wir uns noch gar nicht um denMausklick gekümmert haben. Beim Entwickeln größerer Programme wird man logi-sche Fehler nicht verhindern können. Doch man kann so programmieren, dass mansie rasch entdeckt, indem man schrittweise vorangeht und Teillösungen sofort über-prüft. So bietet sich an dieser Stelle ein Test an, ob unsere Überlegungen richtig sind.Wir geben die Werte für X1 und Y1 auf den Bildschirm aus und schauen, ob das Pro-gramm tatsächlich die richtigen Spielfelder erkennt:

Text 50,50, X1 + ":" + Y1

Fassen wir den bisherigen Mausabschnitt zusammen:

; PUZZLE4.BBX1 = 0Y1 = 0X = MouseX()Y = MouseY()

For I=1 To 6 If X > 95 + I*64 Then X1 = X1+1Next

For J=1 To 6 If Y > 20 + J*64 Then Y1 = Y1+1Next

If X1 = 6 Then X1=0If Y1 = 6 Then Y1=0If X1 = 0 Then Y1=0If Y1 = 0 Then X1=0

If Feld(X1,Y1) = 0 Then X1=0 : Y1 = 0

Text 50,50, X1 + ":" + Y1DrawImage maus, X, Y

Damit haben wir Teilaufgabe 2 gelöst.

Page 293: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

293

Gerüst für ein Verschiebe-Puzzle j e t z t l e r n e i c h

20.6.4 Aktives Feld hervorhebenEigentlich müssten wir die Mausposition nur dann genau auswerten, wenn der Spielereinen Mausklick betätigt. Aber weil wir uns so viel Mühe gegeben haben, wollen wir dieProgrammzeilen besser nutzen: Wie wäre es, wenn das aktive Feld eine andere Farbehätte? Das setzen wir fix um. Zunächst laden wir eine weitere Teilgrafik, einen Spiel-stein in einer anderen Farbe. Wir vergrößern ihn genauso wie den ersten:

; PUZZLE5.BB; aktiven Spielstein erzeugenaktivstein = CreateImage(32,32)SetBuffer ImageBuffer(aktivstein)DrawImageRect tiles, 0, 0, 2, 342, 32, 32ScaleImage aktivstein, 2, 2

Nun zeichnen wir den Spielstein X1,Y1 noch einmal – in einer anderen Farbe:

If (I = X1) And (J = Y1) Then DrawImage aktivstein, 96 + I*64, 20 + J*64

Fertig: Der von der Mausspitze berührte Stein ist hellblau, nicht beige.

20.6.5 Stein verschiebenKommen wir zum Herzstück unseres kleinen Spiels: Drückt man die Maustaste, soll deraktive Stein auf das freie Nachbarfeld geschoben werden. Dazu müssen wir das Nach-barfeld ermitteln. Das aktuelle Feld hat die Position X1,Y1. Es hat maximal vier Nach-barfelder. Wir prüfen jedes Nachbarfeld, wobei wir darauf achten, die Grenzen des Dim-Felds nicht zu überschreiten:

If X1 > 1 Then If Feld(X1-1, Y1) = 0 Then X2 = X1-1 : Y2 = Y1If X1 < 5 Then If Feld(X1+1, Y1) = 0 Then X2 = X1+1 : Y2 = Y1If Y1 > 1 Then If Feld(X1, Y1-1) = 0 Then Y2 = Y1-1 : X2 = X1If Y1 < 5 Then If Feld(X1, Y1+1) = 0 Then Y2 = Y1+1 : X2 = X1

Nun kennen wir mit X1,Y2 die Position des leeren Nachbarfelds. Ist eine der beiden Va-riablen 0, so wurde kein Nachbarfeld gefunden. Der Klick ist damit ungültig, weil er aufeinem Stein erfolgte, der nicht verschoben werden kann.

Diese Abfragen finden nur statt, wenn die linke Maustaste gedrückt wird und sich derMauszeiger über einem gültigen Stein befindet (also Feld(X1, Y1 <> 0):

If MouseDown(1) And Feld(X1, Y1) <> 0 Then

Vor den vier If-Abfragen müssen wir X2 und Y2 wieder löschen, um die Werte des vor-herigen Klicks zu entfernen. Auch in diesem Fall würde es sich anbieten, die ermitteltePosition des Nachbarfelds auszudrucken, um sicherzustellen, dass das Programm rich-tig arbeitet:

Text 50,100, X2 + ":" + Y2

Kommen wir zum letzten Schritt, dem tatsächlichen Verschieben des Steins. Dafürmüssen wir lediglich die Nummer des aktiven Steins auf die Leerstelle setzen und dasaktive Feld löschen:

If X2 <> 0 Then Feld(X2, Y2) = Feld(X1, Y1) Feld(X1, Y1) = 0EndIf

Nun haben wir ein lauffähiges Spiel.

Page 294: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

294

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Abb. 20.10:Die Beschrif-

tung wird aufjeden Stein

einzeln geklebt.Hier bieten sich

ebenfallsBitmap-Fontsund verschie-

denfarbigeSteine an.

20.6.6 AuswertungAllerdings fehlt eine Auswertung. Das heißt, das Spiel erkennt nicht, ob das Puzzle ge-löst wurde, ob alle Zahlen hintereinander angeordnet wurden. Um das zu testen, prü-fen wir nacheinander alle Einträge des Dim-Felds: Hat ein Eintrag den erwarteten Wert,so erhöhen wir die Zählervariable Fertig um 1:

; wie viele Steine sind am richtigen Platz?Fertig = 0For I=1 To 5 For J=0 To 4 If Feld(I, J+1) = I + (J * 5) Then Fertig = Fertig + 1 NextNext

Diesen Test setzen wir am besten in die If-Abfrage ein, die den Mausklick prüft.

Nun wissen wir: Wenn Fertig den Wert 24 enthält, sind alle Steine am richtigen Platz.In diesem Fall ist das Spiel gewonnen.

If Fertig = 24 Then End ; hier zur Auswertung

An dieser Stelle kommt es zu einem kleinen Problem: Um zu testen, ob die Auswertungwirklich funktioniert, müssen wir alle Steine anordnen, also das Puzzle lösen. Selbstsehr gute Spieler benötigen dafür einige Minuten. Es ist kaum zumutbar, dass wir jedesMal einige hundert Klicks opfern, um unser eigenes Programm zu testen. Wir müssenuns eine Erleichterung schaffen, so dass wir innerhalb weniger Sekunden ans Ziel, ansSpielende gelangen. Dazu bauen wir einen Cheatcode ein:

Page 295: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

295

Gerüst für ein Verschiebe-Puzzle j e t z t l e r n e i c h

; Cheatcode If KeyDown(87) And KeyDown(88) Then For I=1 To 5 For J=0 To 4 Feld(I, J+1) = I + (J * 5) Next Next Feld(4,5) = 0 Feld(5,5) = 24EndIf

Drücken wir gleichzeitig Ó und Ô, werden die Steine so angeordnet, dass ein Klickgenügt, um die Endposition zu erreichen. Wir füllen dazu die ersten 23 Felder mit denSteinen 1 bis 23, setzen auf Platz 24 die Leerstelle und auf Feld 25 den Stein 24. Die-ser Trick wird uns bei der Fertigstellung des Spiels sehr helfen. Später kann er deakti-viert werden. Es schadet jedoch nicht, die Zeilen dauerhaft im Programm zu belassen.

Das ganze Programm:

; PUZZLE6.BBGraphics 640,480Dim Feld(5,5)Dim Mischen(24)

hinter = LoadImage("space.jpg")tiles = LoadImage("blocks1.bmp")maus = LoadImage("pointer.bmp")

font = LoadFont("Times New Roman", 40, 1, 0, 0)SetFont font

; Spielstein erzeugen

stein = CreateImage(32,32)SetBuffer ImageBuffer(stein)DrawImageRect tiles, 0, 0, 444, 308, 32, 32ScaleImage stein, 2, 2

; aktiven Spielstein erzeugen

aktivstein = CreateImage(32,32)SetBuffer ImageBuffer(aktivstein)DrawImageRect tiles, 0, 0, 2, 342, 32, 32ScaleImage aktivstein, 2, 2

SetBuffer BackBuffer()

; Spielsteine verteilen

SeedRnd MilliSecs()For I=1 To 5 For J=1 To 5 Repeat A = Rand(0,24) Until Mischen(A) = 0 ; Mischen(A) = 1 Feld(I,J) = A NextNext

Page 296: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

296

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

; Spielfeld zeichnen

Repeat TileImage hinter ; For I=1 To 5 For J=1 To 5 If Feld(I,J) <> 0 Then DrawImage stein, 96 + I*64, 20 + J*64 If (I = X1) And (J = Y1) Then DrawImage aktivstein, 96 + I*64, 20 + J*64 If Feld(I,J) > 9 Then Text 96 + 17 + I*64, 20 + 12 + J*64, Feld(I,J) If (Feld(I,J) < 10) And (Feld(I,J) > 0) Then Text 96 + 25 + I*64, 20 + 12 + J*64, Feld(I,J) Next Next

; Mausposition auswerten

X1 = 0 Y1 = 0 X = MouseX() Y = MouseY()

For I=1 To 6 If X > 95 + I*64 Then X1 = X1+1 Next

For J=1 To 6 If Y > 20 + J*64 Then Y1 = Y1+1 Next

If X1 = 6 Then X1=0 If Y1 = 6 Then Y1=0 If X1 = 0 Then Y1=0 If Y1 = 0 Then X1=0

If Feld(X1,Y1) = 0 Then X1=0 : Y1 = 0 DrawImage maus, X, Y

; Mausklick auswerten

If MouseDown(1) And Feld(X1, Y1) <> 0 Then X2 = 0 Y2 = 0 If X1 > 1 Then If Feld(X1-1, Y1) = 0 Then X2 = X1-1 : Y2 = Y1 If X1 < 5 Then If Feld(X1+1, Y1) = 0 Then X2 = X1+1 : Y2 = Y1 If Y1 > 1 Then If Feld(X1, Y1-1) = 0 Then Y2 = Y1-1 : X2 = X1 If Y1 < 5 Then If Feld(X1, Y1+1) = 0 Then Y2 = Y1+1 : X2 = X1

; ... und Stein verschieben

If X2 <> 0 Then Feld(X2, Y2) = Feld(X1, Y1) Feld(X1, Y1) = 0

; wie viele Steine sind am richtigen Platz?

Fertig = 0 For I=1 To 5 For J=0 To 4

Page 297: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

297

Gerüst für ein Jump'n'Run-Spiel j e t z t l e r n e i c h

If Feld(I, J+1) = I + (J * 5) Then Fertig = Fertig + 1 Next Next If Fertig = 24 Then End ; hier zur Auswertung EndIf EndIf

; Cheatcode

If KeyDown(87) And KeyDown(88) Then For I=1 To 5 For J=0 To 4 Feld(I, J+1) = I + (J * 5) Next Next Feld(4,5) = 0 Feld(5,5) = 24 EndIf

FlipUntil KeyHit(1)

20.6.7 AusblickeDieses Schiebepuzzle lässt sich leicht ausbauen: unterschiedliche Feldgrößen, Zeitlimit,Zusammensetzen eines Bildes statt Zahlen. Relativ leicht ließe es sich dann zu einemMemory-Spiel umfunktionieren, bei dem jeweils zwei gleiche Bilder aufgedeckt werdenmüssen.

20.7 Gerüst für ein Jump'n'Run-Spiel

Ein Jump'n'Run-Spiel ist um einiges komplexer als die bisher beschriebenen Beispiele:

� Die Spielfigur bewegt sich nicht nur auf geraden Bahnen, sondern kann springen.

� Es bedarf mindestens zwei Grafikschichten, damit die Spielfigur an Objekten wieBlumen vorbeiläuft. Außerdem sollte es einen Hintergrund geben.

� Der Spiellevel besteht nicht nur aus einem Bildschirm, sondern scrollt.

� Auch der Hintergrund sollte scrollen – in einer langsameren Geschwindigkeit.

� Es gibt eine Vielzahl von Animationen, etwa Gegner, die hin- und herlaufen odersogar fliegen.

Das Ausarbeiten eines vollständigen Jump’n’Run-Spiels würde den Rahmen des Buchssprengen. Wir konzentrieren uns daher auf einen Hauptaspekt: das Darstellen einesJump’n’Run-Levels und das Scrollen der Karte.

20.7.1 Kachel-ScrollingEine sehr einfache Spielwelt ist kaum komplizierter darzustellen als beim »Pac-Man«-Spiel: einfarbiger Hintergrund, einfarbiger Boden, Kistenstapel in verschiedenen Hö-hen als Hindernisse. Wir machen es uns besonders einfach, indem wir den Bildschirmin Spalten unterteilen und uns nur für jede Spalte merken, wie hoch der Kistenstapel

Page 298: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

298

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

dort ist: 0 steht für eine Ebene, 1 für eine Kiste, 2 für zwei Kisten übereinander ... Aufdiese Weise sieht die Leveldatei JUMP.DAT sehr übersichtlich aus:

66000220040022332200 ...

Im Zentrum eines Jump’n’Run-Spiels steht das Scrolling: Man sieht immer nur einenkleinen Ausschnitt des Levels. Das Programmieren des Scrollings bereitet nicht vielAufwand. Wir speichern den Level fortwährend in einer Datei (und nach dem Laden ineinem Dim-Feld) ab. Um ein Fenster weiter rechts darzustellen, beginnen wir einfachnicht mit 0, sondern mit einem höheren Wert, den wir uns in der Variable Index mer-ken.

Grundsätzlich könnten wir im Speicher mit den gleichen Daten arbeiten, die in derDatei JUMP.DAT stehen. Da jedoch beim Laufen, Springen und Herunterfallen derSpielfigur eine Vielzahl von Kollisionsabfragen nötig sind, empfiehlt es sich, ähnlichwie bei »Pac-Man« einen 1:1-Abzug des Bildschirms nach Zeilen und Spalten zu erstel-len. Dabei legen wir, abhängig von der Kistenhöhe, unterschiedliche Farben fest. DerBoden besteht aus fünf Zeilen brauner Kacheln.

Bei den meisten Jump’n’Run-Spielen erfolgt das seitliche Scrolling, wenn die Spiel-figur das linke oder rechte Viertel des Bildschirms betritt. Sobald sie in diesem Bereichist, bewegt sich der Level gleichauf mit der Spielfigur. Das ist leicht umzusetzen: BeimAuswerten der Tasten { und } achten wir auf die Spaltenposition der Spielfigur. Istsie am Rand, bewegen wir den Level (indem wir Index verändern). Andernfalls verset-zen wir die Figur.

Dabei ist zu berücksichtigen, dass am Anfang und am Ende des Levels nicht gescrolltwird (sonst würde der Level aus dem Bild herauslaufen), sondern die Spielfigur ganz anden Rand laufen kann.

; JUMP1.BBGraphics 640,480SetBuffer BackBuffer()timer = CreateTimer(10)tiles = LoadImage("blocks1.bmp")figuren = LoadImage("invader2.bmp")

; Level von Festplatte lesen

Dim Level(14,69)leveldatei = ReadFile("jump.dat")For Spalte = 0 To 69 A = ReadByte(leveldatei) - 48 For Zeile = 0 To A Level(10 - Zeile, Spalte) = A NextNextEnde = 69

For Zeile = 10 To 14 For Spalte = 0 To 69 Level(Zeile,Spalte) = 99 ; Boden NextNext

ClsColor 127,127,255Index = 0SpielerZ = 9

Page 299: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

299

Gerüst für ein Jump'n'Run-Spiel j e t z t l e r n e i c h

SpielerS = 7

Repeat Cls

; Spielfigur bewegen

If KeyDown(205) Then ; Rechts If (Index = Ende - 19) And (SpielerS < 19) Then SpielerS = SpielerS + 1 EndIf

If SpielerS < 15 Then SpielerS = SpielerS + 1 Else Index = Index + 1 EndIf EndIf

If KeyDown(203) Then ; Links

If (Index = 0) And (SpielerS > 0) Then SpielerS = SpielerS - 1 EndIf

If SpielerS > 4 Then SpielerS = SpielerS - 1 Else Index = Index - 1 EndIf EndIf

If Index = -1 Then Index = 0 If Index = Ende - 18 Then Index = Ende - 19

; Level zeichnen

For Spalte = Index To Index + 19 For Zeile = 0 To 14 A = Level(Zeile,Spalte) Select A Case 99 DrawImageRect tiles, (Spalte-Index)*32, Zeile*32, 172, 342, 32, 32 Case 1 DrawImageRect tiles, (Spalte-Index)*32, Zeile*32, 2, 342, 32, 32 Case 2 DrawImageRect tiles, (Spalte-Index)*32, Zeile*32, 444, 308, 32, 32 Case 3,4,5,6 DrawImageRect tiles, (Spalte-Index)*32, Zeile*32, 444, 172, 32, 32 End Select Next Next

DrawImageRect figuren, SpielerS*32, SpielerZ*32, 481,142,32,26

WaitTimer timer FlipUntil KeyHit(1)

Page 300: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

300

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Abb. 20.11:Einfache

Umgebungenlassen sichbereits mit

Klötzenerzeugen.

20.7.2 SpringenNoch läuft unser Held durch die Kistenstapel hindurch. Eine Kollisionsabfrage machtaber nur Sinn, wenn wir ihn gleichzeitig lehren, wie er springen kann. Sonst würde seinAusflug ein jähes Ende nehmen. Sprunghöhe und Weite sind entscheidende Werte fürdas Design eines Jump’n’Run-Spiels und müssen auf den Aufbau des Levels abge-stimmt sein.

Damit der Sprung möglichst echt aussieht, sollte er in mehreren Phasen ablaufen. Wirlegen dazu in einem Dim-Feld fest, wie viele Bildpunkte sich die Figur jeweils nach obenund dann wieder nach unten bewegt. Im folgenden Beispiel kann sich die Figur nachlinks und rechts bewegen. Ein Druck auf die Leertaste lässt sie in die Höhe springen.Beim Programmieren müssen wir darauf achten,

� dass während eines Sprungs nicht weitere Sprünge möglich sind (es sei denn, sol-che Supersprünge sind beabsichtigt),

� dass Sprünge nach oben und die Bewegung nach links oder rechts gleichzeitigmöglich sein müssen, um Objekte zu überwinden.

Es empfiehlt sich, das Springen in einem separaten Programm zu testen: Die Spielfigurwird auf einer Ebene mit { und } gesteuert; die Leertaste sorgt für Sprünge.

; SPRUNG.BBGraphics 640,480SetBuffer BackBuffer()figur = LoadImage("player.bmp")X = 100Y = 305

Page 301: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

301

Gerüst für ein Jump'n'Run-Spiel j e t z t l e r n e i c h

Dim Sprungweite(18)For I=2 To 18 Read Sprungweite(I)NextData -20,-10,-10,-10,-10,-10,-10,0,0,10,10,10,10,10,10,20,0

Repeat ClsColor 0,0,255 Cls Color 0,255,0 Rect 0,340,640,140,1 DrawImage figur, X, Y

If KeyDown(203) Then ; Links X = X - 5 If X < 0 Then X = 0 EndIf

If KeyDown(205) Then ; Rechts X = X + 5 If X > 609 Then X = 609 EndIf

If KeyDown(57) And Sprung=0 Then ; Sprung Sprung = 1 SprungLinks = 0 SprungRechts = 0 EndIf

If Sprung > 0 Then ; während des Sprungs Sprung = Sprung + 1 If Sprung = 19 Then Sprung = 0 Y = Y + Sprungweite(Sprung) EndIf FlipUntil KeyHit(1)

20.7.3 KollisionsabfrageNun müssen wir die Spielfigur stoppen, wenn sie in eine Kiste laufen oder springensoll. Wir berücksichtigen Folgendes:

� Die Figur darf nicht links oder rechts in eine Kiste hineinlaufen. Das prüfen wir zu-sammen mit der Tastenabfrage: Will sie gegen ein Objekt laufen, ignorieren wirden Tastendruck.

� Die Figur muss auf der obersten Kiste eines Stapels landen und darf nicht ganz zuBoden fallen. Wir testen deshalb das geplante Zielfeld. Ist es nicht leer, ist derSprung beendet.

� Andernfalls muss die Figur am Ende eines Sprungs Boden unter den Füßen habenund somit notfalls tiefer fallen, als sie hochgesprungen ist.

Wir verwenden zur Umsetzung ein vereinfachtes Sprungprogramm: Wir merken unsdie Werte für nur vier Etappen nach oben, binden die Sprungkontrolle aber so in dieSpielschleife ein, dass wir die Spielfigur während des Sprungs bewegen können. Sosind zielgerichtete Sprünge möglich. Die Variable Sprung merkt sich, ob gerade ein

Page 302: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

302

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Sprung ausgeführt wird. Das verhindert Doppelsprünge und lässt das Sprungpro-gramm über mehrere Schleifendurchläufe ausführen.

20.7.4 Aufwendigere LevelsEin Spiel, das nur aus Klötzen besteht, macht keinen Spaß. Originell müssen die Levelssein, abwechslungsreich. Das lässt sich einrichten und zwar ebenfalls basierend auf32x32 großen Quadraten. In den Dateien BLOCKS1.BMP und BLOCKS2.BMP fin-den wir alles Notwendige. Bei der Vielzahl an möglichen Quadraten scheint eine ein-fache Zuordnung eines Zeichens zu einem Quadrat aber zu wenig. Daher speichern wirfür jedes Quadrat drei Zeichen nacheinander:

� 1 oder 2 für die verwendete Grafikdatei BLOCKS1.BMP oder BLOCKS2.BMP

� die Zeile des Quadrats in der Datei von A bis Z

� die Spalte des Quadrats in der Datei von A bis Z

Abb. 20.12:Elemente für

das Zusammen-stellen von2D-Karten

Klingt verwirrend? 2EB ist das zweite Quadrat (B) in der fünften Zeile (E) der DateiBLOCKS2.BMP. Hinter einem Dreiercode setzen wir ein Leerzeichen, um die Über-sicht zu behalten. Für solche Levels schreibt man sich am besten einen Leveleditor, einProgramm, mit dem man visuell Levels erstellt. Aber mit der Hand geht es auch.

In einer dritten Grafikdatei, PICKUPS.BMP, sind alle Gegenstände zum Einsammelnabgebildet. Leider sind sie unregelmäßig zusammengewürfelt. Sie lassen sich also nichtganz so bequem auslesen. Daher verwenden wir den Code 3XX, wobei XX für einelaufende Nummer steht, 301 etwa für die Erdbeere und 302 für die Melone.

Page 303: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

303

Gerüst für ein Jump'n'Run-Spiel j e t z t l e r n e i c h

Abb. 20.13:Unterschied-liche Gegen-stände lockern Levels auf und schaffen Ab-wechslung.

Meine Kollegin Katja Tischer hat netterweise einen vier Bildschirmseiten großen Test-level SCROLLING.DAT erstellt, der in diesem Beispiel zum Einsatz kommt.

20.7.5 ScrollingWährend die Zeilenzahl mit dem Bildschirm übereinstimmt (15 Zeilen mit 32 Punktengroßen Quadraten), geht die Zahl der Spalten über den sichtbaren Bereich von 20 Zei-len hinaus. Unser Testlevel ist 80 Spalten groß, also vier Bildschirmbreiten. Anders alsin den bisherigen Beispielen bewegen wir nicht die Spielfigur seitlich, sondern denHintergrund.

Das Programmieren des Scrollings ist weniger schwer, als es aussieht. Ein Jump'n'Run-Spiel hat einen linken Rand. Dieser entspricht in der Levelkarte der Spalte 0 und wirdauf den Bildschirm ganz links gezeichnet. Läuft die Spielfigur nach rechts, zeichnetman zwar weiterhin vom linken Bildschirmrand an, wählt aber eine spätere Spalte derLevelkarte. Die Variable Offset speichert die Information, wie weit der linke Bild-schirmrand vom Levelanfang entfernt ist. Das Beispiel zeichnet den Level aus der Da-tei SCROLLING.DAT auf den Bildschirm. Mit den Pfeiltasten lässt er sich seitlichscrollen:

; SCROLLING1.BBGraphics 640,480SetBuffer BackBuffer()tiles1 = LoadImage("blocks1.bmp")tiles2 = LoadImage("blocks2.bmp")tiles3 = LoadImage("pickups.bmp")

; Level von Festplatte lesen

Dim Level$(15,80)leveldatei = ReadFile("scrolling.dat")

Page 304: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

304

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

For Zeile=0 To 14 A$ = ReadLine(leveldatei) For Spalte=0 To 79 Level$(Zeile,Spalte) = Mid$(A$, (Spalte*4) +1, 3) NextNextCloseFile leveldateiOffset = 0

; Level zeichnen

Repeat

ClsColor 0,0,255 Cls

If KeyDown(203) Then If Offset > 0 Then Offset = Offset - 1 EndIf If KeyDown(205) Then If Offset < 59 Then Offset = Offset + 1 EndIf

For Zeile=0 To 14 For Spalte=0 To 19

Quadrat$ = Level$(Zeile,Spalte + Offset) BMP$ = Left$(Quadrat,1) BMPZeile = Asc( Mid$(Quadrat,2,1) ) - 65 BMPSpalte = Asc( Mid$(Quadrat,3,1) ) - 65

If BMP$ = "1" Then DrawImageRect tiles1, Spalte*32, Zeile*32, (BMPSpalte*34) + 2, (BMPZeile * 34) + 2, 32, 32 EndIf If BMP$ = "2" Then DrawImageRect tiles2, Spalte*32, Zeile*32, (BMPSpalte*34 + 2), (BMPZeile * 34) + 2, 32, 32 EndIf If Quadrat$ = "301" Then ; Erdbeere DrawImageRect tiles3, Spalte*32, Zeile*32, 421, 171, 32, 27 EndIf If Quadrat$ = "302" Then ; Melone DrawImageRect tiles3, Spalte*32, Zeile*32, 99, 106, 32, 18 EndIf Next Next

Flip Delay 10

Until KeyHit(1)

Page 305: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

305

Gerüst für ein Jump'n'Run-Spiel j e t z t l e r n e i c h

Abb. 20.14:Auch Jump'n'Run-Spiele mit komplexeren Grafiken lassen sich aus einzel-nen Kacheln zu-sammensetzen.

Gescrollt wird jeweils um ein ganzes Quadrat, also 32 Bildpunkte. Daher ist das Scrol-len nicht sehr »weich«, sondern es ruckelt. Besonders fällt das auf, wenn der Hin-tergrund nicht nur aus einer Schicht besteht, sondern wenn mehrere übereinanderliegende Motive mit unterschiedlicher Geschwindigkeit gescrollt werden. Um das zudemonstrieren, habe ich das Listing zum Programm SCROLLING2.BB erweitert. Eslädt zusätzlich Wolkendaten. Die Schichten werden mit unterschiedlicher Geschwindig-keit gescrollt, die Wolken langsamer als die Umgebung. Dabei kommt ein Dim-Feld zumEinsatz. Die Feldeinträge sind Kennungen der Leveldateien. Dadurch lassen sich in ei-ner For-Schleife mehrere Dateien behandeln.

1Um ein geschmeidiges Scrollen zu erreichen, reduzieren Sie die Zahl der Pixel, um dieder Bildschirm jedes Mal bewegt wird. Je nach Spielgeschwindigkeit werden meistensein bis vier Pixel gescrollt. Daraus ergibt sich, dass am linken und rechten Rand jeweilsnur Teile von Quadraten zu sehen sind. Um das zu erreichen, beginnen Sie mit demZeichnen einfach bei einer waagerechten Punktposition kleiner als 0. Der linke Teil desQuadrats bleibt dabei unsichtbar.

Man nennt das Bewegen mehrerer übereinander liegender Schichten Parallax-Scrol-ling.

Page 306: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

306

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Abb. 20.15:Der Hinter-

grund und Wol-ken sollten mit

einer zweitenSchicht darge-stellt werden.So lassen sich

mehrere Scroll-Ebenen (Paral-

lax-Scrolling)einrichten.

20.7.6 AusblickeBonusgegenstände zum Einsammeln, Fallen, sich selbstständig bewegende Gegner –es gibt einiges zu tun, um ein interessantes Jump'n'Run-Spiel zu programmieren. An-regungen gibt Ihnen das Spiel Spiel »Happyland Adventures«, das auf der Buch-CD bei-liegt. Es verwendet die gleichen Blockgrafiken von Ari Feldman wie die mit Blitz Basicmitgelieferten. Zum Spiel gehört ein Leveleditor, an dem Sie sich beim Erstellen eineseigenen Werkzeugs zum Erstellen von Spielwelten orientieren können.

Achten Sie bei eigenen Jump’n’Run-Spielen vor allem auf die Kollisionsabfrage. Sie istkomplex, da es verschiedene Arten von Objekten gibt:

� Pflanzen, an denen man vorbeiläuft

� Erhöhungen, an denen man vorbeiläuft, auf deren Dach man aber springen kann

� unüberwindbare Sperren

� Gegner, deren Berührung Lebensenergie kostet oder den Tod verursacht

� Fallen wie eine Dornengrube oder Lava

20.8 Gerüst für ein Abenteuer-Spiel

Adventures, Action-Adventures, Rollenspiele – an diese Genres sollte sich kein Anfän-ger wagen. Zu komplex ist ihr Aufbau: Räume haben eigene Grafiken, eigene Infotex-te, Gegenstände lassen sich einsammeln und später wieder verwenden, Gegner rauben

Page 307: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

307

Gerüst für ein Abenteuer-Spiel j e t z t l e r n e i c h

Lebensenergie, die Heiltränke wieder auffüllt. Wir wollen uns dennoch ein Beispiel an-sehen, wie sich Plätze mit Informationen belegen lassen. Das Szenarium: Unser Heldist in einem geheimnisvollen Wald gefangen. Jeder Platz kann Gefahren bergen, aberauch Goldstücke und heilende Lebensmittel. Mit den Pfeiltasten navigiert der Held sichvon Position zu Position, bis er 1000 Goldstücke gesammelt hat. Felder mit Bäumenkann er nicht betreten. Somit ist das Ziel, sich an Bäumen und wilden Tieren vorbei-zumogeln, um alle Goldstücke zu finden.

Wir wollen das Prinzip betrachten; daher halten wir das Programm so einfach wiemöglich. Es gibt keine Grafik; alle Ausgaben erfolgen in Textform. Freilich lässt sichdas Gerüst leicht mit Bildern unterlegen.

Für eine Spielwelt mit festen Ausmaßen ist ein Dim-Feld die beste Lösung. Wir sammelnfür jedes Feld folgende Angaben:

� Typ (Wiese, Steinboden, Feld, Moos, Baum)

� Beschreibung des Felds

� Besondere Objekte, die das Feld enthält

� Lebensenergie, die das Feld abzieht oder hinzufügt (da sich wilde Tiere oder Nah-rungsmittel darauf befinden)

� Goldstücke, die sich auf dem Feld befinden (bzw. durch Diebe abgezogen werden)

Die ersten drei Werte speichert ein Zeichenkettenfeld (Welt$()), die letzten beiden einZahlenfeld (WeltD()). Wir lesen sie ausnahmsweise nicht aus einer Datei, sondern legensie als Data-Zeilen in einer zusätzlichen Quelltextdatei fest, die wir mit Include in unserHauptprogramm einbinden:

; ADVLEVEL.BB; für jedes Feld:; - Art des Feldes $ ("Wiese", "Baum", "Feld" ...); - Beschreibung $; - Fundstück $; - Lebensenergie; - Gold

; Zeile 1Data "Wiese", "Sie stehen auf einer Lichtung inmitten eines Waldes.", "", 0, 0Data "Baum", "", "", 0, 0Data "Wiese", "Es duftet nach Blumen.", "Apfel", 5, 0Data "Wiese", "Alles ist grün und saftig.", "", 0, 0Data "Baum", "", "", 0, 0Data "Wiese", "Ein hübscher Schmetterling flattert umher.", "", 0, 0Data "Wiese", "Hier war mal ein Lagerplatz. Man sieht die Feuerstelle noch.", "Goldsäckchen", 0, 20;; Zeile 2Data "Wiese", "Aus der Ferne hören Sie ein Heulen.", "", 0, 0Data "Wiese", "Rote Blumen wachsen auf dem Gras.", "", 0, 0Data "Stein", "Im Geröll steckt ein Schild: 1000 Glitzersteine Du mußt finden ...", "", 0, 0Data "Wiese", "Ein Vogel zwitschert. Sie stechen sich an einer Dorne.", "", 0, -5Data "Wiese", "Ein Zettel: ... sonst wird der Wald Dich ewig binden.", "", -5, 0Data "Wiese", "Hier ist eine verlassene Hütte.", "Birne", 10, 0Data "Baum", "", "", 0, 0;

Page 308: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

308

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

; Zeile 3Data "Wiese", "Ein Wolf greift Sie an!", "", -20, 0Data "Stein", "Kleine graue Steine. Sie knirschen, wenn Sie darüberlaufen.", "", 0, 0Data "Feld", "Hier wurde schon lange nichts mehr angebaut.", "", 0, 0Data "Feld", "Einige Ähren sind abgebrochen.", "Goldsäckchen", 0, 50Data "Wiese", "Woher kommt all das viele Laub?", "", 0, 0Data "Wiese", "Ein Ast liegt auf dem Boden.", "Apfel", 10, 0Data "Wiese", "Ein Knurren ertönt aus dem Wald.", "", 0, 0;; Zeile 4Data "Wiese", "Ein Gebüsch. Einige Äste sind abgeknickt.", "", 0, 0Data "Wiese", "Das Heulen eines Tieres klingt beängstigend.", "Goldtruhe", 0, 75Data "Feld", "Ein Wolf greift Sie an!", "", -25, 0Data "Feld", "Ein Loch im Boden. Es sieht aus wie ein Maulwurfsnest.", "", 0, 0Data "Baum", "", "", 0, 0Data "Wiese", "Ein Wolf greift Sie an!", "", -25, 0Data "Stein", "Diese Steine sehen aus wie ein Straßenpflaster.", "", 0, 0;; Zeile 5Data "Stein", "Kleine Spinnen laufen auf den Steinen. Man sieht sie kaum.", "", 0, 0Data "Stein", "Ein kleiner Hügel aus Steinen. Ein Grab?", "", 0, 0Data "Wiese", "Ein Marder springt aus dem Gebüsch und beißt Sie in die Hand!", "", -15, 0Data "Baum", "", "", 0, 0Data "Wiese", "Sie hören ein Knacken, als ob ein Tier umherstreift.", "", 0, 0Data "Wiese", "Ein Wolf springt Sie an!", "", -30, 0Data "Wiese", "Sie haben einen Schatz gefunden!", "", 0, 750;; Zeile 6Data "Moos", "Hier riecht es etwas faul. Der Boden ist leicht sumpfig.", "", 0, 0Data "Moos", "Der feuchte Boden erzeugt ungewohnte Geräusche beim Laufen.", "", 0, 0Data "Wiese", "Diese Wiese ist besonders grün. Es wachsen viele Blumen darauf.", "Pilz", 15, 0Data "Wiese", "Ein Fuchs zwickt Sie in den Knöchel!", "", -15,0Data "Baum", "", "", 0, 0Data "Wiese", "Ein Birkenpaar hält seine Äste umschlungen wie ein Liebespaar,", "Goldsäckchen", 0, 50Data "Baum", "", "", 0, 0;; Zeile 7Data "Moos", "Eine diebische Elster greift Sie an und bestiehlt Sie!", "", -10, -20Data "Moos", "Hier wächst etwas Gestrüpp.", "", 0, 0Data "Wiese", "Der Platz beherbert einige Gebüsche.", "Goldtruhe", 0, 75Data "Wiese", "Eine schöne, große Birke.", "Pilz", 15, 0Data "Wiese", "Der Pfad schlängelt sich zwischen zwei Gebäuschen hindurch.", "", 0, 0Data "Wiese", "Tierspuren sind auf den Boden gezeichnet.", "", 0, 0Data "Wiese", "Ein riesiger Bär greift Sie an!", "", -80, 0

Der Vorteil: Nach dem Kompilieren besteht das ganze Programm aus einer Datei.

Das eigentliche Programm erstellt die Felder und liest alle Daten ein. In der Haupt-schleife werden die Angaben über das derzeitige Feld ausgegeben und die Richtungs-tasten abgefragt. Baumfelder lassen sich nicht betreten; und da der Rand von Bäumenumsäumt ist, bedarf es keiner gesonderten Randabfrage.

Spezielle Fundstücke erhöhen die Lebensenergie oder das Guthaben. Dabei muss si-chergestellt werden, dass sie sich nur einmal aufnehmen lassen. Beim wiederholtenBetreten eines Felds erfährt der Spieler trotzdem, was sich früher dort befand. Für diewilden Tiere gilt das freilich nicht: Sie greifen jedes Mal an.

Page 309: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

309

Gerüst für ein Abenteuer-Spiel j e t z t l e r n e i c h

Abb. 20.16:Kein »richtiges« Spiel, aber ein Grundgerüst, das sich mit Inhalten und Grafiken füllen lässt.

Der Reiz dieses Beispiels liegt darin, die Goldstücke zu finden, ohne zu wissen, welcheFelder betretbar sind und welche Gefahren dort lauern. In Anlehnung an die Adven-tures der 80er Jahre müsste der Spieler eine Karte erstellen, um alle Felder aufzu-decken. Komfortablere Spiele zeichneten den Spielverlauf in Form einer Automapselbst mit. Wir bauen in unser Programm einen Cheat ein: Drückt der Spieler Ã,sieht er eine Minikarte des ganzen Waldes, wobei Goldfelder grün, Heilfelder blau undGefahrenfelder rot gezeichnet sind. (Die einfache Struktur des Programms verlangt es,dass die Karte erst bei einem Raumwechsel angezeigt wird.)

Include "ADVLEVEL.BB"Graphics 800,600SetBuffer BackBuffer()

fontnormal = LoadFont("Courier", 20)fontgross = LoadFont("Courier", 40)

; ----------------------; *** Daten einlesen ***; ----------------------

Dim Welt$(9,9,3) ; für jedes Feld: Boden, Beschreibung, ObjektDim WeltD(9,9,2) ; für jedes Feld: Änderung Lebensenergie, Gold

; ganze Fläche mit "Baum" belegenFor I=1 To 9 For J=1 To 9 Welt$(I, J, 1) = "Baum" NextNext

Page 310: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

310

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

; Leveldaten einlesenFor Y=2 To 8 For X=2 To 8 Read Welt$(X, Y, 1) ; Bodentyp Read Welt$(X, Y, 2) ; Beschreibung Read Welt$(X, Y, 3) ; Gegenstand (Fundstück) Read WeltD(X, Y, 1) ; Änderung Lebensenergie Read WeltD(X, Y, 2) ; Änderung Gold NextNext

; VoreinstellungenClsColor 127,127,255X = 2Y = 2Leben = 100Gold = 0

; -------------------; ** Spielschleife **; -------------------

Repeat Cls

; Beschreibung des aktuellen Feldes/Raumes SetFont fontgross Text 2,50, Welt$(X, Y, 1) SetFont fontnormal Text 2,100, Welt$(X, Y, 2)

If Welt$(X, Y, 3) <> "" Then If WeltD(X, Y, 1) = 0 And WeltD(X, Y, 2) = 0 Then ; schon eingesammelt Text 2,150, "Früheres Fundstück: " + Welt$(X, Y, 3) Else Text 2,150, "Fundstück: " + Welt$(X, Y, 3) EndIf EndIf

; Lebensenergie erhöhen/verringern If WeltD(X, Y, 1) > 0 Then Text 2,180, WeltD(X, Y, 1) + " Prozent Lebensenergie dazu" Leben = Leben + WeltD(X, Y, 1) WeltD(X, Y, 1) = 0 EndIf If WeltD(X, Y, 1) < 0 Then Text 2,180, Abs(WeltD(X, Y, 1)) + " Prozent Lebensenergie weniger" Leben = Leben + WeltD(X, Y, 1) EndIf

; Guthaben erhöhen/verringern If WeltD(X, Y, 2) > 0 Then Text 2,200, WeltD(X, Y, 2) + " Goldstücke dazu" Gold = Gold + WeltD(X, Y, 2) WeltD(X, Y, 2) = 0 EndIf If WeltD(X, Y, 2) < 0 And Gold > 0 Then Text 2,200, Abs(WeltD(X, Y, 2)) + " Goldstücke weniger" Gold = Gold + WeltD(X, Y, 2) EndIf

Page 311: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

311

Gerüst für ein Abenteuer-Spiel j e t z t l e r n e i c h

; Mögliche Richtungen nennen Richtungen$ = "" If Welt$(X-1, Y, 1) <> "Baum" Then Richtungen$ = " Westen" If Welt$(X+1, Y, 1) <> "Baum" Then Richtungen$ = Richtungen$ + " Osten" If Welt$(X, Y-1, 1) <> "Baum" Then Richtungen$ = Richtungen$ + " Norden" If Welt$(X, Y+1, 1) <> "Baum" Then Richtungen$ = Richtungen$ + " Süden" Text 2, 300, "Mögliche Richtungen:" + Richtungen$

; Lebensenergie + Gold nennen Text 2, 330, "Lebensenergie:" Text 200,330, Leben Text 2, 350, "Goldstücke:" Text 200,350, Gold

; Karte ausdrucken If Karte = 1 Then Text 615,400, "Position Z" + Y + " S" + X For J=1 To 9 For I=1 To 9 If WeltD(I, J, 1) > 0 Then Color 0, 0, 255 ; Heilfeld If WeltD(I, J, 2) > 0 Then Color 0, 255, 0 ; Goldfeld If WeltD(I, J, 1) < 0 Then Color 255, 0, 0 ; Gefahrenfeld

If I=X And J=Y Then Color 0, 0, 0 ; aktuelle Position Text 600 + I*15, 420 + J*15, Left( Welt$(I, J, 1), 1) Color 255, 255, 255 Next Next EndIf

Flip

; Tastendrücke abfragen und abarbeiten

Repeat NeuerRaum = 0 Taste = WaitKey()

If Leben < 1 Then Cls Text 100,300, "Sie sind gestorben!" Flip WaitKey End EndIf

If Gold > 999 Then Cls Text 100,300, "Sie haben mindestens 1000 Goldstücke gefunden und sind frei!" Flip WaitKey End EndIf

Select Taste Case 27 ; Esc End Case 28 ; Hoch If Welt$(X, Y-1, 1) <> "Baum" Then Y = Y - 1 : NeuerRaum = 1

Page 312: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

312

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Case 29 ; Runter If Welt$(X, Y+1, 1) <> "Baum" Then Y = Y + 1 : NeuerRaum = 1 Case 31 ; Links If Welt$(X-1, Y, 1) <> "Baum" Then X = X - 1 : NeuerRaum = 1 Case 30 ; Rechts If Welt$(X+1, Y, 1) <> "Baum" Then X = X + 1 : NeuerRaum = 1 Case 8 ; Enter Karte = Not Karte End Select Until NeuerRaum = 1Forever

0

20.9 KI-Beispiel mit »Nimm weg«

Am »Pac-Man«-Beispiel haben Sie einen ersten Hinweis erhalten, wie man einen Geg-ner »intelligent« programmiert. Der Computer weiß ja, wo sich die Spielfigur befindet.Daher ist es leicht, eine Figur in seine Richtung zu schicken. Kaum einen Spieler würdediese Fähigkeit verwundern. Spielt man gegen den Computer, so ist meistens die eige-ne Geschicklichkeit die eigentliche Herausforderung. Oft genug bewegen sich die Geg-ner »dumm« und stellen allein durch ihre Präsenz und ihre Masse eine Gefahr dar. Ver-blüffend für den Spieler wird es dann, wenn der Computer scheinbar Einsicht undVerständnis in unsere Aktionen zeigt und entsprechend reagiert. Man nennt diesesVerhalten Künstliche Intelligenz (KI). Es stellt oft genug die größte Herausforderungfür den Programmierer dar. Über intelligentes Reagieren von Computern wurden gan-ze Bücher geschrieben; wir können das Thema hier nur anreißen. Im Bewusstsein soll-te bleiben: Egal, was ein Computer tut, er tut es, weil ein Mensch ein entsprechendesProgramm geschrieben hat, ein Regelwerk. Selbst wenn der Computer scheinbar lern-fähig ist, irgendwann auf unsere Bewegungsmuster eine passende Antwort hat, aufunsere Finten nicht mehr hereinfällt – es basiert alles auf Programmzeilen, auf Daten-feldern und If-Abfragen.

Das kleine Beispiel soll Ihnen zeigen, wie sich Abenteuer-Spiele grundsätzlich umset-zen lassen. Für das Erstellen von Adventures im eigentlichen Sinn gibt es spezielleWerkzeuge, die das Entwickeln stark vereinfachen, etwa das Adventure Game Stu-dio (www.agsforums.com)

Auch für Text-Adventures (die in der Regel gar keine Illustrationen haben und überdas Eintippen von Handlungsbefehlen gesteuert werden) existieren etablierte Hilfs-mittel wie der Text-Adventure-Generator T.A.G. (www.martin-oehm.de/tag/, auf derBuch-CD). Dem Programmierer erspart es das aufwendige Entwerfen eines Parsers(der die Eingaben auswertet); der Spieler kann auf vertraute Befehle zurückgreifen.Details zu Text-Adventures gibt es auf www.textfire.de; auf Fragen wartet das Forumwww.ifzentrale.de.

Sebastian Lenk, www.seelenradio.de: »Künstliche Intelligenz ist nicht zwingendkomplex und verwirrend. Es lohnt sich, die Fähigkeiten des Computergegners zumBeginn in Worten auf einem Blatt Papier schriftlich festzuhalten. Gliedern Sie die auf-geschriebenen Fähigkeiten nach Wichtigkeit und beginnen Sie dann, Sie ›aufzulösen‹.Machen Sie aus großen Problemen kleine. Das große Problem ist zum Beispiel, derGegner in einem Ego-Shooter will überleben.

Page 313: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

313

KI-Beispiel mit »Nimm weg« j e t z t l e r n e i c h

Die Strategie, ein Regelwerk zu erstellen und den Computer laufen zu lassen, lässt sichin vielen Spielen umsetzen. Doch es gibt einen weiteren Weg. Bei einigen Spielartenist die Zahl der Stellungen so gering, dass sich für jede Konstellation ein idealer Zug desComputers ergibt. Man denkt, der Computer sei »klug« und dabei schaut er nur in einerTabelle nach, wie er sich verhalten soll. Dieses Verfahren wollen wir uns anhand desSpiels »Nim« näher ansehen. Es ist auch als »Nimm weg« bekannt und lässt sich ohneComputer spielen. Die Regeln sind sehr einfach: Es gibt eine bestimmte Anzahl vonGegenständen, beispielsweise Streichhölzer. Abwechselnd ziehen beide Parteien je-weils ein bis drei Hölzer. Wer das letzte Holz nehmen muss, hat verloren. (Oft spieltman so, dass das letzte Holz gewinnt. Ich gönne mir eine Variation.)

Das setzen wir schnell in ein Programm um, in dem ein menschlicher Mitspieler gegenden Computer antritt. Wir halten es sehr einfach – keine Grafik, keine großen Aus-wahlmöglichkeiten: Es gibt 20 Hölzer und der Computer beginnt.

Der Zufall ermittelt, ob der Computer 1, 2 oder 3 Hölzer zieht (Variable A). Dann wer-den die verbliebenen Hölzer gemalt und der Spieler darf ziehen (Variable B). In beidenFällen wird sichergestellt, dass die Zahl der gezogenen Hölzer kleiner ist als die Zahl dervorhandenen (Variable Anzahl).

; NIMMWEG1.BBGraphics 800,600SetBuffer BackBuffer()SeedRnd MilliSecs()font = LoadFont ("Times New Roman", 20)SetFont fontAnzahl = 20

Repeat Cls

; Computer zieht (B) Repeat B = Rand(1,3) Until Anzahl - B >= 0 Anzahl = Anzahl - B

; Hölzer malen Hoelzer$ = "" For I = 1 To Anzahl Hoelzer$ = Hoelzer$ + "| " Next Text 100,50, "Wer das letzte Holz nimmt, verliert." Text 100,210, Hoelzer$

If B = 1 Then Text 100, 150, "Computer nimmt 1 Holz weg." If B > 1 Then Text 100, 150, "Computer nimmt " + B + " Hölzer weg." Text 100, 180, "Übrig bleiben: " + Anzahl If Anzahl < 1 Then Cls

Ein untergeordnetes Problem kann sein, er lädt nach, wenn seine Waffe leer ist. Undwas ist, wenn er keine Munition mehr hat? Dann wechselt er die Waffe oder er läuftganz einfach weg. Somit müssen Sie sich nicht mehr auf einen Schlag mit dem gro-ßen Problem beschäftigen, sondern Sie kümmern sich um die kleinen Teilaufgaben.«

Page 314: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

314

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Text 100,250, "Sie haben gewonnen! <Mausklick>" Flip WaitMouse End EndIf

; Spieler zieht (A) Text 100, 250, "Wie viele Hölzer wollen Sie wegnehmen (1-3): _" Flip Repeat A = Int( Chr$( WaitKey() ) ) Until (A > 0) And (A < 4) And (Anzahl-A) >= 0

Anzahl = Anzahl - A If Anzahl < 1 Then Cls Text 100, 250, "Sie haben verloren! <Mausklick>" Flip WaitMouse End EndIf

Forever

Das Spiel bietet ein gewisses Maß an Unterhaltung. Aber der Computer ist kein ernst-hafter Gegner; er »überlegt« nicht, sondern zieht zufällig. Es ist nicht besonders schwer,ihn zu besiegen. Analysieren wir, wie der Computer spielen müsste, um absichtlich zugewinnen.

Ein Spieler verliert auf jeden Fall, wenn er am Zug ist und noch ein Holz übrig ist –denn dann zieht er das letzte Holz.

Daraus ergibt sich, dass ein Spieler gewinnt, wenn er am Zug ist und noch 2, 3 oder4 Hölzer übrig sind. Denn dann wird er 1, 2 oder 3 Hölzer wegnehmen und dem an-deren das letzte Holz überlassen.

Und daraus folgern wir: Ein Spieler verliert, wenn er am Zug ist und noch 5 Hölzerübrig sind. Egal, wie viele er zieht: Es bleiben mindestens 2 Hölzer übrig und damitgenügend, um seinen Gegner so handeln zu lassen, dass nur ein Holz übrig bleibt.

Wer bei 1 oder bei 5 Hölzern am Zug ist, verliert. Diese Reihe lässt sich leicht fortset-zen: Jeweils im Abstand von vier Hölzern gibt es einen »Todespunkt«: 1, 5, 9, 13, 17... Wer bei dieser Anzahl Hölzer am Zug ist, muss verlieren, sofern im weiteren Verlaufdem Gegner kein Fehler unterläuft. Um zu gewinnen, muss ein Spieler darauf achten,dass er mit seinem Zug einen »Todespunkt« erreicht.

Dieses Wissen programmieren wir dem Computer. Wir könnten eine Formel ausarbei-ten, doch bei der kleinen Anzahl von Schritten tut es auch eine Zugtabelle: Wir schrei-ben dem Computer auf, wie viele Hölzer er bei jeder Situation wegnehmen soll. Dasich das Ziel alle vier Hölzer wiederholt, ist auch das Zugprogramm auf vier Situationenbeschränkt:

� Befindet sich der Computer auf einem »Todespunkt«, so nimmt er »aus Verlegen-heit« 1 Holz.

� Befindet sich der Computer 1 bis 3 Hölzer von einem »Todespunkt« entfernt, sonimmt er 1 bis 3 Hölzer, um seinen Gegner auf einem Verlierfeld zu platzieren.

Page 315: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

315

KI-Beispiel mit »Nimm weg« j e t z t l e r n e i c h

Würden wir aufschreiben, wie viele Hölzer bei einer vorhandenen Anzahl von 1, 2, 3... 20 Hölzern weggenommen werden müssen, käme eine Folge von

1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3

heraus, also immer wieder 1, 1, 2 und 3 hintereinander. Wir speisen diese Angabe inein Dim-Feld. Ist der Computer am Zug, schaut er einfach nach, wie viele Hölzer er je-weils nimmt. Das lösen wir wie folgt:

; NIMMWEG2.BB; Zug-Tabelle für Computer einlesenData 1, 1, 2, 3Dim Daten(Anzahl)For I=1 To Anzahl Read Daten(I) If Daten(I) = 3 Then RestoreNext

Da bei der 3 die Folge neu beginnt, setzen wir sie mit Restore auf den Anfangswert.Somit erstellen wir ein Zugprogramm für jede beliebige Anzahl von Hölzern. Beim Zie-hen bedient sich der Computer daraus:

; Computer ziehtB = Daten(Anzahl)Anzahl = Anzahl - B

Mit diesem Programm verwendet der Computer eine perfekte Strategie. Beginnt erdas Spiel nicht gerade an einem »Todespunkt«, gewinnt er zwingend. Damit ist er keinstarker, sondern ein unfairer Gegner. Das Spiel macht keinen Spaß. Entscheidend fürdie Spiel-Balance ist hier, ein Mittelmaß zu finden: Zieht er zufällig, ist er ein zu leichterGegner. Nutzt er sein ganzes Wissen, ist er nahezu unbesiegbar. Eine gute Hilfe ist indiesem Fall wieder einmal die Zufallszahl. Denken wir an »Pac-Man«: Wenn der Com-puter bei jedem Zug sein Wissen über die Position der Spielfigur ausnutzen und seineMonster in diese Richtung schicken würde, gäbe es kein Entrinnen.

Zwei Möglichkeiten bieten sich an:

� Sie wägen über einen Prozentwert ab, ob ein Zug zufällig erfolgt oder berechnetwird. Zum Beispiel: Nur jeder zweite Zug ist zufällig.

� Sie verwenden das Regelwerk nur in kritischen Situationen. Bei unserem Spielkönnten Sie so vorgehen, dass bis zu einer bestimmten Holzzahl zufällig gezogenwird. Nur, wenn nur noch wenige Hölzer übrig sind (zum Beispiel 6), dann zieht derComputer »schlau«.

Die zweite Variante ist damit eine Kombination aus NIMMWEG1.BB undNIMMWEG2.BB:

; NIMMWEG3.BB; Computer ziehtIf Anzahl > 6 Then Repeat B = Rand(1,3) Until Anzahl - B >= 0 Anzahl = Anzahl - BElse B = Daten(Anzahl) Anzahl = Anzahl - BEndIf

Page 316: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

316

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

0

20.10 Service-Funktionen

Viele Entwickler bereichern ihre Spiele um nützliche Funktionen, etwa eine Pause-Taste. Was der Spieler zu schätzen weiß, bauen Sie innerhalb von wenigen Minuten inIhren Programmcode ein.

20.10.1 Spielstand speichernBei vielen Genres sollte der Spielstand gespeichert werden können. Für Arcadespieleund Puzzles mit vielen Levels werden auch gern Passwörter verwendet. Für einfacheSpiele ist das Ablegen des Spielstands eine leichte Übung. Das Aufwendigste ist dieVerwaltung der Spielstände – etwa ein Dialogmenü, in dem der Speicherschacht aus-gewählt wird.

Wir wollen unser »Sokoban« mit einer Schnellspeicher-Funktion ergänzen: Drückt derSpieler S, wird der Spielstand gespeichert; drückt er L, wird der Spielstand geladen.Wir überlegen, welche Werte gesichert werden müssen: die Inhalte der beiden Dim-Felder, die Anzahl der Schritte und der Kistenzüge. Diese Daten schreiben wir in eineDatei:

; SpeichernIf KeyDown(31) Then datei = WriteFile("sokoban.sav") WriteShort datei, Schritte WriteShort datei, Zuege For Zeile= 0 To 14 For Spalte=0 To 19 WriteByte datei, Asc( Level$(Zeile,Spalte) ) WriteByte datei, Asc( LevelBackup$(Zeile,Spalte) ) Next Next CloseFile dateiEndIf

Eine gegensätzliche Funktion liest die Daten wieder aus. Dabei muss sichergestellt wer-den, dass überhaupt ein Spielstand existiert und dass natürlich die Daten in der glei-chen Reihenfolge gelesen werden, wie sie zuvor geschrieben wurden. Wichtig ist, nichtmit den Datentypen (WriteByte, WriteShort) durcheinander zu geraten.

; LadenIf KeyDown(38) Then datei = ReadFile("sokoban.sav") If datei <> 0 Then Schritte = ReadShort(datei)

Manchmal erzielen einfache, originelle Lösungen verblüffende Ergebnisse. Im Ego-Shooter »Unreal« gibt es eine Alien-Art, die besonders schwer zu treffen ist, weil siebei Beschuss clever zur Seite springt. Dahinter steckt keine ausgeklügelte Intelligenz:Die Kreatur ist darauf programmiert, auszuweichen, wenn der Spieler die Maustastedrückt. Ähnlich pragmatisch handeln Filmemacher, wenn jemand oder etwas plötz-lich unsichtbar werden soll: Sie halten einfach die Kamera an, nehmen die Personoder den Gegenstand aus dem Bild und drehen dann weiter. Oft bleiben einfache Mit-tel unübertroffen.

Page 317: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

317

Service-Funktionen j e t z t l e r n e i c h

Zuege = ReadShort(datei) For Zeile= 0 To 14 For Spalte=0 To 19 Level$(Zeile,Spalte) = Chr$( ReadByte(datei) ) LevelBackup$(Zeile,Spalte) = Chr$ (ReadByte(datei) ) Next Next EndIf CloseFile dateiEndIf

Sie finden die beiden Programmteile im Listing SOKOBAN2.BB.

Die Lade-Funktion lässt die neuen Daten direkt in die Spielschleife einfließen. Es istnicht nötig, das Spiel erst zu beenden. Das ist freilich nicht immer möglich. Da aber beijedem Schleifendurchlauf der gesamte Bildschirminhalt gezeichnet wird, lassen sichviele Spiele auf diese Weise speichern und laden, ohne dass erst ein Menü aufgerufenwerden muss.

20.10.2 CheatMehrfach haben wir über das Thema Cheats gesprochen. In den meisten Spielen sindSchummelmodi eingebaut und die meisten Spieler nutzen Cheats – einige manchmal,andere immer. Sie sollten sich daher ebenfalls nicht einer Mogelhilfe verschließen.Drückt der Spieler zum Beispiel auf beide Ÿ-Tasten, dann erhält er zehn Leben:

If KeyDown(29) And KeyDown(157) Then Leben = 10

In das Programm PAC4.BB habe ich eine entsprechende Zeile eingefügt: Hier genügtdas Drücken von C.

20.10.3 Pause-ModusJedes ordentliche Spiel erlaubt es, den Ablauf vorübergehend zu unterbrechen. EineSpielpause programmiert sich sehr einfach: Wenn die Tasten P oder ¢Pause£ gedrücktwerden, halten wir das Spiel mit WaitKey einfach an. Um zu unterstreichen, dass derPause-Modus aktiviert ist, programmieren wir eine fette Ausgabe:

; PAUSE.BBIf KeyDown(197) Or KeyDown(25) Then font = LoadFont("Times New Roman",80,0,0,0) SetFont font Text 150,200, "P A U S E" Flip FlushKeys WaitKey FreeFont font EndIf

Auch ein Pause-Abschnitt ist bereits Teil von PAC4.BB.

Page 318: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

318

Programmieren wir ein Spiel!20j e t z t l e r n e i c h

Abb. 20.17:Jedes Spiel soll-

te eine Pause-taste haben -

falls das Telefonklingelt.

20.10.4 Screenshot-TasteEine Reihe von Spielen erlaubt es, ohne zusätzliche Software einen Schnappschussvom Geschehen zu erzeugen. Einen solchen Dienst können Sie ohne viel Aufwand fürIhr Spiel anbieten. Den Befehl SaveBuffer() habe ich Ihnen bereits vorgestellt. Er spei-chert einen Puffer als BMP-Datei auf der Festplatte ab. Meistens verbindet man das Er-stellen eines Screenshots mit einem Tastendruck:

If KeyHit(88) Then SaveBuffer(FrontBuffer(),"shot.bmp")

Schönheitsfehler: Bei jedem Druck von Ô wird der vorherige Screenshot überschrie-ben. Sie sollten daher eine Variable mitlaufen lassen, um den Dateinamen durch eineZahl zu ergänzen:

If KeyHit(88) Then SaveBuffer(FrontBuffer(),"shot" + Str$(Shot) + ".bmp") Shot = Shot + 1EndIf

Das probieren wir doch gleich einmal aus. Um das Thema Fonts wieder aufzufrischen,zeichne ich keine Bilder, sondern Textsterne (»*«). In die Schleife setze ich eineScreenshot-Abfrage:

; SCREENSHOT.BBGraphics 640,480Font = LoadFont("Times New Roman",35,1,0,0)SetFont FontRepeat Text Rand(640), Rand(480), "*" Delay 100 ;

Page 319: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

319

Service-Funktionen j e t z t l e r n e i c h

If KeyHit(88) Then SaveBuffer(FrontBuffer(),"shot" + Str$(Shot) + ".bmp") Shot = Shot + 1 EndIf ;Until KeyHit(1)

Drücken Sie während des Programmlaufs mehrfach Ô, jeweils im Abstand von eini-gen Sekunden. Dadurch erzeugen Sie die Bilddateien SHOT1.BMP, SHOT2.BMP ...mit dem jeweils aktuellen Bildschirminhalt.

1Meistens spielt es keine Rolle, welchen Puffer Sie abspeichern: Hauptsache, Sie tunes in einem Moment, in dem das komplette Bild gezeichnet ist. Beachten Sie, dass dieerzeugten Dateien recht groß sind, da sie unkomprimiert und mit 24 Bit Farbtiefe ab-gelegt werden. Bereits bei einer Bildschirmauflösung von 640x480 nimmt einScreenshot fast 1 Megabyte ein.

Page 320: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 321: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

321

jetz

t le

rne

ich

KAPITEL 21

A3D-Grafik mit Blitz Basic 3D

2D-Spiele sind flach. Man sieht das Geschehen von der Seite oder von oben. Es istnicht ohne Weiteres möglich, etwa bei einem Pac-Man-Spiel in die Spielfigur hinein-zuschlüpfen und das Geschehen aus der Sicht des gelben Punkts (Ego-Perspektive) zubetrachten. Überlegen Sie sich einmal, wie ein dreidimensionales Spielfeld aussehenmüsste. Es würde drei große Unterschiede zur 2D-Grafik aufweisen:

Räumlichkeit: In 2D werden alle Objekte an eine Glasscheibe gepappt. 3D sieht eheraus wie ein Aquarium. Neben der Länge und der Breite kommt eine dritte Koordinatehinzu – die Tiefe.

Blickwinkel: Ein Aquarium würde nur den halben Spaß bieten, könnte man es nur voneiner Seite aus ansehen. In einen 3D-Raum kann man aus allen Richtungen schauen,als ob man frei platzierte Kameras hätte, die sich auf das Geschehen richten.

Körper: Natürlich darf nicht nur die Umgebung dreidimensional sein. Auch die Spiel-figuren und andere Objekte müssen sich von ihrem Dasein als flache Briefmarken tren-nen und zu Körpern werden, die sich aus allen Richtungen betrachten lassen.

So etwas zu programmieren, stellt eine große Herausforderung dar. Bedenken Sie nur,wie viele Animationsstufen Sie für einen einzelnen Körper, etwa einen Zylinder, benö-tigen, der sich um alle Achsen drehen lässt. Und wie ließe es sich realisieren, einenRaum einschließlich seines ganzen Inventars rotieren zu lassen? Doch warum solltenwir das Rad neu erfinden? Genau für solche Aufgaben wurde Blitz Basic 3D geschaf-fen. Die Software kann alles, was ihr kleiner Bruder auch beherrscht. Ihre Spezialitätsind aber zusätzliche Befehle für das Bearbeiten und Darstellen von 3D-Grafik und da-von gibt es mehr als 200.

Page 322: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

322

3D-Grafik mit Blitz Basic 3D21j e t z t l e r n e i c h

1

21.1 Grafikmodus

Genau wie in 2D muss für 3D-Darstellungen zunächst der Grafikmodus initialisiert wer-den. Dazu verwenden Sie den Befehl Graphics3D. Er benötigt die gleichen Parameterwie Graphics:

Graphics3D Breite, Höhe, Farbtiefe, Fenstermodus

Die Angaben wurden bereits für den Befehl Graphics beschrieben, daher fasse ich michkurz: Breite und Höhe sind die Auflösung des Bildschirms, die Farbtiefe in Bit legt fest,wie viele Farben maximal möglich sind. Fehlt die Angabe, verwendet Blitz 3D die glei-che Farbtiefe wie Windows.

Im Normalfall genügt es, die Auflösung anzugeben:

Graphics3D 640, 480

21.2 Das Gerüst eines 3D-Programms

Sehen wir uns noch einmal kurz das Arbeiten mit Grafik im 2D-Modus an. Mit BlitzBasic 2D arbeiten Sie mit Flächen – zweidimensional eben. Die Grafik wird fortlaufendauf den Bildschirm gezeichnet. Sie müssen sich merken, an welcher Position welchesElement zu finden ist. Bei einfachen Spielen kommen Sie mit einer Handvoll Grafik-befehlen aus: Bild laden, Bild zeichnen, vielleicht noch eine Anweisung für die Kolli-sionsabfrage. Abgesehen vom Befehl Graphics und eventuell WaitKey, damit sich dasProgramm nicht beendet, genügt eine Befehlszeile, um ein einfaches Bild zu malen:

Graphics 640, 480Oval 270, 190, 100, 100, 1WaitKey

Einen Körper auf dem Bildschirm darzustellen, ist etwas aufwendiger als die Ausgabeeines Bilds. Dennoch werden Sie schnell erste Erfolgserlebnisse haben. Die Heraus-forderung bei 3D liegt letztendlich in dem unglaublichen Aufwand, die angebotenenMöglichkeiten wirklich zu nutzen. 3D-Modelle müssen entworfen, Levels entwickeltwerden. Die künstlerischen, aber auch die programmiertechnischen Herausforderun-gen sind deutlich höher. Es ist einfacher, ein gutes 2D-Spiel zu programmieren als einschlechtes 3D-Spiel. Dieses Einsteigerbuch konzentriert sich daher auf 2D; der fol-gende 3D-Teil soll als Einführung und Wegweiser in die ersten Schritte dienen. Fürdie folgenden Abschnitte benötigen Sie Blitz Basic 3D.

Fenstermodus Auswirkung

0 Vollbild, im Debug-Modus Fenster (Standard)

1 Vollbild

2 Fenster mit fester Größe

3 Fenster mit veränderbarer Größe

Page 323: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

323

Das Gerüst eines 3D-Programms j e t z t l e r n e i c h

Unter Zuhilfenahme der Doppelpufferung erweitert sich das Programm wie folgt:

Graphics 640, 480SetBuffer BackBuffer()ClsOval 270, 190, 100, 100, 1FlipWaitKey

Um den Kreis zu bewegen, zeichnen wir den gesamten Bildschirm neu, wobei wir beijedem Durchlauf eine andere Position des Kreises wählen:

Graphics 640, 480SetBuffer BackBuffer()For I=100 To 500 Cls Oval I, 190, 100, 100, 1 FlipNextWaitKey

Im 3D-Modus gestaltet sich die Handhabung etwas aufwendiger. Drei Punkte müssenSie beachten:

1. Im 3D-Modus müssen Sie mit BackBuffer() und Flip arbeiten, also in den Back-Buffer zeichnen und zum Darstellen mit Flip umschalten.

2. Zum Zeigen von Grafik müssen Sie mindestens eine Kamera verwenden und sieauf das Geschehen richten. Dazu dient die Funktion CreateCamera().

3. 3D-Objekte werden nur einmal erstellt; danach müssen Sie sich nicht mehr um siekümmern, solange sie zum Beispiel nicht ihre Position verändern sollen. Der BefehlRenderWorld zeichnet alle 3D-Objekte in ihre aktuelle Position und durch das fest-gelegte Kameraauge in den BackBuffer. Setzen Sie diesen Befehl direkt vor Flip.

Das leere Gerüst für ein 3D-Programm sieht daher folgendermaßen aus:

Graphics3D 640, 480SetBuffer BackBuffer()CreateCamera();; hierhin kommen die eigentlichen Grafikbefehle;RenderWorldFlipWaitKey

Wir greifen nun etwas vor, damit Sie einen ersten Eindruck erhalten. Das folgende Bei-spiel zeichnet eine Kugel in die Mitte des Bildschirms:

; KUGEL1.BBGraphics3D 640, 480SetBuffer BackBuffer()CreateCamera() ; Kamera erstellen

kugel = CreateSphere(32) ; Kugel erstellenPositionEntity kugel, 0, 0, 5 ; Kugel positionieren

RenderWorld ; alles zeichnenFlipWaitKey

Page 324: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

324

3D-Grafik mit Blitz Basic 3D21j e t z t l e r n e i c h

Na ja, werden Sie jetzt sagen, wie 3D sieht das nicht gerade aus. Sie haben Recht. DieKugel ist gefüllt und daher sieht sie aus wie ein Kreis. Anders als bei 2D-Figuren wieQuadrat oder Kreis gibt es bei 3D keine Möglichkeit, einen einzelnen Körper »unaus-gefüllt« zu zeichnen. Doch Sie können das für alle Körper auf einmal festlegen, indemSie in den Drahtgittermodus aktivieren. Dort werden alle Körper ohne Hülle darge-stellt. Fügen Sie dazu den Befehl

WireFrame 1

irgendwo in den Bereich zwischen Graphics3D und RenderWorld ein. Das Ergebnis siehtschon mehr nach 3D aus. Besser wäre es freilich, die Kugel würde sich bewegen, sodass man sie von allen Richtungen sieht. Das lässt sich leicht einrichten, indem wir denBefehl TurnEntity hinzufügen und ihn zusammen mit RenderWorld und Flip in eineSchleife packen:

; KUGEL2.BBGraphics3D 640, 480WireFrame 1SetBuffer BackBuffer()CreateCamera()

kugel=CreateSphere(32)PositionEntity kugel, 0, 0, 4

Repeat TurnEntity kugel, 1, 1, 1 RenderWorld FlipUntil KeyHit(1)

Nett, nicht? Sicher sind noch einige Fragen offen, wie dies oder jenes funktioniert.Dem soll in den nächsten Abschnitten abgeholfen werden.

21.3 3D-Koordinaten

Im 3D-Modus müssen wir uns leider von dem liebgewordenen System, bestehend ausX und Y, trennen. Denn wir benötigen ja noch eine Tiefenangabe. Diese Koordinatewird in der Regel Z genannt. Der Nullpunkt, also 0, 0, 0, befindet sich allerdings nichtlinks oben, sondern genau in der Mitte des Bildschirms. Eine Tiefe von 0 bedeutet: DerPunkt liegt praktisch auf dem Glas des Monitors. Je größer Z wird, desto weiter ent-fernt sich der Punkt von uns weg. Wenn wir also das Raumschiff Enterprise zeichnenwürden, das in der Mitte des Bildschirms von uns wegfliegt, dann würden wir Z vergrö-ßern. Da die Koordinaten 0, 0, 0 den Mittelpunkt des Bildschirms darstellen, sind auchnegative Werte für X und Y üblich, nämlich dann, wenn sich ein Punkt links bzw. ober-halb des Mittelpunkts befindet. Wird Z negativ, bewegt sich der Punkt durch das Mo-nitorglas in unsere Richtung und gerät dadurch außerhalb des sichtbaren Bereichs.

21.4 Einfache Körper erstellen

Im 2D-Modus gibt es Befehle zum Zeichnen von Punkten, Linien oder Kreisen. DieseFlächen werden selten in Spielen verwendet, doch sie eignen sich gut für Beispiele undTests. Genauso generiert der 3D-Modus einfache Körper wie Kugeln und Würfel. Die-

Page 325: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

325

Einfache Körper erstellen j e t z t l e r n e i c h

se Grundformen nennt man Primitives. Anders als bei DrawImage und 2D-Grafiken,geben Sie keine Koordinaten an, sondern lassen das Objekt mit einem Bewegungs-befehl zur gewünschten Stelle gleiten.

Der Körper wird an die Position 0, 0, 0 gesetzt. Damit ist er trotz eingeschalteter Ka-mera nicht sichtbar, da er gewissermaßen direkt auf der Linse klebt. Sie müssen daherden Körper in die Tiefe des Raums verschieben, um ihn sehen zu können. Das be-schreibe ich ihnen einige Seiten später.

21.4.1 KugelEin Befehl genügt, um eine Kugel zu erstellen:

kugel = CreateSphere()

Als Parameter können Sie angeben, wie detailliert die Kugel gezeichnet wird. Sicher istIhnen bekannt, dass die Oberflächen dreidimensionaler Objekte aus Polygonen beste-hen. Das Wort bedeutet nichts anderes als »Vieleck«. Tatsächlich handelt es sich fastimmer um Dreiecke. Je mehr Polygone ein Objekt hat, desto feingliedriger ist es. Soschreibt der Spieleverleger Eidos, dass in der sechsten Fassung von »Tomb Raider« diegrazile Lara Croft aus 5000 Polygonen besteht – eine Verzehnfachung gegenüber demVorgänger.

Bei einem Körper wie einer Kugel macht es keinen Sinn, die Zahl der Polygone umeine willkürliche Zahl zu erhöhen. Damit es harmonisch aussieht, verwendet man Zwi-schenschritte. Aus diesem Grund geben Sie nicht die Menge der Polygone an, sonderneine größere Einheit, die Zahl der Segmente, aus denen die Kugel besteht. Ein Seg-ment umfasst eine bestimmte Anzahl an Polygonen:

Polygone = (Segmente ∗ (Segmente – 1) ∗ 2) ∗ 2

Der Standard sind 8 Segmente, was 224 Polygonen entspricht. Zu wenig: Die Run-dungen sind kantig. Wesentlich schöner sehen 32 Segmente aus, was bereits 3968Polygonen entspricht. Erlaubt sind Werte zwischen 2 und 100.

Der Befehl wird als Funktion verwendet, um die Kennung des Körpers in einer Variab-len (kugel) zu speichern. Sie ist für das Anzeigen der Kugel notwendig.

21.4.2 ZylinderÄhnlich erstellen Sie mit

zylinder = CreateCylinder()

einen Zylinder. Als Parameter können Sie wiederum die Anzahl der Segmente ange-ben. Weil ein Zylinder viel einfacher zu zeichnen ist als eine Kugel, benötigt man deut-lich weniger Polygone:

Polygone = (Segmente + (Segmente – 2) ∗ Boden) ∗ 2

Mit einem zweiten Parameter legen Sie fest, ob die Grundflächen (also Boden und De-cke des Zylinders) gezeichnet werden (1, Standard) oder nicht (0). Dieser Wert ist als»Boden« Teil der Rechnung. Kann auf die Grundfläche verzichtet werden, besteht derZylinder aus deutlich weniger Polygonen. 32 Segmente entsprechen 124 Polygonen.Das ist ausreichend für einen Zylinder mit glatten Rundungen. 3 Segmente ergeben üb-rigens ein Prisma, 4 einen Quader. Erlaubt sind Werte zwischen 2 und 100.

Page 326: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

326

3D-Grafik mit Blitz Basic 3D21j e t z t l e r n e i c h

21.4.3 KegelWas ist eine Mischung aus Zylinder und Kugel? Ein Kegel. Diesen Körper erzeugen Siewie folgt:

kegel = CreateCone()

Wiederum dürfen Sie die Anzahl der Segmente angeben. Wie viele Polygone das er-gibt, berechnet die folgende Formel:

Polygone = Segmente + (Segmente – 2) ∗ Boden

32 Segmente alias 62 Polygone genügen für eine ordentliche Darstellung. Wie beimZylinder gilt: Der Segmentwert muss zwischen 2 und 100 liegen. Verwenden Sie 0 alszweiten Parameter, wird der Boden nicht gezeichnet.

Ach so – ein Kegel ist natürlich keine Mischung aus Zylinder und Kugel. Haben Sie esgemerkt? ;-)

21.4.4 WürfelEin Würfel ist der letzte Grundkörper, der sich erzeugen lässt:

würfel = CreateCube()

Im Gegensatz zu den anderen Formen lässt sich hier nicht festlegen, aus wie vielenPolygonen er besteht: Ein Würfel besitzt keine Rundungen, für deren AnnäherungenVielecke verwendet werden. Sein simpler Aufbau lässt sich durch weitere Polygonenicht verbessern.

21.5 Körper färben

EntityColor färbt einen Körper ein. Sie teilen die RGB-Werte der gewünschten Farbemit. Die Farbe kann jederzeit geändert werden; sie wird sofort aktualisiert:

EntityColor kugel, 255,0,0

21.6 Körper bewegen

Wie im vorigen Abschnitt beschrieben, wird ein Körper zunächst an die Position 0, 0,0 gesetzt. Er muss an die gewünschte Stelle verschoben werden.

Dieses Verfahren zeigt deutlich die Unterschiede zwischen 2D und 3D: Im 2D-Modusmüssen Sie sich die Koordinaten einer Grafik merken. Um sie zu verschieben, zeich-nen Sie das Bild an der gewünschten Position neu. In 3D sagen Sie Blitz Basic, dass derKörper xyz an eine neue Stelle gerückt werden soll. Dazu dient der Befehl Position-Entity. Sie übergeben ihm den Namen (die Kennziffer) des Objekts und die Zielkoor-dinaten für die X-, Y- und die Z-Achse.

Die Befehlsfolge

würfel = CreateCube()PositionEntity würfel, 0, 0, 5

erstellt einen Würfel an der Position 0, 0, 0 und versetzt ihn an die Position 0, 0, 5. Da-durch wird er von der Kamera weg in den räumlichen Hintergrund bewegt.

Page 327: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

327

Körper drehen j e t z t l e r n e i c h

Das kürzeste Programm, um einen Würfel zu zeichnen, wäre damit:

; WUERFEL.BBGraphics3D 1024,768SetBuffer BackBuffer()CreateCamera()

würfel = CreateCube()MoveEntity würfel, 0, 0, 5

RenderWorldFlipWaitKey

1Dabei geben Sie keine absoluten Koordinaten an, sondern nennen nur die Richtung.Sie befehlen etwa, dass der Körper um zwei Stellen nach oben und eine Stelle nachlinks verschoben wird. Dazu dient der Befehl MoveEntity. Sie übergeben ihm denNamen (die Kennziffer) des Objekts und die Richtungsänderung für die X-, Y- und dieZ-Achse. Die Befehlsfolge

würfel = CreateCube()MoveEntity würfel, 0, 0, 5

erstellt einen Würfel an der Position 0, 0, 0 und verschiebt ihn um 5 Stellen auf derZ-Achse. Dadurch wird er von der Kamera weg in den räumlichen Hintergrund bewegt.

21.7 Körper drehen

Ein Objekt kann von jeder Seite aus betrachtet werden. Dazu gibt es zwei Möglichkei-ten: Sie drehen den Körper oder Sie ändern die Position der Kamera. Ein Gleichnis:Um ein Auto von vorn zu sehen, müssten wir uns entweder vor das Auto stellen, umdamit die Position unserer Augen (= Kamera) zu verändern. Oder wir müssten daraufhoffen, dass sich das Auto (= Körper) dreht und uns seine Scheinwerfer zuwendet.

Da wir uns im 3D-Raum befinden, wollen wir natürlich einen Körper nicht nur um eineAchse drehen, sondern in jede gewünschte Richtung um die X-, Y- oder Z-Achse. Umein Gefühl dafür zu bekommen, welche Achse welche Wirkung hat, stellen wir uns diedrei Achsen als Speere vor. Wir bohren den Speer in den Körper und drehen ihn umdiese Achse.

Die X-Achse ist waagerecht, verläuft von oben nach unten. Eine Drehung um dieseAchse entspricht einem Sportler, der sich am Reck kopfüber schwingt. Der englischeFachbegriff für diesen Drehwinkel ist Pitch.

Die Y-Achse ist senkrecht, verläuft von unten nach oben. Stellen Sie sich dazu einenSportler vor, der eine Stange hochklettert und sich dabei um sie herum dreht. Mannennt diese Drehung auch Yaw.

Die Z-Achse befindet sich im rechten Winkel zur Monitorscheibe und geht direkt in dieTiefe. Ein Körper, der sich um diese Achse dreht, ist wie ein Flugzeug, das zur Seite

Entity oder deutsch Entität wird in der 3D-Welt als Oberbegriff für alle Objekte ver-wendet, etwa Körper und Kameras. Das Wort meint in seiner eigentlichen Bedeutungnicht viel mehr als ein »Ding«, allerdings ein eindeutig bestimmbares.

Page 328: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

328

3D-Grafik mit Blitz Basic 3D21j e t z t l e r n e i c h

rollt, so dass der eine Flügelt nach unten und der andere nach oben zeigt. Dieser Dreh-winkel wird auch Roll genannt.

Der Befehl TurnEntity dreht einen Körper nach Ihren Wünschen. Er erwartet vierParameter: den Körper, um den es sich handelt, sowie die Drehrichtungen für die X-,Y- und Z-Achse:

0 bedeutet jeweils keine Drehung

1 bedeutet Drehung nach rechts

–1 bedeutet Drehung nach links

Nur eine Drehung um die X-Achse nach links würde man also mit –1, 0, 0 angeben.Schauen wir uns das besser plastisch an:

; DREHEN.BBGraphics3D 1024,768WireFrame 1SetBuffer BackBuffer()CreateCamera();kugel = CreateSphere(32)MoveEntity kugel, 0, 0, 5EntityColor kugel, 255,0,0

zylinder = CreateCylinder(32)MoveEntity zylinder, 3, 0, 5EntityColor zylinder, 0,255,0

kegel = CreateCone(32)MoveEntity kegel, -3, 0, 5EntityColor kegel, 0,0,255;Repeat If KeyDown(71) Then X = -1 If KeyDown(72) Then X = 0 If KeyDown(73) Then X = 1 If KeyDown(75) Then Y = -1 If KeyDown(76) Then Y = 0 If KeyDown(77) Then Y = 1 If KeyDown(79) Then Z = -1 If KeyDown(80) Then Z = 0 If KeyDown(81) Then Z = 1 TurnEntity zylinder, X, Y, Z TurnEntity kegel, X, Y, Z TurnEntity kugel, X, Y, Z RenderWorld FlipUntil KeyHit(1)

Mit den neun Zahlentasten des Ziffernblocks steuern wir die Drehung. Die Tasten 7bis 9 drehen um die X-Achse, 4 bis 6 übernehmen die Y-Achse, 1 bis 3 sind fürdie Z-Achse verantwortlich. Dabei legen die linken und rechten Tasten die Richtungfest; die mittlere Taste hält die Drehung an.

Page 329: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

329

Texturen j e t z t l e r n e i c h

Abb. 21.1:Körper lassen sich in alle Rich-tungen drehen. Die Drahtgitter-Anzeige verrät ihren Aufbau.

21.8 Texturen

Die 3D-Körper sind nackt und ... langweilig. Sie bräuchten eine fesche Tapete. AlleDreiecke, aus denen eine 3D-Welt besteht, sind mit einer farbigen Oberfläche beklebt.Man bezeichnet diese als Textur. Meistens handelt es sich dabei um eine normale Gra-fik. Das Bedecken eines Körpers mit einer Textur nennt man Texture Mapping. Siekönnen jedes Objekt mit einer Textur bekleben. Sie laden dazu eine Grafikdatei undweisen sie dem Objekt zu:

; KUGEL3.BB...textur = LoadTexture("alien.bmp")EntityTexture kugel, textur...

Mit CreateTexture() erzeugen Sie eine Textur, die Sie zum Beispiel einfärben. Sie kön-nen mehrere Texturen auf eine Oberfläche legen – Blitz Basic 3D unterstützt bis zuacht Texturen. Dieses Verfahren heißt Multi Texturing.

Für das Bemalen von Oberflächen verwendet man Brushes. Diese Pinsel bündeln eineReihe optischer Informationen wie Farben, Durchsichtigkeit und Glanz. CreateBrush()erstellt einen Pinsel.

21.9 Meshes

Genau wie im 2D-Modus werden 3D-Grafiken kaum während der Laufzeit erstellt.Man verwendet vorbereitete Körper. Ein komplexes 3D-Gebilde ist ein Mesh. Er wirdmit einer Modellierungssoftware erstellt. Unzählige dieser Programme stehen zur Aus-wahl, von Freeware-Software bis zur Königsklasse 3ds max (www.discreet.de), dasrund 4000 Euro kostet.

Beliebt unter Hobbyentwicklern ist MilkShape 3D (www.swissquake.ch/chumbalum-soft/ms3d/). Das Werkzeug ist mit einem Preis von 50 Euro erschwinglich. Allerdingserfordert das Modellieren Talent und Einarbeitungszeit. Geeignete Tutorials finden Sieauf der Seite des Entwicklers und auf www.robsite.de. Besonders empfehlenswert sinddie deutschsprachigen Anleitungen von Pierre Kretschmer, die sich auch auf der Buch-CD befinden.

Page 330: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

330

3D-Grafik mit Blitz Basic 3D21j e t z t l e r n e i c h

Abb. 21.2:Milkshape 3D

ist ein beliebterund preiswerterModellierer für

Körper.

Freilich können Sie sich bei Archiven bedienen, die kostenlose Meshes zum Downloadanbieten. Eine besonders reichhaltige Auswahl finden Sie auf www.3dcafe.com; wei-tere Links gibt es ebenfalls auf www.robsite.de.

Pierre Kretschmer, www.gargamel.de: »Die wichtigen Voraussetzungen für das Mo-dellieren von 3D-Modellen sind Geduld und vor allem Zeit. Setzen Sie sich intensivmit den Programmen auseinander, um das Handwerkzeug sicher zu beherrschen. Sokönnen Sie das Augenmerk tatsächlich auf das Modellieren legen. Beginnen Sie mitkleinen Modellen. Erste Erfolge motivieren und geben die Erfahrung, um große Pro-jekte sicher zu meistern. Geeignet für den Anfang sind einfache kubische Formen,wie man sie zum Beispiel im Haushalt findet: ein Fernseher, ein Radio. Dadurch ler-nen Sie, mit den richtigen Proportionen eines Objekts umzugehen und es so original-getreu wie möglich nachzubilden. Danach gehen Sie dazu über, runde Objekte wieeine Flasche oder eine Blumenvase zu konstruieren. Sie werden ebenso aus einfa-chen Formen wie Kugeln oder Zylinder erzeugt. Schritt für Schritt steigen Sie aufkomplexe Dinge um, die Sie zunehmend durch eigens erzeugte Polygone erweiternund perfektionieren. Die schwierigsten Objekte dürften anatomische Gebilde sein,die sehr viel Übung und Geduld voraussetzen. Zeichnen Sie den Körper zuerst auf Pa-pier und in verschiedenen Ansichten. Sinnvoll ist es, den Entwurf einzuscannen undin einem 3D-Modellingprogramm als Vorlage einzubinden, damit er mit einem Draht-gittermodell nachkonstruiert wird. Hierfür ist eine ausführliche Kenntnis anatomi-scher Formen nötig, um saubere Ergebnisse abzuliefern. Es empfiehlt sich, viel zuzeichnen, um ein Gefühl für die richtigen Proportionen zu bekommen. Je genauerSie die Anatomie kennen, desto besser bilden Sie sie im virtuellen Raum ab.

Page 331: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

331

Meshes j e t z t l e r n e i c h

Blitz Basic 3D liest Meshes in verschiedenen Formaten wie .3DS (3ds max), .X (DirectX)und .B3D (Blitz Basic ein). Manche Meshes haben zusätzliche Informationen, wie sieanimiert sind. So würden bei einem Roboter nicht nur sein Grundzustand, sondernauch Bewegungsschritte mitgeliefert. Mit LoadMesh() laden Sie einen Mesh ohne undmit LoadAnimMesh() mit diesen Angaben. Für Meshes im Format von »Quake 3« gibt esmit LoadBSP() einen eigenen Befehl.

Ähnlich wie bei den Primitives, legen Sie leicht eine beliebige Textur auf einen Mesh.Oftmals wird eine passende Textur gleich mitgeliefert. Die Mesh-Datei enthält dannden Dateinamen der Textur. Blitz Basic lädt in diesem Fall die Textur gleich mit und legtsie automatisch auf die Oberfläche des Mesh.

Für unser Beispiel schnappen wir uns einen der zu Blitz Basic 3D mitgeliefertenMeshes, einen Rallyewagen. Mit der Leertaste schalten wir die Drahtgitter-Ansicht einund aus.

; MESH.BBGraphics3D 1024,768SetBuffer BackBuffer()CreateCamera()

mesh = LoadMesh("rallycar1.3ds")PositionEntity mesh, 0, 0, 180

;wahlweise wird eine beliebige Textur aufgelegt;textur = LoadTexture("racetrack.bmp");EntityTexture mesh, textur

Repeat If KeyHit(57) Then Drahtgitter = Drahtgitter Xor 1 WireFrame drahtgitter TurnEntity mesh, 1, 1, 1 RenderWorld FlipUntil KeyHit(1)

Gerade für Spiele ist es wichtig zu wissen, wo die Grenzen für die Anzahl der verwen-deten Dreiecke innerhalb eines Objekts liegen. Es gilt: Je weniger Polygone, destoweniger Rechenleistung wird beansprucht. Sie müssen einen Mittelweg zwischenPerformance und Detailreichtum des Modells finden, um den Spielspaß zu bewahren.Große 3D-Modelle, die für Industrie und Filmbranche mit Programmen wie 3Ds ent-wickelt werden, sind ungeeignet für aktuelle Spiele, die mit verhältnismäßig wenigPolygonen auskommen müssen. Ein PC ist eben kein Großrechner. Ein Spiel wie»Quake 3: Arena« verwendet im Schnitt für eine Spielfigur tausend Dreiecke inner-halb eines Drahtgittermodells. Objekte, die detailliert mit Profiprogrammen erstelltwerden, haben zehn- bis hunderttausende Dreiecke. Sie würden momentan jede 3D-Engine sprengen. Zukünftige Spiele werden freilich mehr verarbeiten können.«

Page 332: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

332

3D-Grafik mit Blitz Basic 3D21j e t z t l e r n e i c h

Abb. 21.3:Körper, soge-

nannte Meshes,lassen sich mit

beliebigen Ober-flächen bekle-ben. Bei ferti-gen Objekten

wird die passen-de Textur oft

beigefügt.

Die Breite, Höhe und Tiefe des Mesh ermitteln die Befehle MeshWidth(), MeshHeight()und MeshDepth().

0

21.10 Sprites

Eine Sonderform grafischer Objekte ist das Sprite. Es handelt sich dabei um ein fla-ches Bitmap, das aus zwei Dreiecken zusammengesetzt ist. Dieses 2D-Bild lässt sichbesonders schnell berechnen. Es kann überall platziert werden. Egal, aus welcher Rich-tung man auf ein Sprite schaut: Man sieht immer die gleiche Vorderseite. Wandert manum ein Sprite herum, dreht es sich um seine eigene Achse. Sprites werden auch in 3D-Spielen eingesetzt, um einfache Objekte darzustellen, etwa Blätter von Bäumen. Beifrühen Ego-Shootern wie »Doom« war nur die Umgebung dreidimensional: Alle Cha-raktere und Gegenstände waren Sprites, die dem Spieler nur ihre Vorderseite zeigten.

LoadSprite() lädt eine Grafikdatei als Sprite in den Speicher. PositionEntity zeigt dasBild an.

; SPRITE.BBGraphics3D 640,480SetBuffer BackBuffer()camera = CreateCamera()sprite = LoadSprite("alien.bmp")PositionEntity sprite, 0, 0, 10

Repeat RenderWorld FlipUntil KeyHit(1)

Mit PositionMesh, ScaleMesh und RotateMesh wird ein Mesh nachträglich justiert.Meshes können Sie auch mit Blitz Basic 3D konstruieren. CreateMesh() erstellt einKörperobjekt. Es besteht aus Oberflächen, die CreateSurface() definiert. Die Punktejedes Polygons werden mit AddVertex() erstellt und mit AddTriangle() zu einem Drei-eck zusammengefügt.

Page 333: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

333

Kamera j e t z t l e r n e i c h

21.11 Kamera

In 2D zeigt der Frontbuffer das gesamte Geschehen an. Wenn es eine Kameralinse gä-be, dann würde sie den kompletten Bildschirm einfangen. In 3D kann aus jeder Rich-tung auf die Handlung geblickt werden. Es ist daher notwendig, den Blickwinkel zu be-stimmen. Dazu dienen Kameras. Eine Kamera in Blitz Basic unterscheidet sich kaumvon einer »echten« Videokamera. Sie hat

� einen Standort

� eine Richtung

� eine Zoomstufe

Um etwas zu sehen, muss mindestens eine Kamera erzeugt werden. Dazu dient der Be-fehl CreateCamera().

In einfachen Beispielen genügt es, den Befehl ohne Zusätze zu verwenden. Die Kame-ra wird an die Stelle 0, 0, 0 gerückt und zeigt den gesamten Bildschirm – das ähneltalso dem Auge in 2D-Spielen.

Es gibt eine ganze Reihe von Befehlen zur Steuerung einer Kamera. Um sie später an-zusprechen, setzen Sie CreateCamera() als Funktion ein. Die Kennung der erstelltenKamera speichern Sie in einer Variable:

kamera = CreateCamera()

Wie gewohnt, sprechen Sie die Kamera später über diese Variable an.

21.11.1 HintergrundFür jede Kamera legen Sie eine eigene Hintergrundfarbe fest, in den Einzelfarben Rot,Grün und Blau:

CameraClsColor kamera, 0,0, 255

Anders als bei 2D-Grafik müssen Sie sich um das Löschen des Bildschirms nicht küm-mern.

21.11.2 Sichtfeld festlegenDie meisten Spiele verwenden nur eine Kamera. Mehrere Kameras sind sinnvoll, wennSie etwa ein Mehrspieler-Spiel für einen PC programmieren, bei dem der Bildschirmin zwei oder vier Teile gesplittet wird (Split-Screen) und jeder Spieler seine eigene Sichtauf das Geschehen hat. Ein weiterer Einsatzzweck können Rückspiegel in einem Au-torennen sein. Mit CameraViewPort legen Sie einen Bereich des Bildschirms fest, in deneine Kamera ihr Bild zeichnet:

CameraViewport kamera, 0,0,512,384

2Vermeiden Sie, dass sich die Ansichten mehrerer Kameras überlappen. Ansonstenkommt es zu Anzeigefehlern.

Page 334: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

334

3D-Grafik mit Blitz Basic 3D21j e t z t l e r n e i c h

21.11.3 Zoomstufe festlegenEine Kamera kann stufenlos das Geschehen verkleinern oder vergrößern. Dazu dientder Befehl CameraZoom. Sie übergeben als Parameter die Kamera sowie eine Zoom-stufe. Werte unterhalb von 1 verkleinern das Bild, Zahlen größer als 1 bewirken eineVergrößerung.

Abb. 21.4:Kameras

werden beliebigplatziert, lassen

sich zoomenund auf einen

Bildschirm-ausschnitt

begrenzen.

In einem Beispiel testen wir Sichtfeld und Zoom. Wir erstellen zwei Kameras, die je einViertel des Bildschirms einnehmen. Die Kamera rechts unten lässt sich mit | und ~zoomen.

; KAMERA.BBGraphics3D 1024,768SetBuffer BackBuffer()mesh = LoadMesh("rallycar1.3ds")PositionEntity mesh, 0, 0, 180zoom# = 1

cam1 = CreateCamera()cam2 = CreateCamera()CameraViewport cam1, 0,0,512,384CameraViewport cam2, 512,384,512,384CameraClsColor cam1, 0,0,255CameraClsColor cam2, 255,0,0

Repeat TurnEntity mesh, 1, 1, 1 If KeyDown(208) And zoom > 0.2 Then zoom = zoom - 0.1 If KeyDown(200) And zoom < 10 Then zoom = zoom + 0.1

Page 335: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

335

Licht j e t z t l e r n e i c h

CameraZoom cam2, zoom RenderWorld FlipUntil KeyHit(1)

1

21.12 Licht

Um im 2D-Modus einen roten Kreis zu zeichnen, ändern Sie mit Color die Farbe. In3D sind Sie freilich ebenfalls nicht ewig auf Weiß angewiesen. Doch hier geht es edlerzu: Sie ändern nicht die Zeichenfarbe, sondern die Farbe des Lichts, das die Körper an-strahlt.

21.12.1 UmgebungslichtIm 3D-Modus können Sie verschiedene Lichtquellen positionieren, um Objekte anzu-strahlen. Ein Licht wird automatisch eingeschaltet: Das Umgebungslicht leuchtet alleKörper gleichmäßig mit einer bestimmten Farbe aus. Sie ist standardmäßig weiß, lässtsich aber mit dem Befehl AmbientLight ändern. Wie bei den anderen Farbbefehlenübergeben Sie die RGB-Werte als Parameter, also die Anteile von Rot, Grün und Blauauf einer Skala von jeweils 0 bis 255. Setzen Sie alle Werte auf 0, um das Umgebungs-licht auszuschalten. Stellen Sie die Zeile

AmbientLight 255, 0, 0

hinter den Befehl Graphic3D in einem der vorigen Beispiele, um den Körper in Rot dar-zustellen, selbst wenn er eine andersfarbige Textur haben sollte.

121.12.2 Örtliches LichtCreateLight() erstellt eine lokale Lichtquelle. Es gibt drei Arten:

� Directional Light (Richtungslicht) strahlt ein bestimmtes Ziel an.

� Point Light wirkt so ähnlich wie eine Taschenlampe.

� Spotlight ist ein Scheinwerfer – der große Bruder des Point Light.

Die Art übergeben Sie als Parameter (1, 2 oder 3). Ebenso wie Körper, wird ein Lichtan der Stelle 0,0,0 positioniert und kann von dort an jede Stelle gesetzt werden.

Mit CameraRange legen Sie eine Grenze fest, ab der keine Objekte mehr eingezeichnetwerden. Da nur nah gelegene Elemente zu sehen sind, beschleunigt sich der Bildauf-bau. Nachteil: Bewegt sich die Kamera durch das Geschehen, poppen Objekte plötz-lich auf. Mit einem künstlichen Nebel lässt sich der Effekt abmildern. CameraFogModeerzeugt einen solchen Nebel. CameraFogRange legt seinen Wirkungsbereich fest undCameraFogColor seine Farbe.

Das Umgebungslicht strahlt nur Objekte an. Es hat keinen Einfluss auf die Farbe desHintergrunds.

Page 336: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

336

3D-Grafik mit Blitz Basic 3D21j e t z t l e r n e i c h

Ein Licht wird nach Belieben mit LightColor eingefärbt. Dabei sind negative Wertemöglich, um eine Farbe abzudunkeln. Mit LightConeAngles legen Sie den Leuchtwinkelfest, mit LightRange den Bereich.

; LICHT.BBGraphics3D 1024,768SetBuffer BackBuffer()CreateCamera()

objekt = CreateCube()PositionEntity objekt, 0,0,6

licht = CreateLight(2)PositionEntity licht, -6,0,0LightColor licht, 255,0,0

Repeat TurnEntity objekt, 1, 1, 1 RenderWorld FlipUntil KeyHit(1)

121.13 Ebenen

Unendlich große, flache Ebenen nennt man Planes. Sie werden als Boden oder als De-cke verwendet. Sie können mehrere Planes übereinander legen. CreatePlane() erzeugteine Plane auf dem Boden. Sie müssen die Kamera etwas erhöhen, um sie zu sehen.Um eine Plane als Decke zu verwenden, drehen Sie sie um 180 Grad und verschiebensie nach oben. Damit sie sichtbar wird, weisen Sie ihr eine Textur zu. Um sich auf derPlane zu bewegen, ändern Sie die Kamera.

; PLANE.BBGraphics3D 1024,768SetBuffer BackBuffer()cam = CreateCamera()PositionEntity cam, 0,1,0

textur = LoadTexture("racetrack.bmp")boden = CreatePlane()decke = CreatePlane()EntityTexture boden, texturEntityTexture decke, texturRotateEntity decke, 0,0,180PositionEntity decke, 0,5,0

Repeat If KeyDown(203) Then MoveEntity cam, -0.02,0,0 If KeyDown(205) Then MoveEntity cam, +0.02,0,0 If KeyDown(200) Then MoveEntity cam, 0,0,+0.02 If KeyDown(208) Then MoveEntity cam, 0,0,-0.02

In unseren einfachen Programmen kommen diese Befehle nicht so gut zur Geltung.In komplexen 3D-Spielen tragen aber unterschiedliche Lichtverhältnisse entschei-dend zur Atmosphäre bei.

Page 337: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

337

Terrains j e t z t l e r n e i c h

RenderWorld FlipUntil KeyHit(1)

Abb. 21.5:Planes sind un-endlich große Flächen.

In einer leicht erweiterten Form des Programms (PLANE2.BB) nehmen wir zwei Än-derungen vor: { und } drehen die Karte die seitlich und die Leertaste schaltet denNebeleffekt ein und aus.

21.14 Terrains

Ein Terrain ist ebenfalls eine große Fläche. Es unterscheidet sich in zwei Punkten voneiner Plane: Es hat Grenzen und ist nicht eben, sondern hat Höhen und Tiefen. Ter-rains eignen sich damit sehr gut zur Darstellung eines bergigen Geländes. Es gibt zweiMöglichkeiten, um die jeweiligen Höhen mitzuteilen: Sie laden eine fertige Datei, eineHeightmap. Oder Sie erstellen ein ebenes Terrain und legen die Höhen und Tiefenmanuell fest.

Das Erstellen eines Terrains ähnelt dem einer Plane:

terrain = CreateTerrain(64)textur = LoadTexture("block3.bmp")EntityTexture terrain, textur

Als Parameter übergeben Sie die Größe des Terrains in Feldern je Seitenlänge. Daskleinste Terrain ist ein Feld groß; danach sind nur Vielfache von 2 möglich: 2, 4, 16 ...Ein Terrain in einer Größe von 64 hat demnach 64 x 64 = 4096 Felder. Die Feldgrößelässt sich mit ScaleEntity ändern.

Page 338: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

338

3D-Grafik mit Blitz Basic 3D21j e t z t l e r n e i c h

Felder werden über ihre X- und Y-Koordinate angesprochen. Dabei handelt es sichnicht um Pixel, sondern um die waagerechte und senkrechte Feldnummer auf dem ...Schachbrett. Jedes Feld kann eine Höheninformation haben. Sie liegt zwischen 0 und1, wobei 0 dem Boden entspricht. Negative Werte sind nicht möglich; man kann dahernur Berge, aber keine Täler erzeugen. ModifyTerrain ändert die Höhe eines Feldes.Wahlweise findet dieses »Terraforming« sofort oder, für alle Felder zusammen, nachdem Befehl RenderWorld statt.

; TERRAIN.BBgroesse = 64Graphics3D 1024,768SetBuffer BackBuffer()cam = CreateCamera()PositionEntity cam, 0,1.5,0

terrain = CreateTerrain(groesse)textur = LoadTexture("block3.bmp")EntityTexture terrain, textur

For i=1 To groesse * groesse / 2 ModifyTerrain terrain, Rand(groesse), Rand(groesse), Rnd(-1,+1)Next

Repeat If KeyDown(203) Then TurnEntity cam, 0,+0.5,0 If KeyDown(205) Then TurnEntity cam, 0,-0.5,0 If KeyDown(200) Then MoveEntity cam, 0,0,+0.02 If KeyDown(208) Then MoveEntity cam, 0,0,-0.02 RenderWorld FlipUntil KeyHit(1)

Abb. 21.6:Ein Terrain isteine endliche

Fläche mitHöhen.

Page 339: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

339

Ausblicke j e t z t l e r n e i c h

021.15 Ausblicke

Dieses Kapitel war eine knappe Einführung in die 3D-Grafik. Sie setzen damit einfacheObjekte in Szene, sind aber weit davon entfernt, ein 3D-Spiel zu entwerfen. Wir habennur an der Oberfläche dessen gekratzt, was die Entwicklung eines 3D-Spiels ausmacht.Eine detaillierte Behandlung von 3D würde ein ganzes Buch wie dieses füllen. Für denAnfang rate ich Ihnen zu 2D-Spielen; sie sind erheblich einfacher umzusetzen.

21.16 Aufgabe

1. Erstellen Sie ein Terrain. Setzen Sie eine Handvoll verschiedenfarbiger Primitivesan zufällige Positionen. Schreiben Sie eine Kamerasteuerung, die in der oberenHälfte des Bildschirms nach vorn und in der unteren Hälfte nach hinten (wie bei ei-nem Rückspiegel) schaut.

Sie können ein Terrain wie jedes andere Objekt mit EntityRotate in jede Richtungdrehen. Das ist vor allem für Flugsimulationen interessant, um den Eindruck zu erwe-cken, man würde frei durch die Lüfte gleiten.

Page 340: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 341: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

341

jetz

t le

rne

ich

KAPITEL 22

ABedienoberflächen mit Blitz Plus

Eine entscheidende Neuerung von Blitz Plus sind die mehr als hundert Befehle zumProgrammieren einer grafischen Bedienoberfläche (GUI), mit den Windows-typischenFenstern, Schaltern und Eingabefeldern. Ähnlich wie einen Spielbildschirm bauen Sieein GUI-Fenster auf, indem Sie jedes der Elemente einzeln zeichnen.

1Mit diesen Befehlen lassen Sie Spiele im Windows-typischen Fenstermodus ablaufenund programmieren Anwendungen. Noch fehlen Blitz Basic Möglichkeiten zum aus-giebigen Nutzen von Systemressourcen. Jedoch werden die GUI-Funktionen alsjüngste Mitglieder der großen Befehlsfamilie von Blitz Basic rasch ausgebaut. Diedem Buch beiliegende Demoversion von Blitz Plus kennt nicht alle der hier vorgestell-ten Anweisungen. Einige wurden erst mit der Version 1.34 eingeführt.

GUI ist die Kurzform von Graphical User Interface. Das wird gern mit Grafische Be-nutzeroberfläche übersetzt, doch wer sich den Begriff auf der Zunge zergehen lässt,muss feststellen, dass die Benutzeroberfläche ja unsere Haut ist. :-) Die Kontroll-elemente wie Fenster, Menüs und Schalter nennt man Gadgets. Das englische Wortheißt soviel wie Ding oder Gerät. Verbreitet ist auch der Begriff Widgets für WindowGadgets.

Sie brauchen nicht unbedingt Blitz Plus, um eine Bedienoberfläche zu verwenden. Esgibt eine Reihe von Funktionsbibliotheken, die Blitz Basic (3D) um Befehle ergänzen,wie sie in diesem Kapitel vorgestellt werden. Ein Beispiel ist BlitzUI (www.legacy-games.co.uk, auf der Buch-CD).

Page 342: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

342

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

22.1 Fenster erstellen

Mit einem Befehl pinnen Sie ein Fenster auf den Bildschirm:

CreateWindow ("BlitzTest", 100,100, 300,200)WaitMouse

Erwartungsgemäß wird es an die Koordinaten 100,100 gesetzt und ist 300x200 Punktegroß. Wie in ähnlichen Situationen sollten Sie die Funktion mit einer Variablenzuwei-sung verbinden, mit der wir später auf das Fenster zugreifen. Als Parameter verwendenSie:

� den Namen des Fensters, der in der Titelleiste erscheint

� die Anfangskoordinaten

� die Größe

sowie wahlweise

� die übergeordnete Gruppe (dazu später mehr, normal 0)

� Eigenschaften des Fensters

Die Eigenschaften werden mit einer Zahl angegeben, der Summe folgender Attribute

Fehlt die Angabe der Eigenschaft, geht Blitz Basic von 1 + 2 + 4 + 8 = 15 aus.

022.1.1 Größe verändernEin erstelltes Fenster lässt sich auf vielfältige Weise beeinflussen. Mit einem Befehl wirdes etwa maximiert, also über den gesamten Bildschirm gezogen.

1 Titelleiste vorhanden

2 Fenstergröße lässt sich ändern

4 Fenster hat ein Menü

8 Fenster hat (unten) eine Statusleiste

16 Werkzeug-Fenster mit kleinerer Titelleiste, das nicht in der Taskleiste erscheint

32 Fenstergröße »netto«, ohne Berücksichtigung des Rands

Um zu verhindern, dass ein Fenster in der Taskleiste erscheint, selbst wenn es ver-kleinert wird, weisen Sie ihm als Gruppe ein anderes Fenster zu. Den Namen des Ti-tels ändern Sie später mit SetGadgetText.

ActivateWindow fenster Fenster hervorheben (aktivieren)

MaximizeWindow fenster Fenster maximieren

MinimizeWindow fenster Fenster minimieren

RestoreWindow ursprüngliche Größe eines Fensters wiederherstellen

SetMinWindowSize fenster [, größe, höhe] Mindestgröße für das Fenster angeben

Page 343: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

343

Menüs j e t z t l e r n e i c h

Lassen Sie bei SetMinWindowSize die Größe weg, verwendet Blitz Basic die aktuelleGröße des Fensters. Es kann damit nicht kleiner gemacht werden, als es derzeit ist.

22.1.2 Größe abfragenMit drei ähnlichen Funktionen fragen Sie die Fenstergröße ab. Sie geben »wahr«(also 1) zurück, wenn die entsprechende Bedingung erfüllt wird.

22.1.3 Statuszeile ändernDie Statuszeile im unteren Bereich wird für verschiedene Zwecke genutzt. Sie bieteteine Kurzangabe über den ausgewählten Menüpunkt, eine Prozentangabe oder infor-miert über aktivierte Optionen. Sie ändern sie jederzeit mit

SetStatusText fenster, text$

Freilich müssen Sie dazu ein Fenster mit Statusleiste erstellt haben.

; STATUSZEILE.BBfenster = CreateWindow ("BlitzTest", 100,100, 300,200)SetStatusText fenster, "Alles im Rahmen normaler Parameter"WaitMouse

2 Abb. 22.1:Die Statuszeile eines Fensters kann unter anderem als Mini-Hilfe zu Menüpunkten verwendet werden.

22.2 Menüs

Ein Menü besteht aus einem Namen (wie DATEI) und den dazugehörigen Menüpunkten.Diese Menüpunkte können zugleich selbst Menüs sein, indem bei der Auswahl eineweitere Menüebene ausgeklappt wird. Jedes Menü und jeder Menüpunkt wird einzelnmit der Funktion CreateMenu() erstellt.

WindowMaximized(fenster) Fenster maximiert?

WindowMinimized(fenster) Fenster minimiert?

WindowActivated(fenster) Fenster hervorgehoben (aktiviert)?

Der Mausklick wird nur erkannt, wenn sich der Mauszeiger im Innern des Fensters be-findet. Die Tastaturbefehle funktionieren nur, wenn kein Gadget (zum Beispiel einSchalter) ausgewählt ist.

Page 344: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

344

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

Sie erwartet drei Parameter ...

� den Namen des Menüs oder Menüpunkts

� eine selbst ausgewählte ID-Nummer

� die Kennziffer des Eltern-Menüs

... und liefert eine Kennziffer zurück. Wie bei Dateien oder Bildern greifen Sie über dieKennziffer (Handle) auf den Menüpunkt zurück.

Zusätzlich wird zu jedem Eintrag eine zweite Nummer festgelegt, die Sie selbst auswäh-len. Sie hat einen ähnlichen Zweck wie die Kennziffer; über sie erfahren Sie, welcherMenüpunkt ausgewählt wurde. Der Einfachheit halber nummerieren Sie die Einträge:Menü 1 bekommt die 10, Menüpunkt 1 von Menü 1 die 11, Menüpunkt 2 von Menü1 die 12, Menü 2 die 20 usw.

Die Kennziffer des Eltern-Menüs ist bei Menüpunkten einfach das Menü, zu dem sie ge-hören. Bei einem Hauptmenü (wie DATEI, BEARBEITEN, ANSICHT) muss ebenfalls eineKennziffer angegeben werden, damit klar wird, zu welchem Fenster es gehört. Zu die-sem Zweck übermittelt Blitz Basic mit der Funktion WindowMenu() die Kennung einesscheinbaren Grundmenüs, dem die Hauptmenüpunkte zugeordnet werden.

Nach dem Erzeugen oder Verändern von Menüpunkten wird die Anzeige mit Update-WindowMenu aktualisiert. Als Parameter wird die Kennziffer des entsprechenden Fens-ters angegeben.

Drei Zeilen sind somit notwendig, um ein Fenster zu erzeugen, das ein Hauptmenü ent-hält:

; MENU1.BBfenster = CreateWindow ("BlitzTest", 100,100, 200,100)menu = CreateMenu ("Datei", 10, WindowMenu(fenster))UpdateWindowMenu fensterWaitMouse

Abb. 22.2:Hauptmenü-

punkt

Das Hauptmenü füllen wir leicht mit Menüpunkten:

; MENU2.BBfenster = CreateWindow ("BlitzTest", 100,100, 200,100)menu10 = CreateMenu ("Datei", 10, WindowMenu(fenster))menu20 = CreateMenu ("Bearbeiten", 20, WindowMenu(fenster))menu30 = CreateMenu ("Ansicht", 30, WindowMenu(fenster));menu11 = CreateMenu ("Laden ...", 11, menu10)menu12 = CreateMenu ("Speichern", 12, menu10);UpdateWindowMenu fensterWaitMouse

Page 345: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

345

Menüs j e t z t l e r n e i c h

Abb. 22.3:Aufgeklapptes Hauptmenü

Es bietet sich an, die Variablen für die Kennziffern genauso zu nennen wie die selbstausgewählte ID-Nummer, also menu10 und 10 für das erste Hauptmenü.

22.2.1 Menüpunkt (de)aktivierenManche Menüpunkte sollen vorübergehend ausgeschaltet sein. Das ist nützlich fürFunktionen, die nur in bestimmten Bereichen des Programms Sinn machen, oder umin einer Testversion zu demonstrieren, welche Menüpunkte zusätzlich in der Vollver-sion zur Verfügung stehen. Sie werden dann grau dargestellt und lassen sich nicht an-wählen. DisableMenu schaltet einen Menüpunkt in diesen Modus. EnableMenu aktiviertden Einträg wieder. Um die Änderung wirksam werden zu lassen, müssen Sie danachUpdateWindowMenu verwenden.

Eine verwandte Darstellung ist das Setzen eines Häkchens neben einem Menüpunkt,um eine Funktion ein- oder auszuschalten. Das erreichen Sie mit CheckMenu, währendUncheckMenu den Haken wieder entfernt. Auch hier muss am Ende UpdateWindowMenuerfolgen.

; MENU3.BBfenster = CreateWindow ("BlitzTest", 100,100, 200,100)menu10 = CreateMenu ("Datei", 10, WindowMenu(fenster))menu11 = CreateMenu ("Laden ...", 11, menu10)menu12 = CreateMenu ("Speichern", 12, menu10)menu13 = CreateMenu ("Ohne Nachfrage", 13, menu10)DisableMenu menu12CheckMenu menu13UpdateWindowMenu fensterWaitMouse

Abb. 22.4:Menü mit einem deaktivierten und einem angehakten Menüpunkt

Mit den Funktionen MenuEnabled() und MenuChecked() überprüfen Sie den Status einesMenüpunkts – sie liefern »wahr« (also 1) zurück, wenn der fragliche Menüpunkt aktiviertbzw. mit einem Häkchen versehen ist.

2Normalerweise lässt sich der Haken setzen und wieder entfernen, indem der Menü-punkt einfach angeklickt wird. Dieses Verhalten muss in Blitz Basic programmiertwerden. Dazu kommen wir etwas später, wenn wir Menüpunkte mit Funktionen be-legen. Im Unterschied dazu können »ausgeschaltete« Menüpunkte tatsächlich nichtausgewählt werden. Hier ist kein entsprechender Test notwendig. Hauptmenüs wieDATEI können nicht mit einem Haken versehen werden. In der Version 1.10 lassen siesich auch nicht ausschalten; erst ab Version 1.34 ist das möglich.

Page 346: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

346

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

22.2.2 Name eines Menüpunkts ändernIn einigen Fällen ist es sinnvoll, die Bezeichnung eines Menüpunkts zu ändern. Das er-reichen Sie mit SetMenuText. Übergeben Sie dem Befehl die Kennziffer des Menü-punkts und den neuen Namen als Zeichenkette. Auch hier ist im Anschluss UpdateWin-dowMenu notwendig.

Sie sollten allerdings sparsam damit umgehen, da es den Benutzer Ihrer Programmeverwirren kann, wenn sich am gleichen Platz verschiedene Menüpunkte befinden. EineMöglichkeit wäre, die Bezeichnung als Schalter zu wählen, etwa einen Menüpunkt MitNachfrage zu nennen und den Namen durch Anklicken in Ohne Nachfrage zu än-dern. Ich halte das allerdings für nicht eindeutig genug: Der Benutzer erwartet, dass ereinen Menüpunkt Mit Nachfrage anklickt, um ihn mit einem Haken zu versehen undsomit zu aktivieren – nicht, um seine Bedeutung umzukehren.

22.3 Toolbars

Eine Alternative zu Menüpunkten aus Text sind grafische Werkzeugleisten, neudeutschToolbars. Auch der Editor von Blitz Basic hat eine solche Toolbar. Wir »missbrauchen«sie frecherweise für unser Beispiel.

Abb. 22.5:Eine Toolbar:Symbole stattMenüpunkte

Das Einsetzen einer Toolbar erfolgt so ähnlich wie bei den Stufen eines animiertenBilds mit LoadAnimImage(): Sie benötigen eine Grafikdatei, die alle Icons in gleicherGröße nebeneinander enthält. Mit CreateToolBar() wird sie in den Speicher geladenund sofort angezeigt. Die Funktion liefert eine Kennziffer zurück und erwartet folgendeParameter:

� Dateinamen der Toolbar

� Koordinaten zum Platzieren der Toolbar innerhalb des Fensters

� Breite und Höhe eines Icons

� übergeordnetes Fenster (bzw. anderes Gruppen-Gadget)

Anhand der Breite errechnet Blitz Basic die Anzahl der Symbole selbständig.

; TOOLBAR.BBfenster = CreateWindow ("BlitzTest", 100,100, 300,100)menu = CreateMenu ("Datei", 10, WindowMenu(fenster))toolbar = CreateToolBar ("c:\blitzplus\cfg\ide_toolbar.bmp", 0,0, 16*12, 16, fenster)UpdateWindowMenu fensterWaitMouse

Eine Toolbar ist ein transparentes Bild. Welche Farbe durchsichtig dargestellt wird, ent-scheidet Blitz Basic anhand des oberen linken Punkts in der Grafik. Derzeit werden nurwaagerechte Werkzeugleisten unterstützt.

Page 347: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

347

Ereignisse j e t z t l e r n e i c h

22.3.1 Toolbar beschriftenEin Bild sagt mehr als tausend Worte, heißt es. Manche Symbole verwirren aber eher,als dass sie aufklären. Sinnvoll ist eine Beschriftung: Fährt die Maus über ein Symbol(ohne es anzuklicken), erscheint ein kleiner Text und beschreibt den Sinn des Symbols.Mit SetToolBarTips fügen Sie Ihrer Toolbar eine derartige Beschriftung hinzu. Alle Be-schreibungen müssen, durch Komma getrennt, in einer Zeichenkette stehen. Dabeikönnen Sie einzelne Symbole auslassen, indem Sie zwei Kommas hintereinander set-zen. Gibt es weniger Beschreibungen als Icons, bleiben die letzten Symbole ohne hilf-reiche Erklärung.

Abb. 22.6:Eine eigene Toolbar mit Mini-Hilfe

22.3.2 Icons deaktivierenÄhnlich wie bei Menüpunkten lassen sich einzelne Symbole einer Toolbar deaktivieren.Sie werden dann grau dargestellt. Sie übergeben dazu dem Befehl DisableToolBarItemdie Kennziffer der Toolbar sowie die Nummer des gewünschten Symbols. Dabei ist 0das erste Symbol von links, 1 das zweite usw.

Umgekehrt aktiviert EnableToolBarItem ein Symbol wieder. Anders als bei Menüpunk-ten werden die Änderungen sofort wirksam. Es ist kein UpdateWindowMenu notwendig.

22.4 Ereignisse

Bisher sind unsere Menüs nur eine grafische Hülle. Sie müssen noch mit Funktionenbelegt werden. Die Auswahl eines Menüpunkts (oder etwa eines Schalters) ist in BlitzBasic ein Ereignis oder englisch Event.

Die Funktion WaitEvent() wartet auf ein Ereignis und teilt in Form einer Zahl mit, umwas es sich handelt. Die Liste aller Ereignisse finden Sie im Anhang. Die wichtigstensind:

$1001 Menüpunkt ausgewählt

$401 Gadget (z.B. Schalter betätigt)

$801 Fenster wird verschoben

$802 Fenstergröße wird verändert

$803 Fenster wird geschlossen

$804 Fenster wird hervorgehoben (aktiviert)

Page 348: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

348

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

Eine Handvoll weiterer Funktionen führt Details zum Ereignis auf:

� EventSource() nennt die Kennziffer der Quelle, die das Ereignis ausgelöst hat. Da-mit erfahren Sie, welcher Schalter betätigt oder welches Fenster bewegt wurde.

� EventData() teilt weitere Angaben mit, zum Beispiel den Menüpunkt, der ausge-wählt wurde.

� EventX(), EventY() und EventZ() benennen bei bestimmten Ereignissen neue Ko-ordinaten, etwa beim Bewegen von Fenstern und dem Mauszeiger.

Weniger gebräuchlich sind:

� EventId() nennt das Ereignis, das zuvor mit WaitEvent() ausgelesen wurde. Daman diesen Wert aber sowieso in einer Variable speichert, ist die Funktion über-flüssig.

� PeekEvent() schaut nach, ob ein Ereignis vorhanden ist, das mit WaitEvent() »ab-geholt« werden kann.

� FlushEvents löscht alle anstehenden Ereignisse eines Typs.

Im Grafikmodus bauen Sie den gesamten Bildschirm mehrmals je Sekunde auf. BeiGUIs hingegen warten Sie auf ein Ereignis und werten es aus. Jederzeit können Gad-gets hinzugefügt, geändert oder gelöscht werden, unabhängig vom Rest des Bild-schirms. Alles, was Sie dazu benötigen, ist eine kleine Schleife, die WaitEvent() abfragtund alle Ereignisse auswertet, die wichtig sind für das jeweilige Programm. DieseSchleife zum Auslesen und Verarbeiten von Ereignissen nennt man Event Handler:

Repeat ereignis = WaitEvent() Select ereignis Case ... Case ... End CaseForever

Testen wir einige Ereignisse. Sicher ist Ihnen aufgefallen, dass wir unsere Blitz-Plus-Fenster verkleinern, vergrößern und verschieben, nicht aber schließen können. BeimKlick auf das Kreuz passiert genauso wenig wie mit Ç+Ì. Der Sinn: Dem Pro-grammierer soll Gelegenheit gegeben werden, auf ein erzwungenes Programmende zureagieren, zum Beispiel durch eine Sicherheitsabfrage oder das Speichern von offenenDateien.

Unser Beispiel beendet sich mit einem Klick auf das Schließen-Symbol. Beim Verschie-ben erfolgt die Anzeige der aktuellen Position, beim Verändern der Größe werden diederzeitigen Maße angezeigt.

; EVENT.BBfenster = CreateWindow ("BlitzTest", 100,100, 200,100)Repeat ereignis = WaitEvent() Select ereignis Case $803 End Case $801 SetStatusText fenster, "Position " + EventX() + "," + EventY() Case $802 SetStatusText fenster, "Größe " + GadgetWidth(fenster) + "x" + GadgetHeight(fenster) Case $2005 SetStatusText fenster, "Stillstand." End SelectForever

Page 349: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

349

Hotkeys j e t z t l e r n e i c h

Kümmern wir uns nun um die Steuerung eines Menüs. Wir entscheiden mithilfe einesHakens, ob ein Menüpunkt (EXPERTEN-OPTIONEN/GEHEIM-MENÜ) zugänglich ist. Dazuprüfen wir, ob der Punkt (OPTIONEN/GEHEIM-MENÜ EIN) mit einem Haken versehen ist. Indiesem Fall nehmen wir ihn weg und deaktivieren das Geheim-Menü. Gibt es noch kei-nen Haken, setzen wir ihn und aktivieren das Geheim-Menü. Beim Anklicken von ENDE

wird das Programm beendet – eine leichte Übung.

; MENU4.BBfenster = CreateWindow ("BlitzTest", 100,100, 300,100)menu10 = CreateMenu ("Optionen", 10, WindowMenu(fenster))menu11 = CreateMenu ("Geheim-Menü ein", 11, menu10)menu20 = CreateMenu ("Experten-Optionen", 20, WindowMenu(fenster))menu21 = CreateMenu ("Geheim-Menü", 21, menu20)menu30 = CreateMenu ("Ende", 30, WindowMenu(fenster))DisableMenu menu21UpdateWindowMenu fenster;Repeat ereignis = WaitEvent() wahl = EventData() If ereignis = $1001 Then Select wahl Case 30 ; "Ende" End Case 11 ; "Geheim-Menü ein" If MenuChecked(menu11) Then UncheckMenu menu11 DisableMenu menu21 Else CheckMenu menu11 EnableMenu menu21 EndIf End Select UpdateWindowMenu fenster EndIf Forever

22.5 Hotkeys

Per Hotkey erreicht der Benutzer mit einem Tastendruck häufig verwendete Menüsund Funktionen. Leicht fügen Sie Ihren Programmen Tastenkürzel hinzu. Sie umgehendamit manche Einschränkung von Blitz Basic. So funktionieren in Eingabefeldern fürText typische Steuertasten wie Å zum Wechseln in das nächste Feld nicht.

Mit HotKeyEvent weisen Sie einer Taste, gegebenenfalls zusammen mit Á, Ÿ oderÇ, ein Ereignis zu. Es kann sich dabei um eine Nummer handeln, die bereits vonBlitz Basic verwendet wird, oder um eine erdachte Zahl, die Sie später auswerten. DieParameter:

� Scancode der Taste

� Steuertasten (0 – ohne, 1 – Á, 2 – Ÿ, 4 – Ç; Mehrfachwahl durch Addition)

� Nummer des aufzurufenden Ereignisses

Page 350: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

350

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

sowie wahlweise:

� Daten für EventData()

� Daten für EventX()

� Daten für EventY()

� Daten für EventZ()

� Daten für EventSource()

Unser Mini-Menü MENU4.BB erweitern Sie mit zwei Zeilen um die Hotkeys Ç+G undÇ+X:

; MENU5.BB...HotKeyEvent 34, 4, $1001, 11HotKeyEvent 45, 4, $1001, 30...

Sie reagieren genauso, wie wenn der Benutzer die Menüpunkte DATEI/GEHEIM-MENÜ EIN

und ENDE mit der Maus ausgewählt hätte.

22.6 Gadgets

Auf den kommenden Seiten beschreiben wir nach und nach alle Gadgets – die Kon-trollkomponenten für GUIs: Schalter, Listen, Scrollbalken, Info-Fenster ... Blitz Basicbietet eine Reihe von Befehlen, die sich auf alle Gadgets beziehen. Als Parameter über-geben Sie meistens nur die Kennziffer des betreffenden Gadget. Einige der Funktionenwerden Sie häufig verwenden, vor allem das Hervorheben und Beschriften vonGadgets. Andere benötigen Sie dagegen nur selten.

ActivateGadget hebt ein Gadget hervor. Unter Windows ist die Å-Taste dafür zuständig. Ist ein Schalter hervorgehoben, genügt ein Druck auf die Leertaste, um ihn zu aktivieren. Ein markiertes Eingabefeld enthält den Cursor, so dass sofort losgeschrieben werden kann. In Blitz Basic müssen allerdings Windows-typische Tasten eigens programmiert werden.

HideGadget lässt ein Gadget vom Bildschirm verschwinden. So werden vorübergehend Elemente entfernt, ohne sie zu löschen.

ShowGadget lässt ein durch HideGadget verstecktes Gadget wieder erschei-nen.

DisableGadget deaktiviert ein Gadget. Es wird grau dargestellt, lässt sich nicht mehr auswählen und liefert keine Ereignisse.

EnableGadget aktiviert ein Gadget wieder.FreeGadget entfernt ein Gadget und löscht es aus dem Speicher.GadgetGroup() liefert die Kennziffer der Gruppe, zu der ein Gadget gehört; zum

Beispiel des Fensters, in dem sich ein Schalter befindet.GadgetHeight() liefert die Höhe eines Gadget in Bildpunkten.GadgetWidth() liefert die Breite eines Gadget in Bildpunkten.

Page 351: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

351

Gruppen und Panele j e t z t l e r n e i c h

22.7 Gruppen und Panele

Vier der vielen Gadget-Arten haben eine Besonderheit: Sie dienen als Eltern oderGruppe für andere Gadgets. Jedes Gadget gehört zu einer dieser Gruppen:

� Die meisten Gadgets werden in einem Fenster platziert.

� Eine Sonderform davon ist das Canvas-Fenster, das wir am Schluss dieses GUI-Kapitels besprechen. Es erlaubt das Zeichnen von Grafiken im Fenstermodus.

� Tabber oder Register sind ebenfalls Eltern für Gadget-Elemente. Auch sie werdenwir detailliert vorstellen.

� Die letzte Gruppe sind Panele, Container-Objekte.

Ein Panel kann man sich als unsichtbaren Karton für Gadget-Elemente vorstellen. An-statt Schalter und Eingabefelder direkt in ein Fenster zu setzen, steckt man sie in einPanel. Dieses Panel wird dann dem Fenster zugewiesen. Der Vorteil: Viele Elementewerden zu einem Object zusammengefasst und können mit einem Befehl gesetzt undwieder entfernt werden.

Ein Panel wird mit CreatePanel() erstellt. Es erwartet die vier Größenkoordinaten so-wie die Gruppe, zu der es gehört. Wird als sechster Parameter eine 1 übergeben, erhältdas Panel einen Rahmen. Mit SetPanelColor() und SetPanelImage() bekommt einPanel eine Hintergrundfarbe oder eine Hintergrundgrafik.

; PANEL.BBfenster = CreateWindow ("Panel", 100,100, 200,200)panel = CreatePanel (0,0, 190,100, fenster,1)SetPanelColor panel, 180,60,60WaitMouse

Die Funktionen ClientWidth() und ClientHeight() ermitteln die Breite und Höhe ei-nes Gruppen-Gadget. Dabei wird nur die nutzbare Fläche berücksichtigt, ohne Rand.Bei »normalen« Gadgets wie Schaltern lassen sie sich nicht anwenden.

GadgetX() liefert die X-Koordinate eines Gadget innerhalb seiner Gruppe (zum Beispiel Fenster).

GadgetY() liefert die Y-Koordinate eines Gadget innerhalb seiner Gruppe (zum Beispiel Fenster).

SetGadgetText beschriftet ein Gadget (neu). Nicht bei allen Gadgets ist Text möglich.

GadgetText() liefert die Beschriftung eines Gadget.SetGadgetShape verändert die Größe eines Gadget.SetGadgetFont stellt eine (mit LoadFont() geladene) Schriftart ein.SetGadgetLayout legt die Verankerung eines Gadget innerhalb seiner Gruppe fest.

Dadurch wird bestimmt, wie und in welche Richtung sich das Gadget skaliert, wenn sich die Größe der Gruppe verändert.

Page 352: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

352

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

22.8 Schalter

Ein Schalter dient zum Auswählen von Optionen oder zum Beantworten von Fragen.CreateButton() zeichnet einen Schalter. Die Funktion erwartet

� eine Beschriftung

� die Startkoordinaten

� die Breite und Höhe

� die Gruppe, zu der der Schalter gehört

sowie wahlweise

� die Art des Schalters

Die folgende Tabelle fasst die verschiedenen Arten von Schaltern zusammen.

Typ 2 und 3 sind sich einander ähnlich. Doch während sich eine Checkbox unabhän-gig von anderen Schaltern ein- und ausschalten lässt, treten Radio-Schalter immer ge-meinsam auf: Nur ein Schalter lässt sich jeweils aktivieren. (Man sagt, der Schalter hät-te seinen Namen nach alten Röhrenradios, bei denen immer eine Taste gedrückt seinmusste.)

; SCHALTER.BBfenster = CreateWindow ("Schalter", 100,100, 430,100)schalter1 = CreateButton ("Klick-Schalter", 5,5, 100,20, fenster, 1)schalter2 = CreateButton ("Auswahl-Schalter", 155,5, 100,20, fenster, 2)schalter3 = CreateButton ("Radio-Schalter", 305,5, 100,20, fenster, 3)WaitMouse

Abb. 22.7:Die drei

Schalterartenim Vergleich

Erstellte Checkboxen und Radio-Schalter sind »leer«. Mit SetButtonState legen Sie fest,ob ein Schalter vorausgewählt ist. Übergeben Sie dem Befehl die Kennziffer des Schal-ters sowie eine 1 für »ja« oder eine 0 für »nein«:

SetButtonState schalter, 1

1 normaler Schalter zum Anklicken (Button, Standard)

2 Schalter zum Ankreuzen (Checkbox)

3 Radio-Schalter (Radiobutton)

Page 353: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

353

Textausgabe j e t z t l e r n e i c h

22.8.1 Schalter auswertenDas Betätigen eines Schalters ist ein Ereignis. Es hat die Nummer $401. Mit der Funk-tion EventSource() ermitteln Sie, welcher Schalter betätigt wurde. Damit führen Sieauf Schalterdruck eine Funktion aus:

; SCHALTER2.BBfenster = CreateWindow ("BlitzTest", 100,100, 150,100)schalter = CreateButton ("Programm beenden", 15,5, 100,20, fenster, 1)Repeat ereignis = WaitEvent() If ereignis = $401 And EventSource() = schalter Then EndForever

Üblicherweise werden Checkboxen und Radio-Schalter erst ausgewertet, wenn der Be-nutzer einen Bestätigungsschalter wie »Ok« oder »Übernehmen« gedrückt hat. BeimÜberprüfen der Veränderungen lässt sich mit der Funktion ButtonState() im Nach-hinein abfragen, ob ein Schalter aktiviert ist oder nicht.

0

22.9 Textausgabe

Jede Stelle Ihres Programms lässt sich mit Text beschriften. Sie verwenden dazuCreateLabel(), das eine Zeichenkette an eine festgelegte Stelle eines Gadget (zum Bei-spiel eines Fensters) setzt:

; LABEL.BBfenster = CreateWindow ("Label", 100,100, 200,130)satz$ = "Vielen Dank," + Chr$(13) + "dass Sie dieses Fenster benutzt haben."label = CreateLabel (satz$, 5,5, 195,50, fenster)WaitMouse

Abb. 22.8:Label sind einfache Texte, die sich nicht anklicken las-sen und keine Ereignisse generieren.

Der Text fügt sich genau in die angegebenen Maße. Dabei erfolgt am Zeilenende auto-matisch ein Zeilenumbruch. Mit Chr$(13) erzwingen Sie einen Umbruch an einer be-stimmten Stelle. Ist das Fenster zu klein, wird nur ein Teil des Textes angezeigt. EinLabel ist »passiv«; es löst keine Ereignisse aus. Mit DisableGadget stellen Sie den Text»deaktiviert« dar.

Ein zusätzlicher Parameter rahmt den Text ein: 1 liefert einen schwarzen Rahmen, 3eine 3D-Umrandung. Meistens wirkt die Ausgabe aber besser ohne Begrenzung.

Normalerweise können Sie je Gruppe (Fenster) nur einen Satz Radio-Schalter ver-wenden, weil nur ein Schalter aktiv sein kann. Um mehrere voneinander unabhängi-ge Blöcke nebeneinander zu platzieren, stecken Sie sie jeweils in ein Panel und setzendie Panele in das Fenster.

Page 354: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

354

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

22.10 Texteingabe

Tastatureingaben des Benutzers nimmt ein Textfeld entgegen. Sie haben die Wahl zwi-schen einem ein- und einem mehrzeiligen Eingabefeld.

22.10.1 TextFieldDas TextField ist nur eine Zeile lang und ähnelt daher Input():

eingabe = CreateTextField (5,20, 180,20, fenster)

Geben Sie als weiteren Parameter 1 an, werden statt der Eingaben nur Sternchen an-gezeigt, um Passwörter vor fremden Blicken zu schützen.

Mit SetGadgetText lässt sich das Feld mit einem Standardtext ausfüllen, der vom Be-nutzer überschrieben werden kann. So könnte in einem E-Mail-Feld das @-Zeichen be-reits eingetragen sein.

ActivateGadget hebt ein Eingabefeld hervor. Auf diese Weise wird der Cursor gleich indas Feld gesetzt.

Das Editieren in einem Feld löst ein Ereignis $401 aus. EventSource() nennt die Kenn-ziffer des Feldes.

Die eigentliche Eingabe liest TextFieldText() aus.

Unser Beispiel erzeugt zwei Eingabefelder für Namen und Passwort. Der Kürze halberwird nur das obere Feld ausgewertet; sein Inhalt erscheint zeitgleich in der Statuszeile.Normalerweise wertet man Eingabefelder erst aus, nachdem zum Beispiel ein »Ok«-Schalter angeklickt wurde.

; TEXTFIELD.BBfenster = CreateWindow ("Eingabe", 100,100, 200,180)label1 = CreateLabel("Ihr Name:" , 5,0, 180,20, fenster)label2 = CreateLabel("Ihr Paßwort:", 5,45, 180,20, fenster)eingabe1 = CreateTextField (5,20, 180,20, fenster)eingabe2 = CreateTextField (5,65, 180,20, fenster, 1)ActivateGadget eingabe1

Repeat ereignis = WaitEvent() If ereignis = $401 And EventSource() = eingabe1 Then SetStatusText fenster, TextFieldText(eingabe1) EndIf If ereignis = $803 Then EndForever

Abb. 22.9:Ein Textfeld

liest einzeiligeEingaben ein.

Page 355: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

355

Texteingabe j e t z t l e r n e i c h

0

22.10.2 TextareaEine Textarea kann hingegen mehrere Zeilen lang sein, wobei Æ in die nächste Zeilewechselt. Im ganzen Fenster wird frei mit den Pfeiltasten navigiert und editiert. Dabeigibt es keine Begrenzung: Erreicht der Cursor das Zeilenende, wird nach rechts ge-scrollt. Erreicht er den Fensterboden, erscheint ein senkrechter Scrollbalken. Mit denin der Tabelle stehenden Funktionen überwachen Sie die eingegebene Menge.

Die Auswertung erfolgt ähnlich wie bei einem TextField. Der eingegebene Text wird al-lerdings mit TextAreaText() ausgelesen.

Abb. 22.10:Eine Textarea wird für mehr-zeilige Eingaben verwendet.

Zusätzlich gibt es einige seltener benutzte Anweisungen. So lassen sich in einer Text-area Schriftgröße, Font und Farbe frei festlegen und die eingetippten Daten auf viel-fältige Weise auslesen. Wie immer, stehen die Parameter detailliert in der Online-Hilfe.

EventData() nennt den ASCII-Code des zuletzt eingegebenen Zeichens. Das ist nütz-lich, um Sonderzeichen abzufangen. So könnte bei Æ mit ActivateGadget in dienächste Zeile gewechselt werden. Wichtige Steuertasten wie Å und die Pfeiltastenlassen sich jedoch zumindest in der hier vorliegenden Version 1.34 nicht auswerten.Die Lösung sind Hotkeys. So oder so sollten Sie bei einer Liste von Eingabefeldernmit einem Dim-Feld arbeiten, um bequem das aktive Feld zu ändern.

CreateTextArea() Textarea erstellen

TextAreaText() Inhalt der Textarea liefern

AddTextAreaText() Zeichenkette ans Ende des bestehenden Texts hinzufügen

SetTextAreatText() Zeichenkette an einer beliebigen Stelle einfügen

SetTextAreaFont (mit LoadFont() geladene) Schriftart einstellen

SetTextAreaColor Schriftfarbe oder Hintergrundfarbe einstellen

SetTextAreaTabs Größe des Tabulatorschritts festlegen

FormatTextAreaText Farbe und Schnitt (fett, kursiv) eines Textteils einstellen

TextAreaChar() Position des ersten Zeichens einer Zeile ermitteln

TextAreaCursor() Position des Cursors ermitteln

TextAreaLine() Zeilennummer eines Zeichens ermitteln

TextAreaLineLen() Anzahl der Zeichen einer Zeile ermitteln

TextAreaLen() Anzahl der Zeichen und Zeilen ermitteln

TextAreaSelLen() Anzahl der markierten Zeichen und Zeilen ermitteln

LockTextArea Textarea kurzzeitig für Formatänderungen sperren

UnlockTextArea Textarea wieder entsperren

Page 356: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

356

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

22.11 Listen

Eine Liste ist eine Aufzählung von Werten. Sie erstellen einen Listenkasten (Listbox)mit CreateListBox():

fenster = CreateWindow ("BlitzTest", 100,100, 200,300)liste = CreateListBox (0,0, 100,200, fenster)

Eine Abwandlung der Listbox ist die Combobox, deren Einträge erst per Mausklickaufgeklappt werden. Sie wird mit CreateComboBox() erzeugt:

liste = CreateComboBox (0,0, 100,200, fenster)

Jeden Listeneintrag fügen Sie mit AddGadgetItem hinzu:

AddGadgetItem liste, "Brot"AddGadgetItem liste, "Wurst"AddGadgetItem liste, "Butter"AddGadgetItem liste, "Milch"

Folgt als zusätzlicher Parameter eine 1, wird das Element optisch hervorgehoben, alsob es markiert wäre. In einer Liste kann immer nur ein Element hervorgehoben sein;jede neue Markierung löscht die vorherige.

Gönnen wir uns einen Überblick, wie wir Elemente hinzufügen, entfernen und nach-träglich auswählen:

Wählt der Nutzer einen Eintrag aus der Liste, wird ein Ereignis $401 ausgelöst. Event-Source() enthält die Kennziffer der Liste. SelectedGadgetItem() benennt die Nummerdes Elements, das ausgewählt wurde – beim ersten Eintrag also 0, beim zweiten 1 usw.

Schreiben wir ein kleines Programm, das zwei Listen nebeneinander setzt: eine Listboxund eine Combobox. Um es kurz zu halten, werten wir nur die linke Liste aus. Die je-weils hervorgehobenen Einträge schreiben wir in die Statuszeile des Fensters.

; LISTE.BBfenster = CreateWindow ("Listbox, Combobox", 100,100, 200,200)liste1 = CreateListBox (0,0, 80,120, fenster)liste2 = CreateComboBox (100,0, 80,120, fenster)

AddGadgetItem liste1, "Brot"AddGadgetItem liste1, "Wurst"

AddGadgetItem liste, name$ neues Element ans Ende der Liste hängen

InsertGadgetItem liste, nummer neues Element an einer bestimmten Stelle einfügen

ModifyGadgetItem liste, nummer, name$ Namen eines Elements ändern

GadgetItemText(list, nummer) Namen eines Elements ermitteln

RemoveGadgetItem liste, nummer Element löschen

ClearGadgetItems liste alle Elemente löschen

SelectGadgetItem liste, nummer Element auswählen (hervorheben)

SelectedGadgetItem(liste) ausgewähltes Element mitteilen

CountGadgetItems liste Anzahl der Elemente mitteilen

Page 357: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

357

Register j e t z t l e r n e i c h

AddGadgetItem liste1, "Butter", 1AddGadgetItem liste1, "Milch"SetStatusText fenster, GadgetItemText(liste1,SelectedGadgetItem(liste1))

AddGadgetItem liste2, "Messer", 1AddGadgetItem liste2, "Gabel"AddGadgetItem liste2, "Löffel"AddGadgetItem liste2, "Licht :-)"

Repeat ereignis = WaitEvent() If ereignis = $401 And EventSource() = liste1 Then SetStatusText fenster, GadgetItemText(liste1,SelectedGadgetItem(liste1)) EndIf If ereignis = $803 Then EndForever

Abb. 22.11:Listbox und Combobox im Vergleich

22.12 Register

Eine Erweiterung von Listen sind Register oder Tabber. Über Register lassen sich ein-zelne Seiten auswählen. Viele Menüs von Windows-Programmen verwenden dieseDarstellung, um Texte und Aufzählungen auf mehrere Unterseiten zu verteilen.

Das Erstellen eines Registers ähnelt sehr dem einer Liste:

register = CreateTabber (0,0, 180,120, fenster)AddGadgetItem register, "Brot"AddGadgetItem register, "Wurst"AddGadgetItem register, "Butter"AddGadgetItem register, "Milch"

Aufwendiger wird das Füllen der Unterseiten mit Inhalt. Es gibt keine Möglichkeit, ge-zielt die einzelnen Registerseiten mit Text, Schaltern und Eingabezeilen zu füllen. In-halte gelten für alle Seiten. Allerdings können Sie testen, welche Seite aktiv ist, um un-erwünschte Inhalte auszublenden. Bei komplexen Inhalten bietet es sich an, mitPanelen zu arbeiten: Setzen Sie den Inhalt einer Seite in ein Panel und füllen Sie dieUnterseiten mit Panälen. So sparen Sie sich Arbeit beim Ein- und Ausblenden der ein-zelnen Elemente.

Selbst für kleine Register sollten Sie Kennziffern, Überschriften und den eigentlichenText in einem Dim-Feld speichern. Eine eigene Funktion blendet erst alle Texte aus unddanach den aktuellen Text wieder ein. (Ein If-Vergleich wäre hier aufwendiger.)

Page 358: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

358

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

; REGISTER.BBGlobal fenster = CreateWindow ("Register", 100,100, 200,200)register = CreateTabber (5,5, 180,100, fenster)

Dim Essen$(3,2)Essen$(0,1) = "Brot"Essen$(0,2) = "Gebäck aus Getreidemehl oder -schrot, Wasser, Salz u.a."Essen$(1,1) = "Wurst"Essen$(1,2) = "Masse aus feingehacktem Fleisch, Speck und Gewürzen, das in Därme gefüllt wird"Essen$(2,1) = "Butter"Essen$(2,2) = "aus Milch gewonnenes Fett, das besonders als Brotaufstrich verwendet wird"Essen$(3,1) = "Milch"Essen$(3,2) = "besonders von Kühen gewonnene weißliche Flüssigkeit"

For I=0 To 3 AddGadgetItem register, Essen$(I,1) Essen$(I,0) = CreateLabel (Essen$(I,2), 5,10, 170,110, register)NextNeuerReiter(0)

Repeat id = WaitEvent() If id = $401 And EventSource() = register Then NeuerReiter(SelectedGadgetItem(register)) EndIf If id = $803 Then EndForever

Function NeuerReiter(Reiter) For I=0 To 3 HideGadget Essen$(I,0) Next ShowGadget Essen$(Reiter,0) SetStatusText fenster, Essen$(Reiter,1)End Function

Abb. 22.12:Reiterkarten

eines Registers

0 Listeneinträge und Register können Sie mit Symbolen versehen. Mit LoadIconStrip()laden Sie dazu Icons aus einer Grafikdatei, die Sie mit SetGadgetIconStrip einer Listeoder einem Register zuweisen. Den Befehlen AddGadgetItem, InsertGadgetItem undModifyGadgetItem übergeben Sie die Nummer des Icons (ab 0) als zusätzlichen Para-meter. Benötigen Sie die Icons nicht mehr, löschen Sie die Datei mit FreeIconStripschließlich aus dem Speicher. Diese Befehle funktionieren erst ab Version 1.34 vonBlitz Plus.

Page 359: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

359

Scrollbalken j e t z t l e r n e i c h

22.13 Scrollbalken

Schiebeleisten werden als Scrollbalken oder zum Auswählen von Werten verwendet,ohne konkrete Zahlen eintippen zu müssen. So könnte in einem Spiel die Lautstärkeoder die Empfindlichkeit der Maus durch einen bewegbaren Balken dargestellt werden.CreateSlider() erstellt einen Scrollbalken in der gewünschten Größe:

slider = CreateSlider (0,0, 190,20, fenster)

Soll der Balken nicht waagerecht sein, sondern senkrecht, geben Sie am Ende zusätz-lich den Parameter 2 an.

Mit einem zweiten Befehl bestimmen Sie,

� wie breit der Balken ist und somit wie viele Positionen gleichzeitig ausgewählt sindsowie

� den maximalen Wert und somit den Wertebereich.

Soll der Balken Werte zwischen 0 und 100 annehmen können und 10 Punkt breit sein,schreiben Sie

SetSliderRange slider, 10,100

Nun ist der Balken funktionstüchtig. Mit SetSliderValue legen Sie eine bestimmtePosition fest:

SetSliderValue slider, 50

Das Verschieben des Balkens durch den Benutzer löst ein Ereignis $401 aus. Event-Source() enthält die Kennziffer des Balkens. Der gewählte Wert lässt sich mit Slider-Value() auslesen. Der niedrigste Wert ist 0. Ein Bereich bis 100 umfasst also die Werte0 bis 99.

; SLIDER.BBfenster = CreateWindow ("Slider", 100,100, 200,100)slider = CreateSlider (0,0, 190,20, fenster)SetSliderRange slider, 1,100

Repeat ereignis = WaitEvent() If ereignis = $401 And EventSource() = slider Then SetStatusText fenster, "Position " + SliderValue(slider) EndIf If ereignis = $803 Then EndForever

Abb. 22.13:Scrollelement (Slider) in einem Fenster

2SliderValue() liefert den linken Rand des Balkens. Hat der Balken eine Breite von 20Pixeln, kann bei einem Wertebereich von 100 der Regler nur bis zur Position 80 ge-schoben werden.

Page 360: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

360

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

22.14 Baumstrukturen

Gegliederte Daten lassen sich oft in einer baumähnlichen Struktur darstellen, etwa einStammbaum oder die Verzeichnisse einer Festplatte. Blitz Basic unterstützt dieseBaumstruktur oder Tree Lists mit einem Satz von Befehlen. Damit erzeugen Sie eineGliederung, bei der jedes Element mit einem darüber liegenden Knoten verknüpft istund selbst Bezugspunkt für ein oder mehrere Elemente sein kann. In der grafischenDarstellung lassen sich einzelne Äste aufklappen.

Zunächst erstellen Sie ein Fenster, das die Baumliste anzeigen soll:

baumstruktur = CreateTreeView (0,0, 300,250, fenster)

Nun definieren Sie alle Elemente (auch Knoten genannt) in Form von Zeichenketten.Dabei geben Sie die Kennziffer jedes »Eltern«-Elements an, mit dem es verknüpft wer-den soll. Das allererste Element hat keinen »Eltern«-Knoten. Ihm weisen Sie die Kenn-ziffer eines (nicht vorhandenen) Wurzelelements zu, die Ihnen TreeViewRoot() mitteilt:

baum10 = AddTreeViewNode ("Baum 1", TreeViewRoot(baumstruktur))

Die Zeile erzeugt einen ersten Eintrag namens Baum 1. Schnell wachsen ihm Äste undZweige und Blätter:

ast11 = AddTreeViewNode ("Ast", baum10)zweig11 = AddTreeViewNode ("Zweig", ast11)blatt11 = AddTreeViewNode ("Blatt", zweig11)

Die Elemente des Baums lassen sich mit der Maus auf- und zuklappen. Das geht auchautomatisch: ExpandTreeViewNode zeigt alle unmittelbaren »Tochter«-Elemente, klapptden betreffenden Knoten also auf. CollapseTreeViewNode klappt das Element wiederzu.

2; BAUM.BBfenster = CreateWindow ("TreeList", 100,100, 350,250)baumstruktur = CreateTreeView (0,0, 300,150, fenster)

baum10 = AddTreeViewNode ("Baum 1", TreeViewRoot(baumstruktur))ast11 = AddTreeViewNode ("Ast", baum10)ast12 = AddTreeViewNode ("Ast", baum10)zweig11 = AddTreeViewNode ("Zweig", ast11)blatt11 = AddTreeViewNode ("Blatt", zweig11)blatt12 = AddTreeViewNode ("Blatt", zweig11)blatt13 = AddTreeViewNode ("Blatt", zweig11)

baum20 = AddTreeViewNode ("Baum 2", TreeViewRoot(baumstruktur))ast21 = AddTreeViewNode ("Ast", baum20)zweig21 = AddTreeViewNode ("Zweig", ast21)blatt21 = AddTreeViewNode ("Blatt", zweig21)

ExpandTreeViewNode baum10ExpandTreeViewNode ast11ExpandTreeViewNode zweig11

WaitMouse

Sie sehen die Einträge nur, wenn alle darüber liegenden Knoten ebenfalls aufgeklapptsind.

Page 361: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

361

Standardfenster j e t z t l e r n e i c h

Abb. 22.14:Treelists wer-den für hierar-chisch angeord-nete Daten eingesetzt.

Häufig werden Sie Baumstrukturen sicher nicht verwenden. Daher liste ich selten ge-brauchte Befehle nur kurz auf:

22.15 Standardfenster

Windows hat eine Reihe immer wiederkehrender Fenster mit Standardinhalten, etwazum Laden einer Datei. Sie lassen sich von jedem Programm nutzen. Blitz Plus bietetdazu eine Reihe von Befehlen, die jeweils eines dieser Fenster auf dem Bildschirm er-scheinen lassen. Man nennt diese Fenster Requester, zu Deutsch etwa »Anforderer«.

22.15.1 HinweisFür Hinweise und Warnungen gibt es ein spezielles Mini-Fenster. Es enthält nur einenkurzen Text und einen »Ok«-Knopf zum Bestätigen. Sie erzeugen es einfach mit Notify:

Notify "Alle Dateien gelöscht!"

Abb. 22.15:Notify-Fenster für Mitteilungen ohne Wahl-möglichkeit

CountTreeViewNodes Anzahl der darunter liegenden Elemente eines Knotens ermitteln

InsertTreeViewNode zwischen zwei Knoten ein weiteres Element einfügen

FreeTreeViewNode einen Knoten (und damit alle abgehenden Unterzweige) löschen

SelectedTreeViewNode() hervorgehobenen Knoten ermitteln

SelectTreeViewNode einen Knoten hervorheben

Page 362: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

362

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

Um einen mehrzeiligen Text auszugeben, müssen Sie an der Umbruchstelle Chr$(13)einfügen, das ASCII-Zeichen für Zeilenumbruch:

Notify "Alle Dateien gelöscht." + Chr$(13) + "Es ist nichts mehr da."

122.15.2 BestätigungSoll der Benutzer eine Aktion bestätigen, bietet sich ein Fenster mit einer Sicherheits-abfrage an. Dafür existiert der Befehl Confirm, der ein ähnliches Fenster ausgibt. Statteines Schalters »Ok« gibt es aber zwei Schalter mit »Ja« oder »Nein«. Freilich wollen wirauch wissen, was der Benutzer angeklickt hat. Dazu verwenden wir den Befehl alsFunktion:

antwort = Confirm ("Sollen alle Dateien gelöscht werden?")

Abb. 22.16:Confirm-

Fenster fürBestätigungen

Diese Funktion gibt 0 für »Nein« und 1 für »Ja« zurück.

Soll statt des Info-Symbols ein warnendes Ausrufezeichen erscheinen, verwenden Sie1 als zweiten Parameter:

antwort = Confirm ("Sollen alle Dateien gelöscht werden?",1)

Ganz ähnlich arbeitet Proceed. Hier werden aber drei Schalter eingeblendet: »Ja«,»Nein« und »Abbrechen«. Die Funktion gibt -1 zurück, wenn der letzte Knopf gedrücktwurde. Auch hier kann mit einem zweiten Parameter ein Warnzeichen verlangt wer-den.

Abb. 22.17:Mit Proceed-

Fenstern lassensich gefährliche

Aktionen vomBenutzer

bestätigen.

Steht neben dem Text ein Info-Symbol, können Sie es – wie bei den beiden folgendenBefehlen – mit einem zweiten Parameter in ein Warnzeichen umwandeln.

Page 363: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

363

Standardfenster j e t z t l e r n e i c h

22.15.3 FontauswahlDie Funktion RequestFont() blendet das Windows-Standardfenster zum Auswählen ei-ner Schriftart, einer Schriftgröße und eines Schriftschnitts (beispielsweise fett) ein. Sieist damit die interaktive Variante von LoadFont(). Wurde eine Schriftart geladen, gibtdie Funktion die Kennziffer des Fonts zurück:

font = RequestFont()

Sie setzen sie dann zum Beispiel mit SetTextAreaFont ein.

22.15.4 FarbauswahlDie Funktion RequestColor() blendet ein Fenster zum Auswählen einer Farbe ein. Die-ser Service wird meist zur Verfügung gestellt, um in textlastigen Programmen die Vor-der- und Hintergrundfarbe auszuwählen. Die Felder »Benutzerdefinierte Farben« lassensich nicht belegen. Aber Sie können als Parameter den RGB-Wert einer Farbe über-geben, der vorausgewählt sein soll:

RequestColor(0,0,255)

Gibt die Funktion eine 1 zurück, hat der Benutzer das Fenster mit »Ok« beendet und so-mit eine Farbe ausgewählt. Welche es ist, nennen Ihnen die Funktionen Requested-Red(), RequestedGreen() und RequestedBlue() als einzelne Werte für Rot, Grün undBlau.

Abb. 22.18:Anforderungs-fenster für eine Farbauswahl

22.15.5 OrdnerauswahlRequestDir() blendet ein Standardfenster zum Auswählen eines Verzeichnisses ein. AlsParameter können Sie einen kleinen Text übergeben, der in das Fenster geschriebenwird. Der Zielordner wird als Zeichenkette zurückgeliefert.

ordner$ = RequestDir("Wählen Sie einen Ordner aus:")Notify ordner$ + " ausgewählt"

Page 364: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

364

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

Abb. 22.19:Anforderungs-

fenster für eineVerzeichnis-

auswahl

22.15.6 DateiauswahlAuf ähnliche Weise holen Sie mit RequestFile() das Standardfenster zum Öffnen einerDatei ans Tageslicht. Drei Parameter übergeben Sie wahlweise:

� einen kurzen Aufforderungstext

� ein Suchmuster, welche Dateitypen möglich sind (zum Beispiel "doc")

� eine 1 für den »Speichern«-Dialog oder 0 für »Laden«

Die Funktion übergibt den ausgewählten Dateinamen samt Pfad a ls Zeichenkette. DieDatei muss nicht existieren; der Benutzer kann sich einen Namen auswählen.

datei$ = RequestFile("Wählen Sie eine Datei aus.", "doc", 1)Notify datei$ + " ausgewählt"

0

22.15.7 FortschrittsanzeigeBei langwierigen Aktionen sollte eine Anzeige den Benutzer darüber informieren, wieweit die Arbeit fortgeschritten ist. Dafür genügt ein Balken, der fortwährend größerwird. Blitz Basic bietet zwei Funktionen, um einen solchen Balken (englisch: ProgressBar) darzustellen.

CreateProgBar() erzeugt ein Fenster. Als Parameter werden, wie üblich, Startkoordi-naten, Größe und eventuell Gruppe angegeben.

Den eigentlichen Balken zeichnet UpdateProgBar(). Die Funktion möchte die Kennzif-fer des Balkens wissen (den die vorherige Funktion übermittelt) sowie einen Wert. Die-ser gibt an, wie weit die Arbeit fortgeschritten ist. 0 bedeutet leer, 1 ist ausgefüllt.Zwischenwerte werden als Fließkommazahl angegeben. 0.5 bedeutet: halb voll. Zu be-

Als Suchmuster für das Feld »Dateiname« verwenden Sie nur die Endung, ohne Punktdavor. Sie geben mehrere Endungen an, indem Sie sie durch ein Semikolon trennen.Die Liste mit möglichen Endungen im Feld »Dateityp«, das eine Suche nach einzelnenEndungen erlaubt, füllen Sie, indem Sie die Endungen durch ein Komma trennen.

Page 365: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

365

Grafikfenster j e t z t l e r n e i c h

achten ist, dass auch wirklich Fließkommavariablen verwendet werden. Die Länge desBalkens lässt sich jederzeit verändern. Sie wird sofort aktualisiert.

Abb. 22.20:Fortschritts-balken zeigen dem Benutzer, wie lange er auf die Fertigstel-lung einer langwierigen Aktion warten muss.

; PROGRESS.BBfenster = CreateWindow ("Fortschrittsanzeige", 200,200, 300,100)leiste = CreateProgBar (0,0, 290,40, fenster)For I#=0 To 1.1 Step 0.1 UpdateProgBar leiste, I Delay 300Next

22.15.8 HTML-AnzeigeIm Rahmen eines Luxus-Gadget gibt es eine Browser-Funktion: Mit drei Programm-zeilen lassen Sie eine Website anzeigen. Das ist sehr praktisch, da immer mehr Pro-grammanleitungen in HTML geschrieben sind. Außerdem verlinken Sie von IhremProgramm nicht nur zu Ihrer Website, sondern Sie zeigen sie gleich an.

Die Funktion CreateHTMLView() erstellt ein Fenster zum Anzeigen von HTML-Inhalten.Sie übergeben ihr die Startkoordinaten, die Größe und die Gruppe, zu der das Fenstergehört. Das Fenster ist zunächst leer, bis Sie mit HTMLViewGo() eine HTML-Seite ange-ben, die angezeigt werden soll. Das kann eine lokale Datei oder eine beliebige WWW-Adresse sein.

; HTML.BBfenster = CreateWindow ("HTML-Betrachter", 50,50, 800,600)html = CreateHtmlView (0,0, 790,600, fenster)HtmlViewGo html, "www.eastereggs.de"WaitMouse

Zum Anzeigen greift Blitz Basic auf den Internet Explorer zurück. Die Seiten werdendaher korrekt dargestellt; aber es gibt mit Ausnahme eines Scrollbalkens keine Bedien-funktionen, außer denen, die sich hinter der rechten Maustaste verbergen.

Mit HTMLViewGo() lässt sich jederzeit eine neue Adresse auswählen. HTMLViewBack führtdann zur vorherigen Adresse, während HTMLViewForward wieder eine Seite vorwärtsgeht (was nur möglich ist, wenn mindestens einmal zurückgegangen wurde). Die bei-den Befehle erwarten die Kennziffer der HTML-Anzeige. Sie sind gleichbedeutend mitden Browser-Schaltflächen ZURÜCK und VORWÄRTS.

22.16 Grafikfenster

Auch innerhalb einer GUI lassen sich Grafikbefehle verwenden. Sie richten dazu einspezielles Fenster ein und verwenden es als Puffer. Dieser Puffer heißt Canvas Buffer(Canvas = englisch für Leinwand).

Page 366: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

366

Bedienoberflächen mit Blitz Plus22j e t z t l e r n e i c h

Sie erzeugen mit CreateCanvas() ein Canvas-Fenster ...

fenster = CreateWindow ("BlitzTest", 100,100, 700,500)canvas = CreateCanvas (0,0, 690,490, fenster)

... und richten den Zeichenpuffer dorthin:

SetBuffer CanvasBuffer(canvas)

Nun verwenden alle Zeichen- und Bildbefehle den gewünschten Canvas-Puffer. Auchhier gibt es einen Front- und einen Backbuffer. Wie im Grafikmodus von Blitz Plus,kann nur in den Backbuffer gezeichnet werden, der automatisch aktiviert ist. Statt mitFlip wechseln Sie allerdings mit

FlipCanvas canvas

zwischen beiden Seiten. Theoretisch können mehrere Canvas-Puffer aktiv sein. Dahersollten Sie mitteilen, welcher gemeint ist. Anders als Flip im Grafikmodus, wirkt Flip-Canvas nur im Canvas-Fenster und nicht auf dem ganzen Bildschirm. Ebenso speichertSaveBuffer nur das Abbild des Fensters als Bitmap-Datei ab.

In der Datei CANVAS.BB finden Sie das Überblende-Beispiel aus UEBERGANG1.BB, ange-passt auf eine Darstellung im Canvas-Fenster.

1

Übrigens können Sie in Blitz Plus direkt auf den Desktop zeichnen. Wenn Sie ein Pro-gramm aus dem Editor heraus starten, würde ein Bild im Editor erscheinen. Dazu gibtes den Desktoppuffer. Um direkt auf den Bildschirm zu zeichnen, egal wo Sie sich be-finden, genügt ein:

SetBuffer DesktopBuffer()

Praktischen Nutzen hat das aber nicht.

22.17 Aufgaben

1. Schreiben Sie ein Formular, das Felder für eine Postadresse (Name, Straße, Ort)bietet. Die Adresse wird per Schalterdruck in einer Datei abgespeichert und mit ei-nem zweiten Schalter wieder aus der Datei geladen und in das Formular eingefügt.

2. Schreiben Sie einen einfachen Webbrowser, der beliebige WWW-Seiten anzeigtund per Schalter »Vorwärts« und »Rückwärts« geht.

Mit dem Canvas-Puffer lassen sich Spiele programmieren, die trotzdem eine Win-dows-typische GUI haben. Einfache Desktop-Spiele können im Fenster ablaufen, sodass sie nicht den gesamten Bildschirm ausfüllen. Die Maus- und Tastaturbefehlefunktionieren auch hier. Um die Mauskoordinaten relativ zu den Maßen des Canvas-Fensters zu erhalten, übergeben Sie seine Kennziffer den Mausfunktionen als Para-meter.

Page 367: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

367

jetz

t le

rne

ich

KAPITEL 23

Programmierstil und Fehlersuche

Ein guter Programmierstil hilft dabei, sich besser zurechtzufinden und Fehler schnell zufinden. Einige Hinweise finden Sie im Folgenden zusammengestellt:

� Dokumentieren Sie den Quelltext. Setzen Sie Zwischenüberschriften und trennenSie einzelne Teile durch eine Leerzeile voneinander.

� Rücken Sie den Inhalt von Schleifen mit einem oder mit mehreren Leerzeichenein. Das geht auch nachträglich: Markieren Sie die Zeilen und drücken Sie Åoder Á+Å. Wie Sie die Spaltenbreite ändern, erfahren Sie im Abschnitt Edi-tor anpassen.

� Verwenden Sie sinnvolle Namen für Variablen, zum Beispiel Leben statt A. So ver-wechseln Sie nichts.

� Verwenden Sie kein Goto.

� Teilen Sie Ihr Programm in viele Unterprogramme und Funktionen auf, auch wennSie bestimmte Teile nur einmal aufrufen. Im Idealfall besteht Ihr Hauptprogrammnur aus einer Handvoll Aufrufe.

� Verteilen Sie größere Programmteile auf einzelne Dateien, die Sie mit Include ver-binden. Dadurch erhöhen Sie die Übersicht.

� Berücksichtigen Sie am Anfang nicht das ganze Projekt, sondern beschränken Siesich auf kleinere Teile. So behalten Sie den Überblick, können leichter neue Ideeneinbringen und finden schneller Fehler.

Page 368: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

368

Programmierstil und Fehlersuche23j e t z t l e r n e i c h

Robert Gerlach, www.robsite.de: »Beim Programmieren gibt es besonders am An-fang viel zu beachten. Verzichten Sie auf das so genannte »Hardcoding«, indem Sievariable Daten (Levels, Gegnertypen ...) nicht direkt in Ihr Programm schreiben, son-dern flexibel aus Dateien laden. So werden spätere Änderungen und Erweiterungensehr viel einfacher, da Sie nur einen Wert in einer Datei ändern müssen – alles anderepasst sich automatisch an. Auch ein modularer Aufbau des Codes ist zu empfehlen.Basic muss nicht zwangsläufig zum berüchtigten »Spagetticode« führen. Mit Funktio-nen und Include-Dateien teilen Sie Ihr Programm in kleine, wieder verwertbare Stück-chen (Spiellogik, Grafik, Sound ...) und haben so einen guten Überblick. Sie wissensofort, wo was ist, und können große Projekte nervenschonend entwickeln und pfle-gen. Sehr wichtig: Schreiben Sie Kommentare. Je mehr, desto besser. Alles, was sichnicht von Anfang an selbst erklärt, wird nach ein paar Wochen Pause für sich kaumzu entziffern sein. Sie werden nicht wissen, welcher Codeteil was macht, verlieren dieLust am Projekt und finden sich schlimmstenfalls, von tiefen Sinnkrisen geschüttelt,beim Moorhuhn-Spielen wieder. Lassen Sie es nicht dazu kommen. KommentierenSie Ihren Code. Dabei helfen Ihnen eindeutige Variablennamen (playerspeed stattplsp) und geschickte Einrückungen dabei, den Code übersichtlicher zu gestalten.«

Karlheinz Petry, www.shadowturtle.de: »Vor dem Schreiben eines Codes solltenSie sich sicher sein, was Ihr Programm alles enthalten soll. Haben Sie einmal ange-fangen, einen großen Batzen an Quellcode für ein Spiel zu schreiben, so wird esschwierig, die Zeilen wegen eines Features umzuschreiben. Daher ist es am besten,wenn Sie sich zuvor notieren, welche Eigenschaften Ihr Spiel haben soll. Das erleich-tert das spätere Strukturieren.

Es lohnt sich, immer mal den Programmcode zu überschauen und zu optimieren. Sobleibt er sauber und schnell.

Sparen Sie nicht mit Kommentaren. Dadurch behalten Sie den Überblick. Diese Hilfeist besonders bei Team-Projekten unerlässlich, wenn auch andere Einsicht in IhrenCode haben.«

Christian »DivineDominion« Tietze, www.art-fx.org: »Strukturieren Sie sinnvoll.Benutzen Sie Types, wenn es dynamisch sein soll. Tüfteln Sie kleinere Besonderhei-ten am besten in separaten Programmen aus. So sind Sie von anderen Sachen un-gebunden und bewahren die Übersicht. Schlagen Sie sich nicht mit Kleinigkeitenherum. Wenn Sie gleich ein ganzes Spiel entwickeln wollen, tun Sie es. Blocken SieKritik und Tipps dann aber nicht ab, wenn Ihr Code kritisiert wird. Haben Sie denMut zuzugeben, wenn es nicht weitergeht. Fehler einzugestehen, herauslösen und se-parat zu beseitigen und so die Funktionen nach und nach zu verfeinern, bringt Ihnenmehr Erfolge und Erfahrung, als mit Ihrem alten (und wohl schlechteren) Code wei-terzuarbeiten. Halten Sie Funktionen möglichst unabhängig voneinander, um sie pro-blemlos zu ändern und in späteren Projekten zu verwenden. So steigern Sie die Qua-lität und Dynamik im Code; und das spätere Ergebnis wird nach und nach mehr IhrenVorstellungen entsprechen.«

Page 369: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

369

Programmierstil und Fehlersuche j e t z t l e r n e i c h

Stefan Kurowski, www.kurowski.de: »Ein Programmcode ist schnell geschrieben,aber – nachlässig hingeschludert – nur schwer zu debuggen und zu ändern. Die fol-genden Hinweise sollen Ihnen daher eher langfristig helfen. Wenn Sie nach einerWoche eine neue Funktion programmieren wollen, aber nicht mehr wissen, wo dieseansetzen muss und welche Auswirkungen das auf andere Programmteile hat, dannhaben Sie etwas an diesen Zeilen falsch verstanden.

Bevor Sie mit dem Programmieren beginnen, machen Sie sich theoretische Gedan-ken zum Aufbau des Programmcodes. Schreiben Sie sie ruhig auf. Ein Programm-Ablaufschema auf dem Papier hilft Ihnen dabei, Engpässe oder logische Fallen zu er-kennen, die sonst erst bei der Programmierung aufgefallen wären. Auf diese Weiseersparen Sie sich mühselige Änderungen an bereits geschriebenen Zeilen. ÜberlegenSie sich schon zu Anfang, in welche Richtung das Programm später eventuell erwei-tert werden könnte.

Zerlegen Sie die Funktionen in sinnvolle Einheiten. Auch wenn eine bestimmte Be-rechnung nur wenige Zeilen Programmcode umfasst – sobald sie an mehreren Stellenaufgerufen wird, sollte sie in eine eigene Prozedur oder Funktion ausgelagert werden.

Strukturieren Sie den Programmcode optisch. Spätestens, wenn Sie hilflos auf meh-rere hundert Zeilen einer formlosen Masse starren und nach einer bestimmten Stelleim Code suchen, werden Sie sich ein paar Orientierungspunkte wünschen. RückenSie Code bei Schleifen oder mehrzeiligen Befehlsstrukturen (wie If-Then-Ausdrü-cken) deutlich sichtbar ein. Setzen Sie Leerzeilen ein, wo immer eine logische Einheitbeginnt und endet. Kommentieren Sie die Zeilen. Sie müssen nicht jedes Komma be-schreiben. Aber es muss klar sein, was der Codeabschnitt wie bewirkt.

Strukturieren Sie den Programmcode logisch. Versuchen Sie, das Programm ineigenständige Funktionsabschnitte zu unterteilen, die sich nicht gegenseitig beeinflus-sen. Auf diese Weise können Sie später die Auswirkungen nachträglicher Änderun-gen überschaubar halten und müssen nicht mehr das gesamte Programm durchprü-fen. Wenn Beziehungen zwischen mehreren Programmbestandteilen unvermeidbarsind, schaffe Ihnen eine möglichst einheitliche Form der Datenübergabe (durch wie-derkehrende Variablennamen, Datentypen, Reihenfolgen usw.).

Schreiben Sie sauberen Code. Bevor Sie eine einfach anmutende Basisfunktionschreiben, prüfen Sie, ob sie nicht vielleicht schon als Befehl in der Programmierspra-che existiert (manche Befehle braucht man so selten, dass man sie jahrelang niewahrgenommen hat). Überlegen Sie, welche Befehle die Aufgabe am effektivsten lö-sen. Es ist besser, einen neuen Befehl dazuzulernen, als die gleiche Aufgabe aus Be-quemlichkeit mit fünf bekannten, aber uneffektiven Kommandos zu lösen. Halten Sieeinen einheitlichen Programmierstil durch. Versuchen Sie, immer wiederkehrendePunkte in ähnlicher Art zu programmieren. Das erleichtert später die Orientierungungemein.

Kurz – sorgen Sie dafür, dass Sie (und vielleicht auch andere) auch nach langer Zeitnoch in dem Programm lesen können wie in einem Buch.«

Page 370: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

370

Programmierstil und Fehlersuche23j e t z t l e r n e i c h

23.1 Fehlersuche

Kein Programmierer arbeitet fehlerfrei. Sie werden sie schnell kennen lernen: die ner-vige Suche nach Fehlern (Bugs). Normale Tippfehler (Syntaxfehler) sind weniger dasProblem. Blitz Basic markiert Schlüsselwörter farbig, nachdem Sie sie geschrieben ha-ben. Spätestens beim Kompilieren erhalten Sie eine Fehlermeldung. Auch Fehler inder Art

For 1=2 To 10

werden vom Compiler erkannt.

Logikfehler sind schwierig zu meistern: Ihr Programm läuft, aber nicht so, wie es soll.

23.1.1 VariablenOftmals liegt der Schlüssel in Variablen. Sie haben einen Namen verwechselt oder eineVariable hat einen falschen Wert. Solchen Fehlern kommen Sie schneller auf die Spur,wenn Sie regelmäßig Ihren Programmcode mit einem Testlauf überprüfen. Läuft esnicht wie geplant, dann ist es sehr hilfreich, sich den Inhalt von Variablen anzeigen zulassen. Oft erkennen Sie daran, was Sie falsch gemacht haben. Ich versuche ein einfa-ches Beispiel: In einer Schleife verwenden Sie in einer Variable Vielfache von 2: 0, 2,4, 6 ... Also setzen Sie so an:

For I=0 To 100 Step 2

Einige Zeilen tiefer, wo Sie I verwenden, haben Sie vergessen, dass Sie die Schrittweite2 bereits mit Step eingestellt haben. Sie gehen davon aus, dass die Schleife in Einer-schritten läuft. Daher multiplizieren Sie I mit 2:

I = I*2

Das Resultat: Sie bekommen nicht jeden zweiten, sondern jeden vierten Wert. WennSie mit einem einfachen Print-Befehl ...

Print I

... den Inhalt der Schleifenvariable ausgeben, fällt Ihnen dieser Fehler sofort ins Auge.

223.1.2 Division durch 0Das Teilen durch 0 ist nicht erlaubt; Blitz Basic meldet es Ihnen mit "Division by zero".Das kann durchaus versehentlich passieren, durch eine falsche Formel oder durch dieUngenauigkeiten beim Arbeiten mit Fließkommazahlen.

23.1.3 FunktionenEine Funktion liefert nur einen Wert zurück, wenn Sie ihren Namen in Klammernschreiben. Das gilt nicht nur für selbst geschriebene Funktionen. Während:

Print MilliSecs()

Achten Sie bei Variablen auf Schreibfehler. Geben Sie an einer Stelle statt Leben ver-sehentlich Lebem ein, so wird das als neue Variable eingeführt. Das Programm ErrorChecker (auf der CD) findet solche Fehler.

Page 371: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

371

Fehlersuche j e t z t l e r n e i c h

Ihnen den gewünschten Wert liefert, erhalten Sie mit:

Print MilliSecs

einfach nur das Ergebnis 0. Mitunter erscheint eine seltsame Fehlermeldung, weil BlitzBasic Klammern erwartet, wo Sie sie vergessen haben.

23.1.4 Zählung ab 0Während wir Menschen für gewöhnlich von 1 an rechnen, zählt der Computer ab 0.Wenn Sie in Dateien, Speicherbänken und Feldern ab Stelle 0 schreiben, dann lesenSie die Dateien ab Stelle 0 (und nicht etwa Stelle 1) wieder aus, um korrekte Werte zuerhalten.

23.1.5 AuskommentierenOft hilft es, Teile des Programmcodes vorübergehend mit ; auszuklammern. Auf dieseWeise schränken Sie ein, in welchen Bereichen der Fehler erzeugt wird.

23.1.6 ÜberschlafenWenn Sie das Problem partout nicht finden: Schlafen Sie eine Nacht darüber. WennSie etwas Abstand gewonnen haben, finden Sie das Problem sicher rasch. Wenn nicht:Vielleicht lassen Sie den Code von einem Freund durchsehen.

23.1.7 Beta-TestVerteilen Sie ein nahezu fertiges Programm an Ihre Freunde. Eventuell treten mit ihrerPC-Konfiguration Probleme auf, vielleicht haben sie Verbesserungsvorschläge oder fin-den Fehler, die Sie übersehen haben. Eine solche Testversion eines Spiels nennt manBeta-Version (nach dem griechischen Alphabet). Eine frühe, lauffähige Fassung be-zeichnet man als Alpha; eine ziemlich stabile, weit fortgeschrittene Version heißt Beta.

Im deutschen Blitz-Basic-Forum (www.blitzforum.de) werden regelmäßig Vorabver-sionen von Spielen vorgestellt und Anregungen gesammelt.

Ein Beta-Test sollte auf folgende Punkte achten:

� Installation und Bedienung

� Programmfehler

� Logik (zum Beispiel Entscheidungen des Computers)

� Schwierigkeitsgrad

� Spielspaß

� Rechtschreibfehler und Ähnliches

Marco Sowa, www.enjoy-e.de: »Zeigen Sie den Fortschritt Ihres Spiels möglichst vie-len Leuten, um ehrliche Meinungen einzufangen. Versuchen Sie, Ihr Werk richtig zuplatzieren. Loben Sie es nicht in den Himmel. Dadurch verlieren Sie die Objektivität.Lassen Sie Ihre Freunde regelmäßig probespielen und achten Sie auf ihre Hinweise.«

Page 372: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

372

Programmierstil und Fehlersuche23j e t z t l e r n e i c h

23.1.8 DebuggerBlitz Basic unterstützt Ihre Fehlersuche mit einem eingebauten Hilfsmittel, dem Debug-ger. Er erlaubt es Ihnen, Ihr Programm jederzeit anzuhalten, um sich den Inhalt allerVariablen anzusehen. Der Debugger funktioniert nur vernünftig, wenn Sie den Debug-Modus (PROGRAM/DEBUG ENABLED?) eingeschaltet haben.

Das Schlüsselwort heißt Stop. Setzen Sie es an eine beliebige Stelle. Wenn Sie das Pro-gramm nun starten, hält es dort vorübergehend an. Der Reiter "debug" in der rechtenSpalte des Editors bietet Ihnen einen Überblick über den Inhalt aller Variablen. Danachwählen Sie einen der folgenden Befehle, je nach Blitz-Version entweder aus dem MenüDEBUG oder über das entsprechende Symbol des Debugger-Fensters.

Abb. 23.1:In älteren Ver-sionen hatten

die Funktionendes Debuggers

ein eigenesMenü. Neuer-dings sind sie

nur noch übereine Toolbar zu

erreichen,während das

Programm imDebug-Modus

läuft.

Stop

hält das Programm vorübergehend an, hat also die gleiche Wirkung wie das Schlüssel-wort Stop. Allerdings ist es schwieriger, den Punkt im rechten Moment auszuwählen.Oft klappt das nur, wenn das Programm auf eine Eingabe wartet.

Continue

setzt das Programm normal fort, bis das Ende oder ein weiteres Stop erreicht wird.

Step Over

führt den nächsten Befehl aus und benimmt sich danach so, als ob Stop gewählt wur-de. Eine Funktion wird dabei vollständig ausgeführt.

Step Into

führt den nächsten Befehl aus, auch innerhalb einer Funktion. Im Gegensatz zu StepOver lassen sich mit Step Into auch Befehle einer Funktion einzeln ausführen.

Step Out

führt alle restlichen Befehle der aktuellen Funktion aus; sollte nach Step Into verwen-det werden.

Das sechste, pilzähnlich Symbole im Debugger-Fenster beendet die Fehlersuche.

Carsten Fichtelmann, www.dtp-ag.com: »Das Programm muss unter allen gängigenWindows-Systemen laufen, also ab Version 98. Hier steckt oft das Problem, weil einTitel möglicherweise unter Windows 2000 läuft, aber Details bei anderen Betriebs-systemen zum Absturz führen. Ebenso sollte es gängige Sound- und Grafikkarten un-terstützen.«

Page 373: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

373

Fehlersuche j e t z t l e r n e i c h

0

23.1.9 DebugLogDas Ausdrucken von Variableninhalten oder bestimmter Hinweise (etwa über die Aus-führung einer bestimmten Funktion) ist eine hilfreiche Methode, um Fehler aufzuspü-ren. Blitz Basic erlaubt es Ihnen, solche Texte nicht nur auf den Bildschirm, sondern inein spezielles Fenster auszugeben. Es heißt DebugLog.

Mit dem Befehl DebugLog schreiben Sie etwas in das DebugLog-Fenster, gefolgt von ei-nem Text:

DebugLog ADebugLog "Funktion SpielerTod läuft"

Im Editor schauen Sie sich die Ausgaben später, je nach Blitz-Version, über den Menü-punkt DEBUG/VIEW LOG bzw. die Taste Ñ oder über den Reiter im Debugger-Fensteran.

Mit diesen Hilfsmitteln lassen sich gezielt die Werte von Variablen anzeigen oder dasProgramm Zeile für Zeile ausführen, um nach jedem Befehl die Inhalte von Variablenzu prüfen. Dabei ordnen Sie Quelltext, DebugLog-Fenster, Programmfenster und Va-riablenanzeige nach Belieben an.

Abb. 23.2:Im Debug-Modus können gleichzeitig der Quelltext, die Programm-ausgabe und die Werte von Variablen betrachtet werden.

Der Debug-Modus gibt Ihnen genauere Fehlermeldungen als der »normale« (der alsRelease-Modus bezeichnet wird). Ein Beispiel: Sie überschreiten die Grenzen einesDim-Felds, wollen etwa ein negatives Feld auslesen. Normalerweise stürzt das Pro-gramm mit dem Fehler Memory access violation ab. Das kann vieles bedeuten. ImDebug-Modus erhalten Sie das hilfreichere Array index out of bounds und im De-bug-Fenster sehen Sie die Zeile, in der der Fehler auftrat.

Page 374: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

374

Programmierstil und Fehlersuche23j e t z t l e r n e i c h

23.2 Optimierung I: Programmstruktur

Personalcomputer sind schnell. Aber Sie wissen: Aktuelle Spiele zwingen ihn in dieKnie. Ab einer bestimmten Auflösung, ab einer bestimmten Detailstufe beginnt es zuruckeln. Weshalb? Weil der Rechner (oder die Grafikkarte) mit den Aufgaben nicht hin-terherkommt. Entlasten Sie ihn. Jeder Befehl in Blitz Basic wird letztendlich in Prozes-sorbefehle umgewandelt. Davon werden manche schneller als andere ausgeführt. Siebeschleunigen Ihr Programm, indem Sie es dem Prozessor nach dem Mund schreiben.

1

23.2.1 Überflüssiges meidenNiemandem würde in den Sinn kommen, überflüssige Tätigkeiten fortwährend zu wie-derholen. Merkwürdigerweise wird das bei der Programmierung schnell vergessen. Sowerden ständig Befehle ausgeführt, die in der derzeitigen Situation nicht notwendigsind. Setzen Sie viele If-Bedingungen und lassen Sie nur die Zeilen ausführen, die be-nötigt werden.

23.2.2 Fließkommazahlen vermeidenBlitz Basic kennt drei Variablentypen: Ganze Zahlen (Integer), Fließkommazahlen(Float) und Zeichenketten (Strings). Integer ist die schnellste Variante. Float ist wesent-lich langsamer. Vermeiden Sie daher Fließkommazahlen, wo immer es möglich ist.

Kommt bei Berechnungen mindestens ein Wert mit Kommazahl vor, dann wird internnicht mit Integern gerechnet, sondern mit Fließkommawerten. Dadurch wird die Be-rechnung stark verlangsamt.

Strings sind am langsamsten. Wenn Sie für eine Aufgabe Zahlen nehmen können,dann tun Sie das.

23.2.3 Werte vorausberechnenFalls Sie mit Formeln arbeiten, die feste Ergebnisse liefern (etwa für Sinus-Kurven), bie-tet es sich an, die Berechnungen vorher durchzuführen und die Ergebnisse in ein Feldzu schreiben. Das lesen Sie in der Spielschleife einfach aus. Das Gleiche gilt für die Er-gebnisse von Funktionsaufrufen. Statt

For I=1 To ImageWidth(bild)

schreiben Sie besser:

Weite = ImageWidth(bild)For I=1 To Weite

So muss nicht bei jedem Durchlauf die Funktion aufgerufen werden.

Vor allem bei einfachen Spielen werden Sie mit den meisten Hinweisen kaum einennachweisbaren Effekt erzielen. Doch in der Summe und vor allem in zeitkritischenAbschnitten lohnt sich vorausschauendes Programmieren. Sie sollten sich angewöh-nen, von Anfang an effizient zu entwickeln.

Page 375: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

375

Optimierung I: Programmstruktur j e t z t l e r n e i c h

23.2.4 Shl und ShrNehmen Sie, wenn möglich, Shl und Shr für Multiplikationen und Divisionen. So rech-net sich 8 * 128 auch als 2 Shl 9. Bei beiden Formeln erhalten Sie das gleiche Ergeb-nis; die zweite Variante wird aber vom Prozessor sehr viel schneller errechnet.

23.2.5 Konstanten statt VariablenWenn sich der Wert einer Variable nicht ändert, dann definieren Sie den Wert als Kon-stante. Da der Compiler weiß, dass sich der Wert nicht mehr ändert, spart er sich etwasAufwand.

23.2.6 Datenfelder statt TypesWenn man sie einmal verstanden hat, lässt sich mit Types bequem arbeiten. Aber diekomplexen Strukturen sind für den Computer ebenso komplex. Nehmen Sie daherbesser Dim-Datenfelder, wenn es auf Geschwindigkeit ankommt.

23.2.7 Schleifen entschlackenPacken Sie nur die notwendigen Befehle in eine Schleife. Setzen Sie alle Zuweisungen,die vorher erfolgen können, vor den Aufruf der Schleife.

23.2.8 Schleifen verkürzenEine Schleife spart vor allem Ihnen Schreibarbeit. Der Computer hat nichts davon. Bei:

For I=1 To 100 Write "!"Next

muss der Computer hundertmal den gleichen Befehl abarbeiten. Viel schneller wäredas Ausführen des Befehls, wenn Sie alle Ausrufezeichen in eine Write-Anweisung set-zen. Oder wenigstens zehnmal zehn Ausrufezeichen drucken würden.

23.2.9 Schleifen vermeidenBei Programmteilen, die besonders schnell ausgeführt werden sollen, vermeiden SieSchleifen, wo immer es möglich ist, durch das Angeben der einzelnen Befehle. Statt:

For I=1 To 3 Print INext

schreiben Sie eben:

Print 1Print 2Print 3

Page 376: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

376

Programmierstil und Fehlersuche23j e t z t l e r n e i c h

23.2.10 If-Bedingungen vereinfachenManchmal lässt sich eine If-Bedingung vereinfachen. Statt einer Schreibweise wie

If X=1 And Y=1 Then ...

ist mitunter

If X + Y = 2 Then ...

möglich. Überprüfen Sie dabei, ob sich nicht ungewollte Nebeneffekte einstellen. Imzweiten Beispiel würde der Then-Block auch dann ausgeführt, wenn X=0 und Y=2 ist.

Durch raffinierte Konstruktionen lässt sich manche If-Bedingung ersetzen. So schrei-ben Sie statt

If X => 100 Then Y = 1

besser

Y = (X => 100)

23.2.11 If-Bedingungen zusammenfassenAuch das Zusammenfassen mehrerer verschachtelter If-Bedingungen zu einer ist mit-unter möglich. Statt

If X=1 Then If Y=1 Then ... EndIfEndIf

schreiben Sie besser:

If X=1 And Y=1 Then ...

Mehrere ElseIf-Verzweigungen sollten Sie durch Select/Case ersetzen.

23.2.12 Gosub statt FunctionUnterprogramme mit Gosub sind schneller als Funktionen. Parameter lassen sich überglobale Variablen übergeben. Allerdings erzeugen viele Unterprogramme oft unüber-sichtliche Quelltexte. Wird ein Programmteil nur an zwei bis drei Stellen benötigt, lohntsich eine eigene Funktion meist ohnehin nicht.

23.2.13 Sprünge vermeidenVersuchen Sie, auf Programmsprünge mit Goto, Gosub und Function zu verzichten. Dasgeht allerdings auf Kosten der Übersicht, so dass es hier abzuwägen gilt.

Karlheinz Petry, www.shadowturtle.de: »Programmieren macht Spaß! Jedoch willes auch gelernt sein. Zum sauberen Entwickeln gehört, dass ein Spiel schnellstmög-lich und speichersparend funktioniert. Freilich kann man High-End-PCs vieles zumu-ten, doch nicht jeder besitzt so eine Maschine. Daher muss der Programmierer auchdie »normalen« Benutzer berücksichtigen. Unnötige Operationen gilt es zu vermei-den.«

Page 377: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

377

Optimierung II: Grafik j e t z t l e r n e i c h

23.3 Optimierung II: Grafik

Noch größere Verbesserungen der Performance lassen sich bei den Grafikbefehlen er-zielen. Bilder sind der Geschwindigkeitskiller Nummer 1 bei PCs – nicht umsonst sindGrafikkarten mittlerweile aufwendiger und nicht selten teurer als Prozessoren. Wäh-rend simple Berechnungen einem PC nur ein müdes Lächeln entlocken, kann einekomplexe Grafik einen PC in die Knie zwingen. Zeichnen Sie darum nur das ein, wasgeändert werden muss. Mitunter genügt es, nur Teilbereiche zu aktualisieren.

123.3.1 Geringere FarbtiefeDie Anzahl der Farben hat großen Einfluss auf die Programmgeschwindigkeit. Bei 16Bit Farbtiefe erreichen Programme die maximale Geschwindigkeit. 24 und mehr Bitsind langsamer.

23.3.2 Geringere AuflösungJe größer die Auflösung, desto langsamer erfolgt die Grafikausgabe. Das kommt daher,weil die Grafikkarte wesentlich mehr Daten schaufeln muss. Einfache Arcade-Spielesehen selbst mit 640x480 Punkten gut aus. Höher als 1024x768 sollten Sie nicht ge-hen.

23.3.3 VollbildmodusArbeiten Sie im Vollbildmodus. Wenn das Programm im Fenster läuft, dann übernimmtWindows eigenständig die Aktualisierung des Fensters. Die Wirkung ist eine seltenereAktualisierung des Bildes – auch wenn Frame-Zähler andere Auskünfte geben sollten.

23.3.4 Punkte beschleunigenPlot arbeitet sehr langsam. Es gibt deshalb einen speziellen Pixelbefehl: WritePixel. Erist wesentlich schneller. Das Verfahren hat nur einen Haken: Die Farbe muss manuellberechnet werden. Bei einer großen einfarbigen Fläche bringt das den meisten Ge-schwindigkeitsschub. Erscheint die Grafik nicht außerhalb des Bildschirmbereichs,dann kann WritePixelFast benutzt werden. Dieser Befehl arbeitet noch schneller.

23.3.5 Linien beschleunigenLine funktioniert nur sehr langsam. Mit einem Trick kann es beschleunigt werden.Wenden Sie bei vielen Linien den Befehl LockBuffer an. Allerdings dürfen Sie dabeinicht außerhalb des sichtbaren Bildschirmbereichs zeichnen.

Sollen einfache waagerechte oder senkrechte Linien gezeichnet werden, denn verwen-den Sie besser Rect. Setzen Sie dazu die Breite auf einen oder zwei Pixel. Dieser Befehlarbeitet erheblich schneller. Noch etwas mehr Geschwindigkeit kitzeln Sie heraus,wenn Sie das Rechteck ausfüllen lassen.

Dieser Abschnitt entstand unter wesentlicher Mitarbeit von Denis »TheShadow«Mischnew, dem Betreiber von www.blitzbase.de, der größten deutschen Blitz-Basic-Seite.

Page 378: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

378

Programmierstil und Fehlersuche23j e t z t l e r n e i c h

23.3.6 Schnelle PixelbilderWenn Sie ReadPixelFast einsetzen, um die Farbe aus einem Bild zu lesen und Write-PixelFast, um es anschließend einzuzeichnen, bietet sich eine spezielle Technik an.Lesen Sie die Bilddaten mit ReadPixelFast in ein Dim-Feld ein. Auf diese Weise über-geben Sie später WritePixelFast wesentlich schneller die Bilddaten, da der Zugriff aufdas Dim-Feld rascher erfolgt.

23.3.7 Farblesen beschleunigenMit ReadPixel lässt sich das langsamere GetColor ersetzen. Die Farbanteile müssendann manuell errechnet werden. Noch arbeitet ReadPixelFast – allerdings darf es nichtaußerhalb des Bildschirms angewendet werden.

23.3.8 Schnelles KopierenFalls nur Pixelfarben kopiert werden sollen, beschleunigt CopyPixel das Programm.CopyPixelFast ist noch ein Stück schneller. Allerdings darf es nicht außerhalb des Bild-schirms angewendet werden.

23.3.9 Bilder ladenDas Laden und Freigeben von Bildern sollte mit Bedacht erfolgen. Sie sparen Spei-cher, wenn Sie nicht mehr benötigte Bilder sofort freigeben. Doch das geht auf Kostender Geschwindigkeit. Soll es besonders rasch gehen, laden Sie am Anfang alle Bilder.

23.3.10 Gleichzeitig kopieren und einzeichnenMit CopyRect kopieren und zeichnen Sie einen Bildbereich gleichzeitig ein. Das gehtschneller als mit dem Paar GrabImage und DrawBlock.

23.3.11 Auf Cls verzichtenWenn Sie ein bildschirmfüllendes Hintergrundbild verwenden, kann Cls entfallen. Zei-chen Sie das Bild aber ohne Transparenz (etwa mit DrawBlock), damit der alte Inhaltnicht durchscheint.

23.3.12 Kollisionsprüfung optimierenVersuchen Sie, auf die langsamen Kollisionsbefehle zu verzichten. Meist genügt es, dieKoordinaten zu überprüfen. Auch Tests, ob ein Rechteck, ein Kreis oder eine Ellipseangeklickt wurde, sind mit einfachen Berechnungen möglich. Eine Kreis-/Ellipsen-berechnung kann vereinfacht für Sechsecke benutzt werden. Die »Fehlerquote« ist nurminimal.

Falls es trotzdem nicht ohne Kollisionsbefehle geht – im Folgenden sehen Sie eine Auf-zählung der Befehle in der Reihenfolge ihrer Geschwindigkeit:

� RectsOverlap

� ImageRectOverlap

Page 379: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

379

Optimierung II: Grafik j e t z t l e r n e i c h

� ImagesOverlap

� ImageRectCollide

� ImagesCollide

23.3.13 Bildgröße ändernDas Ändern der Bildgröße ist ein sehr langsames Verfahren. Etwas schneller geht es,wenn Sie das bilineare Filtern ausschalten (TFormFilter 0). Eine zweite Möglichkeit istdas manuelle Vergrößern und Verkleinern. Ein Beispiel dazu finden Sie im Abschnitt»Ausschnitt kopieren«.

23.3.14 Bilder drehen Das Drehen eines Bildes ist ebenfalls sehr zeitaufwendig. Auch hier lohnt sich dasDeaktivieren des bilinearen Filters. Weiterer Effekt: Sie vermeiden das Verfälschen desBildes durch fortwährendes Drehen und Filtern.

23.3.15 Grafiken vorausberechnenManipulationen an Grafiken wie das Verändern der Größe oder Drehen sollten nicht inder Hauptschleife des Programms erfolgen. Entweder erstellen Sie am Anfang ein Bildund nehmen dort die Veränderungen vor. Dadurch können Sie über die gesamte Lauf-zeit rasch darauf zurückgreifen. Oder Sie legen sich die Grafiken im Vorfeld zurechtund laden sie von der Festplatte.

23.3.16 Platz freischaufelnModerne PCs besitzen Arbeitsspeicher ohne Ende. Aber es gibt auch betagte PCs, aufdenen Spiele laufen sollen. Und gerade weil so viel RAM zur Verfügung steht, neigtman dazu, immer mehr Programme parallel laufen zu lassen. Reicht der Arbeitsspei-cher nicht mehr aus, lagert Windows Daten auf der Festplatte aus. Das ist eine Zeitver-zögerung.

Das Spiel sollte sparsam mit dem Speicher umgehen und nur Daten laden, die im Mo-ment notwendig sind. Geben Sie Grafiken und Klänge von beendeten Levels frei.Schließen Sie Dateien, deren Inhalt Sie nicht mehr benötigen.

Robert Gerlach, www.robsite.de: »Der Code von Blitz Basic wird zwar direkt in Ma-schinensprache kompiliert und ist somit schon ausreichend schnell, es gibt aber sehrviele Wege, um das Ganze zu optimieren. Nichts wirkt sich mehr auf die Geschwin-digkeit aus als eine klare und von Ballast befreite Programmierung. Machen Sie nurdas Notwendigste. Man muss bei einem Shooter nicht unbedingt die Einschlagtiefe ei-ner Kugel in eine Wand berechnen, um somit die Anzahl der Partikel bestimmen zukönnen, die physikalisch korrekt von ihr wegfliegen. Ein Lochbild und ein paarRauchwölkchen reichen aus.«

Page 380: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

380

Programmierstil und Fehlersuche23j e t z t l e r n e i c h

23.4 Datensicherung

Unverzichtbar ist das regelmäßige Sichern von Quelltexten, das Backup. Wenn Sie bis-her »passiv« Ihren Computer genutzt haben, mit Spielen und Surfen im Internet, wares kein Problem, die Festplatte zu formatieren und Windows neu aufzuspielen. DochQuelltexte, an denen Sie wochen- oder tagelang gearbeitet haben, sollten nicht ver-loren gehen – weder durch ein vorschnelles Formatieren noch durch einen Ausfall derFestplatte.

Bewahren Sie alle Dateien zu einem Projekt in einem Ordner auf: Quelltexte, Grafiken,Sounds, Konzepte. Kopieren Sie nach jeder Arbeitssitzung wenigstens den Quelltextauf einen anderen Datenträger, etwa eine zweite Festplatte, eine Diskette oder eineZip-Disk. Überschreiben Sie nie das letzte Backup. Nutzen Sie etwa zwei verschiedeneDisketten, auf denen Sie abwechselnd das Backup speichern. Brennen Sie regelmäßigdas komplette Projekt auf eine CD. Bewahren Sie ein Backup außerhalb Ihrer Woh-nung auf – im Büro oder bei einem Freund.

Thomas Voßfeldt, www.bytecobra.de: »Ich höre immer wieder mit Bedauern, dassSpieleprojekte gescheitert sind, weil bei einem Teammitglied die Festplatte Schadenerlitten hat. Datenverlust kommt doch immer unerwartet! Ich würde mir die Haareraufen, bedeutet doch ein solcher Vorfall den unwiderruflichen Verlust der Geistes-arbeit von mehreren Wochen bis Monaten – und damit oft auch das einzige oder zu-mindest wichtigste Kapital des Teams. Wer so fahrlässig mit seinem Arbeitsgut um-geht, braucht gar nicht erst anzufangen. Denn bereits der erfolgreiche Verlauf derEntwicklung gerät zum Glückspiel.

Gegen den Verlust wertvoller Arbeit gibt es einfache Mittel, die man nur diszipliniertund regelmäßig einsetzen muss. Ich empfehle, spätestens alle ein bis zwei Wochenalle Dateien auf eine CD zu brennen – Quellcodes, Bilder, Sounds, Levels ... Dazu istes zweckmäßig, dass die Dateien für ein Projekt nicht über sämtliche Partitionen ver-streut werden, sondern zusammen in einem Ordner liegen.

Zwischenspeichern kann man nicht genug. Fügen Sie dem Dateinamen eine Ver-sionsnummer an, wie etwa SOCCER_V01.BB. Wenn Sie viel geändert haben, spei-chern Sie die Datei mit einer höheren Versionsnummer ab, also alsSOCCER_V02.BB. Die alten Versionen heben Sie auf und brennen sie mit auf dieDatensicherung. Und erst wenn Sie Wochen später sicher sind, dass Sie diese älterenVersionen nicht mehr benötigen, löschen Sie sie von Ihrer Festplatte.

Speziell für Quellcodes eignen sich weitere Sicherungsmethoden: Die Textdateienlassen sich mit Komprimierprogrammen wie WinZip besonders gut packen. Ich si-chere Quelltexte zwischendurch immer mal auf eine Diskette. Gepackt passen dieQuellcodes mehrerer umfangreicher Spieleprojekte auf eine einzige Floppy.

Zweckmäßig ist es, sich einen kostenlosen Mailaccount, etwa bei www.gmx.de, ein-zurichten, um sich damit die ebenfalls gezippten Quellcodes nach Abschluss eines Ar-beitstags dorthin zu mailen, wo man eine Kopie seiner Daten sicher wähnen kann –nach Hause, in die Firma oder zu einem Teamkollegen. Wenn Sie irgendwo Web-space gemietet haben, sollten Sie Ihre gepackten Quellcodes gut in einen (am bestenper Passwort geschützten) Ordner auf dem Webserver ablegen. Besonders kniffeligeQuellcodepassagen sollte man sich ausdrucken und abheften, wenn sie fertig sind undfunktionieren.

Zu viele Sicherheitskopien kann es nicht geben. Nur zu wenige.«

Page 381: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

381

jetz

t le

rne

ich

KAPITEL 24

Von der Idee zum Spiel

Was macht ein gutes Spiel aus? Was müssen Sie beim Entwurf beachten? Zusammenmit einer Handvoll Experten habe ich viele Ratschläge für Sie zusammengestellt.

1Wenn Ihnen das nicht genügt: In dem wundervollenBuch Game Design, das mittlerweile in einer zweitenAuflage (ISBN 3-8272-9097-X) vorliegt, werden auf400 Seiten weit über hundert Entwickler befragt. Sieerfahren, was Sie beim Erstellen von Menüs, Levelsund Puzzles beachten müssen, wie Sie Grafik undMusik hinzufügen und ein Spiel am besten bekanntmachen. Leider ist das Buch mittlerweile vergriffen,aber Sie können es gebraucht zum Beispiel aufwww.ebay.de oder www.abebooks.de erwerben.

Ebenfalls empfehlenswert ist Computerspiele – Design und Programmierung(ISBN 3-8266-0920-4) vom Verlag mitp. Der 800 Seiten starke Wälzer konzentriertsich auf das Spieldesign und Management von Projekten einerseits sowie Program-mierung andererseits. Er behandelt dabei C++, doch viele Kapitel sind sprachüber-greifend. In englischer Sprache gibt es eine ungleich größere Anzahl an einschlägigenBüchern. Einer der Referenztitel wurde übersetzt: Spieleprogrammierung – Gems 1(ISBN 2-8266-0923-9), ebenfalls von mitp. Es behandelt Programmiertechniken,höhere Mathematik, Künstliche Intelligenz und andere Themen für Fortgeschrittene,die C++ beherrschen. Eine umfassende Katalogisierung von Büchern über Spieleent-wicklung bietet die Site www.games-net.de.

Page 382: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

382

Von der Idee zum Spiel24j e t z t l e r n e i c h

24.1 Spielidee

Für die ersten Schritte sollten Sie ein Genre wählen, das sich leicht umsetzen lässt. Ein-faches Spiel muss nicht schlechtes Spiel bedeuten. Alle Klassiker aus der Goldenen Ärader Spielhallen (Arcades), etwa »Pac-Man«, »Tetris« oder »Space Invaders«, sind einfachstrukturierte Spiele mit Regeln, die sich auf Anhieb erfassen lassen. Sie werden nochheute, teilweise zwanzig Jahre nach ihrem Erscheinen, gern gespielt. Die Ideen setzenSie innerhalb einer überschaubaren Zeit – einiger Tage oder Wochen – um. Das schafftrasche Erfolgserlebnisse. Die gesammelten Erfahrungen helfen Ihnen, größere Projek-te schneller anzugehen.

Auch in punkto Zeitschriften ist uns das Auslandvoraus mit Zeitschriften wie GameDeveloper(www.gamedev.com). Bislang gibt es nur deutsch-sprachige Periodika für Computergrafiker, wie digitalproduction (www.digitalproduction.com). Das willdas neue Magazin Game Face (www.game-face.de)mit einer Mischung aus technischen und kulturellenThemen ändern.

Frank Noack, www.moewendreck.de: »Zunächst brauchen Sie eine originelle Spiel-idee, die sich in dem begrenzten zeitlichen Rahmen auch umsetzen lässt. Dabei mussdas Rad nicht neu erfunden werden. Es reicht oftmals schon, es ansprechend anderszu verpacken. Um neue Ideen zu finden, bediene ich mich bei meinen Pausenspielenmeistens bei klassischen Spielprinzipien. All die guten alten Games, die uns früher anden C64 oder Amiga gefesselt haben. In vielen Fällen wurden Spiele dadurch zu Kult-spielen, weil ihre Entwickler es geschafft haben, sich auf das Wesentliche zu beschrän-ken. Jedes einzelne Feature zielt daraufhin ab; und mit jedem Klick beschäftigt er sichnur damit, mag die Masse der Möglichkeiten auch noch so verlockend erscheinen.«

Joe Frohberg, www.spieleflut.de: »Was macht ein gutes Spiel aus? Diese Frage istwohl so alt wie die Existenz von Spielen selbst. Ein gutes Spiel vereint in sich einegute Grafik, einen anziehenden Sound, eine einzigartige Spielidee, eine ausgewoge-ne Spielbalance und noch vieles mehr. Noch heute machen »The Secret of MonkeyIsland« oder »Civilization« einen Heidenspaß, obwohl weder Grafik noch musikalischeUntermalung zeitgemäß sind. Also muss es etwas geben, das fesselt, auch wenn esaussieht, als ob es vor zwanzig Jahren programmiert wurde. Die ultimative Antwortist das Spielprinzip, die Idee oder der Spielwitz. Egal, wie man es bezeichnet, es bleibtdas Gleiche, doch was ist es nun? Ich kann jetzt natürlich nicht eine Spielidee nennen,die dann immer wieder einen Hit produziert. Das geht gar nicht, denn jeder »Com-mand & Conquer«-Klon machte von Mal zu Mal weniger Spaß. Aber es gibt einigeElemente, die ein Spiel interessanter machen.

Page 383: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

383

Spielidee j e t z t l e r n e i c h

Um zu verstehen, was dies ist, darf man nicht bei Spielen bleiben, sondern man mussin die Wissenschaft gehen. Die Frage verlagert sich auf Gebiete der Verhaltensfor-schung und der Vergangenheit. Ein einfaches Prinzip ist der Sammlereffekt. Als dieMenschen noch in Höhlen oder als Nomaden lebten, waren sie oft Stunden auf derSuche nach guten Pilzen, schmackhaften Beeren oder einem großen Wildbestand.Wenn man nun in seinem Spiel den Jäger und Sammlerinstinkt wecken kann, hatman auf alle Fälle den Spieler ein wenig am Monitor gefesselt. Am Beispiel von»Diablo« kann man sehr gut erkennen, dass selbst das Prinzip eines ganzen Spiels aufdiesem Instinkt fußt.

Eine weitere Möglichkeit ist der Einbau einer Bestenliste (Highscore). Um sich fortzu-pflanzen, musste man das stärkste, schnellste und beste Männchen sein, da man dannauch das beste Weibchen bekam. Eine Punktverteilung bedient dieses Prinzip. Manwill der Beste sein und man spielt so lange, bis man besser als alle anderen ist.

Die nächste Herausforderung erkannten bereits die ersten Spieleentwickler mitAdventures. Es ging darum, Rätsel zu lösen. Die Menschheit musste ihre ganze Exis-tenz lang immer wieder Probleme lösen. Ob es nun die Überquerung eines reißendenFlusses oder die richtige Jagdtechnik war. Immer musste man ein Problem bewältigenund wenn man dem Spieler einige stellt, wird er garantiert so lange davor sitzen, biser sie gelöst hat.«

Robert Gerlach, www.robsite.de: »Erwarten Sie nicht, in der ersten Woche ein Rol-lenspiel schreiben zu können oder ein beliebiges anderes Spiel mit Grafik, Sound undStory. Es sei denn, Sie können gleichzeitig gut zeichnen, epische Symphonien kom-ponieren, lustige Geschichten schreiben und haben zudem noch das Buch verstandenund können in Blitz Basic programmieren. Fangen Sie am besten klein an und ver-suchen Sie nicht, »auf Teufel komm raus« vermeintliche Standardspielelemente(Hauptmenü, Spielfigur, schießende Gegner) zu einem Spiel verbinden zu wollen.Denken Sie sich etwas Neues aus, das Sie selbst realisieren können.«

Oliver »Freax« Skawronek, mitglied.lycos.de/thevertex: »Versuchen Sie, sich durchNamen, Design, Bewegung und andere Parameter von eintönigen Spielen abzuhe-ben. Englische Titel gibt es zur Genüge; versuchen Sie etwas Interessanteres. Wiewäre es mit einem Spiel im Cartoon-Stil? Oder komplett ohne Gewalt? In den meis-ten Spielen muss man töten, um zu gewinnen. Das Spielprinzip bleibt dabei gleich,wobei sich die Spiele allein durch grafische Effekte übertrumpfen. Deswegen istKreativität gefragt, denn aus grafischer Sicht werden Sie kein »Quake 4« zaubern.Simple Ideen wie die »Moorhuhn-Jagd« wurden Kult. Erarbeiten Sie trotzdem tief-gehende Storys, um das Spiel so spannend wie möglich zu halten.«

Page 384: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

384

Von der Idee zum Spiel24j e t z t l e r n e i c h

Schauen wir uns die gebräuchlichsten Genres an, die sich für Blitz Basic besonders eig-nen. Genres mit einem Stern sind bereits für Anfänger umsetzbar. Zwei Sterne bedeu-ten fortgeschrittenes Können und an drei Sterne sollten sich nur Profis wagen. Natür-lich verlaufen die Grenzen fließend – ein Brettspiel kann Mühle sein oder auch Schach.

Thomas »4pac« Voßfeldt, www.bytecobra.de: »Bauen Sie Spiele mit einer originel-len Geschichte. Sie werden als Einzelkämpfer kaum mit dem Animations- und Gra-fikniveau der großen Spieleentwicklerschmieden mithalten können. Aber Sie könnensich abheben durch »geistige Substanz«. Und in Genre-Mixes sehe ich eine große Zu-kunft. Mischen Sie mal eine Wirtschaftssimulation mit einem Adventure! In der Musikhaben solche Crossovers die letzten fünfzehn Jahre über die Charts bestimmt. Dennirgendwann kann man einfach nichts Neues mehr machen. Aber etwas Originelles,das geht immer, wenn man sich Mühe gibt.«

Können Genre Beschreibung

* Shooter Ein Raumschiff oder Ähnliches muss feindli-che Objekte abschießen.

* Quizspiele Das Allgemeinwissen wird abgefragt.

Page 385: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

385

Spielidee j e t z t l e r n e i c h

** Geschicklichkeitsspiele Die Spielfigur (oder etwa ein Ball) wird fingerfertig über den Bildschirm bewegt, um zum Bei-spiel Schätze einzusam-meln und Gegnern auszuweichen.

** Denk- und Brettspiele Der Spieler muss über-legt Spielsteine ziehen – teilweise allein, teilweise mit dem Computer als Gegner (wofür Strate-gien programmiert wer-den müssen).

** Handelssimulationen/Managerspiele Der Spieler muss ein Unternehmen gründen oder Reich errichten und es zur Blüte bringen.

Können Genre Beschreibung

Page 386: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

386

Von der Idee zum Spiel24j e t z t l e r n e i c h

** Jump'n'Run- oder Plattformspiele Die Figur läuft und springt über Stock und Stein, sammelt interes-sante Dinge ein und erlegt böse Gegner.

*** StrategiespieleSiedlungen werden erbaut, Armeen kämp-fen gegeneinander.

*** Adventures Der Held treibt durch Unterhaltungen, Sam-meln und kluges Anwen-den von Gegenständen eine komplexe Geschichte voran.

Können Genre Beschreibung

Page 387: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

387

Projektplanung j e t z t l e r n e i c h

24.2 Projektplanung

Freilich können Sie mit einem vagen Vorhaben beginnen und sich während des Pro-grammierens Details ausdenken. Es empfiehlt sich aber sehr, dass Sie ein Konzept er-arbeiten. Spalten Sie Ihre Ideen auf und schreiben Sie sie nieder: Spielinhalt, Art derFiguren, Steuerung, Tastenbelegung, Menüs, Grafiken, Töne, Hintergrundbilder, Spei-cherung. Was müssen Sie beim Laden eines Levels, beim Bewegen von Figuren, beiZusammenstößen beachten?

24.3 Arbeiten im Team

Die meisten Spiele werden nicht von Einzelkämpfern entwickelt, sondern von einerGruppe. Das ist sinnvoll: Wer gut programmiert, ist nicht unbedingt ein Experte imKomponieren von Musik oder Erstellen von Grafiken. Beachten Sie, dass Sie im TeamTeile der Verantwortung abgeben müssen. Ihre Kollegen werden eigene Vorstellungenhaben. Nicht immer ist es leicht, sich zu einigen.

*** Rollenspiele Der Spieler steuert einen Helden (oder eine Heldengruppe), löst Auf-gaben (Quests) und kämpft gegen Monster.

Können Genre Beschreibung

Paul S. Müller, www.virtual-brothers.com: »Halten Sie sich vor Augen, was Sie fürein Spiel entwickeln wollen. Schreiben Sie Ihre Gedanken nieder. Es reicht nicht, dassSie sich überlegt haben, etwa ein Strategiespiel zu entwickeln. Vor allem sollte das an-gestrebte Ziel nicht Ihre Fähigkeiten überschreiten, da es sehr ärgerlich ist, sehr vielZeit in ein Projekt investiert zu haben, das Sie wegen mangelnden Könnens nicht fer-tig stellen können. Sie als Programmierer können sich vor dem Projektstart bereitsüberlegen, was für Probleme auf Sie zukommen. Zum Beispiel ist es nicht leicht, eineWegfinde-Funktion zu programmieren, die alle Einheiten zu dem gewünschten Zielführt. Dabei ist auch noch die Leistung des Computers zu beachten. Manche Featureskönnen einfach nicht umgesetzt werden, da man von dem Spieler nicht verlangenkann, den leistungsstärksten Prozessor und die schnellste Grafikkarte zu besitzen.Sind Sie nach reichlichen Überlegungen sicher, dass Sie alle Probleme bewältigenkönnen? Dann ist ein wichtiger Schritt getan.«

Page 388: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

388

Von der Idee zum Spiel24j e t z t l e r n e i c h

Paul S. Müller, www.virtual-brothers.com: »Haben Sie konkrete Vorstellungen vonIhrem Spiel und bringen Sie den nötigen Willen mit, um ein größeres Projekt über ei-nen Zeitraum von mehreren Monaten zu entwickeln, dann fehlt Ihnen nur noch einTeam. Sie könnten natürlich in ein bestehendes Entwicklerteam einsteigen. Allerdingskönnen Sie dann meist nicht Ihre eigene Spielidee umsetzen, sondern müssen sich aneinem anderen Projekt beteiligen. Sie müssen ein neues Team gründen, damit Sie Ihreigener Chef sind. Ein Teamname ist schnell gefunden, doch das bringt ohne fähigeMitarbeiter nichts. Der wahrscheinlich schwierigste Teil in der Anfangsphase einesProjekts ist es, Leute zu finden, die man für das eigene Projekt begeistern kann. Wennman in seiner Umgebung niemanden findet, dann ist das Internet der geeignete Platz,um Mitarbeiter zu suchen. Sie brauchen Grafiker, Musiker und vielleicht noch Pro-grammierer. Diese finden Sie in unterschiedlichen Foren, wo sie ihr Können zur Schaustellen. Dort sehen Sie, ob jemand das nötige Potenzial hat, um an Ihrem Projekt mit-zuarbeiten. Wichtig ist noch, dass das Team nicht zu viele Mitglieder bekommt, dasonst die Koordination und Kommunikation im Team unnötig erschwert wird.

Folgende Mitarbeiter werden benötigt, um Ihr Spielprojekt erfolgreich umzusetzen:Sie sind der Hauptprogrammierer in Ihrem Team. Natürlich könnten Sie die gesam-te Programmierung übernehmen, aber bei komplexeren Projekten ist es ratsam, sichUnterstützung zu holen. Zum Beispiel können Abschnitte wie die Künstliche Intelli-genz der Computergegner von anderen Programmierern übernommen werden. Diegenaue Absprache zwischen den Programmierern ist besonders wichtig, da der ent-standene Code am Ende perfekt zusammenarbeiten muss. Mehr als drei Program-mierer sind deshalb nicht zu empfehlen.

Grafiker sind für verschiedene Bereiche im Spiel zuständig. Sie brauchen einen Gra-fiker, der das Menü (Buttons, Hintergrundbilder usw.) entwickelt. Ein anderer zeich-net z.B. die Einheiten für Ihr Strategiespiel. Diese müssen auch animiert werden, wasein großes Stück Arbeit bedeutet. Ein anderer Grafiker muss sich noch um die ganzeLandschaft kümmern. Von den Bodentexturen bis hin zu Bäumen und Häusern mussalles entworfen werden. Die Aufgabe des Leveldesigners ist, aus diesen ganzen Ob-jekten mehrere Levels zusammenzubauen, die für alle Spieler gleiche Gewinnchan-cen bieten, damit der Spielspaß nie verloren geht. Für den Grafikbereich brauchenSie nicht mehr als vier Mitarbeiter.

Für die Musik und Soundeffekte reichen zwei Mitarbeiter aus. Die Musiker könnenmeist erst in einem fortgeschrittenen Stadium der Projektentwicklung mit ihrer Arbeitanfangen. Die Musikstücke, die während des Spielens im Hintergrund ablaufen, müs-sen sehr speziell auf das Spiel angepasst sein. Der Musiker muss das Spiel schon ge-spielt haben, damit er die Atmosphäre mit seiner komponierten Musik unterstreichenkann. Wichtig ist auch, dass die Musik nicht zu eintönig wirkt. Unterschiedliche Stü-cke, am besten noch situationsabhängig, sorgen für eine ständige Abwechslung beimSpielen. Die Soundeffekte müssen wie die Musik auf das Spiel angepasst werden.Eventuell werden noch Sprecher gebraucht, wenn das Spiel Sprachausgabe bietet.

Nun haben Sie ein komplettes, motiviertes Team, das nur darauf wartet, mit der Ar-beit anzufangen. Sie als Teamgründer sind für die gesamte Koordination zuständig.Sie verteilen die Aufgaben. Wichtig ist, dass Sie den Mitarbeitern Ihre Vorstellungenvon dem Spiel so konkret wie möglich vermitteln. Doch Sie sollten auf jeden Fall of-fen für neue Vorschläge sein. Ihr Team wird es Ihnen danken und gute Arbeit leisten.

Page 389: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

389

Arbeiten im Team j e t z t l e r n e i c h

Nicht selten müssen Sie mit unerwarteten Problemen zurechtkommen. Plötzlich istein Grafiker wegen mangelndem Interesse abgesprungen oder ein Sprecher hat kei-ne Stimme mehr. Aber all diese Probleme können Sie meistern, wenn Sie Ihr Ziel im-mer fest vor Augen behalten und nicht aufgeben. Als Teamleiter müssen Sie flexibelsein und sich schnell auf neue Situationen einstellen. Sie müssen sich von Mitgliederntrennen, wenn sie ihre Arbeit nicht richtig machen, neue Mitarbeiter suchen und ein-stellen, eigene Ideen verwerfen, die nicht umzusetzen sind, Ihr Team zusammenhal-ten, es ständig motivieren und noch vieles mehr. Das ist alles sehr anstrengend, aberwenn man sieht, wie sich das Spiel entwickelt, dann kann man mit sich zufriedensein.«

Matthias Gall, www.sechsta-sinn.de: »Gerade bei Amateurteams ist es wichtig, dieMotivation über die gesamte Dauer eines Spielprojekts aufrechtzuerhalten. Ich habedie Erfahrung gemacht, dass bei uns vier Dinge entscheidend für das Fortschreitensind:

– Ab einer gewissen Größe ist eine gute Organisation unabdingbar. Das fängt bei-spielsweise mit einer Verwaltung des Quellcodes auf der Softwareseite an undendet dann bei einer guten Sekretärin auf der »Hardwareseite«, unserem Team-manager. Irgendjemand muss ständig nachhaken, wer was macht und wie langees dauert. Bei den Profis nennt man so was wohl den »Development Director«.Ohne jemanden, der einen ein bisschen »in den Hintern tritt«, können offenbarnur die wenigsten arbeiten. Außerdem muss je nach Projektgröße mehr oder we-niger viel schriftlich festgehalten werden. Bei uns gibt es sehr viele Detailfragen,die einen Programmierer beschäftigen: Wie verhält sich die Einheit in einem be-stimmten Modus? Wie ist die maximale Energie dieser Einheit? Wie ist die Scha-denskraft eines Projektils? Wer will da gerne in Tausenden von E-Mails suchen?Besser ist ein zentraler Punkt, wo alles festgehalten wird, das Design-Dokument.Günstigerweise liegt so was auf einem gemeinsamen Webspace, über den maneinfach Dateien innerhalb des Teams austauschen kann. Zum Austausch sindauch weitere Möglichkeiten zu organisieren, etwa eine Mailingliste, ein Chat, einForum.

– Viele Amateurteams beginnen irgendwann in der Schule, sei es Unter- oderOberstufe. Wer als Schüler ausschließlich den Computer als Hobby hat, der hatim allgemeinen viel Zeit dafür und so sind die ersten Schritte schnell gemacht. Oftkommt aber dann der Punkt, wo sich einiges ändert. Das anstehende Abitur, derWehr- oder Zivildienst, die Arbeit oder das Studium rauben oft mehr Zeit, als ei-nem lieb ist. Hier scheitern meistens die Projekte, die noch nicht am fehlendenKönnen misslungen sind. Daher ist es wichtig, dass auch eine Bereitschaft da ist,Zeit für das Projekt zu opfern, egal wie stressig der Rest wird. Innerhalb einesTeams gibt es oft »Leithammel«, die den anderen Aufgaben geben und/oder alleindurch die Tatsache, dass sie am Projekt aktiv sind, die anderen Mitglieder anspor-nen. Ich habe oft den Eindruck gehabt, dass das Projekt etwas eingeschlafen ist,wenn ich mich zur Klausurvorbereitung o.Ä. etwas zurückziehen musste.

Page 390: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

390

Von der Idee zum Spiel24j e t z t l e r n e i c h

– Zwischenergebnisse zeugen vom stetigen Fortschritt der Arbeit und halten dieMotivation aufrecht. Programmierer werden oft durch neue Grafiken motiviert,während Grafiker Lust auf mehr bekommen, wenn sie ihre eigene Arbeit im Spielbetrachten können. Teamarbeit ist ein Teufelskreis. Erfahrene Entwickler solltendaher ein System schaffen, mit dem die Künstler ihre Werke einfach selbst ein-bauen können (zumindest in einem einfachen Rahmen), weniger erfahrene soll-ten wenigstens regelmäßige Versionen zur Verfügung stellen, die den Zwischen-stand zeigen. Damit ergibt sich ein weiteres Problem: Ergebnisse haben eineGeschwindigkeit. Am Anfang sind sie viel schneller da, als zu einem fortgeschrit-tenen Entwicklungsstand. Während das Grundgerüst relativ schnell programmiertist und sich auch relativ schnell ein paar Einheiten darauf bewegen können, sindzahlreiche (Detail-)Arbeiten sehr zeitaufwendig und Ergebnisse sind hier für ande-re als den, der sie selbst umgesetzt hat, manchmal nur schwer sichtbar. Wer dieMuße hat, ein Projekt langfristig und ausgiebig zu planen, sollte darauf achten,dass immer mal wieder ein Feature implementiert wird, das man »sehen« kannund über das sich jeder im Team freut.

– Ohne regelmäßige Treffen (bei uns etwa alle zwei bis drei Monate) wäre das Pro-jekt nie so weit, wie es jetzt ist. Wir treffen uns meist für ein ganzes Wochenendeund schaffen in dieser Zeit pro Person erfahrungsgemäß so viel wie sonst in ei-nem Monat oder länger. Wenn einer arbeitet, arbeiten alle. Ich kann nur empfeh-len, das auszuprobieren. Jedoch sollte man darauf achten, dass man sich nicht zusehr in Nebensächlichkeiten verliert, sei es im Netzwerkspielen (was sicher für einStündchen mal ok ist, um sich etwas abzulenken) oder im Austauschen vonDateien. Sicher, nicht jedes Treffen ist ein voller Erfolg. Manchmal drücken un-auffindbare Bugs, Hardware-Defekte oder ein Kreativitätstief auf die Stimmungeines Einzelnen. Letztendlich schweißt es das Team aber zusammen. Bei uns hatsich durch diesen Zusammenhalt eine Art Eigendynamik entwickelt. Ich glaube,keiner vom Kernteam würde sich trauen, jetzt noch aufzugeben. Nicht nur, weildie Entwicklung schon so weit fortgeschritten ist, sondern weil eine möglicheHemmschwelle hierfür durch das persönliche Kennenlernen gestiegen ist. Jederist sich seiner Verantwortung bewusst – geht einer, bricht das ganze Team zu-sammen.«

Marc Kamradt, www.spieleentwickler.org: »Eine Spieleentwicklung läuft in mehre-ren Schritten ab. Meist werden alle Phasen einer Entwicklung mehrmals durchlaufen,um den aktuellen Gegebenheiten angepasst zu werden. Es wird also immer nur einTeil des Spiels entwickelt, um dann innezuhalten und auf ungeplante Ereignisse zureagieren. Es ist unrealistisch anzunehmen, dass man am Anfang eines Projekts alleUnwegsamkeiten einplanen kann. Trotzdem kann man sich die Planung nicht schen-ken, denn der bestmögliche Plan zu einer gegebenen Zeit ist immer noch um ein Viel-faches besser als gar kein Plan. Grundlage für alle späteren Arbeiten an einem Spielist das Design-Dokument. Es enthält die Informationen, damit Programmierer, Gra-fiker, Leveldesigner und alle anderen Beteiligten wissen, wie das Spiel aussehen undablaufen soll. Gibt es von einem Beteiligten am Projekt eine Frage zum Spiel, so sollteer die Antwort im Design-Dokument finden.

Page 391: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

391

Arbeiten im Team j e t z t l e r n e i c h

Regelmäßige Kommunikation untereinander ist entscheidend für den Erfolg eines Pro-jekts. Bewährt haben sich – neben persönlichen Treffen und dem Telefon – InstantMessenger wie ICQ (www.icq.com), Programme, die über das Internet Kurztelegram-me verschicken. Diese Unterhaltungen sind schneller und unkomplizierter als E-Mails.Die History-Funktion erlaubt es, frühere Gespräche nachzulesen.

Für Absprachen im größeren Rahmen sind Chat-Räume ideal. Besonders leistungsfä-hig ist der IRC (Internet Relay Chat). Sie nutzen ihn üblicherweise mit einer speziellenSoftware, dem IRC-Klienten (zum Beispiel mIRC, www.mirc.com, auf der CD). ZumVerabreden benötigen Sie zwei Informationen: die Namen des Chat-Raums und desChat-Servers (bzw. des Server-Netzes), auf dem er sich befindet. Es gibt Server, die ent-halten nur eine Handvoll Räume, und es gibt Netze mit Zehntausenden von Chat-Räumen (Channels), etwa irc.euirc.net. Leicht lassen sich neue Räume erstellen unddauerhaft in Besitz nehmen. Empfehlenswert ist ein täglicher oder wenigstens wö-chentlicher Treff zu einem bestimmten Termin.

Das Design-Dokument wird meist von einer Untermenge des Teams erstellt, die danndie Rolle des Spieledesigners haben. Auf der Grundlage eines guten Design-Doku-ments wird ein Projektplan erarbeitet, der dazu dient, abzuschätzen, wie lange dasProjekt dauert, wie viele Personen für das Projekt notwendig sind und in welcher Rei-henfolge die einzelnen Zwischenergebnisse geliefert werden müssen, damit alle Be-teiligten möglichst optimal arbeiten können. Ist die Planung abgeschlossen, beginntdie eigentliche Entwicklung. Das Programm, die notwendigen Werkzeuge (wie Level-editor), die Grafiken, Levels, Musik und alle anderen Daten werden von den verschie-denen Beteiligten anhand der Planung und der Design-Dokumente erzeugt und zu-sammengefügt. Während der Entwicklung, spätestens jedoch am Ende, wird dasSpiel auf Herz und Nieren getestet und die Fehler und Unschönheiten werden korri-giert.

Anschließend kann das Spiel veröffentlicht (»released«) werden. Ein Release muss da-bei nicht das Ergebnis sein, das später auf den Markt kommt, sondern kann auch eineZwischenversion sein, die dann die Grundlage für eine Anpassung des Design-Doku-ments, der Planung und einer anschließenden weiteren Entwicklungsphase darstellt.Zwischenversionen lassen sich für Präsentationen beim Publisher, als Demoversionfür Zeitschriften oder als öffentliche Betatests nutzen. Irgendwann kommt für dasTeam der letzte Release des Spiels: die Endversion.«

Page 392: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

392

Von der Idee zum Spiel24j e t z t l e r n e i c h

Abb. 24.3:Im deutschen

Blitz-Basic-Chatherrscht von

Mittag bisnachts Betrieb.

Vor allem sams-tags ab 19 Uhr -

dann ist»Big Chat«.

Der besondere Vorzug von IRC: Die Gespräche lassen sich aufzeichnen (mitloggen)und können auf diese Weise noch Monate später eingesehen werden. Mehr zu IRC fin-den Sie auf einschlägigen Seiten wie www.irc-junkies.de.

1Eine Ergänzung dazu sind lokale Stammtische, die sich vor allem in Großstädten leichtorganisieren lassen. So gab es bereits mehrere Treffen von Blitz-Programmierern.Zum Verabreden eigenen sich die einschlägigen Foren wie www.blitzforum.de,www.usf.de und www.spieleentwickler-board.de. Um einen regelmäßigen Stamm-tisch am laufen zu halten, ist es empfehlenswert, sich zu einem festen Termin – zumBeispiel an jedem ersten Freitag im Monat – zu treffen. Jemand sollte eine Mailing-Lis-te (= ähnelt einem Forum; alle Beiträge werden aber per E-Mail verschickt) pflegen, umrechtzeitig an den Stammtisch zu erinnern.

Der deutsche Blitz-Basic-Chat befindet sich auf dem Server irc.blitzed.org im Raum#german. Jeden Samstag ab 19 Uhr wird dort zum »Big Chat« aufgerufen. Das eng-lische Pendant ist im Raum #blitzbasic untergebracht.

Page 393: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

393

Namensfindung j e t z t l e r n e i c h

24.4 Namensfindung

Wie sage ich es meinem Kinde? Viele Entwickler tun sich schwer, ihre Projekte würdigzu taufen. Doch das ist gar nicht so schwer.

24.4.1 TeamnameÜberlegen Sie sich einen pfiffigen Namen für Ihr Team. Wenn Sie Ihre Spiele als Ein-zelkämpfer programmieren, dann ist gegen eine Bezeichnung wie Ein Spiel von Ge-org Folwerk nichts einzuwenden; manche schreiben auch Georg Folwerk Games.

Sind weitere Mitstreiter beteiligt, bietet sich ein »echter« Name an, unter dem die Spieleveröffentlicht werden. Schauen Sie sich die Namen alt eingesessener Entwicklungs-studios an, wird Ihnen schnell klar, dass es nicht so schwer ist, eine mindestens ebensooriginelle Bezeichnung zu finden: Electronic Arts, Take 2, Revolution Software, NewWorld Computing, Blizzard ... Oft genug sind solche Namen in Sekunden entstan-den. (So schreibt Dieter Bohlen, der Name Modern Talking sei eine Blitzidee einer

Sebastian Lenk, www.seelenradio.de: »Im Mai 2003 haben wir uns zum erstenHamburger Blitz-Stammtisch in einer Gaststätte getroffen. Und es lohnte sich! Nichtnur der mitgebrachten und vorgestellten Projekte und Software wegen, sondernauch, weil die Menschen sympathisch und sehr nett waren.

Achim ließ uns Einblicke in seine Spiele »R2 – The Evil Returns« und »The AmersonFile« gewinnen. Beide Projekte sind super. »R2« versetzt den Spieler in eine Realschu-le, in der offensichtlich nicht alles mit rechten Dingen zugeht. Achim hat für diesesSpiel über 130 Fotos seiner ehemaligen Schule geschossen. Der einfach gehalteneRetro-Look hat einen ganz eigenen, faszinierenden Charme. Spätestens, wenn mandie Texteingabe entdeckt und zu benutzen weiß, fühlt man sich stark an alte Zeiten er-innert. Hinterlegt ist das Geschehen mit atmosphärischen Sounds. In »TAF« setztman sich intensiv mit der guten alten Brotkiste, dem C64, auseinander und versucht,einen Mord zu verstehen und aufzuklären. Wir waren begeistert von den Details. ZumBeispiel dem unverkennbaren Geratter des Diskettenlaufwerks oder dem Geräuschder Tastenanschläge. Und auch der C128 war nicht weit ;)

Wolfgang (Blitzblaster) wollte uns sein »Galaxia War« präsentieren, was allerdings zutechnischen Problemen auf den verfügbaren Notebooks führte. Immerhin konntenwir uns die Menüführung und ein paar sehr interessante Grafiken ansehen. Trotz deraufgetretenen Probleme sind wir sehr gespannt auf diesen Space Shooter. Thomas(4Pac) zeigte uns unter anderem eine kleine BlitzPlus-Anwendung, die aus HTML-Da-teien alle in einem Verzeichnis befindlichen, nicht referenzierten Grafiken findet undauf Wunsch verschiebt. Dieses Tool erleichtert die Arbeit mit z.B. Slices ungemein.

Natürlich haben wir uns nicht nur über unsere Projekte unterhalten. Thema warenauch wir selbst (»Was tust du? Was macht man dort genau? Macht das Spaß?«) und na-türlich Spiele im allgemeinen. Unsere Gemeinsamkeit: die Begeisterung für Retround Old School Games! Immer wieder wurden wir von den anderen Gästen neugierigbeäugt. Zum ersten Mal, als sich Achim daran machte, mit seiner Verlängerungs-schnur zur nächstbesten Steckdose zu gelangen. Und dann immer wieder, wenn wiruns gespannt über die Notebooks beugten, um besser sehen zu können und die nos-talgischen Sounds von Achims Spielen zu hören.«

Page 394: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

394

Von der Idee zum Spiel24j e t z t l e r n e i c h

Sekretärin gewesen, die auf ein Plakat mit den Charts schaute und dort die GruppenModern Romance und Talk Talk sah.)

Das Problem ist allerdings: Für eingängige Begriffe ist der Domainname nicht mehrverfügbar und was ist eine Spieleschmiede ohne Internetseite?

In jüngerer Zeit häufen sich mehr oder weniger sinnvolle Zusammensetzungen vonzwei Begriffen: Deep Red, Blue Byte, Factor 5, Sunstorm, Barking Dog, Black Star,Hot House ... Um einen neuen Namen zu erfinden, müssen Sie sich nur in Ihrem Zim-mer umschauen und mit den Gegenständen gedanklich spielen. Vor allem »universelle«Begriffe wie Fenster, Bildschirm oder Baum könnten in Verbindung mit einem zwei-ten Substantiv oder einem Adjektiv zu einer interessanten Verbindung führen. Diemuss freilich ins Englische übersetzt werden – es ist kaum möglich, einen deutschenNamen zu verwenden. (Der Autor dieses Buchs hat es trotzdem probiert:www.9leben.de :-) Oft genug findet man eine Ergänzung wie Games, Studio, Produc-tion, Entertainment.

0Haben Sie einen geeigneten Namen, folgen zwei Checks: Zum einen sollte eine pas-sende .de-Domain frei sein (nachzuschlagen unter www.denic.de/servlet/Whois). Zumanderen sollten keine fremden Namensrechte verletzt werden. Einen ersten Überblick,ob der Name bereits verwendet wird, bietet Google. Am besten ist es, wenn der ge-wählte Name gar nicht gefunden wird. Eine größere Sicherheit bietet eine Recherchebeim Deutschen Marken- und Patentamt (https://dpinfo.dpma.de), ob der gewählteName bereits als Marke angemeldet ist. Auf der sicheren Seite sind Sie mit einer Mar-kenrecherche durch einen Patentanwalt – ein Service, der allerdings einige hundertEuro kostet. Und den Sie für ein Hobbyprojekt sicher einsparen können, soweitGoogle sein »Ok« gegeben hat.

Wie sieht es jedoch umgekehrt aus? Können Probleme auftreten mit einem Namen,weil ein Unternehmen zukünftig die Bezeichnung als Marke anmelden könnte? ImGrunde nicht. Namensschutz ergibt sich automatisch durch Gebrauch. Die Anmeldungals Marke ist vor allem eine Absicherung, dass ein Name zu einem bestimmten Zeit-

Tobias Reis, www.massive.de: »Eine »gute« Namensfindung für Entwicklerteams soll-te folgende Punkte einfließen lassen: Assoziation mit der Branche (etwa Software,Games, Data), Idee bzw. Grundgedanke des Teams (Art, Development ...) sowieKürze und Einprägsamkeit (»Coolness-Faktor«).

Zum Namen kann ein »passendes« Logo entwickelt werden, das den Namen erkennt-lich macht, auch wenn er nicht ausgeschrieben wird – für Bananasoft etwa eine schö-ne gelbe Banane im Logo oder ein Schriftzug.

Diese Eigenschaften machen es sowohl dem Kunden wie auch für Werbezwecke ein-facher, sich den Namen des Teams zu merken. Natürlich führt ebenfalls ein »Top-Spiel« zur schlagartigen Steigerung des Bekanntheitsgrads. Und wenn der Nameleicht genug zu merken ist, wird er wohl eine längere Zeit im Gedächtnis haften blei-ben.«

Eine große Anzahl von Namen deutscher Entwickler finden Sie unter der Rubrik Port-folio auf der Seite www.usf.de.

Page 395: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

395

Namensfindung j e t z t l e r n e i c h

punkt verwendet wurde. Ältere Rechte bleiben davon unberührt. Das heißt, wenn Sieein Spiel namens »Delosc« veröffentlichen, brauchen Sie keine Sorge zu haben, dasszwei Jahre später eine Firma »Delosc« als Marke anmeldet und Ihnen dann verbietet,den Namen zu verwenden.

Falls Sie die Spieleentwicklung gewerblich betreiben, müssen Sie jedoch zusätzlich Ih-ren Vor- und Zunamen auf Ihrer Website und im Schriftverkehr angeben. Mehr Detailsfinden Sie in der Gewerbeordnung (zum Beispiel auf www.gesetzesweb.de/GewO.html); Auskunft erteilt Ihnen auch das Gewerbeamt und die IHK.

24.4.2 SpielnamenIrgendwann müssen Sie sich ebenfalls einen fetzigen Namen für Ihr Spiel ausdenken.Es kann nicht schaden, sich frühzeitig Gedanken zu machen. Wählen Sie etwas Origi-nelles, verletzen Sie aber dabei keine Namensrechte anderer Entwickler, indem Sie be-kannte Titel übernehmen oder nur leicht verändern.

Denkbar sind ein Fantasiewort (»Kolran«) oder ein Gefüge (»Fire Saber«, »Im Land derOrks«, »Der Rat der Zwölf«), das nicht zu schwer zu merken ist und neugierig macht.Oder eine Zusammensetzung, die bereits auf das Genre hinweist (»Fußball-König«).

Wertvolle Anregungen bieten Ihnen dabei einschlägige Bücher, etwa ein Lexikon überdie Zeit, in der Ihr Spiel handelt. So finden Sie vielleicht für Ihr Wikinger-Spiel denNamen eines zeitgenössischen Gottes oder Gegenstands. Auch für »inhaltsneutrale«Spiele in der Art von »Tetris« sind solche Begriffe denkbar.

Kay Schönewerk, www.4iMEDIA.com: »Denken Sie darüber nach, einen Namen zuwählen, der mit üblichen Konventionen bricht – etwa mit einer Zahl beginnt oder en-det. Dadurch heben Sie sich bereits im Namen von anderen Entwicklern ab. Lesermüssen zweimal hinschauen, wenn Sie in der Literatur, bei Besprechungen oderEmpfehlungen auf Ihren Namen stoßen. Denn sie können es aufgrund der Unterbre-chung des Leseflusses einfach nicht überfliegen. Sie stoppen also, überlegen – undsetzen sich mit Ihnen auseinander. Außerdem lässt sich mit der Interpretierbarkeit desNamens Öffentlichkeit schaffen. Beispiel: Immer wieder werden wir gefragt, was derName 4iMEDIA bedeutet. Und schon haben wir auch bei steifen Erstkontakten soforteine lockere Gesprächsatmosphäre, bei der es nicht nur ums harte Geschäft geht.Und der Name lässt mehrere Interpretierungen offen. Etwa »four eyes media«, einHinweis auf das Sprichwort, dass vier Augen mehr als zwei sehen, und unsereRecherchearbeit als Journalisten. 4iMEDIA könnte aber auch für »vier innovativeMedien« stehen – da ein Redaktionsbüro meist alle vier Bereiche (Print, Funk, TV undOnline) abdeckt. Oft genug kommen solche Interpretierungen erst vom Leser.«

Alexander Krug, www.softgames.de: »Der Name sollte nicht mit den letzten Buch-staben des Alphabets anfangen, sondern eher mit A oder B, so dass in großen Archi-ven, Zeitschriften usw. Ihr Spiel an erster Stelle steht und nicht untergeht. Oft klickendie Besucher von Websites nur die ersten paar Spiele zu einem Genre an. Nur wirk-lich Interessierte gehen tiefer ins Archiv.«

Page 396: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

396

Von der Idee zum Spiel24j e t z t l e r n e i c h

24.4.3 Namen für SpielfigurenBei komplexeren Spielen sollten die handelnden Figuren einen Namen haben. Bei ein-fachen Arcade-Spielen kann freilich darauf verzichtet werden – der Spieler identifiziertsich ja so oder so mit der Figur, die er steuert. Nicht immer ist eine Hintergrund-geschichte ein Gewinn; nicht immer muss der Spieler wissen, wie der Held heißt undwieso er handelt.

Wenn Ihre Hauptfigur einen Namen bekommt, sollten Sie überlegen, ob Sie nichtgleich das Spiel danach benennen. Erfolgreiche Titel wie »Rayman« oder »SuperMario« zeugen davon, dass das Konzept aufgeht, wenn die Figur so individuell gestaltetist, dass sie sich von der Masse abhebt.

Einschlägige Software hilft Ihnen dabei, passende Namen für Ihre Spielfiguren zu fin-den. The Everchanging Book of Names (http://ebon.pyorre.net/, auf der Buch-CD)bildet authentisch klingende Namen in jeder nur denkbaren Sprache – ob Japaner,Wikinger oder Elb, für jeden ist etwas dabei. Weitere Sprachdateien, etwa für das Star-Trek-Universum, können von der Website des Entwicklers geladen werden.

Nicht ganz so differenziert arbeitet der NameGenerator (http://travel.to/niclas/, auchauf der Buch-CD). Er erfindet Begriffe, die sich als Namen verwenden lassen – oderauch nicht, wie Gebilde wie Fleklup und Uklageo beweisen.

Nathalie S. Groh, www.no.lo.to: »Interessant sind Wörter, die mit dem Inhalt desSpiels zusammenhängen, aber in eine andere Sprache übersetzt wurden. Nehmenwir als Beispiel »Biest« – es klingt recht gewöhnlich und wurde schon oft benutzt.Übersetzt man es jedoch ins Japanische, kommt mit »Kemono« ein exotisches undungewöhnliches Wort heraus, das sich möglicherweise förderlich auf das Interesse amSpiel auswirkt und sogar Hintergrund besitzt. Auf www.babylon.com finden Sie eintaugliches Übersetzungsprogramm. Synonyme könnten eine ähnliche Wirkung erzie-len. Diese finden Sie unter anderem in einem Fremdwörterlexikon. Wollen Sie als Ti-tel für Ihr Spiel einen Namen benutzen, sollte es der gleiche sein, den auch ein Heldin Ihrem Spiel trägt. Im Internet finden Sie Namenslisten aller Art. Darin finden Siein der Regel die Bedeutung des Namens. Wissenschaftliche Bezeichnungen für Tiereund Pflanzen können ebenfalls eine Fundgrube für einen Titel sein oder Mineralien-bezeichnungen und chemische Formeln. Natürlich können Sie sich aus all den Wor-ten etwas komplett Neues zusammenstellen, was die Gefahr einer Copyright-Verlet-zung verringert.«

Page 397: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

397

Spieldesign j e t z t l e r n e i c h

Abb. 24.4:Wo die Phanta-sie versagt, hel-fen spezielle Generatoren beim Auswäh-len von Namen.

24.5 Spieldesign

Spaß ist das A und O. Ein langweiliges Spiel gerät schnell in Vergessenheit. Wenn sichIhre eigene Kreation langweilt, dann wird sie niemand anderem gefallen. Achten Siedarauf, dass der Spieler Spaß, keinen Frust und keine Langweile hat.

Jan Fleck, www.lexigame.de: »Machen Sie sie süchtig! Wie ein Spiel Kultstatus er-reicht und von aller Welt geliebt wird, dafür gibt es kein 100% sicheres Rezept – aberdie wichtigsten Zutaten will ich Ihnen nennen. Zunächst sollten Sie ein paar der per-fekt gestylten Spielhallenklassiker unter die Lupe nehmen. Wühlen Sie sich dabei ru-hig querfeldein durch die Jahre und Genres. Als Anregung helfen vielleicht das uralte»Pac-Man« und »Dig Dug«, weiter über »Gradius« und »R-Type«, »Street Fighter«, »As-sault« bis hin zu grafischen Highlights wie »Time Crisis« und »Gauntlet Legends«. Allehaben eines gemeinsam: eine Erfolg versprechende Mixtur aus gelungener Grafik,perfektem Gameplay und vor allem unverkennbarer Akustik. Leider ist gerade dieGrafik etwas sehr Relatives, aber zum Glück nicht das absolut Entscheidende, und zu-letzt wissen Sie am besten, was gefällt. Beim Gameplay wird es schon riskanter, dochauch hier lassen sich grobe Fehler vermeiden, wenn Sie sich zwei Dinge zu Herzennehmen. Erstens überlegen Sie sich, ob der (Allein-)Spieler von Story und Action ab-solut gefesselt sein soll oder ob das fertige Produkt eher für Wettkämpfe herhaltenmuss. Danach entscheidet sich, wie detailverliebt Sie programmieren oder was Siedem Punktejäger anbieten wollen. Lassen Sie es zweitens nie langweilig werden. Einzu einfaches Spiel ist ebenso öde wie ein unbesiegbarer Endgegner. Gehen Sie esganz gemächlich an und steigern Sie den Schwierigkeitsgrad auf ein erträglichesMaß. Und so richtig Pepp kommt herein, wenn von Zeit zu Zeit anscheinend unbe-zwingbare (Vorsicht, nicht übertreiben!) Situationen auftauchen – das weckt den Ehr-geiz und wenigstens ebenso viel Freude, wenn man endlich durch ist.

Page 398: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

398

Von der Idee zum Spiel24j e t z t l e r n e i c h

24.5.1 MotivationSchaffen Sie Anregungen, damit Ihr Spiel zu einem längeren Zeitvertreib wird. Nebenden Hinweisen »technischer Art«, die noch folgen, und einem ansprechenden Erschei-nungsbild (Grafik, Sound) gelingt Ihnen das am besten durch ein interessantes Level-design. Bieten Sie dem Spieler Abwechslung durch neue Gegner, neue Umgebungs-grafiken, sich ändernde Musik, stärkere Herausforderungen. Überraschen Sie ihndurch Unerwartetes, versteckte Boni, Zusatzleben ab einer bestimmten Punktzahl, stär-kere Zwischengegner. Belohnen Sie ihn nach dem Vollbringen einer besonderen Tat(etwa das Besiegen besonders vieler Gegner hintereinander).

Wenn Sie etwa ein Jump'n'Run-Spiel entwerfen, dann gestalten Sie nicht jeden Levelmit den gleichen Grafikelementen und den gleichen Gegnern. Unterteilen Sie das Spielin Themenwelten, zum Beispiel Wald, Wüste, Zukunft, Fabrik, Stadt.

Auch bei einem Puzzle- oder Geschicklichkeitsspiel können Sie etwa nach jeweils zehnoder zwanzig Levels den Grafiksatz austauschen.

Der wichtigste Punkt sind jedoch die Klänge. Nicht nur der Hintergrund muss passen,auch jede Aktion, Schläge, spezielle Manöver, Schlachtrufe, Detonationen usw. Allesmuss knacken und zu einer unvergesslichen »Erkennungsmelodie« verschmelzen. Ambesten, Sie überzeugen sich davon selbst und drehen Ihrem Lieblingsspiel bei nächs-ter Gelegenheit den Ton ab.«

Alexander Krug, www.softgames.de: »Heutzutage sind besonders kleine, schnell er-lernbare Spiele gefragt. Damit machen Sie sich schnell einen Namen in der Szene derSpieleentwickler. Später wenden Sie sich größeren Projekten (Adventures, Strategie,Jump’n’Run) zu, um die Stellung zu festigen und zu vergrößern. Wichtig auf alle Fälleist die Story. Man möchte einem Spiel verfallen sein, in die Geschichte hineinwach-sen. Vermeiden Sie lange Sätze und benutzen Sie lieber kurze, prägnante Häppchen,die immer wieder im Spiel auftauchen und dem Spieler klar machen, warum er ei-gentlich sitzt und spielt. Letztendlich soll der Spieler alle Stückchen zu einer großenTorte – der Story – zusammenfassen. So wird eine Menge Spannung aufgebaut.Auch die Grafik soll überzeugen. Begnügen Sie sich nicht mit Kompromissen: Su-chen Sie einen anständigen Grafiker, wenn Ihnen das Talent fehlt. Die Grafik ist dasAushängeschild Ihres Spiels. Musikeffekte dienen nicht nur der Unterhaltung. Ge-schickt eingesetzt, helfen sie dabei, Spannung aufzubauen.«

Frank Noack, www.moewendreck.de: »Alle Computerspieler zu begeistern, ist un-möglich. Es ist deshalb besser, sich auf eine Gruppe zu konzentrieren und ihre Anfor-derungen so gut wie möglich zu berücksichtigen. Die Art, wie sie das Spiel erlebensoll und auf welchen Bereich des Spiels am meisten Wert gelegt werden soll, stecktden Rahmen dafür ab, welche Ideen umgesetzt werden können und welche nicht.«

Page 399: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

399

Spieldesign j e t z t l e r n e i c h

24.5.2 SchwierigkeitsgradEntwickeln Sie Ihr Spiel lieber zu einfach als zu schwer. Gestalten Sie mindestens denersten Level als Eingewöhnungsphase zum Aufwärmen, ohne besondere Hürden. Las-sen Sie den Schwierigkeitsgrad dann behutsam ansteigen. Bieten Sie am besten meh-rere Schwierigkeitsstufen an.

Vermeiden Sie tückische Fallen. Die Spielfigur sollte nicht unvermittelt sterben. WennSie eine tödliche Vorrichtung ausgelegt haben, dann geben Sie Warnhinweise (z.B.durch Blutflecken, Skelette ...).

Lassen Sie den Spieler bei einem Bildschirmtod das Spiel nicht ganz von vorn begin-nen, auch wenn er nicht gespeichert hat. Versorgen Sie ihn regelmäßig mit Nachschubwie Medizin-Kits zum Steigern der Lebensenergie und Munition.

24.5.3 BedienungAchten Sie darauf, dass der Spieler schnell ins Geschehen springen kann, ohne end-lose Zwangsmenüs durchqueren zu müssen und ohne den Vorspann überspringen zukönnen. Selbst ablaufende Sequenzen müssen mit È, Leertaste und Mausklick zu be-enden sein.

Füllen Sie Angaben wie Spielernamen, Art der Spielfigur, Eigenschaften (etwa bei Rol-lenspielen) mit Vorgaben, die gegebenenfalls nur bestätigt werden brauchen. Wer IhrSpiel zum ersten Mal sieht, will sich nicht mühsam einen Charakter erstellen. Er will IhrWerk zunächst anspielen.

Ihr Spiel sollte intuitiv zu bedienen sein. Im besten Fall muss der Spieler keine Anlei-tung lesen. Legen Sie die Spielfunktionen auf gebräuchliche Tasten: Pfeiltasten, Ÿ,Ç, ¢Leertaste£. Vorbildlich ist es, wenn der Spieler seine Lieblingsbelegung frei wählenkann.

È sollte ins Pause-/Hauptmenü wechseln. Dort sollte auch die Möglichkeit angebo-ten werden, das Spiel zu beenden. Quälen Sie den Spieler nicht mit Zwangsbildschir-men beim Beenden.

24.5.4 SpeichernIm Regelfall spielt man ein Spiel nicht in einem Stück durch. Je nach Genre ist es üb-lich, verschiedene Arten des Speicherns zu verwenden. Bei Spielen ohne durchgehen-den roten Faden, aber mit vielen Levels, verwendet man oft Passwörter. Hat der Spie-ler einen Level geschafft, teilen Sie ihm einen Code mit. Diesen Code gibt er später ineinem speziellen Menü ein, um wieder zum entsprechenden Level zu gelangen. Beson-

Frank Noack, www.moewendreck.de: »Ich programmiere hauptsächlich Online-Spiele für den kleinen Zeitvertreib in der Mittagspause. Sie sind direkt im Browserspielbar. Bei diesen Pausenspielen ist die Zugänglichkeit der Bedienung besonderswichtig. Niemand hat Lust, für ein Spiel, dass 90 Sekunden dauert, erst minutenlangdie Steuerung zu erlernen. Die Bedienung verleiht dem Spiel einen Großteil seinesCharakters und muss deshalb gut durchdacht sein. Eine einfache, leicht zugänglicheBedienung und ein gutes Tutorial machen den Unterschied zwischen einem gutenund einem genialen Spiel aus.«

Page 400: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

400

Von der Idee zum Spiel24j e t z t l e r n e i c h

ders bequem ist es, wenn der Spieler damit gleichzeitig Zugriff auf alle vorherigen Le-vels erhält.

Alternativ speichern Sie den Fortschritt automatisch ab. Sie legen dazu eine Datei an,die einfach den erreichten Level als Zahl enthält. Der Nachteil: Auf diese Weise lässtsich nicht der Fortschritt mehrerer Personen im gleichen Zeitraum ablegen. Es seidenn, Sie speichern auf Wunsch unter verschiedenen Namen ab.

Für komplexe Spiele, bei denen der genaue Zustand einzufrieren ist, sollten Sie ein Ab-speichern zu jeder Zeit erlauben. Unbeliebt ist in diesem Fall ein automatisches Spei-chern an bestimmten Stellen.

24.5.5 CheatsIn die meisten Spiele bauen die Entwickler Schummelcodes ein, die im Notfall dasSpielen erleichtern. Es ist nahezu unmöglich, die Fähigkeiten vom Gelegenheitsspielerbis hin zum »Profi-Zocker« angemessen zu berücksichtigen. Wer nur einmal in der Wo-che für eine halbe Stunde Zeit für seinen PC hat, der möchte stressfrei unterhalten wer-den und keinen Frust erleben. Bauen Sie also getrost Cheats in Ihr Spiel ein; einigeBeispiele finden Sie an den passenden Stellen im Buch.

0

24.5.6 HilfeBauen Sie eine Spielanleitung direkt ins Spiel ein; oder liefern Sie wenigstens eineTextdatei mit den notwendigen Angaben mit. Die Taste É sollte eine Kurzhilfe bie-ten. Gestalten Sie das Spiel so, dass es mit möglichst wenig Hilfestellung zu verstehenist.

24.6 Das Spielpaket

Ihr Spiel ist fertig und kann in die Welt hinausgetragen werden. Kleinigkeiten, die IhrWerk abrunden, gilt es dabei zu beachten.

24.6.1 Icon erstellenDas i-Tüpfelchen ist ein eigenes Symbol (Icon) für Ihr Spiel, das auf dem Windows-Desktop abgelegt wird. So muss der Spieler nur das Symbol anklicken, um Ihr Spiel zustarten. Ein Icon ist eine normale BMP-Datei, 32x32 Punkt groß, die Sie mit der En-dung ICO und am besten mit 16 Farben (4 Bit) abspeichern. Sie erstellen sie mit einembeliebigen Malprogramm, etwa dem Windows beiliegenden Paint. Besser geeignetsind spezielle Icon-Editoren. Sie begrenzen von vornherein die Größe auf 32x32 Punktund stellen die Leerstellen »durchsichtig« (transparent) dar. Geeignete Programme da-für sind Icon Editor (www.ipl-soft.de) und Icon EDITor (www.hodder.cc/aprogram-ming.html).

Senden Sie die Cheats für Ihr Spiel an die E-Mail-Adresse [email protected],so dass sie auf der Website www.mogelpower.de, der größten Datenbank für Cheats,aufgenommen werden. Die Cheats werden zusammen mit einem Screenshot und ei-nem Link zum Spiel veröffentlicht. Liefern Sie am besten diese Angaben mit. Das isteine gute Werbung für Ihr Spiel.

Page 401: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

401

Das Spielpaket j e t z t l e r n e i c h

Abb. 24.5:Mit Icon-Edito-ren lassen sich individuelle Symbole für Spiele erstellen.

0Beim Einsatz des Icons ergibt sich eine unerwartete Schwierigkeit: Bei den meistenProgrammen ist das Icon fester Bestandteil der EXE-Datei. So auch bei den Program-men, die der Blitz-Compiler erzeugt: Alle tragen die gleiche Rakete als Symbol. Umdieses Icon zu ersetzen, benötigen Sie ein spezielles Werkzeug, etwa den ResourceHacker (www.users.on.net/johnson/resourcehacker/) oder das (nach einer Testzeitkostenpflichtige) Microangelo (www.impactsoft.com). Sollen künftig alle Dateien miteinem bestimmten Icon kompiliert werden, empfiehlt es sich, das Icon direkt im Com-piler zu ändern. Ersetzen Sie das Bild in diesem Fall in der Datei BIN\RUNTIME.DLLim Blitz-Basic-Ordner.

1

24.6.2 Elektronische AnleitungenNeben den eigentlichen Spieldateien sollten Sie eine Beschreibung in Form einer Text-datei beilegen. Diese sollte den Namen README.TXT oder LIESMICH.TXT tragen.Wählen Sie besser reines Textformat oder HTML, aber keine DOC-Datei, wie sieMicrosoft Word erzeugt. Die Beschreibung sollte folgende Angaben enthalten:

� Programmname

� Versionsnummer

� Betriebssysteme, unter denen das Programm läuft

� Autor und Kontakt

� Art des Vertriebs (Demo, Shareware, Freeware)

� Kurzbeschreibung

Im Netz finden Sie eine Vielzahl fertiger Icon-Sammlungen, etwa auf www.soft-ware.net/system/desktop/icons/sammlungen/ oder www.iconlibrary.com.

Um das Icon einer EXE-Datei mit dem Resource Manager zu ersetzen, öffnen Sie diegewünschte EXE-Datei. Wählen Sie ACTION/REPLACE ICON... und klicken Sie das ge-wünschte Icon an. Enthält die Datei mehrere Icons, wählen Sie das sichtbare. KlickenSie nun auf OPEN FILE WITH NEW ICON, laden Sie das Icon, das Sie künftig verwendenwollen und klicken Sie auf REPLACE. Am Schluss speichern Sie die EXE-Datei.

Page 402: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

402

Von der Idee zum Spiel24j e t z t l e r n e i c h

Geht die Anleitung Ihres Spiels über viele Seiten, dann setzen Sie sie besser in eine se-parate Datei.

24.6.3 FILE_ID.DIZBei frei kopierbaren Spielen sollten Sie zusätzlich eine Minibeschreibung in einer Text-datei namens FILE_ID.DIZ ablegen. Vor allem Mailboxen (sozusagen die Hobbyfas-sung des Internets) nutzen sie, um Programme automatisiert in die Datenbank zu lesen.Die Datei sollte nicht länger als 8 Zeilen sein und keine Leerzeilen enthalten. Die Längeeiner Zeile darf nicht mehr als 45 Zeichen betragen:

LANDLORD DELUXE v1.71/DOS (shareware) von Wooden Hut Studios------------------------------------------DIE Wirtschaftssimulation mit Strategie-Elementen. Versetzen Sie sich in eine Welt, inder das Schwert regiert, und kaempfe um dasRecht, dieses Land zu fuehren. Durch List,geschickte Kriegsfuehrung und Handel werdenSie Ihr Ziel erreichen.Benoetigt: mind. 486, 2 MB RAM, VGA-Karte,MS-kompatible Maus, SoundBlaster und biszu 3 Spieler werden unterstuetzt.------------------------------------------eMail: WWW:[email protected] http://www.gretzsoft.de

1

24.6.4 ZIP-ArchivEgal, ob Ihr Spiel kostenlos oder gegen Gebühr, per Internet oder CD-ROM übertra-gen wird, der Anwender erhält es auf elektronischem Weg und muss es zunächst in-stallieren.

Downloads aus dem Internet werden im gepackten Format abgelegt. Das hat zwei Vor-teile: Zum einen werden alle Dateien zu einem Archiv reduziert, was das Herunterladenstark vereinfacht. Zum anderen reduziert sich die Größe oft auf die Hälfte des ur-sprünglichen Platzes. Das spart Kapazitäten des Anbieters und Download-Zeit desSpielers.

Reiner Prokein, www.reinerstileset.de: »Ich bin dazu übergegangen, meine Lies-mich-Dateien in HTML-Form mitzugeben. Hier lassen sich wunderbar Grafiken ausdem Spiel einbinden, die meist mehr sagen als tausend Worte. Außerdem: Auf dieVerpackung kommt es an. Immerhin sind die Hinweisdaten oft der erste Teil, denman von einem Spiel zu sehen bekommt.«

Eine Ergänzung zur guten alten FILE_ID.DIZ, die bereits in den 80er Jahren Pro-grammen beigefügt wurde, ist eine PAD-Datei. Sie wurde als moderner Nachfolgerentwickelt, ist aber bisher wenig verbreitet. Details finden Sie auf den Webseitenwww.asp-shareware.org/pad/ und www.o-grahl.de/deupad/; Editoren dafür auf derBuch-CD.

Page 403: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

403

Das Spielpaket j e t z t l e r n e i c h

Weit verbreitet ist das ZIP-Format. Die meisten Interessenten für Ihr Spiel werden mitihm umgehen und ein entsprechendes Werkzeug zum Entfalten einsetzen können.Windows XP kann von Haus aus ZIP-Dateien auspacken.

Zum Erstellen einer ZIP-Datei nehmen Sie einen der vielen Packer wie WinAce(www.winace.de) oder InfoZIP (www.info-zip.org). Deren Bedienung ist recht einfach;Sie markieren alle gewünschten Dateien und erhalten nach einigen Sekunden eine fer-tige ZIP-Datei. Wohl gibt es andere Formate als ZIP, etwa RAR und ACE, doch ichempfehle Ihnen, das am weitesten verbreitete Verfahren zu nutzen.

24.6.5 InstallerBequemer für den Anwender ist das Verwenden eines Installers. Er packt Ihr Spiel zueiner EXE-Datei zusammen, die bei ihrem Aufruf einen Installationsdialog startet.Schauen Sie dazu am besten die beiden Programme GKSetup (www.gkware.de) undInno Setup (www.jrsoftware.org) an. Installieren Sie bei Inno Setup auch die deut-schen Sprachdateien.

Abb. 24.6:Installations-manager erstel-len Dialoge zum Einrichten eines Spiels auf der Festplatte.

Aus dem Blickwinkel des Nutzers bevorzuge ich allerdings ZIP-Dateien. Sie sind blitz-schnell in einen Ordner meiner Auswahl ausgepackt, ohne dass ich mich durch Dialogequälen muss. Und ich kann am Schluss den Ordner einfach löschen und stelle dadurchsicher, dass das gesamte Spiel verschwunden ist. Bei Installern muss häufig eine »De-installationsroutine« gestartet werden und oft genug bleiben noch Reste auf der Fest-platte übrig. Andererseits gibt es unerfahrene Anwender, die nicht wissen, was sie miteiner ZIP-Datei anstellen sollen. Vorbildlich ist es, wenn Sie beide Versionen zumDownload anbieten.

Page 404: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 405: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

405

jetz

t le

rne

ich

ANHANG A

Die Buch-CD

Die CD, die diesem Buch beiliegt, enthält Demo-Versionen von Blitz Basic (2D, 3D,Plus), die deutsche Online-Hilfe sowie alle größeren Listings. Damit Sie sie schnell fin-den, habe ich im Buch jeweils ihren Dateinamen als Kommentar vorangestellt. Außer-dem enthält die CD Folgendes:

� Quelltexte von Blitz-Basic-Programmen

� unzählige Hintergrundbilder, Texturen und Grafiken

� Musikdateien und Klangeffekte

� eine Reihe von weiterführenden Texten über Spieleentwicklung

� einen Blumenstrauß voller Werkzeuge, darunter Grafikprogramme, Installer undPacker

� andere Entwicklungssysteme zum Erstellen von Programmen

� Ein Bonus-Kapitel: Vertriebsformen von Spielen (Kurse\Bonus)

� Lösungen zu den Aufgaben (Kurse\Bonus)

� Menüpunkte des Editors (Kurse\Bonus)

Page 406: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 407: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

407

jetz

t le

rne

ich

ANHANG B

Der Editor von Blitz Basic

B.1 Editor anpassen

Der Editor von Blitz Basic ist recht spartanisch in seinen Fähigkeiten. Immerhin lassensich einige Eigenschaften wie die Farbgestaltung anpassen. Allerdings lässt sich dasnicht bequem über Menüpunkte regeln. Sie müssen die Datei BLITZIDE.PREFS imOrdner CFG öffnen, um dort die Werte manuell zu ändern.

prg_debug 0

Debug-Modus ein (1) / aus (0)

win_maximized1

Vollbildmodus für den Editor ein (1) / aus (0)

win_notoolbar 0

Symbolleiste ein (0) / aus (1)

win_rect 0 0 225 480

Größe des Editorfensters, wenn kein Vollbild

font_editor blitz 16

Schriftart und Größe für das Editorfenster

font_tabs verdana 8

Schriftart und Größe für die rechte Leiste

font_debug verdana 8

Schriftart und Größe für das Debug-Fenster

rgb_bkgrnd 206060

Hintergrundfarbe als RGB-Wert

Page 408: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

408

Der Editor von Blitz BasicBj e t z t l e r n e i c h

rgb_string ff00

Farbe für Zeichenketten als RGB-Wert

rgb_ident ffffff

Farbe für Variablen und Felder als RGB-Wert

rgb_keyword ffe75f

Farbe für Befehle als RGB-Wert

rgb_comment ffff

Farbe für Kommentare als RGB-Wert

rgb_digit c8f0ff

Farbe für Zahlen als RGB-Wert

rgb_default fff0c8

Standardfarbe als RGB-Wert

edit_tabs 4

Anzahl der Schritte (Leerzeichen) bei Å

edit_blkcursor 0

Block- oder Strichcursor (1 oder 0)

edit_backup 2

Anzahl der zu erstellenden Backup-Dateien (.BB_BAK1, .BB_BAK2 ...)

img_toolbar toolbar.bmp

Symbolleiste

cmd_line

Kommandozeilenparameter (Menüpunkt PROGRAM/PROGRAM COMMAND LINE...)

file_recent C:\basic\test1.bb…

Namen der zehn zuletzt geöffneten Dateien

0B.2 Compiler separat aufrufen

Lange Zeit konnte ein Quelltext nur aus dem Editor von Blitz Basic heraus übersetztwerden. Wer einen anderen Editor benutzte, musste das Programm zunächst über dieZwischenablage nach Blitz Basic übertragen und dort kompilieren. Mit der Version1.78 von Blitz Basic 2D/3D wurde das Verwenden alternativer Editoren erleichtert:Editor und Compiler wurden in zwei separate Programme aufgeteilt.

Mit dem Programm IDE Manager, das der Buch-CD beiliegt, passen Sie die Farbenbequemer an. Ein fertiges Farbpaket, das »anständige« Windows-Farben einstellt, fin-den Sie ebenfalls auf der CD.

Page 409: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

409

Der Editor von Blitz Basic j e t z t l e r n e i c h

Wenn Sie sowieso mit dem mitgelieferten Editor arbeiten, müssen Sie nichts darüberwissen. Für die Arbeit mit Blitz Basic macht es keinen Unterschied, ob der CompilerTeil des Editors oder eine eigenständige Datei ist, die im Hintergrund aufgerufen wird.

Anders verhält es sich jedoch, wenn Sie einen anderen Editor verwenden. Der kannnun das Blitz-Basic-Programm übersetzen lassen, ohne dass Sie seine Oberfläche ver-lassen müssen. Der separate Compiler ist im Ordner BIN als Datei BLITZCC.EXE zufinden. Er hat keine Bedienoberfläche, sondern wird über Kommandozeilenparametergesteuert, wie einst zu DOS-Zeiten. Der Aufruf ist:

blitzcc [Optionen][Quelldatei]

Als Quelldatei geben Sie den Quelltext an, der übersetzt werden soll. Gültige Optionensind:

-o datei EXE-Datei namens datei erzeugen

-d im Debug-Modus kompilieren und starten

Hinzu kommen noch die folgenden, weniger wichtigen Optionen:

-k alle Schlüsselwörter von Blitz Basic anzeigen

+k alle Schlüsselwörter von Blitz Basic mit Syntax anzeigen

-q wenig Bildschirmanzeigen über den Kompiliervorgang

+q so gut wie keine Bildschirmanzeigen über den Kompiliervorgang

-hf kurzen Hilfetext anzeigen

Um den separaten Compiler zu benutzen, müssen Sie ihn informieren, in welchemVerzeichnis Sie Blitz Basic installiert haben. Kann er die notwendigen Dateien nicht fin-den, meldet er sich wie folgt:

Can’t find blitzpath environment variable

Das Verzeichnis muss in der Umgebungsvariable BLITZPATH angegeben werden.Eine Umgebungsvariable kann von jedem PC-Programm erzeugt, verändert und gele-sen werden. Sie verwenden dazu den DOS-Befehl SET. Schreiben Sie am besten dieZeile

set blitzpath=c:\verzeichnis

in die Textdatei C:\AUTOEXEC.BAT, die Sie anlegen, sofern sie nicht existiert. Na-türlich müssen Sie c:\verzeichnis durch den entsprechenden Blitz-Ordner ersetzen.

B.3 Der Editor BlitzView

Dank BLITZCC.EXE verwenden Sie bequem einen beliebigen Texteditor zum Pro-grammieren. Besonders empfehlenswert ist das Werkzeug BlitzView. Der Editor wur-de speziell für das Arbeiten mit Blitz Basic entwickelt. Sein Leistungsumfang geht weitüber den Standardeditor hinaus. Sie können:

� Projekte anlegen und verwalten

� To-Do-Listen mit noch zu erledigenden Aufgaben anlegen

� Lesezeichen im Quelltext setzen und schnell anspringen

� eigene Funktionen separat bearbeiten und in Bibliotheken verwalten

Page 410: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

410

Der Editor von Blitz BasicBj e t z t l e r n e i c h

� ganze Programmabschnitte auskommentieren (;)

� Textbausteine nutzen (also Kürzel, die beim Eingaben automatisch in längeren Textverwandelt werden)

� allerlei Multimedia-Dateien direkt aus dem Editor abspielen

� Grafik- und Sounddateien zu einer großen Paketdatei zusammenfügen

1Das nützliche Werkzeug von Sven Langenkamp ist Freeware. Das Programm befindetsich auf der Buch-CD. Die aktuelle Fassung wartet auf www.blitzview.de.

Abb. B.1:BlitzView bieteterheblich mehr

Komfort als dermitgelieferte

Editor.

BlitzView kann ihren Quelltext direkt kompilieren. Dazu benötigen Sie Blitz Basic abVersion 1.78. Damit BlitzView den Compiler findet, müssen Sie im Menü BEARBEI-TEN/EINSTELLUNGEN den Pfad zu Blitz Basic angeben.

Sven Langenkamp, www.blitzview.de: »Eines der nützlichsten und interessantestenFeatures ist wohl die Projektverwaltung von BlitzView. Sie bietet einen schnellen Zu-griff auf alle zum Projekt gehörigen Quellcodes. Mit einem Klick hat man die einzel-nen Dateien geöffnet. Und dank des Assistenten ist es sehr einfach, ein neues Projektanzulegen. Außerdem kann einem Projekt eine To-Do-Liste hinzugefügt werden. Sieenthält verschiedene Informationen wie Aufgabenname, Priorität, Fortschritt undStatus.

Page 411: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

411

Der Editor von Blitz Basic j e t z t l e r n e i c h

BlitzView bietet Funktionen, um noch schneller zu programmieren: Mit »Quick Code«und der Funktionsbibliothek werden ganze Abschnitte mit einem Tastendruck in denQuellcode eingefügt, zum Beispiel das Gerüst einer Funktion. Kleine Tools wie derTaschenrechner und der Media Browser erleichtern die Arbeit. Da BlitzView Plug-Insunterstützt, ist es möglich, das Programm beliebig zu erweitern. Diese Zusätze lassensich mit jeder Programmiersprache erstellen, die DLLs kompiliert. Im Diskussions-forum von BlitzView ist Platz für weitere Ideen. Viele der bereits umgesetzten Eigen-schaften basieren auf Anregungen von Benutzern. Jeder kann an der Entwicklungmitwirken.«

Page 412: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 413: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

413

jetz

t le

rne

ich

ANHANG C

Tabellen

In der deutschsprachigen Online-Hilfe finden Sie detaillierte Tabellen mit Scancodes,ASCII-Codes und Farbcodes. Daher beschränke ich mich auf einige wichtige Angaben.

Wichtige Scancodes

Taste Scancode

{ 203

} 205

| 200

~ 208

¢Leertaste£ 57

È 1

Ç 56

Ÿ links 29

Ÿ rechts 157

Á links 42

Á rechts 54

Å 15

Æ 28

Page 414: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

414

TabellenCj e t z t l e r n e i c h

Wichtige ASCII-Codes

Wichtige FarbcodesAufgeführt habe ich einige wichtige Farbcodes. Eine ganze Reihe mehr finden Sie inder deutschsprachigen Online-Hilfe – dort allerdings als Hexwert.

Zeichen ASCII-Code(s)

0 bis 9 48 bis 57

A bis Z 65 bis 90

a bis z 97 bis 122

|, ~, } und { 28 bis 31 (63232 bis 63235 bei Blitz Plus)

¢Leertaste£ 32

Æ 13

È 27

Farbe RGB-Wert

Rot 255, 0, 0

Weinrot 127, 0, 0

Violett 128, 0, 128

Hellblau 0, 255, 255

Blau 0, 0, 255

Dunkelblau 0, 0, 127

Grün 0, 255, 0

Dunkelgrün 0, 127, 0

Gelb 255, 255, 0

Olivgrün 127, 127, 0

Weiß 255, 255, 255

Hellgrau 192, 192, 192

Schwarz 0, 0, 0

Grau 127, 127, 127

Page 415: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

415

Tabellen j e t z t l e r n e i c h

Ereignisse (Events) in GUIsFolgende Ereignisse meldet Blitz Plus über die Funktion WaitEvent().

(*) Der Tastendruck wird nur erkannt, wenn kein Gadget ausgewählt ist. Die Eingabenin Textfelder lassen sich damit nicht abrufen. Hierfür gibt es spezielle Funktionen wieTextFieldText() und TextAreaText().

$101 Taste gedrückt; EventData() = Scancode der Taste (*)

$102 Taste losgelassen; EventData() = Scancode der Taste

$103 langer Tastendruck; EventData() = ASCII-Code der Taste

$201 Maustaste gedrückt; EventData() = Maustaste; EventSource() = Gadget-Kennziffer

$202 Maustaste losgelassen; EventData() = Maustaste; EventSource() = Gad-get-Kennziffer

$203 Mausbewegung im Canvas-Fenster; EventSource() = Canvas-Kennziffer; EventX(), EventY() = Mauskoordinaten

$204 Mausrad gedreht; EventData() = Anzahl der Radbewegungen

$205 Maus gerät in ein Canvas-Fenster; EventSource() = Canvas-Kennziffer; EventX(), EventY() = Mauskoordinaten

$206 Maus verlässt Canvas-Fenster; EventSource() = Canvas-Kennziffer

$401 Gadget (z.B. Schalterdruck, Textfeld-Eingabe); EventSource() = Gadget-Kennziffer; EventData() = spezifische Daten (**)

$801 Fenster wird verschoben; EventSource() = Fenster-Kennziffer; EventX(), EventY() = Position des Fensters

$802 Fenstergröße wird verändert; EventSource() = Fenster-Kennziffer; EventX(), EventY() = Größe des Fensters

$803 Fenster wird geschlossen; EventSource() = Fenster-Kennziffer

$804 Fenster wird aktiviert; EventSource() = Fenster-Kennziffer

$1001 Menüpunkt ausgewählt; EventData() = Menüpunkt (als Id-Nummer, nicht Kennziffer!)

$2001 Wechsel zu einem anderen Programm

$2002 Wechsel zurück zum Blitz-Basic-Programm

$2004 »Modal Loop« – Skalieren und Verschieben eines Fensters oder Bewegen des Scrollbalkens

$2005 »Modal Loop« beendet

$4001 mit CreateTimer() eingestellter Zeitgeber erzeugt einen Taktschlag; EventSource() = Kennziffer

Page 416: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN
Page 417: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

417

jetz

t le

rne

ich

Stichwortverzeichnis

cDiese Seitenverweise beziehen sich auf Kapitel 25, welches Sie auf der CD-ROM finden.

- 30# 56$ 32, 56$ (hex) 83% 56, 83( 391* 30+ 29, 32< 38<= 38= 38> 38>= 38\ 66^ 73⁄ 30

AAbs() 72absoluter Betrag 72ACos() 76ActivateGadget 350ActivateWindow 342AddGadgetItem 356AddTextAreaText() 355Adventure Game Studio 312After 68AmbientLight 335And 38, 77– binäres Rechnen 83Animation 209

Antialiasing 121AppTitle 34Arrays 60Asc() 80, 153ASCII-Code 80, 151ASin() 76Assembler 22ATan() 76ATan2() 76Audio-CD 164Auflösung 100, 103Aufsatz 132AutoMidHandle 122AvailVidMem() 103

BBackbuffer 104Backup 380Balance 165Bank 182Basic 22Before 68Beta-Version 371Bildschirmfoto 318Bildwiederholrate 261Bin$() 83binär 79Binäre Suche 95Bit 20, 79Bitmap 115Bitmap Font Builder 257

Page 418: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

418

Stichwortverzeichnisj e t z t l e r n e i c h

Blitz Array 64BLITZCC.EXE 409BLITZIDE.PREFS 407BlitzPlay 196BlitzView 409BMP 115boolesche Operatoren 77Bubble Sort 92Buffer 104Bugs 370BUID 26ButtonState() 353Byte 79, 178

CCallDLL 190CameraClsColor 333CameraFogColor 335CameraFogMode 335CameraFogRange 335CameraRange 335CameraViewPort 333Canvas-Puffer 365Case 40– und logische Operatoren 79Ceil() 72ChangeDir 176Channel 165ChannelPan() 166ChannelPitch() 167ChannelPlaying() 166ChannelVolume() 166Chat 391Cheat 317Cheats 192, 400CheckMenu 345Chr$() 80, 153ClearGadgetItems 356Client 196ClientHeight() 351ClientWidth() 351CloseDir 175CloseFile 178CloseMovie 171CloseUDPStream 204Cls 105ClsColor 112CollapseTreeViewNode 360Color 111, 135ColorBlue() 135ColorGreen() 135ColorRed() 135Combobox 356CommandLine() 192Compiler 24Confirm 362Const 59CopyBank 184

CopyFile 177CopyImage() 127CopyPixelFast 137CopyRect 124Cos() 76Cosinussatz 75CountGadgetItems 356CountGfxDrivers() 102CountGfxModes() 103CountTreeViewNodes 361CreateBank() 183CreateBrush() 329CreateButton() 352CreateCamera() 323, 333CreateCanvas() 366CreateComboBox() 356CreateCone() 326CreateCube() 326CreateCylinder() 325CreateDir 177CreateHTMLView() 365CreateImage() 128CreateLabel() 353CreateLight() 335CreateListBox() 356CreateMenu() 343CreateNewPlayer() 198CreatePanel() 351CreatePlane() 336CreateProgBar() 364CreateSlider() 359CreateSphere() 325CreateTabber() 357CreateTerrain() 337CreateTextArea() 354, 355CreateTextField() 354CreateTimer() 262CreateToolBar 346CreateTreeView 360CreateUDPStream() 204CreateWindow 342CurrentDate$() 86CurrentDir$() 174CurrentTime$() 86

DData 62Datei 173Datum ermitteln 86Debugger 372DebugLog-Fenster 373Default 40Delay 84, 263Delete 68DeleteDir 177DeleteFile 177DeleteNetPlayer 198Design-Dokument 390

Page 419: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

419

Stichwortverzeichnis j e t z t l e r n e i c h

DesktopBuffer() 366Dim 60– und Types 67DirectX 100DisableGadget 350DisableMenu 345DisableToolBarItem 347DLL 189DottedIP$() 205Double Buffering 104DrawBlock 126DrawBlockRect 126DrawImage 118DrawImageRect 123DrawMovie() 170

EEach 68Eingabefunktion 230Einrücken des Quelltextes 367Else 39ElseIf 40EnableGadget 350EnableMenu 345EnableToolBarItem 347EndIf 39Entity (Entität) 327EntityColor 326Eof() 181Ereignis 347Eulersche Zahl 74Event 347Event Handler 348EventData() 348EventId() 348EventSource() 348, 353EventX() 348EventY() 348EventZ() 348ExecFile 188Exit, bei Schleifen 44Exp() 74ExpandTreeViewNode 360Explosion 213

Ffalsch 77False 77, 78Farben 111Farbtiefe 101Felder 60Fenstermodus 101Field 66FILE_ID.DIZ 402FilePos() 181FileSize() 175FileType() 175First 68Fließkommazahlen 55

Flip 105– im 3D-Modus 323Flip 0 261FlipCanvas 366Float 56Float() 59Floor() 72FlushEvents 348FlushJoy 158FlushKeys 155FlushMouse 147FontHeight() 143Fonts 139, 141– als Bitmaps 257FontWidth() 144For 41Forever 45FormatTextAreaText 355FPS 222Frame 209Frame-Rate 222Frame-Sync 261FreeBank 183FreeFont 144FreeGadget 350FreeIconStrip 358FreeImage 117FreeSound 163FreeTimer 262FreeTreeViewNode 361Freeware c1Frequenz 261Frontbuffer 104Function 49Funktionen 48

GGadgetGroup() 350GadgetHeight() 350Gadgets 341GadgetText() 351GadgetWidth() 350GadgetX() 351GadgetY() 351GammaBlue() 242GammaGreen() 242GammaRed() 242Gamma-Wert 239ganze Zahlen 55GEMA 162GetColor 135GetEnv() 193GetJoy() 158GetKey() 152GetMouse() 146Gewerbe anmelden c2GfxDriverName$() 102GfxModeDepth(Modus) 103GfxModeExists() 103

Page 420: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

420

Stichwortverzeichnisj e t z t l e r n e i c h

GfxModeHeight(Modus) 103GfxModeWidth(Modus) 103Global 52Globale Variablen 51Glücksrad 91Gosub 47Goto 45Grafikmodus 99Grafiktreiber 102Graphics 34, 99Graphics3D 322GraphicsBuffer() 104Grundfarben 111GUI programmieren 341

HHandleImage 122Hex$() 83Hexzahlen 81HideGadget 350HidePointer 149Hintergrund 235Host 196HostNetGame() 197HotKeyEvent 349Hotkeys in GUIs 349HTMLViewBack 365HTMLViewForward 365HTMLViewGo() 365Hypotenuse 74

IIcon 400ICQ 391If 38Imagebuffer 126ImageHeight() 119ImageWidth() 119ImageXHandle() 122ImageYHandle() 122Include 173Input() 33Insert 68InsertGadgetItem 356InsertTreeViewNode 361Installer 403Instr() 89Int() 59Integer 56, 178Interpreter 24IP-Adresse 197IPCONFIG.EXE 197

JJoinNetGame() 197JoyDown() 158JoyHit() 158Joystick 157JoyType() 157

JoyWait 158JoyWait() 158JoyX() 158JoyXDir() 158JoyY() 158JoyYDir() 158JoyZ() 158JoyZDir() 158JPG 115

KKamera 333Kanal 165Katheten 74KeyDown() 154, 155KeyHit() 155Kollision 214Kommandozeilenparameter 191Kommentare 33Konsole bei Blitz Plus 34Konstanten 59Koordinaten im Graphikmodus 105Kreis 109Künstliche Intelligenz 312

LLabel bei Goto 46, 47Last 68Lautstärke 165Layer 272Left$() 88Len() 89LightColor 336Line 108Listbox 356Little Endian Format 181LoadAnimImage() 210LoadAnimMesh() 331LoadBuffer 129LoadFont 141LoadIconStrip() 358LoadImage() 117LoadMesh() 331LoadSound() 163LoadSprite() 332Local 52Locate 140LockBuffer 137LockedFormat() 138LockedPitch() 138LockedPixels() 138, 183LockTextArea 355Log() 74Log10() 73Logarithmus 73logische Operationen 77logische Operatoren 38Logo und Teamname 394LoopSound 163

Page 421: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

421

Stichwortverzeichnis j e t z t l e r n e i c h

Lower$() 88LSet$() 88

MMarke– bei Goto 46, 47– bei Goto 46– bei Restore 63– bei Unterprogrammen 47Maschinensprache 22Maskieren von Bits 83MaskImage 125Maus 145Mausrad 147Mauszeiger 145, 149MaximizeWindow 342MenuChecked() 345MenuEnabled() 345Microcode 21Mid$() 88MidHandle 122MilliSecs() 85, 261MinimizeWindow 342Mod 71ModifyGadgetItem 356ModifyTerrain 338MoreFiles() 175Motion Capturing 209MouseDown() 146MouseHit() 147MouseWait() 146MouseX() 148MouseXSpeed() 149MouseY() 148MouseYSpeed() 149MouseZ() 147MouseZSpeed() 148MoveEntity 327MoveMouse 149MovieHeight() 171MoviePlaying() 170MovieWidth() 171Multiplayer-Spiel 195Musik 163

NNameGenerator 396Namensrecht 394NetMsgData$() 199NetMsgType() 200NetPlayerLocal() 200NetPlayerName$() 200Netzwerk 195New 66Next 41NextFile 174Not 77Notify 361Null bei Typen 69

OOgg Vorbis 162OpenFile() 177OpenMovie() 169Optimierung des Programms 374Or 38, 77– binäres Rechnen 83Origin 132Oval 109

PPanel 351Parameter 191Patchen 185PauseChannel() 165Pause-Modus 317PeekByte() 184PeekEvent() 348PeekFloat() 184PeekInt() 184PeekShort() 184Pi 73Pitch-Drehwinkel 327Planes 336PlayCDTrack() 164PlayMusic 163PlaySound 163Plot 107PNG 115PokeByte 184PokeFloat 184PokeInt 184PokeShort 184Polygone 325Port für Joystick 157PositionEntity 326PostIdent c5Potenz 73Pressearbeit c21Primitives 325Print 29Proceed 362Programm 22Programmierstil 367Progress Bar 364Projektplanung 387Puffer 104

QQuadratwurzel 73Quelltext 22

RRahmen 131Rand 214Rand() 86Read 62ReadByte() 179ReadDir() 174

Page 422: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

422

Stichwortverzeichnisj e t z t l e r n e i c h

ReadFile() 177ReadFloat() 179ReadInt() 179ReadLine() 179ReadPixel() 136, 137ReadPixelFast() 137ReadShort() 179ReadString() 179Rect 108RecvNetMsg() 199RecvUDPMsg() 205reelle Zahlen 55Registrierungscode c3Rekursion 52RemoveGadgetItem 356RenderWorld 323Repeat 44Replace$() 89RequestColor() 363RequestDir() 363RequestedBlue() 363RequestedGreen() 363RequestedRed() 363Requester 361RequestFile() 364RequestFont() 363ResizeBank 183ResizeImage 120Rest beim Dividieren 71Restore 63RestoreWindow 342ResumeChannel() 165Return– bei Funktionen 49– bei Unterprogrammen 47RFC 204RGB 111, 135– und Transparenz 125Right$() 88Rnd() 87RndSeed() 87Roll-Drehwinkel 328RotateImage 120RSet$() 88Rückgängig-Funktion 28RunDLL32.exe 189RuntimeError 193

SSaat für Zufallszahlen 86Sar 84Satz des Pythagoras 75SaveBuffer 129SaveBuffer() 318SaveImage 128ScaleImage 120Scancode 153Schalter 220Schleifen 41

Schnappschuss 318Schwerkraft 253Schwierigkeitsgrad 399Screenshot 318SeedRnd 87SeekFile 181Select 40SelectedGadgetItem() 356SelectedTreeViewNode() 361SelectGadgetItem 356SelectTreeViewNode 361SendNetMsg 199SendUDPMsg 205SetBuffer 104SetButtonState 352SetEnv 193SetFont 141SetGadgetFont 351SetGadgetIconStrip 358SetGadgetLayout 351SetGadgetShape 351SetGadgetText 351SetGamma 240SetGfxDriver 102SetMenuText 346SetMinWindowSize 342SetPanelColor() 351SetPanelImage() 351SetSliderRange 359SetSliderValue 359SetStatusText 343SetTextAreaColor 355SetTextAreaFont 355SetTextAreaTabs 355SetTextAreatText() 355SetToolBarTips 347Sgn() 72Shareware c2Shl 84Short Integer 178ShowGadget 350ShowPointer 149Shr 84Sibly, Mark 23Sin() 76Sinussatz 75SliderValue() 359Sortieren von Daten 92Sound 161Source 22Speicherbank 182Speichern im Spiel 399Spielbalance 278Spieldesign 397Spielidee 382Spielname 395Spielstand speichern 316Sprungmarken– bei Goto 46

Page 423: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

423

Stichwortverzeichnis j e t z t l e r n e i c h

– bei Restore 63– bei Unterprogrammen 47Sqr() 73Stack 53StartNetGame() 196Step 43StopChannel() 165StopNetGame 198Str$() 59String 32, 58String$() 89StringHeight() 144StringWidth() 144Syntax 22Syntax Highlighting 28SystemProperty() 188

TT.A.G. 312Tabber 357Tan() 76Tastatur 151Team bilden 387Teamnamen finden 393Text 139TextAreaChar() 355TextAreaCursor() 355TextAreaLen() 355TextAreaLine() 355TextAreaLineLen() 355TextAreaSelLen() 355TextAreaText() 355TextFieldText() 354Textur 329TFormFilter 121The Everchanging Book of Names 396Then 38Tile 272TileBlock 119, 126, 235TileImage 235Timing 261To 41Tonhöhe 165Toolbar programmieren 346TotalVidMem() 103Transparenz 125Tree List 360TreeViewRoot() 360Trigonometrie 74Trim$() 88True 77, 78TTF-Datei 141TurnEntity 328Typen 65– dynamische 67

UÜbergang 237UDP 204

UDPMsgIP() 205Uhrzeit ermitteln 86Umgebungslicht 335Umgebungsvariable 193UncheckMenu 345Undo-Funktion 28Unicode 152UnlockBuffer 137UnlockTextArea 355Unterprogramme 47Until 44UpdateGamma 240UpdateProgBar() 364UpdateWindowMenu 344Upper$() 88Userlibs 190Using$() 89USK-Sticker c5

VVariablen 31, 55– globale 51Verlag c6Vertrag mit einem Verlag c12Video 169ViewPort 131Vorzeichen 72

WWackeln des Bildschirms 239wahr 77WaitEvent() 347WaitJoy() 158WaitKey 33, 34WaitKey() 151WaitMouse 33WaitMouse() 145WaitTimer 262Website c17Wend 45While 45WideChar 152Widgets 341WindowActivated() 343WindowMenu() 344WindowMinimized() 343WindowsMaximized() 343WINIPCFG.EXE 197Winkelfunktionen 74WireFrame 324Write 31WriteByte 179WriteFile() 177WriteFloat 179WriteInt 179WriteLine 179WritePixel 136, 137WritePixelFast 137WriteShort 179

Page 424: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

424

Stichwortverzeichnisj e t z t l e r n e i c h

WriteString 179Wurzel ziehen 73

XXor 78

YYaw-Drehwinkel 327

ZZahlen 55Zeichenkette 31Zeichenketten 55, 58– verändern 87Zeichentabelle 141Zeilennummern 45Zeilenumbruch 234Zeit messen 84ZIP-Dateien 402Zufallszahlen 86Zusammenstoß 214

Page 425: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

In Zusammenarbeit mit den Top-Autoren von Markt+Technik, absolutenSpezialisten ihres Fachgebiets, bieten wir Ihnen ständig hochinteressante,brandaktuelle Informationen und kompetente Lösungen zu nahezu allen IT-Themen.

www.InformIT.de

wenn Sie mehr wissen wollen ... www.InformIT.de

InformIT.de, Partner von Markt+Technik, ist unsere Antwort auf alle Fragender IT-Branche.

... aktuelles Fachwissen rund,

um die Uhr – zum Probelesen,

Downloaden oder auch auf Papier.

Page 426: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

1

jetz

t le

rne

ich

KAPITEL 25

Vertriebsformen von Spielen

Für Ihr Spiel stehen Ihnen mehrere Vertriebsarten zur Auswahl. Zunächst stellt sich dieFrage, ob Sie Ihr Spiel kostenlos abgeben oder verkaufen wollen.

25.1 Freeware

Kostenlose Spiele erklären Sie zur Freeware. Solche Spiele können frei verteilt wer-den. Die Urheberrechte verbleiben allerdings bei Ihnen. Eine ähnliche Form ist PublicDomain, zu Deutsch ungefähr öffentliches Gut: Hier verschenken Sie Ihr Spiel an dieÖffentlichkeit. Jeder kann damit machen, was er will.

Achim Tober, www.softworxs.de: »Fasziniert von den Möglichkeiten eines Home-computers begann ich vor rund zwanzig Jahren mit dem Programmieren einfacherSpiele, die ich an andere Computerbegeisterte weitergab. Diese wiederum taten esmir gleich, so dass sich innerhalb kurzer Zeit ein reger Software- und Erfahrungsaus-tausch ergab. Es ging auch freilich darum, sich in der Szene einen Namen zu machenund mit Programmierkünsten und Spielen aus der Masse herauszuragen. Auf denPunkt gebracht, war es eine Art sportlicher Wettkampf. Mal gewann man – mal verlorman. Aber dabei sein war trotzdem alles. Damals war der Begriff »Freeware« nochnicht verbreitet. Aber seine Regeln haben sich bis heute bewahrt. Nach einer langenPause gelangte ich mithilfe von Blitz Basic zum Programmieren zurück. Und die Er-innerungen wurden lebendig. Mehr als einmal wurde mir von der Community bereit-willig geholfen. Ich konnte spezielle Funktionen fremder Quellcodes für meine Pro-gramme als Lösungsansatz übernehmen. Der Freeware-Gedanke basiert für mich aufder Basis von helfen und sich helfen lassen. Man gibt etwas und erhält sehr viel mehrzurück. Ich komponiere zum Beispiel sehr gern Musik. Jeder, der lizenzfreie Musik-stücke für seine Spiele benötigt, kann sich die Songs von meiner Website runterladenund frei in seinen Projekten verwenden.

Page 427: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

2

Vertriebsformen von Spielen25j e t z t l e r n e i c h

25.2 Shareware

Möchten Sie mit dem Spiel Geld verdienen, so stehen Ihnen grundsätzlich zwei Mög-lichkeiten zur Verfügung. Viele selbst gemachte Spiele werden als Shareware abgege-ben: Shareware kann kostenlos ausprobiert werden; wer sie länger nutzen will, bezahlt.Weil man selten für das bezahlen möchte, was man bereits hat, ist Shareware häufigeingeschränkt und eher als Demoversion zu sehen. Wem die Demo gefällt, der regis-triert sich kostenpflichtig beim Autor und erhält die komplette Fassung. Wenn Sie sichfür einen Vertrieb als Shareware entschließen, rate ich Ihnen, ungefähr ein Fünftel biszu einem Drittel des vollständigen Spiels als Shareware-Fassung zu verteilen. Fügen Sieden Spieldateien ein Bestellformular (am besten mit dem Namen REGISTER.TXT)bei.

2

Den Verkaufspreis sollten Sie eher knapp bemessen – angesichts der Tatsache, dassProfispiele neu meist für 40 bis 50 Euro abgegeben werden und nach einem Jahr häu-fig nur noch 20 oder 10 Euro kosten. Verkaufen Sie daher besser fünf Spiele für jeweils10 Euro als ein Spiel für 30 Euro.

Als Zahlungsmöglichkeiten stehen dem Käufer vor allem Bargeld (unsicher) und Über-weisung zur Verfügung. Sprechen Sie mit Ihrer Bank, ob Sie eine Zulassung zum Last-schrifteinzug erhalten. Dann könnten Sie den Kaufbetrag vom Konto des Käufers ein-ziehen lassen. Nachteil: Der Käufer könnte nach Erhalt des Spiels die Summerückbuchen lassen. Das dürfte allerdings in der Praxis selten vorkommen.

Statt die Bezahlung selbst abzuwickeln, können Sie den Dienst ShareIt!(www.shareit.de) in Anspruch nehmen. Er bietet registrierfreudigen Nutzern IhresSpiels verschiedene Zahlungsmöglichkeiten wie Überweisung, Kreditkarte oderScheck. Die Bestellung ist rund um die Uhr per Internet, Telefon oder Fax und auchaus dem Ausland möglich. Im Gegenzug zahlen Sie pro verkaufter Software eine Pro-vision von 5 Prozent zuzüglich eines Festbetrags von 2,95 US-Dollar. Das sind bei ei-nem 15 Euro teuren Spiel rund 4 Euro. ShareIt! lohnt sich vor allem bei internationa-len Bestellungen, die im Regelfall über Kreditkarte erfolgen.

Wenn jeder etwas auf diese Weise anbietet, entsteht schnell ein Archiv aus Funktio-nen, Grafiken und Sounds, aus dem sich wiederum jeder bedienen kann. WeitererEffekt: Die Verteilung meiner Programme und meiner Musik hat mir viele wertvolleKontakte ermöglicht. Freeware verbindet!«

Beachten Sie dabei, dass die Erlöse aus dem Verkauf selbst programmierter Spieleversteuert werden müssen und die Anmeldung eines Gewerbes erfolgen muss. EinGewerbe (Entwicklung und Vertrieb von Software) melden Sie beim GewerbeamtIhrer Gemeinde an. Je nach Ort ist es für Minderjährige nicht oder nur mit Zustim-mung der Eltern möglich, ein Gewerbe zu betreiben. Die Anmeldung kostet einmaleinen Betrag von höchstens 25 Euro. Viele Details über den Vertriebsweg als Share-ware finden Sie im Internet auf den Seiten www.shareware.de/autoren/faq/ undwww.s-a-ve.com/faq/.

Page 428: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

3

Shareware j e t z t l e r n e i c h

Es sind zwei Möglichkeiten verbreitet, wie der Käufer der Vollversion an sein Pro-gramm gelangt. Die eine: Vollversion und Demo bzw. Shareware-Fassung sind zweigetrennte Programme. Bei der Registrierung senden Sie dem Käufer die Vollversionper E-Mail oder Briefpost zu. Sie verbreiten damit öffentlich nur die Testfassung, dieabgespeckt und damit meist kleiner als die Vollversion ist. Und Sie behalten die Kon-trolle, wer die Vollversion erhalten hat. Um dem Verbreiten der Vollversion als Raub-kopie entgegenzuwirken, bietet es sich an, dem Käufer eine personalisierte Version zurVerfügung zu stellen: Sein Name wird im Vorspann genannt. Natürlich ist dieser Pro-zess aufwendiger, da Sie für jedes Exemplar den Namen des Käufers in den Quelltexteintragen müssen, um das Spiel erneut zu kompilieren. Der Name sollte übrigens nichtim Klartext in der EXE-Datei stehen, um es findigen Hackern schwerer zu machen, ihnherauszulöschen. Es bietet sich eine Verschlüsselung an, wie etwa die an anderer Stellebeschriebene Xor-Kodierung.

Der zweite Weg: Die Shareware-Fassung wird durch Eingabe eines Registrierungs-codes zur Vollversion. Dazu bieten Sie im Programm einen entsprechenden Menü-punkt zum Eintragen an. Damit der Käufer nicht bei jedem Programmstart den Codeeingeben muss, speichern Sie ihn in einer Datei ab – am besten ordentlich verschlüsseltund um zahllose sinnvolle Zeichen ergänzt. Das Spiel überprüft beim Starten, ob dieDatei existiert und ob sie einen gültigen Code enthält. Zur Aufnahme des Codes bietetsich ebenfalls die Registrierungsdatenbank an. Doch Blitz Basic enthält keine Befehlezum Zugriff auf die Registry.

Carsten Scheibe, www.typemania.de: »Shareware ist Prüf-vor-dem-Kauf-Software.Die Shareware-Fassung verteilt sich wie von selbst über das Internet und über dieHeft-CDs der Magazine. So können viele tausend Anwender ein Programm noch vordem Kauf ausführlich testen. Gefällt einem potenziellen Kunden die Software, kaufter sie. Und zwar direkt bei Ihnen. So fließt der volle Gewinn in Ihre Hände – und nichtnur ein Bruchteil wie bei der kommerziellen Verwendung. Versuchen Sie, ein Spieloder Tool als Shareware zu vermarkten, so lohnt es sich, vorher den Markt zu beob-achten – etwa bei großen Archiven wie www.winload.de, www.jumbo.com undwww.tucows.com. Es gibt bereits zigtausend Spiele. Programmieren Sie also nichts,was es schon hundertfach gibt. Der x-te Tetris-Klon hat keine Chance mehr. AchtenSie auf die Preise, die andere Programmierer verlangen. Auch wenn Sie der Meinungsind, dass Ihr Spiel 100 Euro wert ist – die meisten Games im Netz kosten keinenPfennig oder sind für ein paar mickrige Mücken zu haben. Die meisten Programmie-rer wundern sich, dass so wenig Bestellungen bei ihnen eingehen. Kein Wunder: Sievergessen, ihren Namen und die Adresse im Programm zu erwähnen, oder erklärennicht, wie der Anwender das Produkt bezahlen kann. Und Sie müssen sich fragen:Warum soll jemand überhaupt Ihr Spiel bezahlen? Die Shareware muss also ein-geschränkt sein, während die Vollversion neue Funktionen bietet: vielleicht mehrLevels, mehr Grafiken, mehr Sound. Zahlungen können auch nur dann eingehen,wenn sich die Shareware stark verbreitet. Schicken Sie Ihr Spiel zusammen mit ei-nem Anschreiben, einer Beschreibung und einer Genehmigung zur Veröffentlichungan alle wichtigen PC-Zeitschriften. Und laden Sie die Software in die einschlägigenShareware-Foren hoch. Ein Gedankenaustausch mit anderen Programmierern derDeutschen Shareware-Autoren-Vereinigung (wwww.s-a-ve.de) macht auch Sinn.«

Page 429: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

4

Vertriebsformen von Spielen25j e t z t l e r n e i c h

Der Vorteil des Verfahrens: Sie senden dem Verkäufer keine Software, sondern nur ei-nen Code. Auch hier werden Raubkopien eingeschränkt, wenn der Code zusammenmit dem Käufernamen eingegeben wird. Damit der Name nicht geändert wird, mussder Code aus dem Namen gebildet werden. Sie könnten sich dazu mehrere Buchsta-ben herausgreifen, die ASCII-Codes addieren und die daraus entstandene Prüfsummein den Code einfließen lassen. Beim Registrieren testet das Spiel, ob sich aus demCode der eingegebene Name bilden lässt. Natürlich wird sich ein Käufer davor scheu-en, die Kopie eines Programms weiterzugeben, das auf seinen Namen registriert ist.Und natürlich wird es Hacker geben, die Ihren Schutz aushebeln – sofern Ihr Spiel in-teressant genug ist.

Alexander Gruel, www.lcm-network.info: »Bei sehr kleinen Auflagen ist der Ver-trieb über Diskette oder selbst gebrannte CD-R zu empfehlen. Doch ab einem gewis-sen Erfolg entsteht der Wunsch nach »mehr«: Eine gepresste CD muss es sein. Siesieht professioneller aus und ist unempfindlicher. Das Herstellen ist jedoch mit deut-lich höheren Kosten verbunden, als wenn Sie die CD am heimischen Rechner selbstduplizieren. Das liegt vor allem am so genannten Glasmaster, das erstellt werdenmuss. Von dieser Ur-CD zieht das Presswerk die Kopien. Bei www.osmaa.de kostetein Glasmaster rund 250 Euro, unabhängig davon, wie viele CDs gepresst werden.Hinzu kommt ein Stückpreis je gebrannter CD-ROM – dort 45 Cent bei 500 Stück.Somit kostet das Pressen und Bedrucken von 500 CD-ROMs rund 500 Euro. Beisteigender Anzahl sinkt der Stückpreis; ab 2000 Stück entfallen die Kosten für dasGlasmaster. Doch mit der Silberscheibe allein ist es nicht getan: Auch die Plastikhülle(ab 17 Cent), ein Einlegeblatt bis hin zum mehrseitigen Booklet (ab 7 Cent), eine Pau-schale für die Druckplatte und gegebenenfalls eine Verschweißung (3 Cent) kostenGeld.

Pressen Sie zu viele Exemplare, besteht die Gefahr, dass Sie auf Hunderten voraus-bezahlter CD-ROMs sitzen bleiben. Zweiter Nachteil: Programmfehler lassen sichnachträglich nicht entfernen.

Eine günstigere Möglichkeit ist das manuelle Bedrucken (Labeln) von selbst gebrann-ten CDs. Auch hier lässt sich eine gewisse Professionalität erzeugen. Es werden le-diglich ein Label(ling) Kit, Druckvorlagen, ein Tintenstrahldrucker sowie etwas hand-werkliches Geschick benötigt. Einfache Kits sind bereits ab 10 Euro (zum Beispiel beiwww.cdrohlinge24.com) erhältlich.

Letztendlich müssen Sie entscheiden, ob Ihnen die professionelle Produktion desDatenträgers einen relativ hohen finanziellen Aufwand wert ist oder ob eine in Heim-arbeit gefertigte Kleinserie nicht auch den Ansprüchen der Käufer gerecht wird. Esschadet nicht, erst mit einem Label Kit zu beginnen und im Falle eines unerwartetgroßen Erfolgs eine Massenfertigung in Auftrag zu geben.«

Page 430: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

5

Jugendschutz j e t z t l e r n e i c h

Abb. 25.1:Kopierroboter und hochwerti-ge Labelprinter helfen beim Pro-duzieren kleine-rer CD-Aufla-gen.

25.3 Jugendschutz

Zum Zeitpunkt der Manuskriptabgabe des Buchs war das neue Jugendschutz-Gesetz inDeutschland erst kurze Zeit in Kraft – und brachte ein Chaos mit sich. War der USK-Sticker (www.usk.de) bisher freiwillig, müssen nun alle Computerspiele mit einerAlterskennzeichnung versehen werden. Fehlt sie, ist das Spiel automatisch erst ab 18Jahren freigegeben. Doch welcher Hobbyentwickler kann sich die Prüfgebühr von1000 Euro zur Ermittlung der Altersfreigabe leisten? Derzeit sieht die Situation folgen-dermaßen aus: Spiele, die per Download angeboten werden, benötigen keine Alters-freigabe. Es muss aber sichergestellt sein, dass sie nicht jugendgefährdend sind. Eineschwammige Regelung, mit der sich leben lässt: Jeder kann ja ungefähr abschätzen,wie brutal sein Spiel ist, ob es sich für die achtjährige Schwester eignet.

Wer sein Spiel auf einem Datenträger (CD, DVD, Diskette) vertreibt, muss gewährleis-ten, dass der Käufer mindestens das Alter erreicht hat, für das das Spiel freigegeben ist.Da ein Hobbyprogrammierer kaum sein Spiel bei der USK einreichen wird, heißt das:Das Spiel darf nur an Erwachsene abgegeben werden. Wie das Alter nachgewiesenwird, ist derzeit noch nicht eindeutig bestimmt. Die sichere Methode ist die Überprü-fung mit PostIdent, das von der Deutschen Post (www.deutschepost.de) angebotenwird. Die Kopie des Personalausweises sollte ebenfalls genügen. Auch das Bezahlenmit Kreditkarte wird als ausreichender Beweis angesehen, da Kreditkarten nur anErwachsene vergeben werden. Auf der Buch-CD befindet sich ein Infoblatt, das vomVUD (www.vud.de) herausgegeben wurde. Es enthält Details zu den neuen Rege-lungen.

Björn Christophersen, www.cd-duplizieren.de: »Für den Kleinverlag, der monatlicheinige hundert CDs dupliziert, ist der Einsatz eines Kopierroboters überlegenswert.Diese Geräte brennen CD-Rs und bedrucken sie gleichzeitig. Das Labeln der CDs ent-fällt: Die Silberscheiben werden mit einem Papierlack versehen und mit Tinte be-druckt (Kosten: circa 55 Cent je Stück). Alternativ wird im Thermotransfer-Verfahrengedruckt. Dabei wird Heißwachs auf die CD geschmolzen. Das ist ein wenig teurer,dafür wird die CD kratz- und wasserfest. Solche Geräte kosten ab 2000 Euro. Nachoben ist mit DVD- und Netzwerkunterstützung alles offen. Nach unten runden spe-zielle CD-Bedrucker ohne Brennfunktion die Palette ab.«

Page 431: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

6

Vertriebsformen von Spielen25j e t z t l e r n e i c h

Vielleicht bietet die USK künftig ein preiswerteres Prüfverfahren für Freeware-Spielean; dauert doch das Testen eines Titels à la »Pac-Man« bei weitem nicht so lange wiebei einem komplexen Vollpreisspiel.

25.4 Kommerzieller Erfolg

Der Traum eines jeden Hobbyentwicklers ist ein Vertrag: Sie finden einen Verleger(Publisher) für Ihr Spiel, der es auf eine CD-ROM presst, mit einem hübschen Coverversieht und damit die Händlerregale füllen lässt, zu einem Preis von 5 bis 10 Euro,vielleicht sogar mehr, von dem Sie einen Anteil erhalten. Voraussetzung dafür ist einganz besonders gut gelungenes Spiel und das Einhalten einiger Spielregeln.

1 Abb. 25.2:Der Traum

eines Entwick-lers: Das eigene

Spiel in einerHandels-

verpackung.

25.4.1 Kontakt zu einem VerlagBevor Sie einen Verlag mit einem Konzept, einer Demo oder gar einem fertigen Spielbeglücken, sollten Sie den geeigneten Ansprechpartner im Verlag herausfinden. Dasist meistens der Produktmanager. Rufen Sie am besten an oder schreiben Sie eineE-Mail. Die passenden Adressen finden Sie meistens auf den Webseiten der Verlage.Schildern Sie in kurzen Worten, was Sie ihm zusenden möchten. Meist klären Sie be-reits, ob es überhaupt Sinn macht, eine ganze Mappe zuzusenden. Nicht jeder Verlagist an Spielen interessiert; vielleicht hat er gerade ein ähnliches Spiel in Planung. In die-sem Fall lohnt sich die Arbeit eines Angebots nicht.

Dieses Kapitel entstand unter maßgeblicher Mitarbeit von Ralph J. Kraft, dem Pro-duktmanager des Topos-Verlags.

Page 432: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

7

Kommerzieller Erfolg j e t z t l e r n e i c h

1

Es ist keine gute Idee, alle deutschen Verlage in einem Massenmailing anzuschreiben.Verlage sind verärgert, wenn sie erfahren, dass das Angebot auch an die Konkurrenzunterwegs ist. Der Nimbus des Einzigartigen und Geheimnisvollen ist dann verspielt.Die Unternehmen haben wenig Lust, sich wie bei einer Versteigerung gegenseitig aus-spielen zu lassen.

Eine Auswahl geeigneter Verlage sind im Folgenden aufgeführt:

Produktmanager sind die zentralen Ansprechpartner im Verlag, wenn es um Soft-ware geht. Sie stehen in Kontakt mit der Geschäftsleitung, der Marketing- und Presse-abteilung und dem Vertrieb. Bedenken Sie beim Umgang mit Produktmanagern, dassSie auf alle möglichen Typen von Menschen treffen können. Den Beruf Produkt-manager erlernt man nicht; Sie treffen auf Lehrer, Physiker, ehemalige Programmie-rer, Marketingleute und noch viele andere Typen. Gehen Sie auf den Produktmanagerein. Er ist Ihr »Anwalt« im Verlag, der in der Regel Ihre Interessen vertritt. Der Pro-duktmanager gehört in die Gruppe der »Jäger und Sammler«. Er ist ständig auf der Su-che nach Beute, nach neuen Programmen und einzigartigen Ideen. Geben Sie ihm dasGefühl, dass Sie ihm das bieten können. Verkaufen Sie ihm Ihr Spiel. Versuchen Sieherauszufinden, was ihn besonders interessiert, woran der Verlag gerade arbeitet, inwelche Richtung er gerade tendiert. Prüfen Sie seine Produktpalette und vergleichenSie, ob Ihr Spiel hineinpasst – oder ob Sie es dafür passend machen können.

Astragon www.astragon.de Telefon 0180/5004709

CDA www.cda-verlag.com Telefon 0043-7262 57557-11 (Österreich)

CDV www.cdv.de Telefon 0721/9 72 24-0

dtp www.dtp-ag.com Telefon 040/66 99 10-0

Koch Media www.kochmedia.com Telefon 089/8 57 95-1 20

Magnussoft www.magnussoft.de Telefax 035204/60 249

NBG www.nbg-online.de Telefon 09471/70 17-0

Topos www.topos-verlag.de Telefon 02131/795 490

Michael Derbort, www.derbort.de: »Der Trick, mit dem ich die Kontakte knüpfe, istrecht einfach: Ich gehe in die Computerabteilung eines beliebigen Kaufhauses. Dannschaue ich nach, welche Spielsammlungen es so gibt. In den meisten Fällen steht dieVerlagsadresse oder gar die Homepage-Adresse auf der Rückseite der Verpackung.Diese notiere ich mir. Zu Hause angekommen, surfe ich die notierten Seiten gezieltab und schaue mir deren Verlagsprogramm an. Finde ich dort etwas Passendes, kon-taktiere ich den Verlag per E-Mail und verweise ihn auf meine Homepage. Hier ist eswichtig, eine funktionierende und übersichtliche Homepage zu haben. Begnügen Siesich nicht nur damit, Ihre Produkte zum Download anzubieten, sondern stellen Sie sieauch vor. Eine kurze Programmbeschreibung mit Screenshots genügt. Und übertrei-ben Sie es nicht. Floskeln wie »Das ultimative Action Game« bringen nichts und schre-cken nur ab. Man könnte es als klaren Hinweis für Selbstüberschätzung interpretie-ren. Beschreiben Sie nüchtern und in kurzen Sätzen das Spiel und vermeiden Sie,wenn möglich, Adjektive.

Page 433: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

8

Vertriebsformen von Spielen25j e t z t l e r n e i c h

25.4.2 Unterlagen sorgfältig vorbereitenDie Unterlagen, die Sie einem Verlag zusenden, sollten in jedem Fall folgende Infor-mationen enthalten:

� Die eigene Adresse

� Eine Kurzbeschreibung des Programms; nicht länger als eine DIN-A4-Seite

� Screenshots des Programms, auch wenn eine Demo mitgeschickt wird: Produkt-manager sind viel beschäftigte Menschen. Ihre Lust und ihre Zeit, Programme zuinstallieren, sind sehr begrenzt. Man muss sie neugierig machen. Das gelingt amehesten mit bunten Bildchen.

� Konkurrenzvergleich: Wenn der Produktmanager das Spiel in der Konferenz vor-stellt, muss er beschreiben, welche ähnlichen Programme es zurzeit auf dem Marktgibt und worin sich das Spiel von den anderen abhebt. (Der Fachbegriff für eineneinzigartigen Vorzug heißt USP = Unique Selling Point.) Wenn Sie diese Auflis-tung bereits mitschicken, nehmen Sie ihm eine Menge Arbeit ab. Stellen Sie IhrLicht nicht unter den Scheffel!

� CD mit einer Demo oder Vorabversion: Es ist sehr schwierig, einem Verlag (nur)ein Konzept zu verkaufen. Gerade im Budgetbereich (also bei niedrigen Produkt-preisen) hat der Produktmanager keine Zeit, am Konzept mitzuarbeiten. Er will(fast) fertige Lösungen sehen.

� Referenzen: Eine Liste der bisherigen Veröffentlichungen (sofern vorhanden). EineWebseite, die Ihre bisherigen Erfolge aufzeigt, ist hier sehr nützlich.

Üben Sie sich nach dem Zusenden in Geduld. Geben Sie ihm mindestens eine WocheZeit, die Unterlagen durchzusehen. Wenn Sie danach noch nichts von ihm gehört ha-ben, dann ist es erlaubt nachzufragen – am besten zunächst per E-Mail, später auchtelefonisch. Wenn Sie nach drei oder vier Wochen noch keine Reaktion erhalten ha-ben, wird Ihr Angebot nicht auf große Gegenliebe gestoßen sein. Bitten Sie in diesemFall um die Rücksendung der Unterlagen.

Wenn Produktmanager Ihre Seite besuchen und sich einen Überblick verschaffenmöchten, dann reagieren sie sehr dankbar auf den Verzicht allzu geschwätziger »Wer-betexte«. In vielen Fällen antworten die Verlage auf meine Mail und dann ist der Zeit-punkt gekommen, eine Demo-CD zuzusenden. Auch bei den CDs gilt: klare undübersichtliche Startoberfläche, kurze Beschreibungen für jedes Programm und ambesten noch ein Screenshot. Kleben Sie bedruckte Labels auf die CD und vermerkenSie auch darauf Ihren Namen und Ihre Adresse. Es kann sonst zu schnell passieren,dass CDs und Hüllen und Begleitschreiben durcheinander geraten, und dann fällt esschwer, die Sachen wieder zuzuordnen.

Neben den reinen Software-Verlagen können Sie es bei Zeitschriftenverlagen ver-suchen. Hier taucht allerdings häufig das Problem auf, dass diese Verlage für Vollver-sionen gar nichts bezahlen möchten und nur »Werbung« anbieten. Darauf sollten Siesich nur in Ausnahmefällen einlassen. Eine solche Werbung bringt im Allgemeinennichts und Sie haben das Nachsehen. Einige wenige Verlage zahlen hingegen etwasfür eine gute Vollversion. Hier lassen Sie sich darauf ein, dass Ihr Spiel für einenMonat auf der Heft-CD erscheint und neben dem Recht der einmaligen nicht exklu-siven Veröffentlichung gehen Sie keinerlei weitere rechtlichen Verpflichtungen ein.«

Page 434: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

9

Kommerzieller Erfolg j e t z t l e r n e i c h

0

25.4.3 Mögliche ErlöseWas springt für Sie heraus? Das interessiert Sie natürlich am meisten und daher mussich Ihnen zunächst einen Dämpfer geben: Schrauben Sie Ihre Erwartungen herunter.Es ist nahezu unmöglich, heute noch mit einem Spiel reich zu werden. Die Zeit der Ga-ragenfirmen mit Pionieren wie Bill Gates ist vorbei.

Die Bedingungen, die Ihnen Verlage anbieten, können sehr unterschiedlich ausfallenund sind nur selten vergleichbar. Wenn Sie eine Rechnung aufstellen, Sie hätten 100Stunden an Ihrem Spiel gearbeitet und Ihre Arbeitsstunde würde nun mal 100 Eurokosten, dann werden Sie es schwer haben, einen geeigneten Verleger zu finden.Grundsätzlich unterscheidet man die im Folgenden beschriebenen Vertragsarten.

Pauschale (Flat)Ein Garantiebetrag ist eine nicht mehr so häufige Art des Programmeinkaufs: Der Ver-lag bietet Ihnen eine feste Summe an und erwirbt damit alle Rechte an der Software.Dies ist für den Autor nicht die schlechteste Wahl. Hier gibt es kein Wenn und Aber:Sie müssen sich entscheiden, ob der gebotene Betrag Ihre Mühen entlohnt. Wenn ja,sollten Sie zugreifen, denn damit haben Sie alle Risiken aus dem Weg geräumt undkönnen sich neuen Projekten widmen. Aber Vorsicht: Wenn Ihnen ein Verlag aus demStand heraus einen relativ hohen Betrag anbietet, dann hat er meist schon einen festenAbnehmer dafür. Versuchen Sie herauszubekommen, wer das sein könnte. Vielleichtlohnt es sich, in diesem Fall vorsichtig nachzuverhandeln und eine Garantie plus einer– zumindest kleinen – prozentualen Beteiligung vorzuschlagen.

Prozentuale BeteiligungWenn der Verlag nur eine prozentuale Beteiligung anbietet, ist Vorsicht geboten. Selbstwenn die Beteiligung sehr hoch ist, haben Sie keine Garantie, dass Sie anständigesGeld sehen. Ist das Spiel ein Flop, bekommen Sie kaum Honorar. Rein theoretisch hatder Verlag sogar die Möglichkeit, das Programm zu lizenzieren, aber niemals zu veröf-fentlichen. So sind mögliche Konkurrenzprodukte vom Markt verschwunden, ohnedass sie jemals veröffentlicht wurden.

Garantiehonorar mit prozentualer BeteiligungDie sicherlich gängigste Art des Vertrags ist ein Garantiehonorar mit einer bestimmtenprozentualen Beteiligung am Verlagsumsatz. Für beide Seiten ist das der goldene Mit-telweg, weil es eine gute Art der Risikoverteilung ist. Die Höhe von Garantiesummeund Prozentsatz sind schwer zu verallgemeinern. Einige Anhaltspunkte:

� Das Garantiehonorar sollte zwischen 50% und 100% des zu erwartenden Lizenz-erlöses der ersten Auflage sein.

� Die erste Auflage liegt meist zwischen 2000 und 5000 Stück. Damit testet der Ver-lag den Markt und die Akzeptanz des Spiels.

Vor und während Messen herrscht in Verlagen besonders große Betriebsamkeit. Ver-meiden Sie es, sich zu Zeiten wie der Frankfurter Buchmesse, der Leipziger GamesConvention oder zu internationalen Messen wie der E3 zu melden. Auch das Jahres-ende ist kein guter Termin.

Page 435: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

10

Vertriebsformen von Spielen25j e t z t l e r n e i c h

� Das Lizenzhonorar liegt im Allgemeinen zwischen 10% und 20% vom Verlags-umsatz (oder Nettoumsatz).

Beispiel:

Verkaufspreis 15,99 Eurominus 16% Mehrwertsteuer -2,21 Eurominus 40–60% Händlerrabatt -5,51 bis -8,26 Euro= Verlagsumsatz 8,27 Euro bis 5,52 Euro= Honorar 10--20% 0,55 Euro bis 1,65 Euro

Je verkauftes Spiel können Sie also einen Betrag von 0,55 bis 1,65 Euro erwarten. Eintypischer Vertrag sieht damit so aus:

Garantiehonorar: 1500 bis 3000 Euro

Lizenzhonorar: 15%

Mit Software lässt sich nicht nur im klassischen Markt der UnterhaltungselektronikGeld verdienen. Sprechen Sie mit dem Verlag darüber, wo er sich noch einsetzen kann.Einige Verlage sind stark im Discountgeschäft (wie Lidl, Aldi, Plus) oder in personali-sierten Industrieversionen vertreten. Hier können alle Beteiligten sehr viel Geld verdie-nen. Eine gute Idee ist es, die Konditionen für solche Geschäfte nicht von vornhereinin den Vertrag aufzunehmen, sondern eine Klausel wie »Besondere Geschäfte bedür-fen der individuellen Absprache« hinein zu schreiben. Damit sind Sie immer darüber imBild, was der Verlag mit Ihrem Spiel »anstellt«.

Michael Derbort, www.derbort.de: »Wenn Sie mit überzogenen Preisvorstellungeneinen Verlag kontaktieren, dann haben Sie schon verloren. Ich blicke hier auch aufmeine Zeiten als Produktmanager zurück. Einige Programmierer hatten Preisvorstel-lungen, die teilweise über denen namhafter Software-Hersteller lagen. Alleine derZeitaufwand für zähe Verhandlungen wäre in vielen Fällen bereits zu teuer. In solchenFällen wurden mehr als einmal interessante Produkte kurzerhand von der Liste gestri-chen. Es ist schwierig, hier konkrete Zahlen zu nennen. Das hängt von der Größe desSpiels ab, aber auch davon, wie Sie die Spiele weiter lizenzieren. Sie sollten sich fer-ner Gedanken darum machen, ob Sie die Spiele exklusiv oder nicht exklusiv weiterlizenzieren.

Exklusiv bedeutet, dass nur der Verlag, mit dem Sie einen Vertrag abgeschlossenhaben, Ihr Spiel vertreiben kann. Das könnte zwar mehr Geld bringen, birgt aber einerhebliches Risiko in sich. Es kann ohne Weiteres passieren, dass der Vertrieb IhresSpiels überhaupt nicht in die Gänge kommt. Das kann mehrere Ursachen haben.Entweder der Verlag hat das Produkt nicht richtig beworben oder die Leute dorthaben die Zielklientel falsch eingeschätzt. Hinzu kommt, dass der Software-Marktziemlich undurchschaubar ist. Was heute der Riesenrenner ist, kann morgen schonein Super-Ladenhüter sein. In einem solchen Fall sind Sie zwei oder drei Jahre an denVertrag gebunden und können Ihre eigene Software nicht mehr weiter vermarkten.Aus persönlicher Erfahrung rate ich Ihnen daher dringend, auf exklusive Lizenzen zuverzichten.

Page 436: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

11

Kommerzieller Erfolg j e t z t l e r n e i c h

AuslandsrechteViele Autoren suchen sich den Verlag aus, der die meisten Auslandskontakte bietet.Dies ist oft ein Irrweg. Richten Sie Ihren Blick in erster Linie auf den deutschsprachigenMarkt. In »DACH« (Deutschland, Österreich und Schweiz) warten rund 100 Millionenpotenzielle Kunden. Die Erlöse aus Auslandsversionen sind vergleichsweise gering, be-deuten aber zusätzliche Arbeit durch die Übersetzung und Anpassung an andere Win-dows-Versionen. (Sie sollten die US-Version Ihres Spiels nicht in den Ordner C:\PRO-GRAMME installieren wollen.) Versuchen Sie allerdings, die Rechte für das Ausland zubehalten. Wenn Sie einem Verlag im Vertrag das weltweite Recht zur Veröffentlichungzusichern, haben Sie kaum Möglichkeiten, später selbst aktiv zu werden. Verlangen Siefür das Verkaufen weltweiter Rechte erhöhte Garantiesummen.

Bei nicht exklusiven Lizenzen können Sie hingegen Ihre Produkte auch anderenVerlagen anbieten, ohne dass Sie besonderen Einschränkungen unterworfen sind.Doch auch hier ist etwas Vorsicht angebracht: Wenn Ihre Produkte zu inflationär ver-breitet werden, ziehen Sie Ihnen selbst den Boden unter den Füßen weg. Irgendwannsagen die Verlage: »Damit können wir nichts mehr anfangen. Dieses Produkt istschon über zu viele andere Anbieter erhältlich.« Dann wäre noch die Frage der Be-zahlung zu klären. Entweder die Verlage bieten Ihnen eine Gewinnbeteiligung an oderaber Sie erhalten eine so genannte Flat Fee, einen – im Allgemeinen recht niedrigen– Pauschalbetrag. Für ein kleines Pausenspiel sind 200 bis 300 Euro drin, komple-xere Spiele bringen schon etwas mehr. Für Sie hat das den Vorteil, dass Ihnen IhrGeld sicher ist. Egal, ob der Vertrieb ein Flop ist oder nicht – Sie bekommen die ver-einbarte Summe. Der Nachteil liegt auf der Hand: Wird das Produkt ein Riesenerfolg,bleiben Sie auf Ihrer Flat Fee sitzen und der Verlag verdient daran.

Gewinnbeteiligungen sind durchaus eine Alternative. Hier können Sie sehr oft einenicht rückzahlbare Vorschusszahlung auf die zu erwartenden Gewinne aushandeln.Die Höhe dieser Summe hängt von mehreren Faktoren ab: voraussichtlicher Endver-kaufspreis, angestrebte Auflage, prozentuale Beteiligung. Erst wenn genügend Exem-plare verkauft wurden, um den bereits gezahlten Vorschuss abzudecken, bekommenSie Ihre Beteiligung für die weiteren Verkäufe. Aber auch hier ist wieder Vorsicht an-gebracht: Wenn vom Fachhandel die nicht verkauften Exemplare wieder zurückkom-men, kann es Ihnen passieren, dass Sie bereits ausgezahlte Gewinnbeteiligungen wie-der zurückzahlen müssen. Damit ist schon so mancher Programmierer unverhofft indie roten Zahlen gerutscht.

Es ist im Großen und Ganzen Ermessenssache, welche Form der Lizenzierung dieoptimale Lösung darstellt. Bei potenziell erfolgversprechenden Spielen sind Siesicherlich mit einer Gewinnbeteiligung am besten bedient. Spiele, die groß genug fürein Stand-alone-Produkt sind, wären zum Beispiel ein optimaler Kandidat fürGewinnbeteiligungen. Als Programmierer von Pausenspielen, die meist so zwischen2 und 6 MB Dateigröße liegen, habe ich mit Flat Fees und nicht exklusiven Lizenzendie besten Erfahrungen gemacht. In den meisten Fällen finden sich die Spiele inCompilations wieder und die Gewinnbeteiligung wäre dann ohnehin verschwindendgering.«

Page 437: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

12

Vertriebsformen von Spielen25j e t z t l e r n e i c h

0

25.4.4 Der VertragDer Vertrag ist naturgemäß nicht immer leicht zu verstehen. Verlage haben ihren Stan-dardvertrag, der meist in grauer Vorzeit von einem Anwalt erdacht wurde und natürlichvorrangig Wohl und Wehe des Verlags im Sinn hat. Viele Verlage zeigen Flexibilität,wenn es um Änderungswünsche der Autoren geht – allerdings nur in gewissen Gren-zen. Nach Möglichkeit sollte ein Anwalt einen Blick auf den Vertrag werfen – allerdingssind die Kosten hierfür so hoch, dass sich das für Software im Budgetbereich seltenlohnt. Fragen Sie im Zweifelsfall beim Produktmanager schriftlich nach, was dieseroder jener Satz zu bedeuten hat. Seine Antworten sind in Form einer E-Mail nicht un-bedingt rechtsverbindlich, aber Ihr Ansprechpartner wird sich, anders als vielleicht amTelefon, genau überlegen, was er Ihnen schreibt.

Das Übertragen Ihres Spiels an einen Verleger heißt nicht, dass Sie die Hände in denSchoß legen müssen. Sie können die Verkäufe Ihres Spiels weiterhin unterstützen –mit einer Website, dem Verteilen einer Demoversion, mit Pressearbeit. Sprechen Sieaber mit dem Verlag über Ihre Aktivitäten und handeln Sie nicht in dessen Namen.

Carsten Fichtelmann, www.dtp-ag.com: »Um ein Spiel erfolgreich zu vermarkten,muss es entweder massentauglich oder ein interessantes Nischenprodukt sein. Wasaus meiner Sicht nicht funktioniert, ist das Kopieren von erfolgreichen Ideen aus demVollpreisbereich. Also Finger weg von Fußballmanagern, Rollenspielen oder Auto-rennen.

Welche Publisher es gibt und welche in Frage kommen, kann man z.B. auf Branchen-seiten wie www.mcvonline.de, www.gamesmarkt.de oder www.insider-borgmei-er.de recherchieren. Zu raten ist auch, einfach mal in ein Fachgeschäft wie den MediaMarkt zu gehen und zu schauen, wer vergleichbare Produkte herstellt. Eine weitereMöglichkeit ist es, den VUD (www.vud.de) anzusprechen. Der VUD ist der Branchen-verband der Spieleentwickler. Allerdings sind nicht alle Unternehmen Mitglied imVUD.

Wenn wir von Hobbyentwicklern sprechen, dann reden wir zwangsläufig von CasualGames, von einfachen, leicht zugänglichen Titeln für Gelegenheitsspieler. DieserMarkt ist enorm schwer zu erobern, weil jedes 10-Euro-Produkt gleichzeitig mit Top-Titeln in der Zweit- oder Drittvermarktung konkurrieren muss, die genauso viel kos-ten. Im Regelfall lassen sich nicht mehr als 5000 Stück absetzen. Aufgrund der ge-ringen Absatzerwartung ist wenig Marketing möglich. Man hat bei Publishern vielbessere Chancen, wenn man einen Kooperationspartner anbieten kann. So wäre esnatürlich nicht schlecht, wenn man bei einem Bankerspiel die Deutsche Bank und beieinem Spiel, wo es um Schokolade geht, Milka oder Nutella mit im Boot hat. Das istnatürlich sehr schwer – aber nicht unmöglich. Das Moorhuhn hat auch so angefan-gen ...«

Page 438: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

13

Kommerzieller Erfolg j e t z t l e r n e i c h

Michael Derbort, www.derbort.de: »Wenn Sie mit Verlagen zusammenarbeitenmöchten, sollten Sie sich im Klaren darüber sein, dass Sie es mit Profis zu tun haben.Wenn Sie sich auf einen Vertrag einlassen, gehen Sie auch eine ganze Menge Ver-pflichtungen ein. Dabei gibt es eine ganze Menge Fehler, die Sie vermeiden sollten:

– Unpünktlichkeit: Abgabetermine sind bindend. Die Verlage haben einen engenZeitplan. Das erfordert unter anderem, dass sie sich auf ihre Vertragspartner ver-lassen müssen. Vor Abschluss des Vertrags werden Sie meistens noch gefragt, biswann Sie die gewünschten Änderungen durchführen könnten. Sagen Sie dannnicht: »Kleinigkeit! Das habe ich in zwei Tagen erledigt.« Packen Sie lieber nochein paar Tage mit drauf. Dann haben Sie nach hinten Luft, wenn etwas dazwi-schen kommt. Wenn die finale Version früher fertig wird, freuen sich die Leutemehr, als wenn sie erst drei Tage nach dem Stichtag mitbekommen, dass sichnoch gar nichts getan hat. Im ungünstigsten Fall platzt dann der Vertrag und Siebekommen bei ihnen keinen Fuß mehr in die Tür.

– Mogeln: Wenn Sie ein Spiel bereits über einen anderen Verlag veröffentlichthaben, können Sie sich nicht hinstellen und sagen, dass es dieses Spiel noch nieim Fachhandel gab. Wenn das durch Zufall herauskommt, kann Ihnen bei nichtexklusiven Lizenzen zwar nicht viel passieren, aber Sie sind dadurch nicht mehrvertrauenswürdig. Seien Sie ehrlich, plaudern Sie aber nicht gleich alle Detailsheraus.

– Meckern: Missverständnisse können immer wieder vorkommen. Ein falsch inter-pretierter Punkt im Vertrag oder ein Tippfehler bei den Lizenzgebühren oder Ab-gabeterminen sorgt auch immer rasch für heilloses Gezeter. Bevor Sie beim Ver-lag anrufen und gleich mit Rechtsanwälten um sich werfen, lassen Sie sichzunächst den zuständigen Produktmanager geben und erzählen ihm, dass Ihnenda etwas aufgefallen ist. Oft lassen sich diese Dinge rasch klären. Wenn diezuständigen Leute in einem Anruf sofort zu »Mafiosi« und »Halsabschneidern«mutieren, sind sie bei eventuellen weiteren Vertragsabschlüssen nicht mehr son-derlich kooperativ.

– Pfusch: Man sieht, ob bestimmte Änderungen rasch zusammengepfuscht wur-den. Versuchen Sie nicht, Rekorde bei der Abgabe der Endversion zu brechen.Arbeiten Sie lieber sorgfältig. Rasche »Verbesserungen« bewirken oft das Gegen-teil. Wenn Ihnen etwas an Ihrem Programm auffällt, was man nochmals über-arbeiten könnte, dann klären Sie das mit dem Produktmanager ab. Wenn Siedeswegen mehr Zeit benötigen, spielen Sie mit offenen Karten. Der Verlag ent-scheidet dann, ob er Ihnen noch Zeit einräumt, um diese Änderung durchzu-führen.«

Page 439: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

14

Vertriebsformen von Spielen25j e t z t l e r n e i c h

25.5 Werbespiele

Das große Zeitalter der Werbespiele scheint vorbei: In den frühen 90er Jahren schos-sen kostenlose Spiele, die zu Promotion-Zwecken verteilt wurden, wie Pilze aus demBoden. Doch das Moorhuhn zeigt, wie populär ein gut gemachter Zeitvertreib nochheute werden kann (wenngleich eher der Verleger Phenomedia und weniger dasbeworbene Produkt davon profitierte). Viele Agenturen konzentrieren sich auf dieseAdgames oder Promotion Games, oft Hand in Hand mit anderen PR-Werkzeugen.

Theoretisch kann ein Entwickler gutes Geld machen, wenn er einen Sponsor findet,der die Kosten übernimmt. Praktisch sind die großen Marken fest in der Hand vonAgenturen; und die Konkurrenz ist groß. Professionelles Auftreten, Referenzen undeine erstklassige Qualität der Arbeiten sind Pflicht. Es gibt Dienstleister, die zwischenEntwicklern und Werbekunden vermitteln. Deren Arbeitsweise, bisherige Erfolge unddie Vertragsmodalitäten sollten äußerst genau überprüft werden. Nicht selten tauchtder Name der eigentlichen Programmierer gar nicht im Spiel auf.

Doch es muss nicht gleich Coca Cola oder McDonald’s sein. Stellen Sie zunächst si-cher, dass Ihr Spiel wirklich gut aussieht. Suchen Sie lokale Unternehmen, die für einWerbespiel offen sein könnten. Städtische Einrichtungen wie Museen haben meistenskein Budget. Doch wie wäre es mit den Verkehrsbetrieben? Oder einem Getränkeher-steller? Einem Fußballverein? Sprechen Sie die Marketing-Abteilung des Unterneh-mens an. Freilich muss der Inhalt des Spiels zugeschnitten sein auf den potenziellenAbnehmer.

Sebastian Lenk, www.seelenradio.de: »Werbespiele sind eine sehr gute Möglich-keit, um dem potenziellen Kunden eine Marke näher zu bringen und zu vermitteln.Spiele verknüpfen eine Marke, die Botschaft und den Spaß auf angenehme und un-aufdringliche Weise. Der Spieler beschäftigt sich aus freien Stücken mit dem Spiel,einen Vorteil, den kein anderes Medium bietet und den es unbedingt zu nutzen gilt.

Worauf müssen Sie als Entwickler achten? Der wichtigste Grundsatz lautet auch beiAdgames: Qualität in der Ausführung ist Pflicht! Sparen Sie nicht an der zu investie-renden Zeit, um aus Ihrer Idee einen Hit zu machen. Legen Sie Wert auf gut ausge-arbeitete Grafiken und Sounds. Achten Sie auch auf die einfache Zugänglichkeit IhresSpiels. Der potenzielle Spieler ist nicht bereit, sich lange Anleitungen durchzulesen.Das Spielprinzip muss einfach sein und die gestellte Aufgabe klar und verständlich.Erschließt sich dem Spieler das Adgame nicht in kurzer Zeit, dann wird er sich ab-wenden und Sie haben ihn wortwörtlich verloren.

Mit Adgames reich werden? Das ist ein verlockender Gedanke. Betrachten Sie dieEntwicklung aber auch einmal von der anderen Seite: Sie haben die Chance, sich miteinem guten, innovativen, kleinen Produkt einen Namen zu machen! Sie liefern dasSpiel – für die Verbreitung sorgen in der Regel andere, meist der Auftraggeber. Ist IhrSpiel gut, wird es sogar von den Spielern selbst weiterverbreitet. Suchen Sie sich klei-ne Firmen in Ihrer Nähe. Vielleicht eine lokal angesiedelte Getränkekette, ein mittel-ständisches IT-Unternehmen oder eine Buchhandlung. Machen Sie sich die Arbeit,bereiten Sie ein Konzept vor, welches Sie nach Möglichkeit so offen gestalten, dasses sich auf mehrere Kunden gleichzeitig anwenden lässt. Hilfreich dabei ist wiedereine einfache, zeitlose und universelle Spielidee.«

Page 440: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

15

Online-Vertrieb j e t z t l e r n e i c h

25.6 Online-Vertrieb

Mit den eigenen Computerspielen Geld zu verdienen, ist für viele hoch motivierte Ent-wickler der große Traum. Ein attraktives Spiel zu entwickeln, ist allerdings kein leichtesUnterfangen. Dafür noch zahlende Kunden zu finden, ist noch weitaus schwieriger.Häufig haben Hobbyentwickler kaum eine Vorstellung, wie das traditionelle Geschäftin der PC-Spiele-Branche abläuft. Kapitalträchtige Produktions- und Vertriebsfirmenlassen Spiele oft im Auftrag entwickeln. Häufig sind die Entwickler nicht einmal amspäteren Umsatz beteiligt. Wenn doch, dann bekommen nur wenige Teams mehr als20 Prozent.

Wie kann man aber nun sein Spiel groß herausbringen, ohne Millionen für Werbungund Vertrieb ausgeben zu müssen? Viele Hobbyentwickler setzen ihre Hoffnung aufdas Internet. Aus dem Gedanken der Shareware heraus entwickelten sich neue Ver-triebsformen, etwa der Einsatz eines speziellen Internetbezahlsystems auf der eigenenWebsite. Der Vorteil: Der Kunde bekommt die Ware, in diesem Fall das Spiel, sofort.Er kann es sich ohne Wartezeit herunterladen.

Marktführer für Online-Payment in Deutschland ist die Firma Firstgate (www.firstga-te.de). Als Anbieter kann man hier sehr leicht Teile der eigenen Webseite kostenpflich-tig machen. Dazu zählt natürlich der Download einer Vollversion. Der Nachteil ist, dassman als Käufer eine aufwendige Registrierung durchlaufen muss, wozu auch die Anga-be der Bankverbindung zählt. Ein ähnliches System mit dem Namen T-Pay (www.t-pay.de) wird von der Telekom angeboten. Bei T-Pay muss man nicht unbedingt perLastschrift oder Kreditkarte bezahlen. Man kann den Betrag über seine Telekomrech-nung begleichen. Diese Option muss allerdings erst umständlich freigeschaltet werden,da T-Pay sicherstellen muss, dass der Internetnutzer identisch mit dem Telekom-Kun-den ist. Ein weiterer Nachteil von T-Pay ist, dass es sehr auf größere Anbieter fixiert ist.

Eine Alternative ist das von 4FO (www.4fo.de) entwickelte Bezahlsystem Paybest(www.paybest.de). Hier wählt der Käufer unterschiedliche Zahlungsvarianten aus. Einanonymes Bezahlen ohne Registrierung steht bei diesem System im Mittelpunkt: Manwählt eine 0190-Telefonnummer und erfährt eine Codenummer, die man in ein For-mular eingibt. Schon lässt sich die Vollversion herunterladen. Die Gebühren für dasTelefonat entsprechen dem zu zahlenden Preis für das Spiel – etwa 2,50 oder 5 Euro.Das Shareware-Spiel »Rohrfrei« (http://rohrfrei.paybest.de) zeigt, wie Paybest mit we-nigen Zeilen (als PHP-Skript) auf der eigenen Webseite eingebunden wird. Der großeVorteil des Verfahrens ist die sehr einfache Handhabung sowohl für Anbieter als auchfür Käufer. Nachteil ist die teilweise geringe Ausschüttung für die Anbieter.

Die Zukunft könnte in großen Portalen liegen, die eingeschränkte Fassungen zum kos-tenlosen Download anbieten, aber gleichzeitig den Erwerb der Vollversion ermögli-chen. Führend in Deutschland ist T-Online (www.t-online.de), wo regelmäßig neueSpiele getestet und für einen geringen Betrag erworben werden können. Eine erheb-lich größere Besucherzahl erreicht das weltweit ausgerichtete Spieleangebot von Real(www.real.com). Die deutsche Niederlassung des Unternehmens hat kein Interessedaran, weiterführende Hinweise zu geben, so dass nur der Rat bleibt, sich mit Spielean-geboten per E-Mail in englischer Sprache an [email protected] zu wenden.

Weil der Platz auf solchen Portalen begrenzt und begehrt ist, versprechen Agenturenwie Bluefish Media (www.bluefish-media.de) eine Vermittlung. Wie überall gilt: Las-sen Sie sich nicht von Marketing-Sprüchen und einem professionellen Auftreten blen-

Page 441: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

16

Vertriebsformen von Spielen25j e t z t l e r n e i c h

den. Fragen Sie nach Referenzen. Schließen Sie keine exklusiven Vermittlungsverträgeab. So machen Sie sich nicht von der Fähigkeit einer Agentur abhängig.

Abb. 25.3:Über den Dienst

Paybest lässtsich in kurzerZeit aus einer

Demo eine Voll-version machen.

Dr. Jürgen Nützel, www.4fo.de: »Unsere Game-Feature-Plattform (GFP,www.4fo.de/de/gfp) verbindet Komfort für den Spieler mit der Sicherheit für den Ent-wickler. Der Spieler startet das Spiel, welches durch den Entwickler für die GFP an-gepasst wurde, wie eine normale Demo oder Shareware. Möchte er weitere Funkti-onen wie etwa Levels oder Missionen, so verbindet er sich direkt im Spiel mit demOnline-Shop der GFP. Dort wählt er diejenigen Spielerweiterungen aus, die vom Ent-wickler dort zum Download abgelegt wurden. Sie werden automatisch installiert. Indem Online-Shop ist das Bezahlsystem Paybest integriert. Es ermöglicht dem Ent-wickler, für seine Spieleerweiterungen individuelle Preise festzulegen. Der Entwicklerkann über einen speziellen Zugang jederzeit sehen, welche Features in welcher An-zahl verkauft wurden.

Die patentierte Technik der GFP sorgt dafür, dass die heruntergeladenen Levels nichtkopiert werden können. Muss der Spieler dennoch eine Neuinstallation seines Sys-tems durchführen, so kann er sich mit seinem GFP-Login alle bereits bezahlten Er-weiterungen noch einmal kostenlos herunterladen. Die Kopierschutz- und Online-Funktionalität wird für den Entwickler komplett in einer DLL gekapselt. Der Entwick-ler muss daher mit dem Einbinden zusätzlicher DLLs vertraut sein. Für Entwickler, diesystemnah mit C++ und DirectX entwickeln, ist dies keine Hürde. Bei der Verwen-dung von diversen Spiele-Entwicklungssystemen ist der Einsatz der GFP oft nichtoder nur eingeschränkt möglich. Derzeit sind wir damit befasst, die Nutzung der GFPfür Entwickler leichter zu machen. Künftig wird die GFP speziell den Entwicklern vonwww.softgames.de in einer vereinfachten Version angeboten.«

Page 442: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

17

Verbreitungshilfen j e t z t l e r n e i c h

25.7 Verbreitungshilfen

Für die Verbreitung eines Freeware-Spiels, einer Shareware-Version oder der Demo ei-nes kommerziellen Titels bieten sich zwei Wege an: das Internet und Cover-CDs vonZeitschriften. Gezielte Pressearbeit fördert die Bekanntheit Ihres Werks.

25.7.1 WebsiteEine eigene Website lässt sich ohne Kostenaufwand mit relativ geringen Kenntnissenins Netz stellen. Anlaufpunkt für Gratisspeicherplatz ist die Adresse www.kosten-los.de. Eigene Domains (Adressen der Form www.name.de) registrieren Sie bei Dis-countern wie 1&1 (www.puretec.de) und Strato (www.strato.de) oder kleineren An-bietern wie UD Media (www.unique-designs.de), die keine schlechteren Preise habenmüssen. Einsteigerpakete erhalten Sie für ein oder zwei Euro im Monat.

Zwei Kenngrößen sind wichtig: Der Speicherplatz (Webspace) gibt an, wie viele DatenSie hochladen können. Für eine Vorstellung auf einer Handvoll Seiten genügt bereitsein Megabyte. Normalerweise bieten selbst die kleinsten Pakete bereits ein Vielfachesan Platz. Größeres Augenmerk gilt dem Übertragungsvolumen, dem Traffic. Er misstdie Menge an Daten, die Besucher von Ihrer Website abrufen. Bei einer kleinen Web-site mit einigen Dutzend Besuchern am Tag dürfte sich das Volumen unterhalb von ei-nem Gigabyte bewegen.

Das Problemkind sind Downloads: Wenn Sie auf Ihrer Website ein Spiel anbieten, das10 MB groß ist, und dieses Spiel wird 1000 Mal heruntergeladen, ist der Traffic bereitsauf 10 GB gewachsen – eine Menge, die Einsteigerpakete in der Regel nicht mehr bie-ten. Das bedeutet: Nachzahlen. Eine häufige Methode ist, die Software großen Porta-len zur Verfügung zu stellen (dazu gleich mehr) und auf der eigenen Website nur Linkszu diesen Downloads anzubieten. Dabei schickt es sich nicht, direkt auf die Datei zuverweisen (so genannter »Deep Link«), sondern man linkt auf die HTML-Seite, auf dersich die Beschreibung und der eigentliche Download-Link befinden.

Mithilfe von www.teamone.de/selfhtml/ erlernen Sie die Websprache HTML (die aufjeden Fall einfacher als Blitz Basic ist!). Notfalls tut es auch ein Word-Text, den Sie imHTML-Format abspeichern. Wenn es besonders schick werden soll, dann verwendenSie ein Weblayout-Programm wie Fusion oder Frontpage. Eine Website für Ihre Spielesollte folgende Elemente umfassen:

� Beschreibung der Spiele, Bildschirmfotos

� Download-Möglichkeit

� bei kostenpflichtigen Spielen Bestell-/Registrierformular für Vollversionen

� Gästebuch

� Diskussionsforum

� Kontaktadresse zu Ihnen, dem Autor

Page 443: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

18

Vertriebsformen von Spielen25j e t z t l e r n e i c h

Abb. 25.4:Eine Website ist

ein unschätz-bares Instru-

ment fürWerbung und

Kommuni-kation.

Robert Gacki, www.robic.de: »Das eigene Spiel ist fertig. Aber wem wollen Sie dasmitteilen? Nicht nur die eigenen Freunde sollen an Ihren Erfahrungen teilhaben dür-fen. Auch jeder andere soll in den Genuss Ihres Spiels kommen. Der beste Weg ist na-türlich eine eigene Internetseite. Doch wie heben Sie sie aus der Masse hervor? Derscheinbar einfachste Weg ist es, sich die Werbeseiten der großen Spieleentwickler an-zusehen und deren Ideen zu kopieren. Besser ist es jedoch, einen Weg zu gehen, dendie Großen vernachlässigen. Meistens veröffentlichen die Verleger einfach nur dasABC eines Spiels. Außer aneinander gereihten Screenshots, einer Spielbeschreibungund Leistungsdaten (z.B. der Grafik-Engine) gibt es selten interessante Informationen.Sie sollten etwas anderes machen. Lassen Sie den potenziellen Spieler doch schon imVorfeld am Spielgeschehen teilhaben. Eine gute Internetseite zu einem Spiel zeichnetsich durch ihre Kompaktheit aus. Möglichst anregende Informationen ohne viele»Klicks« zu verpacken, lautet die Devise. Am besten eignet es sich hier, eine Art Co-mic von Ihrem Spiel anzufertigen – also die Verbindung von Bildern aus dem Spiel-geschehen und dessen Text. So zwingen Sie den Besucher weiterzulesen und weckengarantiert Interesse am weiteren Spielgeschehen. Dazu reicht eine einzige HTML-Seite, die am besten seitwärts gescrollt werden muss. Bauen Sie die Seite so zusam-men, dass der Leser vielleicht nur drei bis vier Bilder und den Text dazu lesen kann.Für weitere Informationen muss er dann scrollen. Lassen Sie die Internetseite durchFreunde oder Familienmitglieder testen. Natürlich sollten Hinweise zu Ihnen nichtfehlen, genauso wenig wie Hinweise zum Entwicklungsstadium oder zu bekanntenFehlern im Spiel. Eine Download-Seite, auf der Ihre Besucher neuere Versionen odereine Anleitung herunterladen können, gehört zum guten Ton. Wie Sie Ihre Seite auf-bauen, hängt letztendlich von Ihnen und Ihrer Kreativität ab. Wichtig ist, dass Sie esnicht übertreiben und nur das versprechen, was das Spiel halten kann.«

Page 444: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

19

Verbreitungshilfen j e t z t l e r n e i c h

Wenn Sie es sich nicht zutrauen – fragen Sie einen Freund. Nun genügt es nicht, eineHomepage ins Netz zu stellen und auf Besucher zu warten. Das wäre genauso, wiewenn Sie eine neue Telefonnummer erhalten würden und diese nicht bekannt machen– wenn niemand die Nummer kennt, ruft niemand an. Es wurden ganze Bücher alleinüber das Thema »Bekanntmachen von Websites« geschrieben; das Thema würde hierzu weit führen. Sinnvolle Ansatzpunkte für den Anfang sind Einträge in Suchmaschi-nen (Hintergrund: www.kso.co.uk) und geeignete Linklisten, Linktausch und Banner-tausch (z.B. www.game-xchange.de).

025.7.2 SoftwarearchiveEine eigene Website kann nur ein »Zubrot« sein. Viele Interessenten für Ihr Spiel errei-chen Sie nur über ein gut besuchtes Softwarearchiv.

Erste Anlaufstelle sollte für Sie die Seite www.softgames.de sein. Sie enthält eine Viel-zahl von Spielen von Amateurentwicklern, detailliert besprochen und bewertet. IhrSchwerpunkt liegt bei der deutschen Szene, für die es vielerlei weiterführende Hilfe-stellung gibt.

Abb. 25.5:Software-Sammlungen sind froh über Zusendungen von Spielen. Autoren finden im Gegenzug Anregungen für eigene Spiele.

Die Liebhaber Ihrer Programme könnten aus der ganzen Welt kommen. Ziehen Siedaher in Betracht, neben einer deutschen auch eine englische Fassung Ihrer Websiteanzubieten.

Page 445: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

20

Vertriebsformen von Spielen25j e t z t l e r n e i c h

Ebenfalls eine besondere Empfehlung verdient die Adresse www.drload.de. Hier wer-den mehrere hundert Freeware-Spiele in Text und Bild besprochen und zum Downloadangeboten. Die Seite setzt ihren Schwerpunkt eher auf internationale Spiele und hatbesonders viele Besucher – nicht selten werden einzelne Spiele mehrere tausend Malheruntergeladen.

Weitere Adressen, denen Sie Ihr Spiel zugänglich machen sollten, sind:

� www.giggle.de

� www.blitzbasic-pc.de

� www.download-tipp.de

� www.chip.de

� www.pc-welt.de

25.7.3 ZeitschriftenNeben dem Internet sind die Beilage-CDs von Zeitschriften eine hervorragende Metho-de, um Ihr Spiel vielen Menschen zugänglich zu machen: Große Zeitschriften habeneine Auflage von mehr als 100.000 Exemplaren! Neben einschlägigen Spiele-Maga-zinen wie GameStar, PC Games und ComputerBILD Spiele empfehlen sich auch dieKlassiker wie CHIP, PC WELT und PC Praxis. Schauen Sie sich am besten in einemgrößeren Zeitschriftenladen (Tipp: Bahnhofskiosk) um und schreiben Sie sich Adressenvon Magazinen heraus, die Ihnen gefallen und eine Cover-CD haben.

Egal, wohin Ihr Spiel geht, legen Sie auf jeden Fall eine universelle Einverständniser-klärung bei:

Das von mir entwickelte Spiel XYZ [eventuelle Ergänzung: in der Shareware-Ver-sion] darf von jedermann auf jeder Art von Medien, Datenträger wie Websites, un-eingeschränkt verbreitet werden. Eine Gebühr hierfür fällt nicht an. Es ist nichtnotwendig, eine Genehmigung einzuholen. Rechte Dritter bestehen nicht.

Datum, Unterschrift

0

Frank Surholt, www.computerbildspiele.de: »ComputerBILD Spiele bemüht sich,die attraktivsten Vollversionen und Demos seinen Lesern auf der Heft-CD-ROM an-zubieten. Spieleprogrammierer sind jederzeit eingeladen, uns ihre Produkte zur An-sicht zukommen zu lassen. Die Redaktion entscheidet dann nach Attraktivität, Genre,aktuellem Bezug und Platz auf der CD über die Verwendung des eingereichten Pro-gramms.«

Eine lohnenswerte Investition ist es, Ihr Spiel an das Redaktionsbüro Typemania zuschicken. Dieses stellt regelmäßig Zeitschriften mit Shareware und Freeware zusam-men und bespricht Programme auf einschlägigen Websites. Schicken Sie dazu eineMail an [email protected]. Nennen Sie Details zu Ihrem Spiel und ver-gessen Sie einen Download-Link nicht. Weitere Details erfahren Sie auf der Webseitewww.typemania.de.

Page 446: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

21

Verbreitungshilfen j e t z t l e r n e i c h

25.7.4 CD-ROMNicht mehr ganz so verbreitet wie in den frühen 90er Jahren sind CD-ROMs mit Free-ware- und Shareware-Spielen. Sie werden meistens für 5 bis 10 Euro vertrieben undenthalten ein Dutzend bis mehrere hundert Programme. Oftmals suchen sich die Leu-te, die diese CDs zusammenstellen, ihre Programme aus dem Netz. Dennoch empfehleich Ihnen, den oben genannten Verlagen auch die kostenlose Fassung eines Spiels zu-zusenden. Vergessen Sie nicht die Einverständniserklärung.

(Sollte zu diesem Buch eine aktualisierte Auflage erscheinen, kann natürlich IhrSpiel mit auf die CD. Senden Sie es mir einfach per Post zu: René Meyer, Naun-hofer Straße 40, 04299 Leipzig.)

25.7.5 PressearbeitNeben Mundpropaganda sind Journalisten eine preiswerte Möglichkeit, ein Spiel be-kannt zu machen. Schreiben Sie getrost Ihre Tageszeitung, Anzeigenblätter und Stadt-magazine an und weisen Sie auf Ihr Spiel hin. Redakteure suchen immer interessanteGeschichten und ein Computerspiel entsteht in Ihrem Wohnort bestimmt nicht alle Ta-ge. Nicht nur das Erscheinen eines Spiels selbst kann eine Nachricht für die Pressesein: Wenn Ihr Spiel auch in Spanien vertrieben wird oder einen interessanten Preisgewonnen hat, sollten Sie die Presse darauf hinweisen. Rufen Sie im Zweifelsfall vor-her an. So erfragen Sie das Interesse, erhalten einen geeigneten Ansprechpartner undkönnen sich später im Schreiben auf das Telefonat beziehen.

Kay Schönewerk, www.4imedia.com: »Der Weg über die Medien ist in vielen Fällendie kostengünstigere Möglichkeit, potenzielle Käufer zu erreichen – oder Ihr Spiel ein-fach nur bekannt zu machen. Und Medienarbeit ist sinnvoll. Denn ein Journalist, dersich positiv über Ihr Programm äußert, ist immer glaubwürdiger als Sie selbst, auchwenn der Redakteur exakt das Gleiche sagt. Für die Medienarbeit brauchen Sie einenso genannten Verteiler: Der Presseverteiler ist, simpel gesprochen, eine Sammlungvon Adressen und Namen, um den schnellen und effizienten Kontakt mit Ansprech-partnern in den Medien zu ermöglichen. Die Adressen dafür bekommen Sie aus demTelefonbuch und dem Impressum der jeweiligen Zeitung. In den meisten Städtenschickt auf Anfrage auch das Rathaus die Mediendaten zu.

Zudem sollten Sie die zu informierenden Medien nach Themenschwerpunkten unter-teilen – denn jedes Ressort braucht andere Informationen: Der Lokalredakteur hateine andere Sichtweise als der Vertreter der Wirtschaftsredaktion. Ihn interessiert derLokalbezug: In welchem Stadtteil sitzt der Programmierer? Kommt er von der örtli-chen Universität oder dem Gymnasium aus dem Nachbarort? Der Wirtschaftsredak-teur interessiert sich dagegen mehr für strategische Fragen: Soll das Programm ver-kauft werden? Erobert das Spiel vielleicht eine Marktlücke? Wieder anders nähert sichder Computer-Fachjournalist dem Thema. Ihn interessieren Details der Programmie-rung.

Bei den Tageszeitungen sollten Sie darauf achten, dass die Pressemitteilung am Vor-mittag eingeht, damit sie noch ins Blatt des Folgetags kommt. Und verlassen Sie sichnicht darauf, dass die Mitteilung von so weltbewegender Bedeutung ist. Im Zweifelfällt sie unter den Tisch, wenn sie zu spät kommt. Im Regelfall bringt die Zeitung siedann auch nicht mehr am übernächsten Tag, denn dann ist sie bereits veraltet.«

Page 447: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

22

Vertriebsformen von Spielen25j e t z t l e r n e i c h

Auch an einschlägige Fachzeitschriften sollten Sie Ihr Spiel schicken, mit der Bitte, esvorzustellen. Legen Sie eine Pressemeldung bei – ein A4-Blatt mit Ihrer Adresse, denVorzügen Ihres Spiels und einer kurzen Beschreibung des Inhalts. Seien Sie aber nichtenttäuscht, wenn kein Beitrag erscheint: Die Redaktionen werden überschüttet mitSpielen und bereits mit den Neuerscheinungen auf dem Vollpreisniveau lässt sich eineZeitschrift füllen.

Abb. 25.6:Pressemeldun-

gen bieten Jour-nalisten eine Zu-sammenfassungzu einem Spiel.Sie werden per

Mail und alsBriefpost ver-

schickt. Wichtigist die Angabedes Ansprech-

partners.

Page 448: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

23

Verbreitungshilfen j e t z t l e r n e i c h

Verlassen Sie sich in der Vermarktung Ihres Spiels nicht nur auf Gedrucktes. Auch Ra-diosender haben Computersendungen. So stellt etwa der überregionale Sender JAMFM (www.jamfm.de), im Übrigen der einzige, den der Autor seit Jahren hört :-), regel-mäßig Software und Websites vor. Oftmals haben TV- und Radiosender auf ihren Web-sites eine Multimedia-Rubrik mit Spielen zum Download. Eine besondere Empfehlunggeht hierbei an die TV-Sendung Giga Games (www.giga.de). Die Spielevorstellungenerzielen eine hohe Aufmerksamkeit; die Website hat mehrere Millionen Besucher imMonat. Kehrseite der Medaille: Die Anforderungen für eine Vorstellung sind natürlichbesonders hoch.

25.7.6 PR-AgenturNicht jedem ist der Umgang mit Journalisten vertraut und das Schreiben guter Presse-meldungen beherrschen nur wenige. Viele Unternehmen arbeiten deshalb mit PR-Agenturen zusammen. Eine PR-Agentur (Public Relations, »Öffentliche Beziehungen«)stellt die Schnittstelle zur Presse dar. Sie nimmt Telefonate von Journalisten entgegen,verwaltet Presseverteiler, versendet Testmuster.

Meistens werden zwei Listen geführt: Redaktionen, die viele Spiele vorstellen, erhaltenjeden Titel unaufgefordert zugeschickt. Bei Top-Spielen gibt es meistens nicht nur einePressemeldung, sondern eine kleine Mappe mit mehreren Texten (Überblick, Hinter-grund, Interview, Making of ...) sowie eine CD-ROM mit Screenshots. Journalisten, dieweniger oft Spiele besprechen, wird zunächst nur eine Pressemeldung gesandt, mitdem Angebot, sich (kostenfrei) eine Vollversion als Testmuster zu bestellen.

Große Verleger lassen ganze Pressekonferenzen und Partys von Agenturen organisie-ren. Bei Spielen, die noch in der Entwicklung sind, werden Präsentationsbesuche mitden Redaktionen vereinbart. Diese Dienstleistung kostet freilich viel Geld und kommtfür Hobbyentwickler in der Regel nicht in Frage.

Kay Schönewerk, www.4imedia.com: »Falsch machen können Sie beim Umgangmit Journalisten viel. Nachfolgend daher einige Fehler und wie Sie sie umgehen.

Fehlerquelle 1: Unkenntnis. Wenn Sie mit einer Redaktion Kontakt aufnehmen,ohne die grundlegenden Informationen eingeholt zu haben, blamieren Sie sich. Be-sonders entlarvend sind Fragen in der Art von »Wie oft erscheinen Sie denn?« oder»Gibt es bei Ihnen auch einen Computerteil?«

Fehlerquelle 2: Irrläufer. In der schnelllebigen Medienwelt ändern sich die Zuständig-keiten häufig. Wenn Ihre gesammelten Faxnummern und Mailadressen der Mediennicht aktuell sind, verhallt auch die beste Botschaft ungehört.

Fehlerquelle 3: Berufsehre. Wenn Sie einem Journalisten zu verstehen geben, dassSie seinen Artikel nur als Werbung für sich sehen, dann zeigen Sie ihm, dass Sie seineTexte als beliebig schaltbare und obendrein noch kostenlose Anzeige betrachten.Dies spricht gegen seine Unabhängigkeit und kränkt ihn in seiner Berufsehre.

Fehlerquelle 4: Übertreibung. »Die absolute Weltneuheit«, »das Superprogramm«,»das revolutionäre Spiel« – nichtssagende Werbefloskeln und Anpreisungen im Ba-sarstil erwecken den Eindruck, dass Sie tatsächlich nichts zu sagen haben.

Fehlerquelle 5: Deutschfehler. Das Handwerk der Journalisten ist die Sprache. Des-halb reagieren sie besonders empfindlich auf Schlampereien. Achten Sie in Presse-mitteilungen peinlichst auf Rechtschreib- und Grammatikfehler.

Page 449: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

24

Vertriebsformen von Spielen25j e t z t l e r n e i c h

Manche Agentur leistet mehr als Pressearbeit: Between Us! (www.betweenus.de) etwasucht für Spieleprojekte den passenden Abnehmer, führt also Entwickler und Verlegerzusammen.

25.8 Beruf Spieleentwickler?

Möglicherweise ist Ihr Hobby der Einstieg zu einer Karriere als Profi – entweder im ei-genen Unternehmen oder als Programmierer, Grafiker oder Spieledesigner bei einemetablierten Entwicklungsstudio. Dort zählen als Eignungsnachweis weniger ein abge-schlossenes Studium oder absolvierte Kurse. Maßgeblich ist das Können, das am bes-ten durch eigene Arbeiten wie Zeichnungen und Demos unter Beweis gestellt wird. Essind Fälle bekannt, wo Hobbyautoren mit ihren Shareware-Spielen so gut verdienen,dass sie davon leben können, wo fantasievoll gestaltete Zusatzlevels die Eintrittskartewaren für eine Einstellung bei einem amerikanischen Entwicklungsstudio. Die texani-sche Spieleschmiede id Software, bekannt durch ihre »Doom«- und »Quake«-Serien,fing Anfang der 90er Jahre schlicht an: mit kleinen, allerdings unterhaltsamen Share-ware-Spielen wie die heute legendäre »Commander Keen«-Reihe.

Dennoch: Die Branche ist knallhart, die Verdienstaussichten sind eher gering. Geradein Deutschland ist der Drang, für Software Geld zu bezahlen, besonders gering. Eskann passieren, dass Ihr Shareware-Spiel viele tausend Mal heruntergeladen wird unddennoch nur eine Handvoll an Registrierungen eintrudeln. Halten Sie sich nur eins vorAugen: Sie können nichts verlieren. Viele Hobbys verursachen Kosten. Als Program-mierer investieren Sie nur Ihre Arbeitskraft. Und möglicherweise ergibt sich daraus einnetter Nebenverdienst.

Elvira von Eichborn, www.betweenus.de: »Eine PR-Agentur kann individuell auf ei-nen freien Entwickler oder ein kleines Team eingehen. Da es häufig an Erfahrungenmit Publishern und strategischen Maßnahmen mangelt, steht zuerst eine Beratungüber die Abläufe an. Das Verfassen und Verbreiten von Pressemeldungen ist dernächste Schritt. Telefonische Auskünfte und regelmäßiger Kontakt per E-Mail zu denJournalisten sind wichtige Faktoren. Eine PR-Agentur kann außerdem den Versandvon Testmustern steuern und die Presse-Clippings (eine Sammlung von Artikeln, dieüber ein Produkt oder Unternehmen erschienen sind) erstellen. Die Vergütung derDienstleistungen richtet sich nach den individuellen Wünschen des Auftraggebers. Inder Regel werden auch Porto-, Verpackungs- und Reisekosten vom Kunden getra-gen.«

Marc Kamradt, www.spieleentwickler.org: »Eine eigene Firma ins Leben zu rufen,ist keine leichte Aufgabe. Die Freiheit, der eigene Chef zu sein, wird von dem Mehr-aufwand, den eine solche Firmengründung mit sich bringt, meist mehr als wett-gemacht. Die eigene kleine Spieleschmiede ist sicher der Traum der Selbstverwirk-lichung, verlangt aber neben dem ohnehin schon hohen Aufwand der Softwareent-wicklung noch viel Aufmerksamkeit für betriebswirtschaftliche Aufgaben. Mindestensdie folgenden Punkte sollten Sie daher beherzigen.

Page 450: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

25

Beruf Spieleentwickler? j e t z t l e r n e i c h

Eine der wichtigsten Voraussetzungen ist die Auftragslage. Mindestens einen festenAuftraggeber oder Abnehmer für das eigene Spiel sollten Sie haben. Dies erreichtman jedoch meistens nur durch die Präsentation eines Prototyps bei einem Publisher.Mit einem Konzept allein kommt man nur in den seltensten Fällen zum Ziel. Die Ar-beit an dem Prototypen muss man aus eigener Tasche finanzieren und nicht seltenfindet man am Ende überhaupt keinen Abnehmer.

Hand in Hand mit dem ersten festen Auftrag geht das Vorhandensein eines gut funk-tionierenden Teams, welches sich nicht erst zur eigentlichen Firmengründung zusam-menfinden sollte. Der größte Teil der Beteiligten sollte sich bereits vom einen oder an-deren gemeinsamen Projekt her kennen. Von den an einem Projekt arbeitendenPersonen hängt der Erfolg der Firma ab und gerade bei einer Neugründung hat manoft keine Reserven für Fehlschläge.

Sowohl beim Arbeitsamt als auch bei der Industrie- und Handelskammer (IHK,www.ihk.de) sollten Sie sich über die Gründung und Leitung einer Firma informie-ren. Dort werden Existenzgründerseminare angeboten und es kann so genanntesÜberbrückungsgeld als Starthilfe beantragt werden.«

Marco Sowa, www.enjoy-e.de: »Wer sich als Spieleverleger selbständig machen will,benötigt Startkapital, viel Glück und mindestens ein Produkt, das sich vermarktenlässt. Das kann ein eigenes oder ein fremdes sein. Da die Chance sehr gering ist, anöffentliches Geld, Kredite (ohne Absicherungen) oder Venture Capital zu kommen,bleibt meistens nur die Eigenfinanzierung der Idee, bis Einnahmen kommen. Über-treiben Sie es am Anfang nicht. Ein teures »Office« muss nicht sein. Jungunterneh-mer-Büros tun es für die erste Zeit auch, sind günstig und haben kurze Kündigungs-fristen. Das Gründen einer GmbH bedeutet erhöhten Aufwand, zum Beispiel bei derSteuererklärung, vermindert aber das Haftungsrisiko. Und die Bezeichnung lässt dieUnternehmung größer klingen, als sie vielleicht ist. Das kann bei Verhandlungen vonVorteil sein. Bringen Sie über einen Distributor ein oder zwei Spiele auf den Markt.Sind sie gut gelaufen, ist es möglich, mit ausführlichen Konzepten an Publisher her-anzutreten und zu versuchen, Entwicklungen zum Teil finanziert zu bekommen. DieBranche ist nicht einfach. Aber mit viel Arbeit, Elan und dem nötigen Glück könnenSie auf lange Sicht Erfolg haben.«

Page 451: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

1

jetz

t le

rne

ich

Lösungen zu den Aufgaben

Kapitel 1: Die ersten Schritte1. Wo hat sich im Editor die Rückgängig-Funktion (Undo) versteckt?

Drücken Sie Ÿ+Z, um eine eben vorgenommene Lösung rückgängig zu machen.

2. Was ist ein String?

Ein String ist eine Zeichenkette, eine Folge von Buchstaben, Ziffern und Sonderzei-chen. Er wird in einer String-Variable gespeichert, die als Kennung ein $ erhält. Stringssetzen Sie immer in Anführungsstriche: Print "Hallo!"

3. Schreiben Sie ein Programm, das den Nutzer nach seinem Namen fragtund ihn dann persönlich begrüßt.

Name$ = Input("Wie heißen Sie? ")Print "Guten Tag, " + Name$ + "."WaitKey

4. Schreiben Sie ein Programm, das nach der Kantenlänge eines Würfelsfragt. Berechnen Sie daraus das Volumen des Würfels. (Hinweis: Das Volu-men entspricht der Seitenlänge hoch 3.)

Kante = Input$("Geben Sie die Kantenlänge ein: ")Volumen = Kante * Kante * KantePrint "Das Volumen beträgt " + Volumen + "."WaitKey

5. Womit legen Sie fest, ob ein Programm im Windows-Fenster oder imVollbild läuft?

Übergeben Sie dem Befehl Graphics neben der Fenstergröße und der Farbtiefe einenFensterparameter: 0 – Vollbild (Fenster im Debug-Modus), 1 – immer Vollbild, 2 – Fens-ter, 3 – Fenster mit veränderbaren Maßen. Beispiel:

Graphics 640,480,0,2

Page 452: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

2

Lösungen zu den Aufgabenj e t z t l e r n e i c h

Kapitel 2: Die Grundpfeilen von Programmen1. Was ist der maßgebliche Unterschied zwischen einer Repeat/Until- undeiner While/Wend-Schleife?

Bei Repeat werden die Abbruch-Bedingungen am Schluss der Schleife geprüft. BeiWhile bereits am Anfang. Eine Repeat-Schleife wird mindestens einmal durchlaufen.Wird die Abbruchbedingung bei While bereits vor dem ersten Durchlauf erfüllt, wird dieSchleife nie ausgeführt:

While 1=2 Print "Hallo"WendWaitKey

2. Womit programmieren Sie eine Schleife, die nie enden soll?

Sie verwenden eine Abbruchbedingung, die nie wahr wird, zum Beispiel 1=2. Oder Sieverwenden Repeat/Forever:

Repeat If KeyHit(1) Then EndForever

3. Schreiben Sie ein Programm, das die Zahlen 1 bis 100 auf den Bild-schirm druckt. Dabei sollen jeweils 10 Zahlen auf einer Zeile stehen.

For I=1 To 100 Step 10 For J=0 To 9 Write I + J + " " Next Print ""Next WaitKey

Kapitel 3: Variablen1. Programmieren Sie eine kleine Adressbuch-Verwaltung. Sie soll einer-seits das Eingeben von Name, Vorname und Telefonnummer erlauben. An-dererseits soll sie auf die Eingabe eines Namens warten und die dazugehö-rige Nummer ausgeben.

; ADRESSEN.BBDim Adressen$(100,2)Repeat Print "1 - Adresse eingeben" Print "2 - Adresse abfragen" Print "3 - Ende" Wahl = Input("Ihre Wahl: ") Select Wahl Case 1 Index = Index + 1 Adressen$(Index,0) = Input("Telefonnummer: ") Adressen$(Index,1) = Input("Vorname: ") Adressen$(Index,2) = Input("Nachname: ") Case 2 Gefunden = 0 Suche$ = Input("Nachnamen eingeben: ") For I=1 To Index

Page 453: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

3

Lösungen zu den Aufgaben j e t z t l e r n e i c h

If Adressen$(I,2) = Suche$ Then Print Adressen$(I,1) + " " + Adressen$(I,2) + " - " + Adressen$(I,0) Gefunden = 1 EndIf Next If Gefunden = 0 Then Print "Kein Eintrag gefunden" Case 3 End Default Print "Ungültige Wahl!" End Select Print "Taste drücken." WaitKeyForever

2. Durch welche Kürzel weisen Sie einer Variable den Typ Zeichenkette,Ganz- und Fließkommazahl zu? Wie verwandeln Sie Daten von einem Typin den anderen um?

$, # und % kennzeichnen Variablen für Strings, Ganz- und Fließkomma-Zahlen. MitStr$(), Int() und Float() wandeln Sie in den gewünschten Typ um:

Y = 5X$ = Str$(Y)

Blitz Basic konvertiert automatisch, wo immer es möglich ist. Erlaubt ist etwa:

Y = 5X$ = Y

wodurch X$ den Inhalt »5« bekommt.

Kapitel 4: Zahlen und Zeichenketten«1. Schreiben Sie eine Funktion, die ausdrückt, wie oft jeder Buchstabe ineiner beliebigen Zeichenkette enthalten ist.

; BUCHSTABEN.BBDim Buchstaben(255)Wort$ = Input("Geben Sie ein Wort ein: ")BuchstabenZaehlen(Wort$)WaitKey;Function BuchstabenZaehlen$(Wort$)For I=1 To Len(Wort$) A = Asc (Mid$(Wort$,I,1)) Buchstaben(A) = Buchstaben(A) + 1Next

For I= 1 To 255 If Buchstaben(I) <> 0 Then Print Chr$(I) + " = " + Buchstaben(I) + "x"NextEnd Function

2. Erweitern Sie das Programm WÜRFEL.BB so, dass der Würfelvorgangwiederholt wird. Der Punktestand soll gespeichert und bei jedem Durch-gang ausgedruckt werden.

Sie finden die Lösung im Programm WÜRFEL2.BB.

Page 454: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

4

Lösungen zu den Aufgabenj e t z t l e r n e i c h

3. Erweitern Sie das Programm GLÜCKSRAD.BB um folgende Funktionen:

3a. Groß- und Kleinschreibung sollte nicht beachtet werden.

Gleichen Sie Suchbegriff und Eingabe mit Lower$() oder Upper$() einander an:

Eingabe$ = Lower$(Left$(Eingabe$,1))

3b. Kommt ein Buchstabe im Wort mehrfach vor, dann sollen alle Vorkom-men aufgedeckt werden. Im Moment können solche Wörter (wie »weber«)nicht gefunden werden .

Das lässt sich mit String-Befehlen gut lösen. Diese Methode ist recht übersichtlich:

Dim Buchstaben$(20)For I = 1 To 20 Buchstaben$(I) = "*"Next...Geraten$ = ""For I=1 To Len(Wort$) If Eingabe$ = Mid$(Wort$,I,1) Then Buchstaben$(I) = Mid$(Wort$,I,1) Geraten$ = Geraten$ + Buchstaben$(I)Next

3c. Das Programm soll die mehrfache Eingabe eines Buchstabens zurück-weisen.

Eine einfache Lösung könnte so aussehen:

Repeat Eingabe$ = Input("Welcher Buchstabe fehlt: ") Eingabe$ = Lower$(Left$(Eingabe$,1))Until Instr(Probiert$,Eingabe$) = 0Probiert$ = Probiert + Eingabe$

Das komplette Programm finden Sie in der Datei GLÜCKSRAD2.BB.

Kapitel 5: Arbeiten im Grafikmodus1. Erläutern Sie Vor- und Nachteile einer hohen und einer niedrigen Bild-schirm-Auflösung.

Hohe Auflösung: Viele Details, viele Objekte passen auf den Bildschirm. Dafür größe-rer Speicherverbrauch der Bilder, höherer Rechenaufwand. Niedrige Auflösung: Bilderkönnen »pixelig« werden, niedriger Rechenaufwand; Programme laufen auch auf lang-samen PCs.

2. Beschreiben Sie das Prinzip des Double Buffering.

Es gibt zwei Bildschirmseiten. Gezeichnet wird auf der Rückseite. Ist das Bild fertig,wird der Inhalt beider Seiten blitzschnell vertauscht. Das Bild wird somit sehr schnellund synchron zur Darstellung des Monitors angezeigt.

3. Nennen Sie die Unterschiede zwischen Blitz Basic (3D) und Blitz Plusbeim Initialisieren des Grafikmodus und die Konsequenzen für Ihre Pro-gramme.

Page 455: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

5

Lösungen zu den Aufgaben j e t z t l e r n e i c h

In Blitz Basic kann in den Frontpuffer gezeichnet werden. Grafikbefehle zeigen sofortWirkung. In Blitz Basic kann nur in den Backpuffer gezeichnet werden, der standard-mäßig aktiviert ist. Flip ist daher notwendig.

Kapitel 6: Zeichnen1. Zeichnen Sie im Grafikmodus eine Sinus-Kurve.

In den Programmen SINUSKURVE1.BB und SINUSKURVE2.BB finden Sie Beispiele.

2. Zeichnen Sie ein Oval, das alle vier Seiten des Bildschirms berührt.

Graphics 640,480SetBuffer BackBuffer()ClsOval 0,0, 640,480,0FlipWaitKey

3. Erweitern Sie das Haus-Beispiel um eine kleine Animation, etwa ein vor-beifahrendes Auto (wofür ein Rechteck genügt).

Sie finden ein Beispiel in der Datei HAUS3.BB.

Kapitel 7: Bilder1. Erstellen Sie ein Bild in der Größe 640 x 480. Als Motiv verwenden Sie100 zufällig platzierte Kuhköpfe vor einem grünen Hintergrund. SpeichernSie das Bild als Bitmap-Datei auf der Festplatte ab.

; KUH11.BBGraphics 640,480bild = CreateImage(640,480)kuh = LoadImage("cow.bmp")SetBuffer ImageBuffer(bild)For I=1 To 100 DrawImage kuh, Rand(0,600), Rand(0,440)NextSaveImage bild, "c:\100kühe.bmp"

Kapitel 8: Sichtfenster und Aufsätze1. Teilen Sie den Bildschirm durch eine Mittellinie in zwei gleich große Be-reiche. Füllen Sie jeden Teilbereich mit einem (riesigen) Kuhkopf aus.

In die Irre geführt! Für die Lösung genügen ResizeImage und DrawImage.

; KUH12.BBGraphics 640,480kuh = LoadImage("cow.bmp")ResizeImage kuh, 319, 479Line 320,0,320,480DrawImage kuh, 0,0DrawImage kuh, 321,0WaitKey

Page 456: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

6

Lösungen zu den Aufgabenj e t z t l e r n e i c h

Kapitel 9: Pixeleien1. Schreiben Sie ein Programm, das in eine Hälfte des Bildschirms zufälligerzeugte bunte Vierecke malt. Erzeugen Sie mit Hilfe der Pixel-Befehle da-nach eine Kopie der Ausgabe auf der anderen Hälfte des Schirms.

; READPIXEL.BBGraphics 640,480Line 320,0,320,480Viewport 0,0,319,479

For I=1 To 100 Color Rand(0,255), Rand(0,255), Rand(0,255) Rect Rand(0,319), Rand(0,479), 30,30Next

Viewport 0,0,640,480For J=0 To 479 For I=0 To 319 RGB = ReadPixel(I,J) WritePixel I + 321, J, RGB, FrontBuffer() NextNextWaitKey

Kapitel 10: Text und Fonts1. Schreiben Sie ein Programm, das einen kreisförmigen Text auf den Bild-schirm zaubert. Oberer Teil: »Mit diesem Buch«. Unterer Teil: »habe ich vielgelernt!«

Die Lösung steht in der Datei SINUSTEXT.BB.

Kapitel 11: Maus abfragen1. Schreiben Sie ein kleines Spiel, das für anderthalb Sekunden ein Qua-drat entweder in der linken oder in der rechten Hälfte des Bildschirms er-scheinen lässt. Der Spieler bekommt einen Punkt, wenn er in der Zeit, inder das Quadrat sichtbar ist, für das Erscheinen in der linken Hälfte die lin-ke und für das Erscheinen in der rechten Hälfte die rechte Maustaste drückt– beziehungsweise einen Minuspunkt, wenn er zu spät oder falsch klickt.

; QUADRATE.BBGraphics 640,480SetBuffer BackBuffer()SeedRnd MilliSecs()

Repeat Cls Text 0,0, Punkte + " Punkte" Line 320,0,320,480 Seite = Rand(0,1) Rect Rand(325 * Seite, 265 * (Seite+1)), Rand(0,420), 50,50,0 Flip

Punkt = 0

Page 457: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

7

Lösungen zu den Aufgaben j e t z t l e r n e i c h

Start = MilliSecs() Repeat If MouseDown(Seite + 1) Then Punkt = 1 Until Start + 1500 < MilliSecs()

If Punkt = 1 Then Punkte = Punkte + 1 Else Punkte = Punkte - 1 EndIfUntil KeyHit(1)

Kapitel 12: Tastatur abfragen1. Schreiben Sie ein kleines Spiel, das alle paar Sekunden einen zufälligausgewählten Buchstaben auf dem Bildschirm erscheinen lässt. Alle Buch-staben addieren sich zu einer immer länger werdenden Zeichenkette. DerSpieler muss schnell die jeweiligen Tasten drücken, um einen Buchstabenzu entfernen und die Schlange damit kürzer werden zu lassen.

Schlüsselstelle ist das Löschen eines Zeichens aus einer Zeichenkette, das sich mit ver-schiedenen Methoden umsetzen lässt. Zu beachten ist, dass immer nur ein Buchstabeentfernt werden soll, auch wenn das Zeichen vielleicht mehrfach auf dem Bildschirm zusehen ist.

; TIPPEX.BBGraphics 640,480SetBuffer BackBuffer()font = LoadFont("Courier",50)SetFont fontSeedRnd MilliSecs()

Repeat If Start + 1000 < MilliSecs() Then If Len(Wort$) = 25 Then End Start = MilliSecs() Buchstabe$ = Chr$(Rand(65,90)) Wort$ = Wort$ + Buchstabe$ EndIf

Cls Text 50,200, Wort$ Taste = GetKey() Zeichen$ = Upper$(Chr$(Taste)) Ort = Instr(Wort$, Zeichen$)

If Ort > 0 Then SchonWeg = 0 NeuesWort$ = ""

For I=1 To Len(Wort$) If (Mid$(Wort$,I,1) <> Zeichen$) Or SchonWeg = 1 Then NeuesWort$ = NeuesWort$ + Mid$(Wort$,I,1) Else SchonWeg = 1 EndIf Next

Page 458: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

8

Lösungen zu den Aufgabenj e t z t l e r n e i c h

Wort$ = NeuesWort$ EndIf FlipUntil KeyHit(1)

Kapitel 13: Joystick abfragen1. Beschreiben Sie den Unterschied zwischen einem digitalen und einemanalogen Joystick.

Ein digitaler Joystick erkennt nur, ob eine Taste oder ein Hebel gedrückt ist. Die Inten-sität muss daher anhand der Dauer ermittelt werden. Ein analoger Joystick nennt Da-ten, die Aufschluss über die Kräftigkeit des Drückens geben.

Kapitel 14: Töne und Musik1. Schreiben Sie ein Programm, das einen Klang fortlaufend abspielt. PerTastendruck kann der Nutzer Lautstärke, Tonhöhe und Balance ändern.Zeigen Sie die Werte optisch – zum Beispiel mit einem Balken – auf demBildschirm an.

Das Programm liegt im Quelltext MUSIKREGLER.BB vor. Die drei Parameter werden mitden Zahlentasten auf dem Ziffernblock gesteuert.

Kapitel 15: Videos1. Schreiben Sie ein kleines Programm, das ein festgelegtes Video lädt undabspielt. Mit Tastendrücken kann das Video pausiert, fortgesetzt oder vonvorn begonnen werden.

Die Lösung finden Sie in der Datei VIDEO4.BB.

Kapitel 16: Dateien1. Schreiben Sie ein Programm, das alle Ordnernamen im Windows-Ver-zeichnis ausliest und in eine Datei auf der Festplatte speichert.

; ORDNER3.BBordner = ReadDir(SystemProperty$("WINDOWSDIR"))datei = WriteFile("c:\dateien.txt")Repeat Name$ = NextFile(Ordner) If Name$ <> "" And FileType(SystemProperty$("WINDOWSDIR") + Name$) = 2 Then WriteLine datei, Name$ EndIfUntil Name$ = ""CloseDir(Ordner)

2. Schreiben Sie ein kleines Quiz-Spiel. Die Fragen und Lösungen sollenaus einer Textdatei gelesen werden. Sie können die Datei QUIZ.TXT nut-zen, die sich auf der Buch-CD befindet. Sie enthält einige Quizfragen rundum die Welt des Kinos. Keine Frage soll zweimal gestellt werden.

Ein Beispiel wartet in der Datei QUIZ.BB.

Page 459: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

9

Lösungen zu den Aufgaben j e t z t l e r n e i c h

Kapitel 17: Datenaustausch im Netzwerk1. Schreiben Sie ein Chat-Programm für zwei Personen. Jede sieht ihrenText auf einer Hälfte des Bildschirms und den Text des Partners auf der an-deren Seite.

Die Aufgabe lässt sich mit DirectPlay, UDP und TCP umsetzen. Ein Beispiel mit TCPfinden Sie in der Datei MINICHAT.BB. Auf dem Client-PC muss die IP-Adresse des Hostsin den Quelltext eingetragen werden.

Kapitel 18: 3D-Grafik mit Blitz Basic 3D1. Erstellen Sie ein Terrain. Setzen Sie eine Handvoll verschiedenfarbigerPrimitives an zufällige Positionen. Schreiben Sie eine Kamerasteuerung,die in der oberen Hälfte des Bildschirms nach vorn und in der unteren Hälf-te nach hinten (wie bei einem Rückspiegel) schaut.

Ein entsprechendes Programm wurde als TERRAIN2.BB abgelegt.

Kapitel 19: Bedienoberflächen mit Blitz Plus1. Schreiben Sie ein Formular, das Felder für eine Postadresse (Name,Straße, Ort) bietet. Die Adresse wird per Schalterdruck in einer Datei ab-gespeichert und mit einem zweiten Schalter wieder aus der Datei geladenund in das Formular eingefügt.

Eine einfache Lösung finden Sie im Programm FORMULAR.BB. Sie ist nicht für mehrereAdressen geeignet, lässt sich freilich ausbauen.

2. Schreiben Sie einen einfachen Web-Browser, der beliebige WWW-Seitenanzeigt und per Schalter »Vorwärts« und »Rückwärts« geht.

; BROWSER.BBfenster = CreateWindow ("Brower", 0,0, 1024,768)schalter_go = CreateButton ("Go", 360,5, 30,20, fenster, 1)schalter_vorwaerts = CreateButton ("Vorwärts", 500,5, 70,20, fenster, 1)schalter_zurueck = CreateButton ("Zurück", 600,5, 70,20, fenster, 1)schalter_ende = CreateButton ("Ende", 950,5, 50,20, fenster, 1)eingabe = CreateTextField (50,5, 300,20, fenster)SetGadgetText eingabe, "http://"html = CreateHtmlView (0,50, 1024,700, fenster)

Repeat ereignis = WaitEvent() quelle = EventSource()

If ereignis = $401 And quelle = eingabe And EventData() = 13 Then HtmlViewGo html,TextFieldText$(eingabe) If ereignis = $401 And quelle = schalter_go Then HtmlViewGo html,TextField-Text(eingabe) If ereignis = $401 And quelle = schalter_vorwaerts Then HtmlViewForward html If ereignis = $401 And quelle = schalter_zurueck Then HtmlViewBack html If ereignis = $401 And quelle = schalter_ende Then End If ereignis = $803 Then End Until KeyHit(1)

Page 460: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

1

jetz

t le

rne

ich

Menüpunkte des Editors

Da die englische Bedienerführung des Editors manchem Kopfzerbrechen bereitet, fin-den Sie hier eine Beschreibung aller Funktionen. Gewöhnen Sie sich an, die Punkteüber ihre Kurztasten zu erreichen; so geht es viel schneller.

Zwei Funktionen können nicht oft genug genannt werden: Ÿ+Z macht die letzteAktion rückgängig. Zweimal É über einem Befehl öffnet ein Hilfefenster mit einerdetaillierten Beschreibung.

Das Debug-Menü ist in neueren Versionen entfallen. Es wird als Symbolleiste in einemExtrafenster eingeblendet, sobald ein Programm im Debug-Modus gestartet wird.

Menü FILE

NEW (Ÿ+N)

öffnet ein leeres Fenster zum Erstellen eines neuen Programms

OPEN (Ÿ+O)

lädt ein vorhandenes Programm in ein Fenster

CLOSE (Ÿ+Ì)

schließt das aktuelle Fenster

CLOSE ALL

schließt alle Fenster

SAVE (Ÿ+S)

speichert den Inhalt des aktuellen Programms auf Festplatte

SAVE AS ...

speichert den Inhalt des aktuellen Programms unter einem anderen Namen

Page 461: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

2

Menüpunkte des Editorsj e t z t l e r n e i c h

SAVE ALL

speichert alle geöffneten Fenster

NEXT FILE (Ÿ+Å)

aktiviert das nächste geöffnete Fenster

PREVIOUS FILE (Ÿ+Á+Ì)

aktiviert das nächste geöffnete Fenster

RECENT FILES

zeigt eine Liste vorher geöffneter Dateien an

PRINT

druckt den Inhalt des aktuellen Fensters aus

EXIT

beendet Blitz Basic

Menü EDIT

CUT (Ÿ+X)

schneidet den markierten Text aus und verschiebt ihn in die Zwischenablage

COPY (Ÿ+C)

kopiert den markierten Text in die Zwischenablage

PASTE (Ÿ+V)

fügt den Text aus der Zwischenablage in das aktuelle Fenster ein

SELECT ALL (Ÿ+A)

markiert den gesamten Text im aktuellen Fenster

FIND (Ÿ+F)

durchsucht den Text im aktuellen Fenster nach einer Zeichenkette

FIND NEXT (Ë)

springt zur nächsten Fundstelle der mit FIND festgelegten Zeichenkette

REPLACE (Ÿ+R)

ersetzt eine Zeichenkette im Textfenster durch eine andere

SHOW TOOLBARS? (Á+È)

Symbolleiste zum schnellen Erreichen wichtiger Menüpunkte – ein/aus

Page 462: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

3

Menüpunkte des Editors j e t z t l e r n e i c h

Menü PROGRAM

RUN PROGRAM (Í)

startet das Programm im aktuellen Fenster

RUN PROGRAM (Î)

startet das Programm im aktuellen Fenster noch einmal

CHECK FOR ERRORS (Ï)

überprüft das Programm im aktuellen Fenster auf Syntaxfehler

CREATE EXECUTABLE

erzeugt vom Programm im aktuellen Fenster eine selbst ablaufende EXE-Datei (nurin der Vollversion von Blitz Basic verfügbar)

PROGRAM COMMAND LINE ...

übergibt Kommandozeilenparameter an das Programm

DEBUG ENABLED?

ergänzt den Programmcode um zusätzliche Informationen für leichtere Fehlersu-che – ein/aus

Menü DEBUG

STOP

hält das Programm vorübergehend an

STEP OVER

führt den nächsten Einzelbefehl oder die nächste Funktion (komplett) aus; hält dasProgramm danach an

STEP INTO

führt den nächsten Einzelbefehl (auch innerhalb einer Funktion) aus; hält das Pro-gramm danach an

STEP OUT

führt alle folgenden Befehle der derzeit laufenden Funktionen auf einmal aus; hältdas Programm danach an

CONTINUE

setzt das Programm normal fort, bis zum Ende (oder bis der Befehl Stop erreichtwird)

END (Á+Í)

beendet das Programm

Page 463: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

4

Menüpunkte des Editorsj e t z t l e r n e i c h

Menü HELP

HOME (Ÿ+H)

öffnet das Hilfe-Fenster von Blitz Basic

BACK

eine Seite zurück in der Hilfe

FORWARD

eine Seite vor in der Hilfe

QUICK COMMAND HELP (É)

beim ersten Anwählen Syntaxbeschreibung, beim zweiten Anwählen detaillierteHilfe des Befehls unter dem Cursor

ABOUT BLITZ!

Copyright-Anzeige

Page 464: Jetzt lerne ich Spiele programmieren mit Blitz Basic  GERMAN

Copyright Daten, Texte, Design und Grafiken dieses eBooks, sowie die eventuell angebotenen

eBook-Zusatzdaten sind urheberrechtlich geschützt. Dieses eBook stellen wir lediglich als persönliche Einzelplatz-Lizenz zur Verfügung!

Jede andere Verwendung dieses eBooks oder zugehöriger Materialien und Informationen, einschliesslich

• der Reproduktion,

• der Weitergabe,

• des Weitervertriebs,

• der Platzierung im Internet, in Intranets, in Extranets,

• der Veränderung,

• des Weiterverkaufs

• und der Veröffentlichung

bedarf der schriftlichen Genehmigung des Verlags. Insbesondere ist die Entfernung oder Änderung des vom Verlag vergebenen

Passwortschutzes ausdrücklich untersagt!

Bei Fragen zu diesem Thema wenden Sie sich bitte an: [email protected]

Zusatzdaten Möglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die

Zurverfügungstellung dieser Daten auf unseren Websites ist eine freiwillige Leistung des Verlags. Der Rechtsweg ist ausgeschlossen.

Hinweis Dieses und viele weitere eBooks können Sie rund um die Uhr

und legal auf unserer Website

http://www.informit.de

herunterladen