Continuing with the series, we have Part 2 of the Level Creation lessons. In this lesson, we will be adding a method that will read a .txt file's information and draw a map to the screen accordingly.
A typical map file may look like this:
A typical map file may look like this:
In such a file, each space would represent a tile (or an empty tile), and we would be able to create corresponding structures on the screen in this way.
Using this method, we will be able to create multiple levels for our character to traverse through.
Let's begin.
Let's begin.
Making Changes to the StartingClass
I. We will begin at the beginning by adding a few more types of tiles to the game.
1. Find the line (yay syntax highlighting):
1. Find the line (yay syntax highlighting):
public static Image tiledirt, tileocean;
And change it to this one:
public static Image tilegrassTop, tilegrassBot, tilegrassLeft, tilegrassRight, tiledirt;
2. Find this segment in your init() method:
tiledirt = getImage(base, "data/tiledirt.png");
tileocean = getImage(base, "data/tileocean.png");
tileocean = getImage(base, "data/tileocean.png");
Update like so:
tiledirt = getImage(base, "data/tiledirt.png");
tilegrassTop = getImage(base, "data/tilegrasstop.png");
tilegrassBot = getImage(base, "data/tilegrassbot.png");
tilegrassLeft = getImage(base, "data/tilegrassleft.png");
tilegrassRight = getImage(base, "data/tilegrassright.png");
II. You will want to download these (overwriting tiledirt.png and deleting tileocean.png).
They go inside your data folder.
They go inside your data folder.
![]()
|
![]()
|
![]()
|
![]()
|
![]()
|
While you're at it, download the map file also (place it also in the data folder):
![]()
|
III. Now that we got our assets ready, navigate to your start() method.
In here, we have a double for loop that creates our Tile map. We will now be encapsulating this inside a method. Find the following section:
// Initialize Tiles
for (int i = 0; i < 200; i++) {
for (int j = 0; j < 12; j++) {
if (j == 11) {
Tile t = new Tile(i, j, 2);
tilearray.add(t);
} if (j == 10) {
Tile t = new Tile(i, j, 1);
tilearray.add(t);
}
}
}
Change it to the following. Ignore errors.
// Initialize Tiles
try {
loadMap("data/map1.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
loadMap("data/map1.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This is a pretty straightforward segment of code. We call the loadMap() method (which we will now create) and pass in the parameter map1.txt which you should have downloaded above.
Since we are dealing with files, Java requires us to create a try/catch statement in case an exception occurs.
IV. Now we will create the loadMap() method.
Since we are dealing with files, Java requires us to create a try/catch statement in case an exception occurs.
IV. Now we will create the loadMap() method.
The easiest way to do so is to put your mouse over the error shown in the try/catch statement like so:
Click "Create method 'loadMap(String)'"
Eclipse will automatically create the loadMap for you. You have to make a few changes.
1. You want to change the name of the parameter (string) to filename.
2. In addition, as we are dealing with files in this method, we want to handle the exceptions. Rather than use try/catch statements, we have an alternative. Declare "throws IOException" after the parameters are stated in the method declaration.
If you do so, the method will look like this.
Eclipse will automatically create the loadMap for you. You have to make a few changes.
1. You want to change the name of the parameter (string) to filename.
2. In addition, as we are dealing with files in this method, we want to handle the exceptions. Rather than use try/catch statements, we have an alternative. Declare "throws IOException" after the parameters are stated in the method declaration.
If you do so, the method will look like this.
private void loadMap(String filename) throws IOException{
// TODO Auto-generated method stub
}
Let's now talk in detail about what this loadMap() method will do.
LoadMap() Method
The functions of this method are as follows:
1. To create an ArrayList and fill it with the lines parsed from the .txt file.
2. To utilize a double for loop to create tiles (we are basically rewriting the tile initializing for loops in the init() method in this method).
3. Assigning a type (recall in the last unit, we used integers to represent whether the tile was an ocean tile or a grass tile) by reading the text file at the (x , y) index of the tile.
The completed method looks like this:
1. To create an ArrayList and fill it with the lines parsed from the .txt file.
2. To utilize a double for loop to create tiles (we are basically rewriting the tile initializing for loops in the init() method in this method).
3. Assigning a type (recall in the last unit, we used integers to represent whether the tile was an ocean tile or a grass tile) by reading the text file at the (x , y) index of the tile.
The completed method looks like this:
private void loadMap(String filename) throws IOException { ArrayList lines = new ArrayList(); int width = 0; int height = 0; BufferedReader reader = new BufferedReader(new FileReader(filename)); while (true) { String line = reader.readLine(); // no more lines to read if (line == null) { reader.close(); break; } if (!line.startsWith("!")) { lines.add(line); width = Math.max(width, line.length()); } } height = lines.size(); for (int j = 0; j < 12; j++) { String line = (String) lines.get(j); for (int i = 0; i < width; i++) { System.out.println(i + "is i "); if (i < line.length()) { char ch = line.charAt(i); Tile t = new Tile(i, j, Character.getNumericValue(ch)); tilearray.add(t); } } } } |
Discussion:
We initialize some variables in the first section (including the ArrayList) and the width and height (which represent the number of lines and characters per line in the text we read). We use a while loop to fill the ArrayList lines with the lines read from the text file. If the line begins with an "!", we ignore it (I used ! to begin comments in the map file). We give width and height the appropriate values to serve their function. The familiar double for loop creates tiles at the (i, j) index, i representing the x coordinate and j representing the y coordinate. |
Now, we check what the character at the index i of the current line is (which has index j). We then create a new Tile with the parameters x position, y position, and type. Since the characters we read from the text file are characters, not integers (there's a distinction between '1' and 1 much like there's a distinction between "a" and a), we use a built-in method: Character.getNumericValue(ch) to convert it to a number.
The purpose of the if(i < line.length()){... statement is there to ensure that our i index never searches for a character that does not exist. If this is not there, we can have all kinds of problems with our map.txt so this is very important!
The purpose of the if(i < line.length()){... statement is there to ensure that our i index never searches for a character that does not exist. If this is not there, we can have all kinds of problems with our map.txt so this is very important!
Finishing Touches
Now all we have to do is handle the tile types inside the Tile class. Make these changes to the if statements within the constructor, and we will be good to go!
public Tile(int x, int y, int typeInt) {
tileX = x * 40;
tileY = y * 40;
type = typeInt;
if (type == 5) {
tileImage = StartingClass.tiledirt;
} else if (type == 8) {
tileImage = StartingClass.tilegrassTop;
} else if (type == 4) {
tileImage = StartingClass.tilegrassLeft;
} else if (type == 6) {
tileImage = StartingClass.tilegrassRight;
} else if (type == 2) {
tileImage = StartingClass.tilegrassBot;
}
}
Finally, let me explain my reasoning for choosing the seemingly arbitrary typeInt values.
If you look at a typical numpad:
If you look at a typical numpad:
There are arrows below the numbers 8, 4, 6, and 2. I used these numbers to represent dirt tiles with grass on the side that the arrows point towards. 5, of course, has no arrows and represents a dirt tile with no grass on any side.
Examine the map1.txt file to see how I applied this technique to create a simple level.
At this time, you can run the code and it will work!
In the next lesson, we will implement some basic collision detection to these tiles, and we will move on from there! (Please don't send me emails saying "I can't jump on the platforms!" because we haven't coded anything to make them platforms yet. They are as of now just images).
Like Kilobolt Studios on Facebook and I will keep you posted.
Examine the map1.txt file to see how I applied this technique to create a simple level.
At this time, you can run the code and it will work!
In the next lesson, we will implement some basic collision detection to these tiles, and we will move on from there! (Please don't send me emails saying "I can't jump on the platforms!" because we haven't coded anything to make them platforms yet. They are as of now just images).
Like Kilobolt Studios on Facebook and I will keep you posted.

unit3day2.zip |