As we get deeper into the series, I want to add character upgrades, different types of platforms and power ups, and much more.
But first, let us talk about the game thread and the game loop.
(*Name not final)
Lesson #2-3: Implementing a Thread:
As mentioned in the previous unit, threads are a way of running simultaneous processes.
We will be adding a thread to our code like so:
Figure 2-4: start() in StartingClass.java
@Override
public void start() {
Thread thread = new Thread();
thread.start();
}
Simple right? The first line creates a new instance of a thread (a Thread object called "thread"), and the second line starts the thread.
When you call: thread.start(); , however, nothing will happen. Why?
Refer to this example from Lesson #1-21:
Figure 2-5: Example of a Thread
Thread thread = new Thread() {
public void run() {
for (int i = 0; i < 10; i += 2) {
System.out.println("hello");
}
}
};
1. Implement the Runnable interface by adding: "implements Runnable" to the class declaration like so:
public class StartingClass extends Applet implements Runnable{...
2. Create a run() method in the class by typing out run and then pressing Ctrl + Space and selecting the first option: run() : void. It will auto complete the method for you.
When you try to create a run method, it will give you the following information:
So to "bridge" or connect this newly created run() method and the thread that we have created above:
3. Go back to this statement in the start method:
Thread thread = new Thread();
and add "this":
Thread thread = new Thread(this);
We will talk more about "this" in the future. It is quite a flexible keyword, and therefore I think it's best if we talk about it from another perspective with more understanding. For now, think of it as "this" class. More specifically, "this" instance of the class.
The final result:
Figure 2-6: StartingClass.java
package kiloboltgame;
import java.applet.Applet;
public class StartingClass extends Applet implements Runnable {
@Override
public void init() {
}
@Override
public void start() {
Thread thread = new Thread(this);
thread.start();
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
More sophisticated game loops will be used in our later games, but for our purposes, all our game loop needs to do is the following:
1. Update characters
2. Update environment
3. Repaint the scene.
4. Sleep for 17 milliseconds.
Why 17 milliseconds you ask? I'll tell you why.
I'm sure many of you know that when you go on YouTube and watch the Epic Rap Battles or something, you are seeing a sequence of still images that are changing fast enough to give your brain the illusion of fluid motion. The number of times that the image changes in one second is referred to as FPS or frames per second (frame rate).
At about ~30, we are able to see a smooth movement in games and movies; however, 60 fps is what most people consider an ideal to have no noticeable glitches or stuttering.
Sleeping for 17(1000/60) milliseconds each time that the game loop runs means that the game will update every 17 milliseconds (which results in 60 updates per second). Of course this assumes that the computer is capable of handling the processes every 17 milliseconds and can be disastrous when the machine slows down (hence this is a bad game loop), but for the purposes of our simple Java game on your modern day computer (and for this beginner's tutorial), it is simple, effective, easy to implement, and very intuitive.
So first we create a game loop in the run() method of the class:
1. This loop will be a while loop, and will run indefinitely. To make a while loop run forever, we just write true as the condition for the loop:
while(true){
}
2. Within this add the following segment of code:
repaint(); // this calls paint
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
Your run() method will look like this:
Figure 2-7: run() in StartingClass.java
@Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
repaint(); - built in method - calls the paint method (in which we draw objects onto the screen). We haven't created the paint method yet, but every 17 milliseconds, the paint method will be called..
Whenever we do something that may fail (like Thread.sleep(17);) the Java Compiler gives us an error saying that we need to surround the statement with a Try and Catch.
1. In try, we attempt to do something, like sleep.
2. If something goes wrong, then the catch will save information regarding errors, and will print it to a console.
Don't worry too much about it. It's just a built-in fail-safe system. It won't fail here. Just click the suggested quick fix.
At this point the StartingClass.java will look like this:
Figure 2-8: StartingClass.java
package kiloboltgame;
import java.applet.Applet;
public class StartingClass extends Applet implements Runnable {
@Override
public void init() {
}
@Override
public void start() {
Thread thread = new Thread(this);
thread.start();
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
This will be a short lesson that should wrap up most of our setup process.
We briefly talked about the four methods that we setup in Day 1: init(), start(), stop(), and destroy().
These four methods run according to the program's life cycle. We will now discuss the init() method.
When the applet runs for the first time, it will run the init() method (much like how a typical program runs the main(String args[]) method).
So within this method, we define certain parameters for the applet including:
1. Size of the applet
2. Background color.
3. Applet Title.
Inside this method, we will be adding
1. setSize(800, 480);
to change the size to 800 pixels by 480 pixels (the most common Android resolution)
2. setBackground(Color.BLACK);
to set background with the Color Black. NOTE: Color.BLACK refers to a constant called BLACK in the Color superclass, and hence you must import Color:
This statement makes sure that when the game starts, the applet takes focus and that our input goes directly into it. If this is not enabled, then you would have to click inside the applet before it starts handling keyboard events.
4. Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Q-Bot Alpha");
Here again, you must import Frame to create a Frame object called frame. This is slightly complicated, but just know that the first line assigns the applet window to the frame variable an the second line just sets the title to be Q-Bot Alpha.
At this point, you will have this:
Figure # 2-9: StartingClass.java, end of Day 2
package kiloboltgame;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Frame;
public class StartingClass extends Applet implements Runnable {
@Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
setFocusable(true);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Q-Bot Alpha");
}
@Override
public void start() {
Thread thread = new Thread(this);
thread.start();
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Ctrl+Shift+O: Auto import code (may import the wrong classes)
Ctrl+Shift+F: Auto format code into proper indents
Ctrl+Space: Open auto complete suggestions.
Thank you everyone for reading, and feel free to leave comments and questions below!

KiloboltGame - Day 2 |