Java/Tutorials/Karteneditor Kapitel 3
| Entwicklung eines einfachen Karteneditors | |
|---|---|
| Autor | |
| Thematik | Java |
| Vorraussetzungen | Programme: Fähigkeiten: |
| Andere Teile |
Material |
Kapitel 2 Karten Model II
In diesem Kapitel befassen wir uns mit dem Einlesen der Tiles in unseren Array. Aber zuvor brauchen wir einen Konstruktor für unsere Klasse aus Kapitel 2. Aus Platzgründen wird in diesem Tutorial nur der Konstruktor gezeigt. Schreibt ihn einfach in die Klasse Karte.
public Karte() { }
Nun erweitern wir ihn um folgende Parameter:
- die eigentliche Karte
- der Dateiname des Tilesets
- der Name der Karte
public Karte(int[][] karte, String dateiname, String name) { this.kartenName=name; this.karte=karte; this.tilesetDateiname=dateiname; }
Wir verwenden den Ausdruck this um sicher zu stellen, dass auch wirklich die Klassen-Variablen verwendet werden. Würde man diesen Ausdruck weg lassen (z.B. karte = karte), wäre dies fatal, da die JVM nicht weiß welche Variable gemeint ist.
Da wir nun alles haben ( die Karte, den Kartennamen und den Dateinamen für das Tileset), wollen wir das Tileset laden und unsere ArrayList mit Tiles auffüllen. Hierfür bietet uns Java die statische Klasse ImageIO zur Verfügung. Mit ihr ist es einfach Bilddateien zu laden. Über die Methode read() können wir nun unser Bild laden. Diese Methode verlangt die Klasse File als Parameter.
public Karte(int[][] karte, String dateiname, String name) { this.kartenName=name; this.karte=karte; this.tilesetDateiname=dateiname; try { BufferedImage bildTileset=ImageIO.read(new File(dateiname)); } catch (IOException fehler) { System.err.println("Tileset "+dateiname+" nicht gefunden."); fehler.printStackTrace(); } }
Die Klasse ImageIO wirft eine Ausnahme, falls die Datei nicht existiert. Hier wäre z.B. mit Hilfe von JOptionPane.showMessageDialog() möglich z.B. "Datei XYZ konnte nicht gefunden werden" grafisch auszugeben. Dies aber nur als kleiner Tipp. Wir haben nun unser Tileset geladen, können aber leider damit noch nicht viel anfangen. Wir müssen es erst noch in unsere ArrayList schreiben, da wir nur einfache Tilesets und keine Animationen sowie autotile verwenden. Vorher müssen wir uns noch auf eine Tilegröße einigen. In diesem Beispiel werden wir eine Tilegröße von 32 Pixel verwenden. Wenn ihr die Zahl 32 seht, könnt ihr euch sicher sein, dass die Tilegröße gemeint ist. Als erstes benötigen wir die Anzahl der Tilesets in den Zeilen und Spalten. Daher werden wir die Methoden getWidth() (Breite) und getHeight() (Höhe) der BufferedImage-Klasse verwenden um die Höhe und Breite des Bildes zu ermitteln. Anschließend teilen wir die Höhe und Breite durch 32 um die Anzahl der Tiles zu ermitteln.
public Karte(int[][] karte, String dateiname, String name) { this.kartenName=name; this.karte=karte; this.tilesetDateiname=dateiname; try { BufferedImage bildTileset=ImageIO.read(new File(dateiname)); int breite=bildTileset.getWidth()/32; int höhe=bildTileset.getHeight()/32; } catch (IOException fehler) { System.err.println("Tileset "+dateiname+" nicht gefunden."); fehler.printStackTrace(); } }
Da wir nun alle Größen haben (Tile-Größe, Anzahl der Tiles in der Breite, Anzahl der Tiles in der Höhe), brauchen wir eine Möglichkeit diese Tiles aus dem Bild zu bekommen. Die Klasse BufferedImage besitzt die Methode getSubimage(x,y, Breite, Höhe), womit man sehr einfach aus dem riesigen Bild einen kleinen Teil herausholen kann. Da wir aber nicht nur ein Tile, sondern alle automatisch aus den Tileset-Bild holen wollen, werden wir zwei For-schleifen verwenden. Es ist also so, als ob wir einen zweidimensionalen Array durchlaufen.
public Karte(int[][] karte, String dateiname, String name) { this.kartenName=name; this.karte=karte; this.tilesetDateiname=dateiname; try { BufferedImage bildTileset=ImageIO.read(new File(dateiname)); int breite=bildTileset.getWidth()/32; int höhe=bildTileset.getHeight()/32; for(int x=0;x<breite;x++) { for(int y=0;y<höhe;y++) { BufferedImage tile=bildTileset.getSubimage(x*32, y*32, 32, 32); this.tileset.add(tile); } } } catch (IOException fehler) { System.err.println("Tileset "+dateiname+" nicht gefunden."); fehler.printStackTrace(); } }
Wie man erkennt durchlaufen wir das Bild in 32x32 großen Blöcken, also die Größe der Tiles. Wir übergeben der Methode getSubimage die Parameter x und y, die wir mit 32 multiplizieren, da wir ja oben durch 32 dividiert haben. Dadurch durchlaufen wir das Bild nicht in 1er-Pixel-Schritten, sondern in tilegroßen Schritten. Nachdem wir nun mit getSubimage() das Tile aus den Bild-Tileset geholt haben, fügen wir es unserer ArrayList hinzu.
Vollständigkeitshalber hier noch einmal wie die Klassen mit dem Konstruktor auszusehen haben.
public class Karte { int[][] karte; String kartenName; String tilesetDateiname; ArrayList<BufferedImage> tileset=new ArrayList<BufferedImage>(); public Karte(int[][] karte, String dateiname, String name) { this.kartenName=name; this.karte=karte; this.tilesetDateiname=dateiname; try { BufferedImage bildTileset=ImageIO.read(new File(dateiname)); int breite=bildTileset.getWidth()/32; int höhe=bildTileset.getHeight()/32; for(int x=0;x<breite;x++) { for(int y=0;y<höhe;y++) { BufferedImage tile=bildTileset.getSubimage(x*32, y*32, 32, 32); this.tileset.add(tile); } } } catch (IOException fehler) { System.err.println("Tileset "+dateiname+" nicht gefunden."); fehler.printStackTrace(); } } public BufferedImage getTileImage(int x, int y) { int tile=karte[x][y]; return tileset.get(tile); } public void setTile(int x, int y, int tileID) { karte[x][y]=tileID; } }