-end-
Solutions
Chapter 3. Slick0120: Starting your program*
It is licensed under the Creative Commons Attribution License:
http://creativecommons.org/licenses/by/3.0/
2013/02/04 08:23:58 -0600
Summary
Learn how and why you should extend the BasicGame class instead of implementing the Game
interface directly. Learn about the behavior of the constructors for the AppGameContainer class.
Learn about the behavior of the setup and getDelta methods that are called by the start method of
the AppGameContainer class.
3.1. Table of Contents
General background information
Behavior of an object of the AppGameContainer class
Behavior of an object that implements the Game interface
The constructors for the AppGameContainer class
The setup method of the AppGameContainer class
The getDelta method of the GameContainer class
The gameLoop method of the AppGameContainer class
3.2. Preface
This module is one in a collection of modules designed to teach you about the anatomy of a game
engine.
Although the modules in this collection will concentrate on the Java game library named Slick2D,
the concepts involved and the knowledge that you will gain is applicable to different game engines
written in different programming languages as well.
Viewing tip
I recommend that you open another copy of this module in a separate browser window and use the
following links to easily find and view the listings while you are reading about them.
Listings
Listing 1 . The main method.
Listing 2 . The start method of the AppGameContainer class.
Listing 3 . Constructor for the AppGameContainer class that takes a single parameter.
Listing 4 . Constructor for the AppGameContainer class that takes four parameters.
Listing 5 . The getDelta method of the GameContainer class.
Listing 6 . Source code for Slick0120a.java
3.3. Preview
The main purpose of this module is to analyze the behavior of the Slick2D game engine when you
start a Slick2D game running.
What you have learned
In previous modules, you learned how to download Slick2D and how to install Slick2D in such a
way that you can easily compile and execute Slick2D programs from the command line with no
need for a high level IDE such as Eclipse or NetBeans.
You also learned what we often mean when we speak of a "game engine" and how that
terminology relates to a "software framework."
You learned how to write a minimal Java application in conjunction with a set of Slick2D jar files
to create your own Slick2D game engine. Using that program as an example, you learned about the
overall structure of the Slick2D game engine.
You learned that game engines are typically service provider programs and you learned about a
common set of services that is provided by most game engines.
You learned about the two cooperating objects that form the heart of the Slick2D game engine.
An object instantiated from a subclass of the Slick2D class named GameContainer .
An object instantiated from a class that implements the Slick2D interface named Game .
And last but not least, you learned about the five abstract methods declared in the interface named
Game :
boolean closeRequested()
String getTitle()
void init(GameContainer container)
void render(GameContainer container, Graphics g)
void update(GameContainer container, int delta)
What you will learn
You will learn how and why you should extend the BasicGame class instead of implementing the
Game interface directly.
You will learn about the constructors for the AppGameContainer class.
You learned earlier that you need to call the start method on an object of the
AppGameContainer class to cause your Slick2D game program to start running. You will learn
that the start method calls the following three methods:
setup
getDelta
gameLoop
You will learn about the behavior of the setup and getDelta methods in this module. An
explanation of the gameLoop method will be deferred until the next module.
3.4. General background information
Listing 6 shows the skeleton code for a basic game class named Slick0120a . This code differs from the skeleton code presented in earlier modules in two important respects:
1. The class named Slick0120a extends the Slick2D class named BasicGame instead of
extending Object and implementing the Slick2D interface named Game .
2. The class named Slick0120a does not override the methods named getTitle and
closeRequested . (They are overridden with default behavior in the BasicGame class.)
Instead, it overrides only the following methods that are declared in the Slick2D Game
interface:
1. init
2. update
3. render
The class named BasicGame
Regarding the first item in the above list, while it is technically possible to write a Slick2D game program by implementing the Game interface directly, the Slick2D helper class named
BasicGame implements the Game interface and provides a number of useful methods as well.
Therefore, by extending the BasicGame class, you not only implement the Game interface, you
also get the benefit of the methods that are defined in the BasicGame class.
The methods named init, update, and render
Note, however that the Basic game class does not define concrete versions of the methods named
init , update , and render . Therefore, you are still required to provide concrete versions of those
methods in your class that extends the BasicGame class (or some subclass of that class) .
The class named Slick0120a does provide concrete versions of methods as indicated in the second
The methods named getTitle and closeRequested
Further regarding the second item in the above list, the class named BasicGame does provide concrete versions of the methods named getTitle and closeRequested . Therefore, unless you need
to provide different behavior for those two methods, you don't need to override them in your new
class that extends the BasicGame class.
3.5. Discussion and sample code
Behavior of an object of the AppGameContainer class
Behavior of an object that implements the Game interface
The constructors for the AppGameContainer class
The setup method of the AppGameContainer class
The getDelta method of the GameContainer class
The gameLoop method of the AppGameContainer class
Listing 1 shows the main method for our new class named Slick0120a .
public static void main(String[] args)
throws SlickException{
AppGameContainer app =
new AppGameContainer(new Slick0120a());
app.start();//this statement is required
}//end main
Figure 3.1. Listing 1 . The main method.
Listing 1 . The main method.
We will dissect this code to make certain that we understand what it means and why we need it.
Two primary objects
You learned in an earlier module that a Slick2D game that runs as an application (not an applet)
consists of at least two cooperating objects:
1. An object instantiated from a subclass of the Slick2D class named GameContainer .
2. An object instantiated from a class that implements the Slick2D interface named Game .
Behavior of an object of the AppGameContainer class
The GameContainer object ( item 1 above ) manages the program startup and the game play after the game program starts running. For example, this is the object that manages the game loop.
As shown in Listing 1 , for the program named Slick0120a , this object is an object of the class named AppGameContainer , which extends the class named GameContainer .
The AppGameContainer class provides many public methods (including the method named start
, which is called in Listing 1 ) by which you can manipulate the behavior of the container object.
The authors of the Slick2D library did not intend for you to physically modify the source code in
the GameContainer class or the AppGameContainer class.
Behavior of an object that implements the Game interface
The behaviors of the methods of the Game object ( item 2 above ) are what distinguishes one Slick2D game from another Slick2D game.
You need not implement the Game interface directly. The authors of the Slick2D library provided
a helper class named BasicGame that implements the Game interface and provides a number of
useful methods. They intended for you to extend the BasicGame class and to override at least
three of the methods declared in the Game interface in order to provide the desired behavior for
your game..
As mentioned earlier, the class named Slick0120a extends the BasicGame class, thereby
implementing the Game interface and getting the benefit of methods defined in the BasicGame
class.
The code in the main method in Listing 1 instantiates an object of the Slick0120a class and passes that object's reference to the constructor for the class named AppGameContainer .
Therefore, Listing 1 instantiates both of the required objects and connects them in the manner intended by the authors of the Slick2D library.
Starting the game
The main purpose of this module is to analyze the behavior of the Slick2D game engine when you
start a Slick2D game running.
Listing 1 calls the start method on a reference to the AppGameContainer object. The source code for the start method is shown in Listing 2 .
public void start() throws SlickException {
try {
setup();
getDelta();
while (running()) {
gameLoop();
}
} finally {
destroy();
}
if (forceExit) {
System.exit(0);
}
}//end start
Figure 3.2. Listing 2. The start method of the AppGameContainer class.
Listing 2. The start method of the AppGameContainer class.
Copyright and license information
Copyright and license information:
I was unable to find any copyright or license information in the zip file that I downloaded
from http://slick.cokeandcode.com/index.php . I acknowledge that I am not the author of the code in that zip file and the copyrights for that material are held by someone other than
myself.
Constructors and methods
This and the next few modules will explore and discuss the constructors for the
AppGameContainer class (see Listing 1 ) along with salient aspects of the following methods that are called in Listing 2 :
setup
getDelta
gameLoop
The constructors for the AppGameContainer class
Listing 1 instantiates a new object of the AppGameContainer class by calling a constructor that takes a single parameter of the Slick2D interface type Game .
The source code for that constructor is shown in Listing 3 .
public AppGameContainer(Game game) throws SlickException {
this(game,640,480,false);
}//end constructor
Figure 3.3. Listing 3. Constructor for the AppGameContainer class that takes a single parameter.
Listing 3. Constructor for the AppGameContainer class that takes a single parameter.
A constructor with four parameters
The code in Listing 3 simply calls another overloaded version of the constructor passing four default parameters that specify a game window of 640x480 pixels.
The constructor that takes four parameters is shown in Listing 4 .
public AppGameContainer(Game game,
int width,
int height,
boolean fullscreen)
throws SlickException {
super(game);
originalDisplayMode = Display.getDisplayMode();
setDisplayMode(width,height,fullscreen);
}//end constructor
Figure 3.4. Listing 4. Constructor for the AppGameContainer class that takes four parameters.
Listing 4. Constructor for the AppGameContainer class that takes four parameters.
The first parameter is a reference to the game that is to be wrapped by the GameContainer
object. The code in Listing 4 passes that reference to its superclass, GameContainer , where it is saved in a protected variable of type Game named game . As a protected variable, it is accessible to all of the methods of the AppGameContainer class for use later.
Then Listing 4 saves the current display mode in a variable named originalDisplayMode , presumably to be used later.
Finally, Listing 4 calls the method named setDisplayMode to set the display mode to match the incoming parameters.
(This is the constructor that you would use if you wanted to cause the size of the game window to
be something other than the default of 640 by 480 pixels.)
The setup method of the AppGameContainer class
The setup method is fairly long and complicated. Most of the code in the method has to do with
the creation and formatting of the game window. I will skip over that code and leave it as an
exercise for interested students to analyze.
Initialization of the game
Finally a statement near the end of the setup method calls a method named init on a reference to
the Game object, passing a reference to the object of type AppGameContainer as a parameter.
This is what we would refer to as a callback that uses the reference to the Game object that was
passed to the constructor to call the method named init on the Game object.
The effect is to call the method named init belonging to the game program shown in Listing 6 .
This causes the initialization code (if any) that you have written into the overridden init method to
be executed. If the overridden version of the method has an empty body (as in Listing 6 ) , it simply returns without doing anything. This is how your game gets initialized.
The getDelta method of the GameContainer class
The AppGameContainer class inherits a protected method named getDelta from its superclass
named GameContainer .
The getDelta method is called from the start method shown in Listing 2 .
What is delta?
An int parameter named delta is received by the update method shown in Listing 6 . (The update
method s a concrete version of the method having the same signature that is declared in the Game
interface.)
According to the documentation for the update method in the Game interface, delta is
"The amount of time that has passed since last update in milliseconds"
Having that time available can be valuable in some game programs. For example, you might like
for one of the actors to light a fuse on a bomb and have that bomb detonate some given number of
milliseconds later. In that case, the program would need real time information to know when to
detonate the bomb.
Listing 5 shows the source code for the getDelta method.
protected int getDelta() {
long time = getTime();
int delta = (int) (time - lastFrame);
lastFrame = time;
return delta;
}//end getDelta method
Figure 3.5. Listing 5. The getDelta method of the GameContainer class.
Listing 5. The getDelta method of the GameContainer class.
Without getting into the details, the method named getTime that is called in Listing 5 returns the amount of time, (with a resolution of one millisecond) , that has elapsed since a historical point in
time before the game started running.
The GameContainer class contains a protected instance variable of type long named lastFrame
that is used to store a time value.
The code in Listing 5
subtracts the time value stored in lastFrame from the current time,
converts the time difference to type int , saving it in delta , and
stores the current time in lastFrame .
stores the current time in lastFrame .
The difference between the two time values represents a time interval and that difference is
returned as type int .
Various methods in the AppGameContainer and GameContainer classes call the getDelta
method in such a way that the value of delta represents the time required to update and render one
frame when the program is running. (There are some other options as well that I may discuss in a
future module.)
When the method named update is called in Listing 6 , the incoming parameter named delta contains the number of milliseconds that have elapsed since the last time that the update method
was called.
When the method named getDelta is called in Listing 2 , the return value is discarded. This suggests that the call to the getDelta method in Listing 2 is made simply to cause the variable named lastFrame to be initialized with time that the start method was called.
The gameLoop method of the AppGameContainer class
That leaves us with one more method call from Listing 2 that we need to examine -- gameLoop . I anticipate that will be a fairly long discussion, so I am going to defer that discussion until the next
module.
3.6. Run the program
As explained earlier, the skeleton code in Listing 6 is different from the skeleton code that I presented in earlier modules. Therefore, I encourage you to copy the code from Listing 6 .
Compile the code and execute it, making changes, and observing the results of your changes.
Make certain that you can explain why your changes behave as they do.
3.7. Summary
The main purpose of this module was to analyze the behavior of the Slick2D game engine when
you call the start method to cause a Slick2D game program to start running.
You learned how and why you should extend the BasicGame class instead of implementing the
Game interface directly.
You learned about the behavior of the constructors for the AppGameContainer class.
You learned that the