www.codeworx.org/game-dev/Aus Dateien einlesen

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 aufh”ren,
denn was bringt es, Tutorials zu schreiben fr die sich eh keiner
interessiert? *g*
Wenn da aber das W”rtchen *FAST* nicht w„r ... einige Personen (darunter
auch Prometheus und Dragen!) interessieren sich komischerweise fr 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 gengend Feedback
in Form von Emails, Drohbriefen oder Geld von euch bekomme (die letzteren
beiden MšSSEN nicht unbedingt sein!), werde ich diese Serie fortsetzen.
Falls ihr irgendwelche bestimmten Wnsche oder Vorschl„ge haben solltet,
die diese Tutorials betreffen, dann nichts wie her damit!! Ich bin immer
fr Kritik offen (naja, meistens).

Euch wird natrlich 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 L”ffler 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 w„re 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 fllt 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 gekl„rt wurde, zwingt sich unweigerlich die Frage
auf: "Wie soll ich das ganze bittesch”n 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 w„re, 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 hinzufgen
oder ver„ndern wollen. Dadurch muss nicht jedesmal der Programmierer des
Spiels den Code mhsam ver„ndern und neu kompilieren.

Die obrige Liste von Objekten ist noch sehr unkomplett. Alleine der Name
und die Nummer eines Objektes reichen nicht mehr fr ein Rollen- oder
Actionspiel aus! Zum Beispiel muss noch gekl„rt werden, ob der Spieler
durch einen Baum "hindurchlaufen" kann oder nicht, oder ob z.B Lava
Energie vom Spieler abzieht, wenn er "draufl„uft". In der Fachsprache
heiát das "Clipping".

So sieht die fertige Liste nun aus: (weitere Werte k”nnen natrlich
noch hinzugefgt 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 ausgefhrt, wenn der
(Player "drberl„uft"?)

So sieht das in der abgespeicherten Datei natrlich nicht aus! Wenn wir
den Baum in die Datei eingeben wollten, dann s„he das jetzt so aus:

Baum
1 (1 K„stchen, da ASCII)
2 (2 = Farbe Grn)
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 durchgefhrt)

Das ganze wird natrlich OHNE die Erkl„rungs-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 l„dt.

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_enth„lt
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 erkl„ren
sich wohl von selbst ...

Als n„chstes 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 m”chte!
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 H”he usw) k”nnen in dieser
Struktur auch wieder nach belieben hinzugefgt werden.


ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.5 Der Anfang ... ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Puhh ...ganz sch”n viel Arbeit fr 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 ...
fr alle anderen habe ich hier nochmal den Code. Er ist nicht besonders
schnell oder professionell ...aber dafr 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 w„re fast alles gekl„rt :)
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_n”tig (); 
   Player_zeichnen (); 
   Andere_Spiel_Aktionen (); 
} 
 

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
===³ 1.9 Das Ende naht ... ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Da jetzt alles besprochen w„re, was zum Schreiben eines kleinen
Adventures/Rollenspiels erforderlich ist, wrde 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 bezglich 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 L”ffler aka GD^CRAZY im August 1999

mail: gd_crazy@gmx.net oder andi@unitedbytes.de
web: http://www.unitedbytes.de



]-EOF-[