In Teil I des Iso Guides haben wir die Grundlagen behandelt, nun ist es Zeit weiter zu gehen.
Größere Karten... Die bis jetzt gezeigten isometrischen Karten sind noch sehr klein und als Spielwelt natürlich nicht geeignet. Um die Maps zu vergrößern müssen wir nur die Konstanten MAP_W und MAP_H nach belieben ändern. Am meisten Sinn macht es MAP_H doppelt so groß wie MAP_W zu machen, da die Tiles normalerweise nur halb so breit wie lang sind und so die Form der Map näher an ein Quadrat herankommt.
 Grafik MAP_H = 1/2 MAP_W mit Zoom
...und eine bewegliche Kamera Bis jetzt bringt es uns noch nichts die Maps zu vergrößern, da wir nur einen beschränkten Ausschnitt der Karte sehen. Dieses Problem werden wir mit einer beweglichen Kamera lösen. Eine bewegliche Kamera zu schaffen ist (zum Glück) ganz einfach.Dazu benötigt man lediglich zwei Variablen, die beim Zeichnen der Map auf den Bildschirm festhalten, wie weit die Kamera vom oberen linken Ende der Map entfernt ist: offset x und offset y (kurz: ofs_x und ofs_y). So sieht der erweiterte Code aus:
//Die Funktion TasteGedrueckt ist frei erfunden und soll nur das Prinzip verdeutlichen if (TasteGedrueckt("Pfeil Rechts") { ofs_x = ofsx - 5;} for (int y=0 ;y<MAP_H; y++ ) { for (int x=0; x<MAP_W; x++) { //Neue Reihe der Tiles kommen nach 1/2 Breite eines Tiles y_px = y*(TILE_H/2);
//Jede zweite Reihe der Tiles um 1/2 Länge versetzt //-> wenn y ungerade, dann 1/2 Länge zu Tilepostion hinzuaddieren if (y%2==1){ x_px = x*TILE_W + (TILE_W/2))} else { x = (x*TILE_W)} TileZeichnen(x+ofs_x, y+ofs_y); } }
Wenn die rechte Pfeiltaste heruntergedrueckt wird, so wird (bei jeder Abfrage) ofs_x um 5px kleiner, die Kamera bewegt sich also nach rechts. In der Zeichenroutine (TileZeichnen()) wird zur eigentlichen Position des Tiles (in px) der offset-Wert hinzuaddiert. Bei einem Drücken der rechten Pfeiltaste befindet sich das linke obere Tile bei -5,0 px, es ist also aus dem Bild herausgerückt, da wir uns ja nach rechts weiterbewegt haben.
Den PC entlasten Die kamera funktioniert so weit ganz ausgezeichnet. Leider haben wir nun ein kleines Problem... Einmal angenommen MAP_W ist gleich 5000 und MAP_H ist gleich 10000, dann müssen bei jedem Zeichengang (bei 100 fps macht das 100 mal pro Sekunde) alle 5000 * 10000 Tiles (insgesamt 50 Millionen!) neu gezeichnet werden. Natürlich sind die Maps in der Praxis nicht so riesig, aber das Problem besteht dennoch: Bei jedem Zeichengang zeichnen wir jede Menge Tiles mit, die wir gar nicht sehen. Auf einen Bildschirm (bei 1024 * 768 Auflösung) passen (bei einer Tilegröße von 64*32) ca. 400 Tiles, es reicht also vollkommen aus nur diese vierhundert Tiles zu zeichen, da wir den Rest sowieso nicht sehen.
 Map mit Kamera-Ansicht
Der Code muss also wie folgt geändert werden:
... for (int y=y_start ;y<y_end; y++ ) { for (int x=x_start; x<y_end; x++) {
Damit arbeiten wir in der Zeichenschleife nur die Tiles ab, die wir auch sehen. Doch wie berechnen wir, bei welchem Tile wir anfangen und aufhören können zu zeichnen? Wir haben nur die offset-Angaben in Pixeln, wissen also nicht die Nummer des Start bzw. Endtiles. Die lässt sich aber ganz einfach herausfinden, indem wir die offset-Angaben durch die Länge bzw. Breite eines Tiles teilen. Das letzte zu zeichnende Tile ist demnach die offset-Angabe plus der Bildschirmlänge geteilt durch die Länge eines Tiles. Um aufgrund von Rundungsfehlern nicht ein Tile zu wenig anzuzeigen fangen wir also ein Tile früher an zu zeichnen (start_x = start_x-1) bzw. hören ein Tile später auf (end_x = end_x + 1). So muss der Code erweitert werden:
... y_start = ofs_x / TILE_H - 1; x_start = ofs_y / TILE_W -1; y_end = (ofs_y + SCREEN_H) / TILE_H +1; x_end = (ofs_x + SCREEN_W) / TILE_W +1;
for (int y=y_start ;y<y_end; y++ ) { for (int x=x_start; x<y_end; x++) {
Nachtrag zur Kamera Da wir den Spieler nicht über die Map heraus sehen lassen wollen (und um logische Probleme zu vermeiden), bauen wir eine Kamerabeschränkung ein. Wir wollen den Spieler genrell nicht die erste und letzte Reihe der Tiles sehen lassen, da diese aufgrund der schrägen Kanten das "Nichts" nur halb verdecken. Um den Bereich zu überprüfen den wir sehen können, müssen wir logischerweise bei start_x und end_x (bzw. y) mit der Überprüfung beginnen. So sieht der Code aus:
... start_y = ... .... end_x = ... if (start_y < 1) { start_y = 1;} if (start_x < 1) { start_x = 1;} if (end_y > MAP_H - 1) { end_y = MAP_H - 1;} if (end_x > MAP_W - 1) { end_x = MAP_W - 1;} ...

Bei dem hier beschriebenen Code wird davon ausgegangen, dass die Maps größer als die Bildschirmauflösung sind (etwas anderes würde aber auch wenig Sinn machen ;) ) copyright by Matthias Böhm (headsetmusic.de), Logo created by Marc Buchholz (isogames.de)
|