Tilemap question

Alright, so instead of hard coding my map into my code. I want to load it from a text file.

Wasn’t too sure how to go about this, haven’t done much file i/o. Thanks if you help.


package com.akrillix;

import java.awt.Graphics;
import com.akrillix.*;
import java.awt.Graphics2D;
import java.awt.Image;

import javax.swing.ImageIcon;

public class Map {
	private final int TILE_SIZE = 32;
	private Image grass, dirt, water;
	public static boolean drawGrid = false;
	public static int[][] map = {
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0 },
			{ 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0 },
			{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 0 },
			{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };

	public Map() {
		grass = new ImageIcon("src/grass.png").getImage();
		dirt = new ImageIcon("src/dirt.png").getImage();
		water = new ImageIcon("src/water.png").getImage();
	}

	public void paint(Graphics g) {
		for (int across = 0; across < 25; across++) {
			for (int down = 0; down < 18; down++) {
				if (map[across][down] == 1) {
					g.drawImage(dirt, across * TILE_SIZE, down * TILE_SIZE,
							null);
				} else if (map[across][down] == 0)
					g.drawImage(grass, across * TILE_SIZE, down * TILE_SIZE,
							null);
				if (map[across][down] == 2) {
					g.drawImage(water, across * TILE_SIZE, down * TILE_SIZE,
							null);
				}
				if (drawGrid) {
					g.drawRect(across * TILE_SIZE, down * TILE_SIZE, TILE_SIZE,
							TILE_SIZE);
				}
			}
		}
	}
}


I was playing around with different map formats and the way data was loaded a few days ago. Here is basically how was doing it:


public void loadMap(String mapName) {
		try {
			FileInputStream in = new FileInputStream(new File(mapName+".txt"));
			Scanner s = new Scanner(in);
			
			for (int i = 0; i < width; i++) {
				for (int j = 0; j < height; j++) {
					Tile newTile = new Tile(i, j);
					newTile.setTex(s.nextInt());
					newTile.setHeight(s.nextInt());
					tileData[i][j] = newTile;
				}	
			}
		} catch(IOException e) {
			e.printStackTrace();
		}
	}

In my map file i had the tile data set out one row per tile. Like this:


1 0
1 0
1 0
1 1
etc...

The first number was the index of texture and the second for the height of the tile.

Basically you need to think about what format you would like to use an how you’d like to edit it. There are a lot of factors involved, but for a simple tile based game here are four common solutions.

Text File
This is the easiest to program, but designing the maps will be difficult since you’ll need to type each tile in manually.

You simply output the two-dimensional array in a line-delimited text file. Reading it back is just as simple.

0022
0022
0012
0012

EDIT: Some code to get you started:

	final static int MAPSIZE = 4;
	
	public static int[][] read(InputStream in) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String line = "";
		int[][] map = new int[MAPSIZE][MAPSIZE];
		for (int lineCount=0; (line=br.readLine())!=null; lineCount++) {
			for (int i=0; i<MAPSIZE && i<line.length(); i++) {
				map[lineCount][i] = Character.getNumericValue(line.charAt(i));
			}
		}
		return map;
	}

Result in game:

You can define the format however you’d like, as you can see jammas615 parses his text file a little differently.

Image File
This is the same principle as above, but instead of using characters in a text file, you’re using pixels in an image file. Loop through the pixels, and simply pick the tile type that corresponds to the pixel color (e.g. in this case green (135,184,78) or “#87b84e” corresponds to the grass type).

It makes editing levels much more visual – you can use Photoshop or a similar program as your “level editor.”

Use a pre-existing map editor
Tiled will allow you to very easily design complex 2D tile maps. You just need to code yourself an importer; although I’m sure many implementations for Java2D already exist on the web.

Custom Editor & Format
Define your own format, i.e. using XML, JSON, or a combination of whatever you’d like. It can include game-specific properties, even small “scripts” if you want to get ambitious. Then build yourself an editor to design, save and load these files. This is in my opinion the best route if you really want to learn; although it’s much more challenging.

EDIT: You should also think about object-oriented design to avoid the ugly string of if-else statements (if your game has 50 different tiles, imagine how that will look in code…).