Aus Dateien einlesen
Andreas Löffler aka GD^CRAZY
http://www.unitedbytes.de
mail: gd_crazy@gmx.net
oder: andi@unitedbytes.de
==============================
Datum: 4.8.99
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ Einleitung ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Moins! Hier bin ich wieder mit meinem 3. Tutorial. Nachdem das
1. und 2. Tutorial (gibts unter www.unitedbytes.de) fast niemanden
interessiert hattte, wollte ich eigentlich mit dieser Serie aufhren,
denn was bringt es, Tutorials zu schreiben fr die sich eh keiner
interessiert? *g*
Wenn da aber das Wrtchen *FAST* nicht wr ... einige Personen (darunter
auch Prometheus und Dragen!) interessieren sich komischerweise fr diese
wirklich miserablen, schlechtgeschriebenen Artikel ...naja, ich hoffe
das trifft jetzt nicht ganz zu, oder? *g*
Jedenfalls werde ich es ab sofort so machen: Sobald ich gengend Feedback
in Form von Emails, Drohbriefen oder Geld von euch bekomme (die letzteren
beiden MSSEN nicht unbedingt sein!), werde ich diese Serie fortsetzen.
Falls ihr irgendwelche bestimmten Wnsche oder Vorschlge haben solltet,
die diese Tutorials betreffen, dann nichts wie her damit!! Ich bin immer
fr Kritik offen (naja, meistens).
Euch wird natrlich auch noch aufgefallen sein, das die Optik der Datei
etwas verschlimmbessert wurde. Das liegt daran, das ich dieses Tutorial
auf einem uralten 286er mit CGA/Monochrom-Display schreibe.
Ok, genug des sentimentalen Geschwafels ...sonst wird der Einleitungs-Text
noch gráer als das eigentliche Tutorial! ;)
Viel Spaá und Erfolg,
Andreas Lffler aka GD^CRAZY im August 1999
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.1 Worum gehts? ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Im letzten Tutorial haben wir zusammen ein kleines, primitives Spiel
entwickelt, dass noch berhaupt keinen Sinn gemacht hat. Hier werden
wir die ganzen Routinen nochmal verbessern und die Struktur eines kleinen
Rollenspieles erarbeiten. Es wre von Vorteil, wenn man die anderen
beiden Tutorials schon gelesen hat, es ist aber nicht zwingend notwendig.
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.2 Los gehts! ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Ein einfaches Rollenspiel basiert immer auf sehr einfachen 2D-Karten.
Falls jemand nicht weiss, was 2D-Karten sind, der soll sich einfach mal
ein Schiffeversenken-Raster anschauen. Genau das gleiche wird in der
Spielebranche als 2D-Karte bezeichnet. Das heiát, man definiert ein
beliebig groáes Feld und fllt es mit Werten, die man vorher definiert
hat. Wenn zum Beispiel an der Position 5,5 ein Baum gesetzen werden soll,
dann wird auf der Karte einfach des entsprechende eingetragen (wie auf
einem Schachbrett zum Beispiel).
Da das Prinzip jetzt geklrt wurde, zwingt sich unweigerlich die Frage
auf: "Wie soll ich das ganze bitteschn in die Tat umsetzen?
Ganz einfach! Wir definieren vorher eine Art Liste, in der verzeichnet
ist, welche Zahl welches Objekt angibt.
Beispiel:
0 = Nichts, Graslandschaft
1 = Mauer
2 = See/Fluss
3 = Haus
4 = Baum/Stein/Naturobjekt
5 = ...usw
Und so sieht dann eine Karte (10x10 Felder) aus:
0000000000
0111100000
0000001100
0000000000
0040000004
0000030000
2200000400
2220400000
2200001110
2200000000
Da es aber ungeschickt wre, die gesamten Werte (siehe oben: 1-5) in
den Quellcode fest einzubauen, laden wir sie einfach aus einer Datei
in das Spiel. Diese Methode ist viel besser, weil manche Leveldesigner
(ich meine jetzt garantiert NICHT Alpharay!) selbst Objekte hinzufgen
oder verndern wollen. Dadurch muss nicht jedesmal der Programmierer des
Spiels den Code mhsam verndern und neu kompilieren.
Die obrige Liste von Objekten ist noch sehr unkomplett. Alleine der Name
und die Nummer eines Objektes reichen nicht mehr fr ein Rollen- oder
Actionspiel aus! Zum Beispiel muss noch geklrt werden, ob der Spieler
durch einen Baum "hindurchlaufen" kann oder nicht, oder ob z.B Lava
Energie vom Spieler abzieht, wenn er "draufluft". In der Fachsprache
heiát das "Clipping".
So sieht die fertige Liste nun aus: (weitere Werte knnen natrlich
noch hinzugefgt werden!)
Baum (Name des Objekts)
Farbe (Farbe des Objekts im Spiel)
SizeX (Gráe X des Objekts)
SizeY ( " Y " " )
Clipping (siehe oben!)
Attack (zieht das Objekt Energie ab?)
AttackValue (wenn ja, wieviel?)
Action (welche Aktion wird ausgefhrt, wenn der
(Player "drberluft"?)
So sieht das in der abgespeicherten Datei natrlich nicht aus! Wenn wir
den Baum in die Datei eingeben wollten, dann she das jetzt so aus:
Baum
1 (1 Kstchen, da ASCII)
2 (2 = Farbe Grn)
1 (" " " " )
1 (Man kann durch das Objekt NICHT durch-
laufen! 1=NEIN 0=JA)
0 (Der Baum zieht keine Energie ab)
0 (und damit auch keinen Wert)
0 (eine Aktion wird auch nicht durchgefhrt)
Das ganze wird natrlich OHNE die Erklrungs-Klammern in die Datei
ein-
gegeben ;)
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.3 Jetzt wirds Spannend! ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Da wir jetzt schonmal eine Liste haben, die die ganze Objekte, die im
Spiel vorkommen beinhaltet, brauchen wir jetzt auch eine Funktion, die
die Liste in das Spiel ldt.
Im Pseudo C/C++ Code sieht das folgendermaáen aus:
struct SObjekt
{
char name[40];
int farbe;
int sizex;
int sizey;
int clipping;
int attack;
int attackvalue;
int action;
}
Öffne_die_Datei;
Lade_die_Nummer_die_die_Anzahl_der_Objekte_enthlt
for (int i=0; i<Anzahl_der_Objekte; i++)
{
Lade_Name;
Lade_Farbe;
Lade_Sizex;
Lade_Sizey;
Lade_Clipping;
Lade_Attack;
Lade_AttackValue;
Lade_Action;
}
ANMERKUNG: Diese Schleife wird mit jedem Objekt wiederholt, bis alle
Objekte abgearbeitet sind.
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.4 Das Spiel ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Okay, super! Jetzt haben wir schonmal eine Liste geladen, nennen wir
sie jetzt ab sofort "Objekte.cfg", und haben die Objekte deklariert.
Im 2. Tutorial habe ich ber die Struktur des Players geschrieben. Wer
das zweite Tutorial aber (noch) nicht hat, dem kann geholfen werden :)
Hier ist nochmal die komplette Struktur vom Player des Spiels:
struct SPlayer
{
int xpos;
int ypos;
int energie;
int attackpower;
} Player;
Ich habe die Struktur des Players absichtlich so vereinfacht, weil wir
die anderen Werte noch nicht brauchen. Alle Werte des Players erklren
sich wohl von selbst ...
Als nchstes kommt die eigentliche Levelkarte dran ...anstatt wie oben
die Levelkarte als 2D-Raster in eine Datei zu speichern, werden wir der
Einfachheit halber jeden einzelnen Wert untereinander speichern.
Das sieht dann so aus:
0
0
0
0
1
0
0
1
0
.
..
...etc
Der Lade-Algorithmus ist nun sehr primitiv und einfach, sodas ich zum
Thema "Laden der Karte" nicht weiter eingehen mchte!
Ah, halt! Die Struktur in die die Karte geladen werden soll,
ist noch wichtig :)
Sie ist sehr einfach:
struct SKarte
{
Objekt SObjekt;
} Karte[100][100];
Die Karte bezieht sich also auf die schon vorhandene Struktur "SObjekt".
Weitere Variablen (wie z.B die aktuelle Hhe usw) knnen in dieser
Struktur auch wieder nach belieben hinzugefgt werden.
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.5 Der Anfang ... ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Puhh ...ganz schn viel Arbeit fr so ein kleines Adventure/Rollenspiel,
oder? :)
Aber ihr werdet sehen: Wenn man einmal richtig herausgefunden hat, wie
Spiele entstehen bzw. funktionieren, dann ist es garnicht mehr so schwer!
Jetzt haben wir die Levelkarte geladen, die Objekte geladen und den Player
initialisiert ...
Doch wo soll der Player denn jetzt nur auf der Karte starten, wenn das
Spiel gestartet wird? Das werde ich jetzt mal ausnahmsweise euch ber-
lassen! Ladet in die Werte des Players einfach die X- bzw. Y-Startpostion.
z.B so:
void main ()
{
Player.xpos=3;
Player.ypos=3;
Player.energie=100;
Player.attackpower=5;
}
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.6 Die Steuerung! ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Ich werde in diesem Abschnitt NICHT komplizierte Keyboard-Handler (int 9h)
oder irgendwelche andere "abartigen" Methoden einsetzen.
Da ich davon berzeugt bin, das der Leser (also Du) C/C++ schon ein
biáchen kann, werde ich hier einfach einen kurzen und sehr einfachen
Code "auf den Tisch werfen". Dieser Code beinhaltet auch die Kollisions-
abfrage und Attackwerte.
char ch;
if (kbhit ())
{
ch=getch ();
if (ch==0)
{
ch=getch ();
if (ch==72)
{
if (Player.ypos>0 &&
Karte[Player.ypos-1][Player.xpos].Objekt.clipping==0)
Player.ypos--;
}
if (ch==80)
{
if (Player.ypos<24 &&
Karte[Player.ypos+1][Player.xpos].Objekt.clipping==0)
Player.ypos++;
}
if (ch==75)
{
if (Player.xpos>0 &&
Karte[Player.ypos][Player.xpos-1].Objekt.clipping==0)
Player.xpos--;
}
if (ch==77)
{
if (Player.xpos<80 &&
Karte[Player.ypos][Player.xpos+1].Objekt.clipping==0)
Player.xpos++;
}
}
}
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.7 Zeichnen der Karte ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Die meisten von euch werden jetzt sicher schon wissen, wie man diese
einfache Levelkarte (ist ja eh nur 2D!) auf den Bildschirm bringt ...
fr alle anderen habe ich hier nochmal den Code. Er ist nicht besonders
schnell oder professionell ...aber dafr versteht ihn jeder! (hoffe ich
doch *g*)
void ZeichneLevel ()
{
for (int i=0; i<25; i++)
{
for (¡nt a=0; a<80; a++)
{
textcolor (Karte[i][a].Objekt.farbe)
gotoxy (a,i);
cprintf ("Û");
}
}
}
TIP: Schreibt die ganze Schleife in Assembler! Das geht tausendmal
schneller :)
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.8 Struktur des Codes ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Sodele, jetzt wre fast alles geklrt :)
Nun zeige ich kurz nochmal auf, wie die Struktur des ganzen Codes
aufgebaut sein sollte damit alles reibungslos funktioniert!
Globale Variablen
Globale Strukturen (Karte, Objekte, Player usw)
void main ()
{
Lade_Objekte ();
Lade_Karte ();
Main_Loop ();
Ende ();
}
void Main_Loop ()
{
Tastatur_Abfrage ();
Karte_zeichnen_wenn_ntig ();
Player_zeichnen ();
Andere_Spiel_Aktionen ();
}
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.9 Das Ende naht ... ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
Da jetzt alles besprochen wre, was zum Schreiben eines kleinen
Adventures/Rollenspiels erforderlich ist, wrde ich sagen: Ran an
den Millionenhit! ;)
Ist ja klar, das man dieses kleine Spiel nicht mit solchen Mammut-
projekten wie Lands of Lore oder andere vergleichen kann ...aber jeder
professionelle Spieleprogrammierer hat mal so angefangen! Programmieren
ist (fast) wie Sport: Nur durch Trainieren wird man besser! (ausser
dem man beim Sport danach einen Muskelkater hat *lol*)
Ah ..noch etwas! Ich habe nach dem Release des 2. Tutorials jede Menge
Mails bekommen mit der Frage: "Kannst du mir den Sourcecode oder einen
Teil von dieser und dieser Routine schicken?". Ich werde euch gerne
Fragen bezglich der Programmierung usw. beantworten, aber werde KEINEN
Sourcecode verschicken. Das hat den Hintergrund, das man sich das selber
erarbeiten sollte und nicht einfach irgendwoher nehmen und einbauen ...
dazu ist dieses Tutorial ja da ;)
In diesem Sinne,
Andreas Lffler aka GD^CRAZY im August 1999
mail: gd_crazy@gmx.net oder andi@unitedbytes.de
web: http://www.unitedbytes.de
]-EOF-[