How to Load Images and Text Files (In-Depth Tutorial)

First of all I would like to say this: File loading can make you want to rip your hair out and scream to the lord but trust me, once you get it working you feel like a god. Is that just me? It is? Oh…
Anyways, on to the tutorial.

File loading is a very good thing if you are planning to do something like have a map with many details because who wants to spend hours coding in “here’s the plant, here’s the player spawn, here’s the house, and you can go in the house, and blah blah blah”. No, using files are much easier. A simple example of what loading a file can be useful for is if you have a topdown 2d terrain. You can make an image in Photoshop, GIMP (my preferred program), or even Paint/Paint.net that looks like this:

Then in your code you can say, “Hey load this file and if the pixel at (x, y) is red make that the player spawn and if it’s white put a house there and if it’s purple draw a patch of grass!”. Simple, huh?

Another example is using an XML file or your own file type if you want to load something more advanced. For example, in one of my puzzle games I have this file:


Pad 2 4 
Block 2 6 

Pad 2 8 
Block 2 11 

Pad 2 11 
Block 4 13 

Pad 7 8 
Block 7 6 

Pad 9 3 
Block 9 5 

Pad 11 6 
Block 11 3 

Pad 13 8 
Block 11 8 

Pad 9 10 
Block 9 12 

Now what my code does is look at that code and if a line starts with “Pad” it looks at the numbers after it and says, “Hey look I should draw a pressure pad at these two variables! Wait… It does nothing… But there is a line beneath it that says Block! So this pressure pad should link to the block at the two numbers after Block!”. If that’s not too clear an easier way to understand it is this:
Pressure pad at (x, y) will link to the Block at (x, y).

Time to get to how to code these!
We will start with loading and reading an image.
First we will need an object of BufferedImage. BufferedImage is a handy class that will let us look at the individual pixels of an image:


BufferedImage map;

Now we need to initialize this. To do so we need to utilize the ImageIO class to load the path of the file:


map = ImageIO.read(getClass().getResourceAsStream("/res/yourPicture.png"));

Yes I know that may seem a little complicated but let me spell out all the calls nice and slow before you get all dejected.

What the class ImageIO does is simple. It lets us communicate with things outside of our code whether it be Input, hence the I, or Output, hence the O. Now the read method will “read” a file and let us communicate with it, opening a “phone call” with the resource. That’s great and but it needs a path to our resource. Well if your game is on someone else’s computer it’s most likely not going to be at the path C:/Users/Me/Desktop/GameDev/MyProject/Res/myImage.png. No, it’s going to be somewhere on their computer where we don’t know. So what the getClass() method does is get the file on the computer to that class. Pretty neat. So with this getClass() method we can now load the resource as a stream. What a stream does is basically flow a “stream” of bytes to us, from the image, containing its data. All we have to give it is the local path in the game’s directory because we are using the getClass()!

Sweet so now we have an image loaded into the BufferedImage and we can utilize it. To do so is extraordinarily simple. We just use map.getRGB(int x, int y) and it will return a hexadecimal telling us the color of the pixel at those coordinates. Using this we can do the following:


        for (int x = 0; x < map.getWidth(); x++) {
            for (int y = 0; y < map.getWidth(); y++) {
                Color c = new Color(map.getRGB(x, y));
                if (c.equals(Color.WHITE)) {
	       //we use c.equals() because == checks that the objects are the exact same object in the heap 			and .equals() checks that they contain the same data.		
                   //do stuff for white colored pixel
                } else if (c.equals(Color.GREEN)) {
                   //do stuff for green colored pixel
                } else if (c.equals(Color.RED)) {
                    //do stuff for red colored pixel
                }
            }
        }

Beautiful! Now what if we wanted something more complicated, more in depth? That’s where text files come in handy. We can use these to specify specific things that we want in the code such as if you walk on this x and y coordinate this door will unlock. This is useful also if you want to make a map editor for your players to create custom levels. If you want to save space you can actually do the whole level inside a text file but I won’t go into that right now.

Let’s learn how to load a file containing text. Note that I don’t say .txt because, guess what? You can create your own file type! How cool is that? So to do something like this you should first have the file. What I have is a file that says which blocks are pressure pads, if they are switches or temporary (as long as you are standing on them), and which doors the correspond to:


Pad 2 4 2 6 

Pad 2 8 2 11 

Pad 2 11 4 13 

Pad 7 8 7 6 

Pad 9 3 9 5 

Pad 11 6 11 3 

Pad 13 8 11 8 

Pad 9 10 9 12

So what our program is going to do is look at the file and, if the line starts with “Pad”, look at the next two numbers to see which coordinate the pad is at, and the third and fourth numbers to detect which door it corresponds to.

First we need an InputStream which pretty much does the same thing as ImageIO.read():


InputStream inp = getClass().getResourceAsStream("/res/map1def.mdef");

Next we need to create a buffered reader with this InputStream:


BufferedReader in = new BufferedReader(new InputStreamReader(inp));

The input stream reader acts as the translator for our BufferedReader which is much like a BufferedImage but for text.
Now that we have these two things we can actually read the individual lines of the file:


String str;
while ((str = in.readLine()) != null) {
       if (str.startsWith("Pad ")) {
              float x = Float.valueOf(str.split(" ")[1]);
	  float y = Float.valueOf(str.split(" ")[2]);
	  float blockX = Float.valueOf(str.split(" ")[3]);
	  float blockY = Float.valueOf(str.split(" ")[4]);
       }
}

Ok now let’s decipher this mess. What in.readLine() does is cycles through the different lines one by one as we call it. We check whether or not it is at the end by taking the whole expression str = in.readLine() into parentheses and checking if it is null, or nonexistent. Then we do some trickery with Strings and Floats. We check whether or not the line starts with “Pad” and, if it does, set a few values. Let’s start with explaining str.split(). What this method does is take the whole string and if it finds the character that you passed in, in our case a space, it takes that character out and returns an array of Strings. What we can do is call individual pieces of that array by using the [num] after it. So let’s say we had a


String s = “Bob,Jill,Kory";

What we can do is use


String[] sArray = s.split(“,”);

to get all those commas out and store the names into an array. Then we can call the individual names:


String firstName = sArray[0];
//or, alternatively
String firstName = s.split(“,”)[0]

Make sense? Good. Now in the above code the reason we set the first x to the first in the array is because the array starts at zero. If we set it to zero in the array we would get a type mismatch exception because it would return “Pad”. So we can split Strings but what if we want to load them into Floats? That is what the Float.valueOf() does, it takes a string and converts it to a float. Now you can load files whether it be an Image or a file and rule the world with your amazing file loading skills! Congratulations and thanks for reading this tutorial all the way through.

For the sake of being easy to understand and read, XML files are probably better than your own type.

And if you do the loading/initialising properly, they won’t throw an exception when you forget something.

Don’t use stylish double quotes for strings! You have this.


String s = “Bob,Jill,Kory”;

And it should be


String s = "Bob,Jill,Kory";

I wrote this in Ubuntu’s LibreOffice so I could read it better, sorry about those. I worked hard on this and it’s my first tuturial cut me some slack ;).
@HeroesGraveDev don’t worry I am aware of this, however I wanted to give a ground base on how to read text files.