More fun is just around the corner in Unit 3. Let's finish strong!
In today's lesson, we will be building upon what we covered in Day 9.
If you have not looked at Day 9 yet, please do so before proceeding!
What we will be covering:
1. We will be creating a two-dimensional Array that holds a random set of values.
2. Using this two-dimensional array, we will print colored squares to the screen.
What is the significance of this lesson?
When we continue our 2D game development, we will be creating levels (maps) using text files. In each text file, we will represent objects in the game with keyboard characters, and our game will parse the file to create levels that we can interact with.
This lesson will be an application of what we learned in Day 9. After this, we should be able to accomplish the above task with ease in the coming lessons.
Note: We will be creating a NEW class today. You do not need to open any previous files.
Lesson #2-28: Creating the Tilemap
(Tip: You can create a new Project by right-clicking on the Package Explorer >> New >> Java Project.)
2. Extend Applet and import it.
- add "extends Applet" at the end of the class declaration.
- Press Ctrl+Shift+O to organize imports automatically.
It should look like this:
public class Renderer extends Applet{
}
Since we have extended an Applet (inheritance), Java will look for the paint() and init() methods. As we will be defining these methods ourselves rather than using the one in the Applet method, so we use the "@Override" keyword.
The two methods will look like this (Make sure to import Graphics) (changes in Bold):
import java.awt.Graphics;
public class Renderer extends Applet{
@Override
public void init() {
}
@Override
public void paint(Graphics g) {
}
}
In the init() method, we want to do the following:
- Set the size of the window.
- Set the color of the Background
- Create the Tilemap.
So we add the following lines of code:
setSize(800, 480);
setBackground(Color.BLACK);
createTilemap();
Eclipse will give you an error as follows:
5. Click on the 1 quickfix: Create method 'createTilemap()'.
This should create a method as follows:
private void createTilemap() {
}
We must do two things in the Tilemap() method.
1. We need to create a two-dimensional array. We will call it tilemap and call its height rows and its width columns.
2. Using a random number generator, we will fill tilemap with integers between 0 and 4, inclusive.
Let's do these two things:
1. Creating a 2D Array
Before we begin, to make things easier, we will create three static variables at the top of the class.
- Directly below "public class Renderer extends Applet {", add the following:
static int[][] tilemap;
static int rows, columns;
This creates a static (class-wide) two-dimensional Array called tilemap and two integers called rows and columns.
Scroll back inside the createTilemap() method. We will now define the three variables by declaring the following:
tilemap = new int[50][30];
rows = tilemap.length;
columns = tilemap[1].length;
- The first line creates a new 2D Array with 50 elements, which each contain 30 elements.
- tilemap.length is 50, as tilemap contains 50 elements.
- Each of these 50 elements contain 30 elements. Therefore, tilemap[1] refers to the element with index 1 in this 50 element list (the second element of fifty).
Note: Remember that indexes start at 0.
Note 2: We can refer to all 50 elements in tilemap using the indexes: 0 through 49.
- To fill the tilemap Array randomly, we first create a new Random object:
Random r = new Random();
- Then we use two for loops to fill each index with a random number between 0 and 4, inclusive:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
tilemap[i][j] = r.nextInt(5);
}
}
Note: Recall that tilemap[i][j] refers to the spot with coordinates (i, j) inside the 2D array.
Refer to this simplified illustration if you are confused!
FIGURE 2-36: Renderer Class, createTilemap()
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
public class Renderer extends Applet {
static int[][] tilemap;
static int rows, columns;
@Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
createTilemap();
}
private void createTilemap() {
tilemap = new int[50][30];
rows = tilemap.length;
columns = tilemap[49].length;
Random r = new Random();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
tilemap[i][j] = r.nextInt(5);
}
}
}
@Override
public void paint(Graphics g) {
}
}
Lesson #2-29: Painting the Tilemap
1. Create a square with side length 16 pixels - 50 across and 30 down (800 x 480).
2. Give this square a random color based on the integer value (0 to 4, inclusive) inside the tilemap.
- We begin Scroll to the paint(Graphics g) method. - Add the following code inside the method:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns;
}
}
This is the same nested for loop we saw in the createTilemap() method. We will use i and j to refer to locations in the 2D Array.
We want to translate this (i, j) location into a coordinate system of (16*i, 16*j), because we want to represent, for example, (50, 30), as (800, 480).
So within the inner for loop, we add the following in BOLD:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns;
int mod_i = 16*i;
int mod_j = 16*j;
}
}
Note: The underscore "_" does not have any meaning. It is just part of the variable names, which stand for modified I and modified J.
Now directly below the two variable declarations (and still within the inner for loop), we need to create a switch that takes tilemap[i][j] as the key (recall that switches are used to compare the value of a key against cases) and compare with the integers 0 through 4, inclusive.
For each case, we will set the color of g, which needs to be set directly before you paint an object, and then paint a rectangle on the screen at the coordinates (mod_i, mod_j).
The full class will now look like this:
FIGURE 2-37: RENDERER CLASS, Completed
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.util.Random;
public class Renderer2 extends Applet {
static int[][] tilemap;
static int rows, columns;
@Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
createTilemap();
}
@Override
public void paint(Graphics g) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
int mod_i = 16*i;
int mod_j = 16*j;
switch (tilemap[i][j]) {
case 0:
g.setColor(Color.RED);
g.fillRect(mod_i, mod_j, 16, 16);
break;
case 1:
g.setColor(Color.BLUE);
g.fillRect(mod_i, mod_j, 16, 16);
break;
case 2:
g.setColor(Color.YELLOW);
g.fillRect(mod_i, mod_j, 16, 16);
break;
case 3:
g.setColor(Color.WHITE);
g.fillRect(mod_i, mod_j, 16, 16);
break;
case 4:
g.setColor(Color.GREEN);
g.fillRect(mod_i, mod_j, 16, 16);
break;
}
}
}
}
private void createTilemap() {
tilemap = new int[50][30];
rows = tilemap.length;
columns = tilemap[49].length;
Random r = new Random();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
tilemap[i][j] = r.nextInt(5);
}
}
}
}
In the next lessons, we will be applying these techniques to create our levels, and eventually introduce collision detection.
I hope that this lesson made sense to everyone! I know that everyone is at different levels of Java experience and understanding, and I try to find a good balance as to not bore people and to not leave people behind. I might assume that you remember something from a previous lesson, but you might have forgotten it already. So let me know if you need anything better explained. I'd be glad to do that for you.
And thank you to everyone who liked Kilobolt Studios on Facebook! We have surpassed 1,000 likes and it is all because of your help.
In the next few months, Kilobolt will expand and offer more tutorials, better games, and a super-cool website. If you would like to help us, please consider donating!