Anatomy of A Game Engine 13.40
Anatomy of A Game Engine 13.40
Anatomy of A Game Engine 13.40
By:
R.G. (Dick) Baldwin
By:
R.G. (Dick) Baldwin
Online:
< http://cnx.org/content/col11489/1.13/ >
OpenStax-CNX
This selection and arrangement of content as a collection is copyrighted by R.G. (Dick) Baldwin. It is licensed under
the Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/).
Collection structure revised: February 7, 2013
PDF generated: October 3, 2015
For copyright and attribution information for the modules contained in this collection, see p. 290.
Table of Contents
1
2
3
4
5
6
iv
Chapter 1
1.2 Preface
Turning the crank
Given time limitations and other restrictions, it is not practical to teach those students much about the
inner working of such game engines. Therefore, I have decided to publish a series of modules on the anatomy
of a game engine that my students, (and other interested parties) can read to learn about those inner
workings.
First in a collection
Therefore, this module is the rst in a collection of modules designed to teach you about the anatomy of
a typical game engine (sometimes called a game framework) .
Java is the language with which I am the most comfortable. Hence, I can probably do a better job of
explaining the anatomy of a game engine that uses Slick2D than would be the case for a game engine
written in C++, C#, Python, or some other programming language.
Java has proven in recent years to be a commercially successful game programming language. For
example, I cite the commercial game named Minecraft 3 , written in Java, for which apparently millions
of copies have been sold. Also, Java is used for developing apps for Android.
Slick2D is free and the source code for Slick2D is readily available.
The overall structure of a basic Slick2D game engine is very similar to Dark GDK and XNA, and is
probably similar to other game engines as well.
Java is platform independent.
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 other game engines written in dierent
programming languages.
Purpose
The purpose of this module is to get you started, including showing you how to download and install
Slick2D, and how to compile and execute your rst Slick2D program. Future modules will start digging into
and explaining the inner workings of a basic Slick2D game engine.
This series of modules is not intended for beginning programmers. As a minimum, you should already
know about fundamental programming concepts such as if statements, for loops, while loops, method
or function calls, parameter passing, etc. Ideally, you will have some object-oriented programming knowledge
in a modern programming language such as Java, C#, C++, or possibly Python or JavaScript.
You should also be relatively comfortable with the command-line interface, directory or folder trees, batch
or script les, etc.
Finally, you should also be comfortable downloading and installing software on the machine and operating
system of your choice.
In this module, you will learn how to download and install Slick2D on a Windows XP, Vista, or Windows
7 machine and how to compile and execute a very simple Slick2D program. (If you are using a dierent
operating system, you will need to translate this information to your system of choice. However, since Java
is platform independent, the code details that I will discuss will apply to all or most platforms.)
1.2.1.1 Figures
Figure 1 (p. 9) . Output from Slick2D during program startup.
Figure 2 (p. 13) . A default Slick2D game window.
1.2.1.2 Listings
Listing 1 (p. 6) . Slick2D program named Slick0100a.java.
Listing 2 (p. 7) . The le named CompileAndRun.bat.
1.3 Preview
Most of the Slick2D tutorials that you will nd on the Internet will begin by telling you to download and
install a high-level IDE such as Eclipse or NetBeans. I won't do that.
While high-level IDEs are great for improving productivity for experienced programmers, I consider them
to be overkill for students just learning how to program. Not only are they overkill, they also hide many
details that beginning programmers need to understand.
Therefore, I will show you 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. All you will need is a text editor
(preferably color coded for Java syntax) , the free Slick2D distribution, and the free Java Development Kit
from Oracle.
JCreator 4
jGRASP 5
DrJava 6
Arachnophilia
(Note: as of 06/06/15, this is a 64-bit version of the distribution. The older 32-bit distribution is available
here 9 .)
4 http://www.jcreator.com/
5 http://www.jgrasp.org/
6 http://www.drjava.org/
7 http://www.arachnoid.com/arachnophilia/index.php
8 http://cnx.org/content/m45726/latest/slick-64.zip
9 http://cnx.org/content/m45726/latest/slick-1.zip
If you are not one of my students, you may prefer to go to the Slick2D 10 main page and select the link
to download the latest version of the distribution. Save that le because I will have more to say about it
later.
JDK Installation for Microsoft Windows 13 - Describes how to install the JDK on 32-bit and
64-bit Microsoft Windows operating systems.
Follow the link to the installation instructions for your system and follow those instructions to install the
Java Development Kit. When doing the installation, pay attention to the link that reads Updating the PATH
Environment Variable (Optional) 14 . This is where many of my students encounter installation diculties.
(Note that over time, some of these links may change. However, the general concepts involved
should continue to be relevant.)
There are also issues dealing with something called the
those issues later.
classpath
64-bit versions. Instructions for installing the 32-bit version were similar.)
Begin by creating a folder somewhere on your disk named Code (or some other similar name of your
choosing) .
Create three sub-folders under the Code folder having the following names:
jars
lwjglbin
Slick0100a (this will change from one program to the next)
(See Download source code (p. 14) to download folders named jars , lwjglbin , and
already populated with the minimum required 64-bit Windows-compatible software.)
Slick0100a
Using whatever program you can nd to open a zip le (I use a program named WinZip) , extract and
save the following les from the lib folder in the 64-bit Slick2D distribution that you downloaded earlier
.
lwjgl.jar
slick.jar
natives-windows.jar
10 http://slick.ninjacave.com/
11 http://www.oracle.com/technetwork/java/javase/downloads/index.html
12 http://docs.oracle.com/javase/7/docs/webnotes/install/index.html
13 http://docs.oracle.com/javase/7/docs/webnotes/install/windows/jdk-installation-windows.html
14 http://docs.oracle.com/javase/7/docs/webnotes/install/windows/jdk-installation-windows.html#path
5
There are many other les in the Slick2D distribution le, but we don't need them just yet. If we need them
in a future module, I will tell you.
These three les are needed to satisfy the classpath and java.library.path requirements that I
will describe later.
Copy the rst two jar les from the above list (p. 4) into your new folder named jars .
As you will see later, this results in the need to execute the following command in order to set the
classpath whenever you compile or execute a Slick2D program:
-cp .;../jars/slick.jar;../jars/lwjgl.jar
The third jar le
The third le in the above list (p. 4) applies to Windows only. If you are using a dierent system,
you should nd a similar le in the Slick2D distribution that applies to your system. (For example, the
Using whatever program you can nd to open a jar le (I use a program named WinZip) , extract the
following les from the le named natives-windows.jar :
jinput-dx8_64.dll
jinput-raw_64.dll
lwjgl64.dll
OpenAL64.dll
Copy these four les into your new folder named lwjglbin .
As you will see later, this results in the need to execute the following command in order to set the
java.library.path system property:
-Djava.library.path=../lwjgnbin
(These les can also be stored in the folder from which the program is being run and this will eliminate
the requirement to set the java.library.path if you prefer that approach.)
Slick0100a.java
(Be careful to ensure that the le has the correct extension, particularly if you create it with Windows
Notepad. An extension of .txt won't work.)
Carefully copy the code from Listing 1 (p. 6) into the text le. This is the le that you will attempt to
compile and run to conrm correct operation of your system.
Slick0100a
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.SlickException;
7
Table 1.1
CompileAndRun.bat
(Once again, be careful to ensure that the le has the correct extension, particularly if you create it with
Windows Notepad. An extension of .txt won't work.)
Carefully copy the contents Listing 2 (p. 6) into the text le. This is the le that you will use in your
attempt to compile and run your source-code le named Slick0100a.java . (Line breaks or wrapped lines
are not allowed. Make certain that your batch le has only seven lines of text exclusive of blank lines.)
Table 1.3
Figure 1 (p. 9) shows information produced by Slick2D when a compiled Slick2D program starts running.
The second window to appear should look something like Figure 2 (p. 13) .
10
11
12
13
Table 1.4
Figure 2 (p. 13) is a default Slick2D game window. As you will learn in the next module, this particular
Slick2D program has no interesting behavior. In eect, it is an "empty" game program. Therefore, the only
thing showing in the game window is a counter in the top left corner that shows the execution rate in frames
per second.
1.8 Summary
I showed you 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.
14
1.10 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Module name: Slick0100: Getting started with the Slick2D game library.
File: Slick0100.htm
Published: 02/03/13
Revised: 06/06/15 for 64-bit
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
15 http://cnx.org/content/m45726/latest/AllCode.zip
Chapter 2
Slick0110: Overview
2.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 will concentrate on the Java game library named Slick2D, the concepts involved
and the knowledge that you will gain is applicable to dierent game engines written in dierent programming
languages.
The purpose of this module is to teach you about some of the characteristics of game engines in general,
and to teach you how Slick2D ts those characteristics.
1 This
15
16
2.2.1.1 Figures
Figure
Figure
Figure
Figure
1
2
3
4
(p.
(p.
(p.
(p.
16)
22)
26)
29)
.
.
.
.
2.2.1.2 Listings
Listing 1 (p. 19) . Simplest Slick2D program.
Listing 2 (p. 20) . The le named CompileAndRun.bat.
Listing 3 (p. 28) . Beginning of the class named Slick0110a.
2.4 Preview
The purpose of this module is to teach you about some of the characteristics of game engines in general, and
to teach you how Slick2D ts those characteristics.
In the previous module, 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.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
17
To begin with, you will learn what we often mean when we speak of a "game engine." You will also
learn how that terminology relates to something that we often refer to as a "software framework."
You will learn how to write a minimal Java application in conjunction with a set of Slick2D jar les to
create your own Slick2D game engine. Using that program as an example, you will learn about the overall
structure of the Slick2D game engine.
You will learn that game engines are typically service provider programs and you will learn about a
common set of services that is provided by many game engines.
You will learn about the two cooperating objects that form the heart of the Slick2D game engine.
You will learn about the methods declared in the interface named Game .
inversion of control - In a framework, unlike in libraries or normal user applications, the overall
program's ow of control is not dictated by the caller, but by the framework.
2. default behavior - A framework has a default behavior. This default behavior must actually be
some useful behavior and not a series of no-ops.
3. extensibility - A framework can be extended by the user by selective overriding of framework code
in order to provide specic functionality
4. non-modiable framework code - The framework code, in general should not normally be modied
by the user. Users can extend the framework, but normally should not modify its code.
1.
In short, a framework is a computer program that helps you to write computer programs.
Under this denition, Slick2D in its raw form is not a game engine nor is it a framework. Instead, it is a
library of Java classes that you can use to create a framework or game engine.
In particular, if you combine the contents of the les named slick.jar and lwjgl.jar with the minimal
Java application shown in Listing 1 (p. 19) and described in Figure 1 (p. 16) , you will have created a game
engine. That combination is what I will refer to hereafter as the Slick2D game engine .
Having done that, the framework description given above (p. 17) is a good match for the Slick2D game
engine.
18
(A dierent approach is used to create a Slick2D program that will run as a Java applet, but I probably
won't get into Java applets in this collection of modules.)
I will use this program to explain the overall structure of the Slick2D game engine in this module. I will
explain the inner workings of the game engine in more detail in future modules.
19
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.SlickException;
org.newdawn.slick.Game;
20
Table 2.2
Listing 2 (p. 20) shows the contents of a batch le that you can use to compile and execute the code in
Listing 1 (p. 19) as was explained in an earlier module.
If you double-click the batch le named CompileAndRun.bat (or execute it in whatever manner
you prefer), two new windows should appear on your computer screen.
The rst window to appear should look similar to Figure 2 (p. 22) .
21
22
Table 2.4
Figure 2 (p. 22) shows typical information produced by Slick2D when the compiled Slick2D program
starts running.
The second window to appear should look something like Figure 3 (p. 26) .
23
24
25
26
Table 2.5
Figure 3 (p. 26) is a default Slick2D game window. This Slick2D program (see Listing 1 (p. 19) ) has
no interesting behavior. In eect, it is an "empty" game program. Therefore, the only thing showing in the
game window is a counter in the top left corner that shows the execution rate in frames per second. (I will
The appearance of this empty game window matches the second item in the above list (p. 17) titled
. In particular, the default behavior of the Slick2D game engine is to display an empty
game window with an active FPS counter in the upper-left corner..
default behavior
27
cooperating objects
(For the remainder of this and future modules, unless I specically indicate that I am discussing a Slick2D
game applet, you can assume that I am talking about a Slick2D game program that runs as an application.)
game play after the game program starts running. For example, this is the object that manages the game
loop.
For the program shown in Listing 1 (p. 19) , this object is an object of the class named AppGameContainer , which extends the class named GameContainer .
The AppGameContainer class provides many public methods by which you can manipulate the
behavior of the container object. However, 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.
Slick2D game from another Slick2D game. The authors of the Slick2D library did intend for you to physically
modify the source code in the class that implements the Game interface. This is how you distinguish your
game from games written by others.
(Clarication: See a later discussion of a class named BasicGame , which implements the Game
interface. The authors of the Slick2D library did not intend for you to modify the source code in the
BasicGame class. Instead, they intended for you to subclass that class and to modify the behavior of the
Game object by overriding inherited abstract methods.)
28
Slick0110a
main
To begin with, note that the Slick0110a class implements the interface named Game . Therefore,
an object of this class satises the requirement for the second type of object identied as item 2 in the above
list (p. 27) . In other words, an object of this class is an object of the interface type Game .
Now note the rst statement in the main method in Listing 3 (p. 28) that instantiates a new object of
the class named AppGameContainer and saves that object's reference in the local variable named app
. This object satises the requirement for the rst type of primary object identied as item 1 in the above
list (p. 27) . In other words, an object of this class is an object of the type GameContainer because the
class named AppGameContainer is a subclass of GameContainer .
The class named AppGameContainer provides two overloaded constructors, each of which requires
an incoming parameter that is a reference to an object instantiated from a class that implements the interface
named Game . The code in the main method in Listing 3 (p. 28) uses the simpler of the two overloaded
constructors to instantiate a new object of the class named AppGameContainer and to save its reference
in the local variable named app .
The code in Listing 3 (p. 28) also instantiates a new object of the class named Slick0110a and passes
that object's reference to the constructor for the class named AppGameContainer . This is legal because
the class named Slick0110a implements the interface named Game .
At this point, the two objects described in the above list (p. 27) exist and occupy memory. From this
point forward, the container object knows about the game object and has access to its members.
Finally, the last statement in the main method calls the start method on the new container object
to cause the program to be initialized and to cause the game loop to start running.
29
Not much is required to provide a concrete method denition. All that is necessary to dene concrete
methods that return void is to replicate the signature of the abstract method and to provide an empty
body delineated by a pair of empty curly brackets. If the return type for the abstract method is not void,
the body of the concrete version must contain a return statement that matches the specied return type.
Figure 4
As you can see in Listing 1 (p. 19) , the new class named Slick0110a is not declared abstract.
Therefore, it must provide concrete versions of the inherited abstract methods shown in Figure 4 (p. 29) .
The init , update , and render methods in Listing 1 (p. 19) return void and are dened with
empty bodies. The getTitle and closeRequested methods do not return void. Therefore each of these
concrete versions contains a return statement of the required type.
As you learned earlier, the skeleton code for this Slick2D game program shown in Listing 1 (p. 19) can be
compiled and executed. However, it isn't very much fun to play because it doesn't do anything other than
to sit there and display the frames per second (FPS) rate in the upper-left corner of the game window.
Make no mistake about it, however, the game loop is running meaning that the game is active.
While this is probably the simplest Slick2D game program that can be written to run as a Java application,
it is not the recommended form for an empty Slick2D game skeleton. You will learn in the next module that
instead of implementing the Game interface directly, it is better to extend a Slick2D helper class named
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
30
BasicGame that implements the Game interface and provides some additional services that may be
useful to the game programmer. However, even when you do that, it is still necessary to write code to put
some meat on the skeleton's bones to create a playable game.
2.9 Summary
The main purpose of this module is to teach you about some of the characteristics of game engines and
frameworks in general, and to teach you how Slick2D ts those characteristics.
More specically, you learned what we often mean when we speak of a "game engine." You learned how
that terminology relates to something that we often refer to as a "software framework."
You learned how to write a minimal Java application in conjunction with a set of Slick2D jar les 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.
You learned about the methods declared in the interface named Game .
You learned that in order to write a game program using the Slick2D game engine that will run as a Java
application, you must, as a minimum, perform the steps shown in Figure 1 (p. 16) .
2.11 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
31
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
32
Chapter 3
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 dierent game engines written in
dierent programming languages as well.
33
34
3.2.1.1 Listings
Listing
Listing
Listing
Listing
Listing
Listing
1
2
3
4
5
6
(p.
(p.
(p.
(p.
(p.
(p.
35)
37)
38)
38)
39)
42)
.
.
.
.
.
.
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.
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 les 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.
Game
boolean closeRequested()
String getTitle()
void init(GameContainer container)
void render(GameContainer container, Graphics g)
void update(GameContainer container, int delta)
You will learn how and why you should extend the BasicGame class instead of implementing the
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:
Game
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.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
35
The class named Slick0120a extends the Slick2D class named BasicGame instead of
Object and implementing the Slick2D interface named Game .
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:
extending
a. init
b. update
c. render
Regarding the rst item (p. 35) 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 benet of the
methods that are dened in the BasicGame class.
Note, however that the Basic game class does not dene 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 item
(p. 35) in the above list.
Further regarding the second item (p. 35) 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 dierent behavior for those two methods, you don't need to override them in your new class that
extends the BasicGame class.
main
Slick0120a
We will dissect this code to make certain that we understand what it means and why we need it.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
36
after the game program starts running. For example, this is the object that manages the game loop.
As shown in Listing 1 (p. 35) , 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 (p. 35) ) 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.
37
This and the next few modules will explore and discuss the constructors for the AppGameContainer
class (see Listing 1 (p. 35) ) along with salient aspects of the following methods that are called in Listing
2 (p. 37) :
setup
getDelta
gameLoop
2 http://slick.ninjacave.com/
38
Listing 3 . Constructor for the AppGameContainer class that takes a single parameter.
public AppGameContainer(Game game) throws SlickException {
this(game,640,480,false);
}//end constructor
Table 3.3
The code in Listing 3 (p. 38) 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 (p. 38) .
Listing 4 . Constructor for the AppGameContainer class that takes four parameters.
public AppGameContainer(Game game,
int width,
int height,
boolean fullscreen)
throws SlickException {
super(game);
originalDisplayMode = Display.getDisplayMode();
setDisplayMode(width,height,fullscreen);
}//end constructor
Table 3.4
The rst parameter is a reference to the game that is to be wrapped by the GameContainer object.
The code in Listing 4 (p. 38) 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 (p. 38) saves the current display mode in a variable named originalDisplayMode ,
presumably to be used later.
Finally, Listing 4 (p. 38) 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.)
39
Finally a statement near the end of the setup method calls a method named init on a reference to
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 eect is to call the method named init belonging to the game program shown in Listing 6 (p. 42)
. 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 (p. 42) ) , it
simply returns without doing anything. This is how your game gets initialized.
the
What is delta?
int parameter named delta
An
(The
the
update
Game
is received by the
update
method s a concrete version of the method having the same signature that is declared in
interface.)
update
method in the
Game
"The amount of time that has passed since last update in milliseconds"
interface, delta is
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 (p. 39) shows the source code for the getDelta method.
getDelta() {
getTime();
(int) (time - lastFrame);
time;
return delta;
}//end getDelta method
Table 3.5
Without getting into the details, the method named getTime that is called in Listing 5 (p. 39) 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 (p. 39)
subtracts the time value stored in lastFrame from the current time,
converts the time dierence to type int , saving it in delta , and
stores the current time in lastFrame .
40
The dierence between the two time values represents a time interval and that dierence 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 (p. 42) , 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 (p. 37) , the return value is discarded. This
suggests that the call to the getDelta method in Listing 2 (p. 37) is made simply to cause the variable
named lastFrame to be initialized with time that the start method was called.
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 start method of the AppGameContainer class calls the following three
methods:
setup
getDelta
gameLoop
You learned about the behavior of the
setup
and
getDelta
gameLoop
3.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Module name: Slick0120: Starting your program
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
41
File: Slick0120.htm
Published: 02/04/13
Revised: 06/09/15
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
Slick0120a
42
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.SlickException;
43
Table 3.6
-end-
44
Chapter 4
4.2 Preface
This module is one in a collection of modules designed to teach you about the anatomy of a game engine.
1 This
45
46
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 dierent game engines written in
dierent programming languages as well.
4.2.1.1 Figures
Figure 1 (p. 55) . Screen output from program named Slick0130a.
4.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
4.3 Preview
What you have learned
The main purpose of this and the previous module is to analyze the behavior of the Slick2D game engine
when you call the start method to cause a Slick2D game program to start running.
In the previous module, 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 start method of the AppGameContainer class (see Listing 1 (p. 48) )
calls the following three methods:
setup
getDelta
gameLoop
You learned about the behavior of the
setup
and
getDelta
gameLoop
methods.
about a property of the GameContainer class named running , and how it is used by the start
method to keep the game loop running,
about the salient features of the gameLoop method of the AppGameContainer class,
about the updateAndRender method of the GameContainer class and how it decides when
and if to call the update and render methods of the object of the Game class that is wrapped
in the container,
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
47
The initial value of this variable is true and as near as I can tell, it only goes false
method inside a
while
loop
48
As you can see in Listing 1 (p. 48) , the gameLoop method is called repeatedly while the variable
named running is true. Each time it returns, it is called again.
I will refer to each call to the gameLoop method as one iteration of the game loop in the discussion
that follows.
gameLoop
method of the
AppGameContainer
49
A verbal description
This is my verbal description of what happens each time the start method calls the gameLoop
method.
First the gameLoop method gets the value for delta (the elapsed time since the call to the gameLoop
method during the previous iteration of the game loop) .
If the display (the game window) is not visible and a property named updateOnlyOnVisible is true,
the gameLoop method takes appropriate action. I will leave it as an exercise for interested students to
analyze those actions. (The program goes to sleep for 100 milliseconds.)
If the display is visible, the gameLoop method calls the updateAndRender method of the
GameContainer class passing delta as a parameter. Upon return, the gameLoop method performs
some housekeeping tasks and terminates.
50
51
Table 4.3
gameLoop
updateAn-
(I will not discuss those actions that represent communication with the hardware via the Lightweight
Java Game Library (lwjgl) as well as a few other housekeeping actions) .
The updateAndRender method begins by selecting between normal delta and "smooth deltas."
(Smooth delta values essentially represent a moving average of individual delta values computed in a
somewhat roundabout way.)
The update method of the Game object will be called none, one, or more times during each iteration
of the game loop on the basis of the contents of two variables named minimumLogicInterval and
maximumLogicInterval .
The default value for minimumLogicInterval is 1. The default value for maximumLogicInterval
is 0. Methods are provided by which you can change the values of these two variables.
The render method of the Game object will be called only once during each iteration of the game
loop following the call or calls to the update method.
If storedDelta is less than minimumLogicInterval , don't call update during this iteration
of the game loop.
If storedDelta is greater than or equal to minimumLogicInterval and maximumLogicInterval
has a value of 0, call the update method once passing storedDelta as a parameter. Then set
storedDelta to zero to set the accumulated value back to 0.
If storedDelta is greater than minimumLogicInterval and maximumLogicInterval is not
equal to zero, call the update method several times in succession (if needed) during this iteration of
the game loop, passing a value for delta during each call that is less than or equal to storedDelta .
Continue this process until the sum of the delta values passed in the method calls equals storedDelta
.
Possible outcomes
This algorithm results in the following possible outcomes regarding calls to the
each iteration of the game loop prior to calling the render method:
1.
2.
3.
4.
No call at all .
One call with a delta value of zero .
One call with a non-zero value for delta .
Multiple calls, each with a non-zero value for delta
update
method during
Item 1 (p. 51) represents a situation where you don't want to execute update code for values of delta
that are below a certain threshold and you prefer to execute update code less frequently using accumulated
values of delta instead.
Item 2 (p. 51) represents a situation where the paused property has been set to true and no updates
should be performed. (This situation is indicated by a delta value of zero, which can be tested by code in
52
Item 3 (p. 51) represents a situation where you are willing to execute the code in the update method
once during each iteration of the game loop using the incoming value of delta.
Item 4 (p. 51) represents a situation where you need to execute the code in the update method two or
more times in succession during each iteration of the game loop with the total value of delta being divided
into smaller values.
Although there is some tedious housekeeping code in Listing 4 (p. 52) , one call to the render method
is made during each iteration of the game loop provided that the game window has the focus or a property
named alwaysRender is true.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
53
alwaysRender
54
55
Table 4.5
The text in the upper-left corner of Figure 1 (p. 55) is the rate in frames per second that the game
loop is running.
(Two frames per second in this case.) This value is placed there by default. The
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
56
GameContainer
class provides a public method named setShowFPS that you can call whenever you
have access to the AppGameContainer object to disable or enable the display of this information.
The reported value for FPS is always an integer. On my computer, it bounces back and forth between 2
and 3 frames per second when this program is running.
The rst line of text near the center of Figure 1 (p. 55) shows the computed value of the total elapsed time
in seconds since the game loop started running. As you will see later, this value is computed by accumulating
successive values of the incoming delta parameter in the update method.
If you compile and run this program, you should see this value counting up in one-half second increments,
which is consistent with a frame rate of two frames per second.
The second line of text near the center of Figure 1 (p. 55) shows the value of delta received by the most
recent call to the update method. On my computer, this value seems to range between 499 and 501
milliseconds, which is consistent with a frame rate of two frames per second.
Slick0130a
The instance variables that are declared in Listing 5 (p. 56) are used to compute and display the values
shown near the center of Figure 1 (p. 55) .
Slick0130a
57
A dierent constructor
Listing 6 (p. 57) calls a dierent overloaded constructor for the AppGameContainer class than I
have used in earlier modules.
This version of the constructor allows for setting the width and height of the game window. In this case,
the game window is set to a width of 400 pixels and a height of 200 pixels as shown in Figure 1 (p. 55) .
The last parameter to this constructor is described as a boolean parameter that allows for the selection
of a full-screen game window. As of this writing, I have been unable to get this to work. When I set the
third parameter to true, I get a compiler error. However, I haven't spent any time investigating what I might
be doing wrong.
57) .
Listing 7 (p. 57) calls the setTargetFrameRate on the GameContainer object passing 2 as a
parameter. The description of this method in the javadocs 4 is "Set the target fps we're hoping to get,"
4 http://slick.ninjacave.com/javadoc/org/newdawn/slick/GameContainer.html#setTargetFrameRate%28int%29
58
Listing 8 (p. 58) converts the incoming value of delta in milliseconds into seconds and adds it to the value
stored in the instance variable named totalTime that is declared in Listing 5 (p. 56) . The totalTime
value will be used to display the rst line of text near the center of Figure 1 (p. 55) .
Listing 8 (p. 58) saves the incoming value of delta in the instance variable named i ncrementalTime
that was also declared in Listing 5 (p. 56) . The value stored in incrementalTime will be used to display
the second line of text near the center of Figure 1 (p. 55) .
method.
59
Listing 9 (p. 59) begins by truncating the value of totalTime to only two decimal digits and saving
the truncated value in a local variable named time . I will leave it as an exercise for the student to analyze
the code that I used to do that.
Then Listing 9 (p. 59) calls the drawString method on the graphics context received as an incoming
parameter of type Graphics to display the value in the rst line of text near the center of Figure 1 (p.
55) .
The drawString method takes three parameters. The rst is the string that is to be drawn in the game
window and the next two are the horizontal and vertical coordinates for the location in which the string is
to be drawn.
Then Listing 9 (p. 59) calls the drawString method again to draw the saved value of delta from the
most recent call to the update method as the second line of text near the center of Figure 1 (p. 55) .
4.7 Summary
You learned about a property of the GameContainer class named running , and how it is used by the
start method to keep the game loop running.
You learned about the salient features of the gameLoop method of the AppGameContainer class.
You learned about the updateAndRender method of the GameContainer class and how it decides
when and if to call the update and render methods of the object of the Game class that is wrapped
by the container.
You touched on the dierence between normal delta and smoothed delta.
You learned about minimumLogicInterval and maximumLogicInterval and how the contents
of those two variables are used to determine if, when, and how many times to call the update method
during each iteration of the game loop. You also learned how the contents of these two variables are used to
determine the value that is passed as delta each time the update method is called.
You learned that the render method is normally called once and only once during each iteration of the
game loop.
You saw a simple example of how you can use the value of delta that is received by the update method
to control the behavior of a game program.
You learned that you can set the size of the game window when you instantiate an object of the
AppGameContainer class by passing dimension parameters to the constructor.
You learned that you can set the target frame rate by calling the setTargetFrameRate method on
the GameContainer object.
You learned how to display text in the game window.
60
4.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
Slick0130a
61
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.SlickException;
@Override
public void update(GameContainer gc, int delta)
throws SlickException{
//Compute and save total time since start in seconds.
62
Table 4.11
-end-
Chapter 5
5.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 dierent game engines written in
dierent programming languages as well.
The purpose of this module is to take a rst look at bitmap graphics in Slick2D.
1 This
63
64
5.2.1.1 Figures
Figure
Figure
Figure
Figure
Figure
1
2
3
4
5
(p.
(p.
(p.
(p.
(p.
71)
75)
77)
79)
83)
.
.
.
.
.
84)
85)
85)
86)
89)
.
.
.
.
.
5.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
1
2
3
4
5
(p.
(p.
(p.
(p.
(p.
5.3 Preview
What you have learned
In the previous module, you learned about a property of the GameContainer class named running
, and how it is used by the start method to keep the game loop running.
You learned about the salient features of the gameLoop method of the AppGameContainer class.
You learned about the updateAndRender method of the GameContainer class and how it decides
when and if to call the update and render methods of the object of the Game class that is wrapped
by the container.
You touched on the dierence between normal delta and smoothed delta .
You learned about minimumLogicInterval and maximumLogicInterval and how the contents
of those two variables are used to determine if, when, and how many times to call the update method
during each iteration of the game loop. You also learned how the contents of these two variables are used to
determine the value that is passed as delta each time the update method is called.
You learned that the render method is normally called once and only once during each iteration of the
game loop.
You saw a simple example of how you can use the value of delta that is received by the update
method to control the behavior of a game program.
You learned that you can set the size of the game window when you instantiate an object of the
AppGameContainer class by passing dimension parameters to the constructor.
You learned that you can set the target frame rate by calling the setTargetFrameRate method on
the GameContainer object.
You learned how to display text in the game window.
In this module, you will learn that while there are many classes, interfaces, and methods in the Slick2D
library with names that match classes, interfaces, and methods in the standard edition Java library, they
are not the same.
You will learn how to set the drawing mode so that bitmap images drawn in the game window will either
honor or not honor transparent pixels.
You will learn how to draw bitmap images in the game window using both the draw methods of the
Image class and the drawImage methods of the Graphics class.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
65
Many game programs communicate primarily with the player using interactive graphics. Sometimes those
graphics involve drawing bitmap images. Both the Slick2D Image class and the Slick2D Graphics class
provide methods for drawing bitmap images.
Sometimes game programs involve drawing shapes such as circles, rectangles, polygons, arcs, etc. The
Slick2D Graphics class and other classes such as the Slick2D Shape class provide methods for creating
and drawing such shapes and lling closed shapes with color.
And of course, some game programs involve a combination of the two.
This module concentrates on drawing bitmap images both honoring and not honoring transparent pixels.
The Slick2D library contains numerous classes, interfaces, and methods with names that match the names
in the Java standard edition library, such as Color , Graphics , Image , Line , Rectangle ,
Shape , Transform , TextField , etc.
You need to be aware, however, that even though the names are the same, and the behaviors may be
similar, these are not standard Java classes. Their behaviors will often be dierent from standard Java
classes. Therefore, ready access to the documentation at http://slick.ninjacave.com/javadoc/ 2 while you
are programming in Slick2D is very important even if you are a seasoned Java programmer.
The program that I will present in this module will illustrate some of the major dierences between the
two libraries insofar as graphics programming is concerned. For example, both libraries have a class named
Image , which has generally the same purpose in both libraries. However, the Image class in the Slick2D
library provides about ten dierent overloaded draw methods that you can call to draw images in the
game window.
The Image class in the Java standard library doesn't have any draw methods. Instead, it is necessary
to get a graphics context on the image and then call the drawImage method on that context to draw the
image.
Input images
This program uses two input images. An image le named background.jpg is used to create a
background in the game window. Figure 1 (p. 71) shows what that image looks like when viewed in the
Windows Paint program.
2 http://slick.ninjacave.com/javadoc/
66
67
68
69
Table 5.1
The second input image is a le named ladybug.png , which is a picture of a red and black ladybug
on a transparent black background. Figure 2 (p. 75) shows this image when viewed in the Windows Paint
program.
70
71
72
73
Table 5.2
Figure 3 (p. 77) shows the same ladybug image when viewed in the Windows Picture and Fax Viewer
program. Note that the black background from Figure 2 (p. 75) is transparent in Figure 3 (p. 77) .
74
75
Table 5.3
Figure 4 (p. 79) shows the same ladybug image when viewed in the Gimp image editor program. This
program provides even a dierent treatment for the transparent pixels.
76
77
Table 5.4
Figure 5 (p. 83) shows a screen shot of the game window while the program is running
78
79
80
81
Table 5.5
The same ladybug image is drawn three times in Figure 5 (p. 83) with dierent drawing parameters.
The leftmost image of the ladybug in Figure 5 (p. 83) is drawn with a scale factor of 0.75 and a drawing
mode that honors transparency: MODE_NORMAL.
The center image of the ladybug in Figure 5 (p. 83) is drawn using a dierent approach with a scale
factor of 1.0 and a drawing mode that honors transparency: MODE_NORMAL.
The rightmost image of the ladybug in Figure 4 (p. 79) is drawn using the same approach as
the leftmost image, a scale factor of 1.25, and a drawing mode that does not honor transparency:
MODE_ALPHA_BLEND.
As mentioned above, the two images of the ladybug with transparency were drawn using a Slick2D
constant named MODE_NORMAL .
The image of the ladybug on the right without transparency was drawn using a Slick2D constant named
MODE_ALPHA_BLEND .
These names seem to have been reversed. I would expect the constant with a name that includes the
words alpha and blend to honor transparency but that doesn't seem to be the case.
82
Slick0140a
The instance variables shown in Listing 1 (p. 84) and the values that they contain will be used later to
display the three ladybug images shown in Figure 5 (p. 83) .
There is nothing new in the constructor in Listing 1 (p. 84) .
main
83
init
method is shown in Listing 3 (p. 85) . There is quite a bit of new material in Listing
Listing 3 (p. 85) begins by instantiating two new Slick2D Image objects from the image les discussed
earlier and saving those object's references in two of the instance variables that were declared in Listing 1
(p. 84) .
(Note that in this case, the image les were located in the same folder as the source code for the program.
Therefore, a path specication to the image les was not needed.)
I will remind you again that the Slick2D
edition Java library.
Image
Image
You may have noticed that the FPS display is missing from the upper-left corner of Figure 5 (p. 83) .
That is because it was disabled by the call to the setShowFPS method in Listing 3 (p. 85) , passing false
as a parameter to the method.
The last statement in Listing 3 (p. 85) sets the target frame rate to 60 frames per second.
update
84
render
Listing 4 (p. 86) begins by calling the setDrawMode method on the incoming Graphics parameter
to set the drawing mode to MODE_NORMAL as described earlier. Then it calls one of the overloaded
draw methods of the background Image object and the ladybug Image object to draw the background
and the leftmost ladybug in Figure 5 (p. 83) .
Note that the drawing coordinates and the scale factor are passed to the draw method.
Also note that this drawing of the ladybug image honors transparent pixels.
After that, Listing 4 (p. 86) calls the setDrawMode method on the incoming Graphics parameter
to set the drawing mode to MODE_ALPHA_BLEND and calls the same draw method of the ladybug
Image object to draw the rightmost ladybug in Figure 5 (p. 83) .
Note that this drawing of the ladybug image does not honor transparent pixels.
Finally, Listing 4 (p. 86) calls the setDrawMode method on the incoming Graphics parameter to
set the drawing mode back to MODE_NORMAL and then calls the drawImage method on the incoming
Graphics parameter to draw the middle ladybug in Figure 5 (p. 83) . (This approach is similar to the
approach that would be used to draw an image using the standard edition Java library.)
Note that the reference to the ladybug Image object and the drawing coordinates are passed as
parameters to the drawImage method. Some of the overloaded drawImage methods provide scaling.
However, there is no scale parameter for this version of the drawImage method so the ladybug was drawn
at actual size.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
85
There are many overloaded versions of the draw and the drawImage methods.
That completes the discussion of the program named Slick0140a .
5.7 Summary
You learned that while there are many classes, interfaces, and methods in the Slick2D library with names
that match classes, interfaces, and methods in the standard edition Java library, they are not the same.
You learned that you can access the Slick2D documentation at http://slick.ninjacave.com/javadoc/ 3 .
You learned how to set the drawing mode so that bitmap images drawn in the game window will either
honor or not honor transparent pixels.
You learned how to draw bitmap images in the game window using both the draw methods of the
Image class and the drawImage methods of the Graphics class.
5.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
3 http://slick.ninjacave.com/javadoc/
86
Slick0140a
87
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
ladybug = null;
background = null;
leftX = 100;//leftmost position of ladybug
leftY = 100;
88
Table 5.10
-end-
Chapter 6
6.2 Preface
This module is one in a collection of modules designed to teach you about the anatomy of a game engine.
1 This
89
90
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 dierent game engines written in
dierent programming languages as well.
The purpose of this module is teach you how to make sprites move at a constant speed in front of an
image in the face of a widely varying frame rate. You will also learn about a rudimentary form of collision
detection.
6.2.1.1 Figures
Figure
Figure
Figure
Figure
Figure
rate.
1 (p.
2 (p.
3 (p.
4 (p.
5 (p.
6.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
6.3 Preview
What you have learned
In the previous module, you learned that while there are many classes and interfaces in the Slick2D
library with names that match the names of classes and interfaces in the standard edition Java library, they
are not the same.
You learned that you can access the Slick2D documentation at http://slick.ninjacave.com/javadoc/ 2 .
You learned how to set the drawing mode so that bitmap images drawn in the game window will either
honor or not honor transparent pixels.
You learned how to draw bitmap images in the game window using both the draw methods of the
Image class and the drawImage methods of the Graphics class.
In this module, you will learn how to make sprites move at a constant speed in front of an image in the
face of widely varying frame rates. You will also learn about a rudimentary form of collision detection.
2 http://slick.ninjacave.com/javadoc/
91
Following initialization, the Slick2D game engine switches back and forth between an update method
and a render method.
We write code to control the state of the game in the update method. We write code to display the
state of the game in the render method.
A sprite
According to one denition, a sprite is a computer graphic that may be moved on-screen and otherwise
We will use the image of the ladybug shown in Figure 1 (p. 94) as a sprite in two dierent programs that
I will explain in this module.
92
Table 6.1
We will cause that sprite to move in front of the background image shown in Figure 2 (p. 98) .
93
94
95
96
Table 6.2
A bouncing sprite
In particular, we will cause the sprite to bounce around inside the game window like a pool ball on a
pool table. Whenever it strikes an edge of the game window, it will bounce o in the opposite direction.
This process will continue until the program is terminated.
Sometimes it is important to cause the program to give the appearance of running at the target frame
rate even if it is actually running slower.
One example is when a sprite is moving across the game window. It is often desirable to cause the sprite
to move at the same overall speed regardless of the speed of the computer. For example, you probably
wouldn't want a missile to take a long time to reach its target on a slow computer and a short time to reach
its target on a fast computer.
I will explain a program in this module that is designed to achieve such a result. The upside is that you
can often achieve the appearance of the target frame rate in terms of the overall speed of the sprite. The
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
97
downside is that the motion of the sprite may be less smooth than would be the case if the computer were
actually running at the target frame rate.
Each time the update method is called, it receives an incoming parameter named delta whose value
is the number of milliseconds that have elapsed since the most recent call to the update method. In the
case of a highly varying frame rate, such as may occur when the render method is required to draw a
complex and constantly changing scene, the value of delta may vary signicantly from one call to the next
of the update method.
Fortunately, the value of delta can often be used to give the appearance of running at the target frame
rate even though the actual frame rate may be below the target. I will show you how to do that in this
module.
Slick0150a
98
99
100
101
Table 6.3
The screen shot in Figure 3 (p. 103) caught the ladybug in mid ight. As mentioned earlier, the next time
it collides with one of the edges of the game window, it will bounce o and move in the opposite direction
like a pool ball striking the cushion on the edge of a pool table.
As you learned in an earlier module, the text in the upper-left corner is the frame rate in frames per
second computed and automatically displayed by the game engine. You will see later that a target frame rate
of 60 frames per second was requested by calling the method named setTargetFrameRate and passing
60 as a parameter.
At 60 frames per second, a time interval of 16.6666 milliseconds would be required to complete each
frame. It appears that the setTargetFrameRate method truncates this value to an integer value of 16
milliseconds, which represents a frame rate of 62.5 frames per second. It also appears that the code that
displays the frame rate converts the actual frame rate to an integer for display. Hence you see an FPS value
of 62 in Figure 3 (p. 103) .
The traversalTime output that you see in Figure 3 (p. 103) is computed and displayed by the program
that we will examine shortly. This is the time required for the sprite to complete one round trip from the
right edge to the left edge and back to the right edge.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
102
If you compile and run this program, you will see that the
at around 3015 milliseconds.
traversalTime
Although it isn't shown here, a separate output on the command-line window reported the width of the
background image to be 414 pixels and the width of the sprite to be 48 pixels. The sprite is never allowed
to go outside the boundaries of the game window, so the one-way distance from the left edge to the right
edge is 366 pixels. (This is the distance that the upper-left corner of the sprite travels during the one-way
trip.) The round-trip distance is twice that, or 732 pixels.
You will see later that the sprite is caused to move horizontally by four pixels during each frame. At 62
frames per second, this represents a horizontal speed for the sprite of 248 pixels per second. At that speed,
the sprite should complete the round trip in 2952 milliseconds. That is close enough to the typical reported
time of 3015 milliseconds to validate the theoretical considerations.
When I compile and run this program, I see the sprite moving with a relatively smooth motion. Unless
your computer is very slow, you should probably see the same thing.
Slick0150a
103
bugX = 100;
bugY = 100;
bugWidth;
bugHeight;
Listing 1 (p. 105) consists entirely of instance variable declarations. The purpose of each of these variables
should become clear as they are used later in the code. No explanation beyond the embedded comments
should be needed at this point.
104
The
getTime
I am interpreting this to mean that the method will return the system time good to one millisecond
relative to a well-dened time origin.
(Standard Java uses January 1, 1970 as the origin or epoch of time but Slick2D may use a dierent origin.
Since we will be working with changes in time and not absolute time, the time origin doesn't matter.)
The init method in Listing 2 (p. 106) calls the getTime method to get and save the time in an
instance variable named oldTime . The values in this variable will be used later to compute the round-trip
time required for the sprite to move across the game window and back to the starting point at the right edge
of the window.
Listing 2 (p. 106) creates the ladybug Image object and the background Image object using code
that you have seen before, and stores those object's references in the instance variables named bug and
background .
Get, save, and display the widths and heights of the images
Then Listing 2 (p. 106) calls accessor methods to get, save, and display the widths and the heights of
the bug and background objects.
setTargetFrameRate
105
107) .
The code in Listing 3 (p. 107) uses a very simple approach to cause the sprite to exhibit motion.
Each time the update method is called, Listing 3 (p. 107) computes new location coordinate values
for the sprite, which are either increased or decreased by the values stored in xStep and yStep .
Repetitive displays of the sprite in the new locations by the render method produces the impression
that the sprite is moving.
The step values are multiplied by the contents of direction variables in Listing 3 (p. 107) , each of which
contains either +1 or -1, and the products are added to the current location coordinates.
As you will see shortly, the algebraic signs of the direction variables are changed each time the sprite
collides with an edge of the game window.
This code assumes a constant frame rate and does not correct for variations in the frame rate. In other
words, the size of the step taken during each frame is the same regardless of how long it takes to complete
a frame. If the computer is running below the target frame rate, the sprite will appear to move more slowly
than would be the case if the computer is running at the target frame rate.
Collision detection
The code in Listing 4 (p. 108) begins by detecting a collision of the right edge of the sprite with the right
edge of the game window and reverses the sprite's direction of motion when a collision occurs.
Note that if the rightmost portion of the sprite actually tries to move beyond the right edge of the game
window, it is stopped at the edge of the game window.
106
Table 6.7
Then the code in Listing 4 (p. 108) computes the elapsed time since the previous collision of the sprite
with the right edge of the game window and saves that time interval in the variable named traversalTime
. That traversalTime value will be displayed when the render method is called producing the output
shown in Figure 3 (p. 103) .
Listing 5 (p. 109) tests for collisions between the sprite and the other three sides of the game window
and takes appropriate action when a collision occurs. The code in these tests is less complex than in Listing
4 (p. 108) because they don't need to compute the traversalTime .
107
108
There is really nothing new in Listing 6 (p. 109) . Therefore, it shouldn't require an explanation beyond
the embedded comments.
Each time this method is called, the location of the sprite will have changed by a few pixels relative to
its previous location. Displaying the sprite in a new location each time the picture is drawn produces the
impression that the sprite is moving.
109
110
111
Table 6.10
112
Everything down to the last two lines of code in Listing 7 (p. 114) is the same as the program named
Slick0150a . At that point I inserted code that will cause an additional random time delay ranging from
0 to 43 milliseconds before the render method returns. I did this to simulate a situation in which the
rendering process is very complex and the time to render varies quite a lot from one frame to the next.
In this case, the average additional delay time should be about 21.5 msec. This makes it impossible to
maintain the target frame rate of 60 frames per second or 16.666 milliseconds per frame.
This additional delay should result in an average frame rate of about 46 or 47 frames per second, which
is consistent with the screen output shown in Figure 4 (p. 113) .
Not only does this code result in a reduction in the average frame rate, it also results in a wide variation
in the values of delta received by the update method on a frame to frame basis.
As before, the init method calls the setTargetFrameRate method requesting a frame rate of 60
frames per second. This guarantees that the minimum delta that will be received by the update method
will be in the neighborhood of 16 milliseconds. (The game loop won't be allowed to run any faster than 60
The last two lines of code in Listing 7 (p. 114) will cause the value of delta to be as large as about 43
milliseconds.
Therefore, the incoming delta values in the update method will vary between about 16 milliseconds
and about 43 milliseconds on a totally random basis from one frame to the next.
113
update
//
//
As before, the method begins by computing a new location for the sprite. However, the code in Listing
8 (p. 115) attempts to maintain a constant overall speed as the bug moves across the game window despite
the fact that the value of delta varies quite a bit from one frame to the next.
In order to accomplish this, the step size is caused to vary in proportion to delta or inversely with
the instantaneous frame rate. Given the earlier estimate that the value of delta can vary from about 16
milliseconds to about 43 milliseconds, the step size can vary from about 4 pixels per frame to about 10 pixels
per frame. When the value of delta is small, the step size will be small. When the value of delta is large,
the step size will be large.
As a result of the long time delays introduced into the render method, the average frame rate has
been slowed down to around 47 frames per second as shown in Figure 4 (p. 113) . However, as also shown
in Figure 4 (p. 113) , the traversal time continues to be close to the target of around 3000 milliseconds.
Therefore, the algorithm is deemed to be successful in maintaining a relatively constant overall speed of
motion.
This algorithm and the widely varying values of delta result in sprite motion that isn't as smooth as with
the program named Slick0150b . However, the sprite gets to where it needs to be when it needs to be
there despite widely varying values of delta, and that is the objective of the algorithm.
The last two statements in Listing 8 (p. 115) show an alternative approach that does not attempt to
correct for variations in the value of delta.
(This approach is essentially the same as was used in the program named
Slick0150a
above.)
When the rst two statements in Listing 8 (p. 115) are disabled and the last two statements in Listing
8 (p. 115) are enabled, the output is as shown in Figure 5 (p. 119) .
114
115
116
117
Figure 5 . Screen shot of the program named Slick0150b without correction for varying frame rate.
Table 6.13
Figure 5 (p. 119) shows the output of a system where the value of delta varies widely but no correction is
made for those variations. As you can see, the frame rate is reduced as in Figure 4 (p. 113) . As you can also
see, the traversal time is increased signicantly from around 3000 milliseconds to around 4300 milliseconds.
As a result, the sprite does not get to where it needs to be when it needs to be there.
6.7 Summary
In this module, you learned how to make sprites move at a constant speed in front of an image in the face
of a widely varying frame rate. You also learned about a rudimentary form of collision detection.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
118
draw
drawCentered
, and
drawFlash
methods
6.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Module name: Slick0150: A rst look at sprite motion, collision detection, and timing control
File: Slick0150.htm
Published: 02/04/13
Revised: 06/09/15 for 64-bit
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
119
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
bugX = 100;
bugY = 100;
bugWidth;
bugHeight;
120
Table 6.14
121
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
java.util.Random;
122
Table 6.15
-end-
Chapter 7
7.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 dierent game engines written in
dierent programming languages as well.
1 This
123
124
An earlier module titled A rst look at Slick2D bitmap graphics 2 introduced you to the use of bitmap
graphics in Slick2D. The purpose of this module is dig a little deeper into the use of bitmap graphics
7.2.1.1 Figures
Figure 1 (p. 130) . Output from the program named Slick0160a.
Figure 2 (p. 133) . One output from the program named Slick0160b.
Figure 3 (p. 136) . Another output from the program named Slick0160b.
7.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
7.3 Preview
Bitmap graphics are used in a variety of ways in game and simulation programming. Therefore, I will present
and explain two programs that dig more deeply into the use of bitmap graphics in Slick2D.
The rst program named Slick0160a calls the draw method of the Image class several times in
succession to illustrate some of the options available with the draw method. This program also illustrates
ipping an image. The output from this program is shown in Figure 1 (p. 130) .
2 http://cnx.org/contents/ec409a1f-e946-486a-a681-980d0ea996/Slick0140-A-rst-look-at-Slic
125
126
127
128
Table 7.1
The second program named Slick0160b illustrates the use of the drawFlash method to draw an
image in silhouette and to cause the silhouette to switch back and forth between two or more colors. The
program draws several spiders in silhouette. It causes a large spider to ash back and forth between a white
silhouette and a blue silhouette. A screen shot of the output from the program while the large spider is in
its white state is shown in Figure 2 (p. 133) .
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
129
130
131
Table 7.2
A screen shot of the output from the program while the large spider is in its blue state is shown in Figure
3 (p. 136) .
132
133
134
Table 7.3
In the previous module, you learned how to make sprites move at a constant speed in front of an image
in the face of widely varying frame rates. You also learned about a rudimentary form of collision detection.
draw
drawCentered
, and
drawFlash
methods
135
A complete listing of this program is provided in Listing 13 (p. 148) . As is my custom, I will break this
program down and discuss it in fragments.
Listing 1 (p. 137) shows the beginning of the class down through the constructor.
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.Color;
As usual, it is necessary to declare several import directives that point to classes in the Slick2D library.
Also, as in several previous modules, the new class extends the Slick2D class named BasicGame .
Listing 1 (p. 137) declares several instance variables, initializing some of them.
The constructor simply sets the title on the game window.
136
138) .
There is nothing in Listing 3 (p. 138) that you haven't seen in previous modules.
137
138
Table 7.7
The code in Listing 5 (p. 140) calls four dierent overloaded versions of the
image to draw the top four images in Figure 1 (p. 130) .
draw
The rst call to the draw method in Listing 5 (p. 140) simply draws the image unchanged with its
upper-left corner at the upper-left corner (the origin) of the game window.
The second call to the draw method in Listing 5 (p. 140) applies a color lter to the rabbit image and
draws it with its upper-left corner at 133,0.
I haven't found an explanation as to exactly how the color lter is applied. It appears from experimentation that the pixel color values in the original image are multiplied by the red, green, and blue color values
(expressed in the range from 0 to 1.0) in the color object that is passed as a parameter to the method. However, the Image class denes two constants named FILTER_LINEAR and FILTER_NEAREST
that may have something to do with how color ltering is applied.
The third call to the draw method in Listing 5 (p. 140) applies a scale factor of 0.5 to both dimensions
of the rabbit image and draws it with its upper-left corner at 266,0.
The fourth call to the draw method in Listing 5 (p. 140) resizes the rabbit image to a width of 128
pixels and a height of 192 pixels and draws the modied image with its upper-left corner at 335,0.
The code in Listing 6 (p. 141) calls three dierent overloaded versions of the draw method on the
rabbit image to draw the two images on the center left and the large image on the bottom left of Figure 1
(p. 130) .
139
The rst call to the draw method in Listing 6 (p. 141) simply draws another unchanged version of the
rabbit image in a new location, 0,133.
The second call to the draw method in Listing 6 (p. 141) extracts a rectangular section from the
original image and draws it the same size as the original image with its upper-left corner at 133,133.
The third and fourth parameters (32,32) specify the coordinates of the upper-left corner of the rectangle
that is extracted. The fth and sixth parameters (96,96) specify the coordinates of the lower-right corner
of the rectangle that is extracted.
The third call to the draw method in Listing 6 (p. 141) extracts a rectangular section from the original
image and draws it with a dierent size and also applies a color lter. I will leave it as an exercise for the
student to go to the Slick2D documentation 5 for an explanation of the eight parameters of type oat .
The previous examples have drawn the image in a location based on its upper-left corner. The statement
in Listing 7 (p. 141) draws the image on the center right in Figure 1 (p. 130) . However, instead of
positioning the image based on its upper-left corner, the image is drawn with its center located at 399,266.
The code in Listing 8 (p. 142) makes a call to the getFlippedCopy method of the Image class,
followed by a call to the draw method to draw the image in the bottom-right of Figure 1 (p. 130) . Note
that the rabbit is facing the opposite direction in that image. The boolean parameters specify whether
the image is to be ipped on the horizontal, vertical, or both axes. In this case, a value of true caused the
image to be ipped on the horizontal axis only.
5 http://slick.ninjacave.com/javadoc/org/newdawn/slick/Image.html
140
render
Slick0160a
The Slick2D Image class provides many additional capabilities that are not illustrated in this program.
I will leave it as an exercise for the student to explore them. However, there is one other set of three
overloaded methods named drawFlash that I will illustrate in this module. That is the topic of the next
section.
141
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.Color;
142
Table 7.12
There is nothing new or unusual about the code in Listing 9 (p. 143) . Therefore, no explanation beyond
the embedded comments should be needed. You might want to note the instance variables at the beginning
of the class. They will be used in the code that I will describe later.
(Other programming options are available regarding if, when, and how many times the
is executed during one iteration of the game loop.)
update
method
Each time the update method is called, the incoming value of delta is added to the value in a variable
named timeAccumulator . When the accumulated time meets or exceeds the value of ashInterval
6 http://cnx.org/contents/c92f070e-494f-4eb1-a0b9-e36abe4359fd
143
, the color is switched from white to blue, or from blue to white, depending on its current value. Also the
time accumulator is set to zero and a new white/blue cycle begins.
The color switch should occur approximately every 128 milliseconds, or about eight times per second.
After setting the drawing mode to honor transparency and setting the background color to red, the code
in Listing 11 (p. 145) causes the three images of the spider along the top of Figure 2 (p. 133) to be displayed
each time the render method is called. (Recall that the names of the drawing mode constants appear to
The call to the draw method in Listing 11 (p. 145) displays the spider image in the upper-left corner
of Figure 2 (p. 133) .
The rst call to the drawFlash method calls one of three overloaded versions of the drawFlash
method. This version of the method draws a white silhouette of the spider at a location specied by the
parameters, 133,0.
The second call to the drawFlash method draws a silhouette of the spider at a location of 266,0, with
a width of 131 pixels, a height of 128 pixels and a blue color.
Note that none of the code in Listing 11 (p. 145) depends on the logic that is executed in the update
method. Therefore, the three images appear to be static despite the fact that they are being redrawn about
60 times per second.
The call to the drawFlash method in Listing 12 (p. 146) produces the large ashing spider at the
bottom of Figure 2 (p. 133) and Figure 3 (p. 136) .
144
This is the same version of the drawFlash method that was called to produce the blue spider in the
upper-right corner of Figure 2 (p. 133) . However, in this case, the third and fourth parameters specify that
the spider should be drawn with a width of 262 pixels and a height of 256 pixels.
More importantly, rather than passing a constant color as the last parameter, Listing 12 (p. 146) passes
the reference to the Color object stored in the variable named silohetteColor . Recall that the color
represented by that object is periodically switched between white and blue in the update method of Listing
10 (p. 144) . This causes the color of the spider to switch between white and blue.
render
Slick0160b
7.7 Summary
In this module, you learned about using the
Image 7 class.
draw
drawCentered
, and
drawFlash
methods of the
isKeyDown
isMouseButtonDown
getMouseX
getMouseY
7 http://slick.ninjacave.com/javadoc/org/newdawn/slick/Image.html
8 http://slick.ninjacave.com/javadoc/org/newdawn/slick/Input.html
145
7.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
146
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.Color;
rabbitWidth = rabbit.getWidth();
rabbitHeight = rabbit.getHeight();
System.out.println(
147
Table 7.16
148
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.Color;
149
Table 7.17
-end-
150
Chapter 8
8.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 dierent game engines written in
dierent programming languages as well.
The purpose of this module is to explain some aspects of mouse and keyboard input.
8.2.1.1 Figures
Figure 1 (p. 157) . Output from the program named Slick0170.java.
1 This
151
152
8.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
1
2
3
4
5
(p.
(p.
(p.
(p.
(p.
159)
160)
161)
161)
163)
.
.
.
.
.
8.3 Preview
Most games and many simulations are interactive. By that I mean that they require user input to perform
according to their design.
I will present and explain a program in this module that allows the user to cause a ladybug sprite (see
Figure 1 (p. 157) ) to move inside the game window by pressing the arrow keys on the keyboard or the left
and right mouse buttons. (The mouse pointer must be inside the game window for the mouse buttons to
153
154
155
Table 8.1
Operation
Pressing the right arrow key or the right mouse button causes the sprite to move to the right.
Pressing the left arrow key or the left mouse button causes the sprite to move to the left.
Pressing the up arrow key causes the sprite to move up, and pressing the down arrow key causes the
sprite to move down.
The sprite cannot be caused to move up or down (in this program) by pressing mouse buttons.
draw
drawCentered
In this module, you will learn how to use the following methods of the Input
the user:
, and
drawFlash
isKeyDown
isMouseButtonDown
2 http://slick.ninjacave.com/javadoc/org/newdawn/slick/Image.html
3 http://slick.ninjacave.com/javadoc/org/newdawn/slick/Input.html
156
getMouseX
getMouseY
I like to think of event-driven programs as being somewhat analogous to the way that we normally drive
our cars. When we come to a red stoplight, we remove our foot from the gas pedal, press the brake pedal to
stop, and allow the motor to idle, thus consuming minimal fuel. (If we don't have an automatic transmission,
we will probably also disengage the clutch and move the gearshift leaver to the neutral position.)
When we see that the light has turned green, we reengage the transmission if necessary, gently press the
gas pedal, cause the motor to speed up, and drive through the intersection at a safe and reasonable speed.
I like to think of a polled program as being somewhat analogous to a car in which the gas pedal is
strapped to the oor causing the motor to run at maximum rpm all the time.
In such a car, the only way to stop at a stop light would be to disengage the clutch and press the brake
pedal. While the light is red, the motor would be consuming fuel at a high rate.
When the light turns green, we would reengage the clutch, speed through the intersection, and hope that
we don't receive a trac ticket.
Event-driven programs tend to idle when they have nothing to do, thus conserving computer resources.
Polled programs run at full speed all of the time, thus consuming maximum computer resources.
Game and simulation programs, (this one included) , tend to be written as polled programs. Most
other modern programs tend to be written as event-driven programs. However, you can probably write any
program using either scenario, or perhaps a combination of the two.
With regard to input, Slick2D supports both the polled and the event-driven scenarios.
Probably most user input in a Slick2D game or simulation program should be programmed using the
polled scenario. However, if the user taps a key while the program is in the render method, the program
might not recognize that the key has been tapped. If that tap is critical to the operation of the program, it
might be wise to also employ the event-driven scenario to detect such critical events.
The program that I will discuss in this module is written using only the polled approach to user input.
I have published numerous online tutorials that explain the use of the event-driven approach that you can
nd with a Google search.
The Slick2D Input 4 class supports input from the keyboard, the mouse, or from a game controller. I
will discuss only keyboard and mouse input in this module.
157
A complete listing of this program is provided in Listing 5 (p. 163) . Most of the code that is new and
dierent is contained in the update method, which begins in Listing 1 (p. 159) .
Listing 1 (p. 159) begins by getting a saving a reference to the Input 6 object that is associated with the
GameContainer 7 object. All user input can then be obtained by calling methods on the reference to the
Input 8 object.
Then Listing 1 (p. 159) uses a logical inclusive or operator to determine if either the right arrow key
or the right mouse button (or both) is currently in the pressed (or down) state. In other words, is the
user holding the right arrow key or the right mouse button down?
If the test returns true, the value of bugX is increased. This will cause the visual manifestation of the
sprite to move to the right later when the render method is executed.
Then Listing 1 (p. 159) performs a similar test on the left arrow key and the left mouse button ,
decreasing the value of bugX if either test returns true.
Listing 2 (p. 160) performs similar tests on the up arrow key and the down arrow key for the purpose
of increasing or decreasing the value of bugY . If the value of bugY is changed, this will cause the sprite
to move up or down later when the render method is executed.
6 http://slick.ninjacave.com/javadoc/org/newdawn/slick/Input.html
7 http://slick.ninjacave.com/javadoc/org/newdawn/slick/GameContainer.html
8 http://slick.ninjacave.com/javadoc/org/newdawn/slick/Input.html
158
No
up button
or
down button
There is no up button and no down button on the mouse, so in this program it is not possible to move
the sprite up or down by pressing mouse buttons. There are ways that such a thing could be accomplished
(such as holding down a keyboard key and pressing a mouse button) , but they were not considered
important for the purpose of this module.
The code in Listing 3 (p. 161) is similar to, but simpler than the corresponding code in the earlier
program named Slick0150a .
In this case, if the sprite collides with an edge, it simply stops moving instead of bouncing o the edge
as was the case in the earlier program.
159
Listing 4 (p. 161) calls the getMouseX and getMouseY methods to get and save the coordinates of
the mouse pointer when the mouse pointer is inside the game window. These values will be displayed later
when the render method is executed as shown in Figure 1 (p. 157) .
The Input class also provides two methods named getAbsoluteMouseX and getAbsoluteMouseY
. I'm not certain how these two methods dier from the two methods that were called in Listing 4 (p. 161)
, but I haven't spent any time investigating the dierence.
update
160
8.7 Summary
In this module, you learned how to use the following methods of the Input
isKeyDown
isMouseButtonDown
getMouseX
getMouseY
SpriteSheet
Animation
class
8.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
161
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.Input;
bugX = 100;
bugY = 100;
bugWidth;
bugHeight;
162
Table 8.6
-end-
Chapter 9
The
The
The
The
9.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 dierent game engines written in
dierent programming languages as well.
The purpose of this module is to teach you how to use objects of the SpriteSheet class and the
Animation class to perform simple sprite sheet animation.
1 This
163
164
9.2.1.1 Figures
Figure
Figure
Figure
Figure
1
2
3
4
(p.
(p.
(p.
(p.
167)
169)
170)
171)
.
.
.
.
174)
175)
175)
176)
176)
177)
177)
180)
.
.
.
.
.
.
.
.
9.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
1
2
3
4
5
6
7
8
(p.
(p.
(p.
(p.
(p.
(p.
(p.
(p.
9.3 Preview
I will present a program that uses the top row of sprites from the sprite sheet shown in Figure 1 (p. 167)
along with a SpriteSheet object and an Animation object to produce an animation of a dog playing.
(Note that the overall sprite sheet image is quite small, and the image shown in Figure 1 (p. 167) was
enlarged for this presentation.)
165
166
Figure 2 (p. 169) , Figure 3 (p. 170) , and Figure 4 (p. 171) show random screen shots taken while the
animation was running.
167
Table 9.2
168
Table 9.3
169
Table 9.4
Operating characteristics
The program uses only the ve sprites in the top row of Figure 1 (p. 167) . The ve sprites in the bottom
row are ignored. (A program that uses all ten sprites in both rows will be presented in the next module.)
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
170
By default, the program displays one cycle of ve sprites each second. (Each sprite is displayed for 200
Clock time
As you can see in Figure 4 (p. 171) , clock time in seconds is displayed below the animation. That makes
it easy to visually correlate the repetition rate with the clock.
The time that each image of the dog is displayed is independent of the frame rate. This can be demonstrated by changing the value of a variable named targetDelta and observing the relationship between
the repetition rate and the clock. However, best results are achieved by keeping targetDelta less than
the display time for each sprite ( duration ) .
In the previous module, you learned how to use the following methods of the Input
input:
isKeyDown
isMouseButtonDown
getMouseX
getMouseY
In this module, you will learn how to use objects of the SpriteSheet class and the Animation class
to perform simple sprite sheet animation. In the next module, you will learn how to perform more complex
animation.
(Slick2D also provides the capability to work with packed sprite sheets with fewer restrictions on the
organization of the sprite sheet.)
Since well before the rst Disney movies, animations have been created by displaying a series of images
one after the other.
Each image (or frame) is typically displayed for the same amount of time, but that is not always the
case, as will be demonstrated by the program in the next module.
Slick2D provides a class named Animation that does most of the heavy lifting in the display of an
animation.
There are several dierent ways to create, populate, and congure an Animation object containing a
series of images, with the same or dierent display durations for the images.
2 http://slick.ninjacave.com/javadoc/org/newdawn/slick/Input.html
171
By default, calling one of several overloaded draw methods on the Animation object causes it to
display the sequence of images and to start over when the last image has been displayed. However, that
behavior can be overridden in order to provide more customized behavior.
(It is actually more complicated that that, as you will see later in the discussion of the
render
method.)
Animations can be stopped, started and restarted (returning to the rst frame of the animation) . The
capabilities of the Animation class go far beyond those illustrated in this module and the next.
A complete listing of the program named Slick0180 is provided in Listing 8 (p. 180) . I will break the
program down and discuss it in fragments.
Listing 1 (p. 174) shows the beginning of the class named Slick0180 down through the main method.
172
Instance variables
Listing 1 (p. 174) declares a number of instance variables. The purpose of these variables should become
clear based on their names and their usage that I will discuss later.
main
173
Listing 3 (p. 175) creates a new SpriteSheet object based on the sprite sheet image along with the
width and height of the individual sprites.
SpriteSheet
object
174
Constructor parameters
Obviously, the rst parameter to the constructor for the Animation class species the SpriteSheet
object.
The second and third parameters specify that the rst image in the sequence should be the top-left image
in Figure 1 (p. 167) .
The fourth and fth parameters specify that the last image in the sequence should be the top-right image
in Figure 1 (p. 167) .
The true value for the sixth parameter species that the images should be scanned horizontally.
The duration value in the seventh parameter species that each image should be displayed for 200
milliseconds.
The true value for the last parameter species that the display should continue cycling through the
images until the animation is stopped.
The code is Listing 5 (p. 176) sets the frame rate and species the drawing location. The drawing
location is the location within the game window where the sprite will be displayed.
175
The
draw
render
method is shown in Listing 7 (p. 177) . The only thing that is new here is the call to the
method on the Animation object.
Powerful behavior
Animation
draw
The Animation object keeps track of the scheduling requirements of the animation, such as which
image should be displayed at the current time.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
176
Calling the
draw
method on the
Animation
The image display schedule being managed by the Animation object is independent of the frame rate.
The Animation object does its thing, and the render method does its thing virtually independent
of one another. When the render method decides that it is time to display an animation image, it calls
the draw method on the Animation object.
The Animation object delivers the image that is scheduled for display at that point in time according
to the predetermined animation schedule and the draw method causes the image to be displayed.
There are several overloaded versions of the draw method including versions to lter the colors and to
change the width and height of the displayed image.
Best results
Now you know why, as mentioned earlier (p. 172) , best results are achieved by keeping targetDelta
less than the display time ( duration ) for each sprite. If targetDelta is greater than the duration
, some images will be skipped and not displayed in the proper sequence.
For example, if the Animation object is switching from one image to the next every 0.10 second, but
the draw method is only being called every 0.13 seconds, some of the images in the sequence won't be
displayed and the quality of the animation will probably be poor.
However, this is also dependent on the amount of change from one image to the next. If the change from
one image to the next is small, then skipping an occasional image might not matter that much.
9.7 Summary
In this module, you learned how to use objects of the
perform simple sprite sheet animation.
SpriteSheet
Animation
class to
9.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Animation
class
177
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
178
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.SpriteSheet;
org.newdawn.slick.Animation;
org.newdawn.slick.Color;
179
Table 9.12
-end-
180
Chapter 10
The
The
The
The
10.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 dierent game engines written in
dierent programming languages as well.
The purpose of this module is to teach you how to use objects of the SpriteSheet class and the
Animation class to perform more complex sprite sheet animations than was the case in the earlier module
titled Slick0180: Sprite sheet animation, part 1 2 .
1 This content is available online at <http://cnx.org/content/m45753/1.3/>.
2 http://cnx.org/contents/0fc6c084-4f60-4497-a2d7-802a396bc985
181
182
10.2.1.1 Figures
Figure
Figure
Figure
Figure
1
2
3
4
(p.
(p.
(p.
(p.
185)
187)
188)
189)
.
.
.
.
10.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
10.3 Preview
I will present and explain a program that uses both rows of sprites from the sprite sheet shown in Figure 1
(p. 185) . The program uses a SpriteSheet object and an Animation object to produce an animation
of a dog playing and answering nature's call. (Note that the overall sprite sheet image is quite small, and
the image shown in Figure 1 (p. 185) was enlarged for this presentation.)
183
184
Table 10.1
This animation begins with the sprite running from left to right across the game window. Then the
sprite stops on the right side of the game window and answers nature's call. Although it isn't shown here,
the sprite turns and faces left during that process. Then the sprite runs from right to left across the game
window. This pattern repeats for as long as the program runs, and is illustrated by the three screen shots
that follow.
Figure 2 (p. 187) shows the sprite running from left to right. This is a ipped version of one of the
images in the top row of Figure 1 (p. 185) .
185
Table 10.2
Figure 3 (p. 188) shows the sprite answering nature's call. This is a ipped version of one of images from
the bottom row of Figure 1 (p. 185) .
186
Table 10.3
Figure 4 (p. 189) shows the sprite running from right to left. This is one of the images from the top row
of Figure 1 (p. 185) .
187
Table 10.4
SpriteSheet
In this module, you will learn how to use objects of the SpriteSheet class and the
to perform more complex sprite sheet animations than was in the previous module.
3 http://cnx.org/contents/0fc6c084-4f60-4497-a2d7-802a396bc985
Animation
Animation
class
188
Animation
(Of course, loops are used to make that process easier.) Among other things, this makes it possible to:
Use multiple copies of the individual images on the sprite sheet
Use ipped versions of the images on the sprite sheet
Specify dierent display times for the dierent images on the sprite sheet
For example, the display times for the images from the bottom row of Figure 1 (p. 185) are four times
greater than the display times for the images from the top row. Thus, the animation slows down when the
sprite stops to answer nature's call on the right side of the game window then speeds up again when the
sprite starts running from right to left.
A complete listing of the program named Slick0190 is provided in Listing 11 (p. 199) . I will break
the program down and discuss it in fragments.
Listing 1 (p. 191) shows the beginning of the class named Slick0190 down through the main method.
There is nothing in Listing 1 (p. 191) that should require an explanation beyond the embedded comments.
However, it is worth noting that unlike the previous module, Listing 1 (p. 191) instantiates a new empty
object of the class Animation and saves its reference in the instance variable named animation . This
object will be populated with images by the init method later.
189
190
The code in Listing 3 (p. 192) begins the process of populating the Animation object using images
extracted from the sprite sheet shown in Figure 1 (p. 185) .
The inner loop in Listing 3 (p. 192) calls the getSprite method of the
succession to extract each of the images in the top row in Figure 1 (p. 185) .
SpriteSheet
ve times in
191
The sprites represented by those ve images are facing the wrong direction. Therefore, Listing 3 (p. 192)
calls the getFlippedCopy method of the Image class to ip the images horizontally before adding them
to the contents of the Animation object.
The time duration was set to 100 milliseconds for each of the images from the top row of Figure 1 (p.
185) . However, that is not a requirement. You can set a dierent time duration for every image that you
add to an Animation object if that is required to meet your needs.
The outer loop in Listing 3 (p. 192) causes the process to be repeated four times. Therefore, when the
code in Listing 3 (p. 192) nishes executing, the Animation object contains 20 images made up of four
set of the ve images in the top row of Figure 1 (p. 185) . These 20 images will be used to cause the sprite
to run and jump from left to right across the game window.
Listing 4 (p. 193) uses essentially the same logic (broken into two nested loops) to add four sets of
images from the bottom row of Figure 1 (p. 185) .
The rst two set of images are ipped to face to the right. The last two sets of images are not ipped.
This is the reason for breaking this process into a pair of nested loops instead of using a single nested loop.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
192
If you watch the animation carefully, you will see that the sprite begins answering nature's call facing
to the right. Half way through answering nature's call, the sprite spins around and faces to the left. After
that, it runs across the screen from right to left.
Note that the specied time duration for these twenty images is 400 milliseconds. Two major changes
occur during this part of the animation (relative to the previous part) :
The sprite does not move horizontally while these 20 images are being displayed
Each of the 20 images is displayed four times as long as when the sprite is running.
Listing 5 (p. 194) nishes populating the Animation object by adding four more sets of the ve images
in the top row of Figure 1 (p. 185) . In this case, however, the images are not ipped. Therefore, they are
used to cause the sprite to run from right to left across the game window.
the
Listing 5 (p. 194) also takes care of some common administrative details at the end, signaling the end of
init method.
update
method in this
193
On the basis of the previous discussion, we already know that the Animation object contains a
sequence of 60 images or frames. Rather than to rely on that knowledge, however, Listing 6 (p. 195) calls
the getFrameCount method on the Animation object to determine the number frames in the object.
That value is divided by 3 and saved in the variable named oneThird . The logic that follows is based
on dividing the sprites into three equal size groups and processing them dierently depending on whether
they fall in the rst, second, or third group.
Listing 6 (p. 195) calls the getFrame method on the Animation object to determine which frame
should be displayed by this iteration of the game loop. That value is saved in the variable named frame .
Having determined which image is to be displayed, we must then compute the horizontal position within
the game window at which to display the image.
If the current frame is within the rst third, the display position assigned to the frame should make it
appear that the sprite is running from left to right across the game window. Therefore, the horizontal display
coordinate values for the sprites in this group should be proportional to the frame number from 0 through
19.
If the current frame is within the second third, the horizontal display coordinate should not change.
(The sprite should be stationary.) The sprites in this group are all intended to be displayed in the same
location.
If the current frame is within the third group, things are a little more complicated. The horizontal display
coordinate values assigned to the sprites should make it appear that the sprite is running from right to left
across the game window. Therefore, the coordinate value should be equal to the rightmost excursion less
a value that is proportional to the frame number, after adjusting the frame number to account for the 20
frames during which the sprites were stationary.
This process begins in Listing 7 (p. 195) .
194
Table 10.11
Listing 7 (p. 195) tests to determine if the current frame is in the rst third. If so, it computes a
horizontal position coordinate value as the product of the frame number and the stepSize in pixels, which
was dened in Listing 6 (p. 195) .
The process of computing the horizontal position coordinate value continues in Listing 8 (p. 196) .
Table 10.12
Listing 8 (p. 196) tests to determine if the current frame is in the middle group. If so, it causes the
method to return without changing the horizontal position coordinate value, thus allowing the
sprite to remain in a stationary position.
update
The horizontal position values computed in Listing 9 (p. 196) make it appear that the sprite is running
from right to left across the game window.
This is one of those opportune times when it is appropriate to say that I will leave it as an exercise for
the student to dust o their high-school algebra books and gure out how the code in Listing 9 (p. 196)
achieves the desired result.
update
method.
195
There is nothing left for the render method to do other than to send a message to the Animation
object once during each iteration of the game loop asking it to draw the current frame.
Listing 10 (p. 197) signals the end of the render method, the end of the Slick0190 class, and the
end of the program.
10.7 Summary
In this module, you learned how to use objects of the SpriteSheet class and the Animation class to
perform more complex sprite sheet animations than was the case in the previous module.
10.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
196
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
197
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.SpriteSheet;
org.newdawn.slick.Animation;
org.newdawn.slick.Color;
198
Table 10.15
-end-
Chapter 11
11.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 dierent game engines written in
dierent programming languages as well.
The purpose of this module is to teach you how to develop a sprite class (see Sprite01 (p. 223) ) from
which you can instantiate and animate swarms of sprite objects.
199
200
11.2.1.1 Figures
Figure 1 (p. 206) . Graphic output from program named Slick0200.
Figure 2 (p. 210) . Graphic output from the earlier program.
11.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
11.3 Preview
I will present and explain a program that uses a class named Sprite01 (see Listing 11 (p. 223) ) to
produce an animation of 1000 ladybug sprite objects ying around inside the game window as shown in
Figure 1 (p. 206) .
201
202
203
204
Table 11.1
As you can see from the text in the upper-left corner of Figure 1 (p. 206) , the program is running at 62
frames per second. My rather old desktop computer can maintain this frame rate up to about 7000 sprite
objects. Beyond that, it can no longer handle the computing load and the frame rate begins to decrease.
SpriteSheet
Animation
In this module, you will learn how to develop a sprite class from which you can instantiate and animate
swarms of sprite objects. In the next two modules, you will learn how to put that class to work.
205
In an earlier module titled Slick0150: A rst look at sprite motion, collision detection, and timing
control 2 , you learned how to cause a single sprite to bounce around inside the game window as shown in
Figure 2 (p. 210) .
2 http://cnx.org/contents/c92f070e-494f-4eb1-a0b9-e36abe4359fd
206
207
208
Table 11.2
While it would have been possible to add more sprites to the animation by expanding the code used in
that program, the code would have quickly gotten out of hand without the use of a sprite class and sprite
objects. (To use the common jargon, that program architecture was not very scalable.)
Basically, this program solves that problem by encapsulating many of the properties and methods that
are useful for manipulating sprites into a class from which sprite objects can be instantiated. Most of the
complexity is encapsulated in the class and thereby removed from the program that uses objects of the class.
The scenario
This program shows a baseball coach ( Figure 1 (p. 206) ) being attacked by a swarm of vicious
ladybug sprites. (Don't worry, we will nd a way to save the coach in the next module.)
This program uses the class named Sprite01 to populate the game window with 1000 ladybug sprites
in dierent colors with dierent sizes that y around the game window in dierent directions with dierent
speeds as shown in Figure 1 (p. 206) .
209
210
this image
direction
direction
size
size
for drawing
211
Table 11.3
Straightforward code
The code in Listing 1 (p. 212) is straightforward. It simply declares a number of instance variables, most
of which become properties of the object. Listing 1 (p. 212) also denes a constructor that receives and
saves values for many of those properties.
If you examine the remaining code in Listing 11 (p. 223) , you will see that it consists of simple property
accessor methods along with some methods that control the behavior of an object of the class. I will explain
those behavioral methods when I use them later in this and the next two modules.
A complete listing of the program named Slick0200 is provided in Listing 10 (p. 221) . I will break
the program down and explain it in fragments.
main
212
Everything in Listing 2 (p. 214) is completely straightforward and should not require an explanation
beyond the embedded comments.
215) .
213
There is also nothing new in Listing 3 (p. 215) . Therefore, the embedded comments should suce to
explain the code.
Listing 4 (p. 215) uses a for loop to populate the array object referred to by the variable named
sprites that was declared in Listing 2 (p. 214) . The array object is populated with references to objects
of the class Sprite01 .
214
Table 11.6
Random values
Note that several of the properties of each Sprite01 objects is initialized with random values.
The use of the nextFloat method of the object of the Random class may be new to you. If so, this
method simply returns a random value between 0.0f and 1.0f each time it is called.
If the use of the conditional operator involving the ? character and the : character is new to you, you
will probably need to do some online research in order to understand the use of this operator.
Otherwise, the code in Listing 4 (p. 215) is straightforward and shouldn't require an explanation beyond
the embedded comments.
Listing 4 (p. 215) signals the end of the init method.
Listing 5 (p. 216) uses a for loop to access each of the sprite objects, asking each object to move and
to bounce o the edge of the game window if necessary.
Listing 5 (p. 216) could hardly be simpler. That is because the necessary complexity has been encapsulated in each object of the Sprite01 class.
215
void move(){
xDirection*xStep;
yDirection*yStep;
move
Table 11.8
The code in Listing 6 (p. 217) is also simple. However, in this case, the simplicity is somewhat deceiving.
The apparent simplicity derives from the fact that the four required property values are routinely maintained
by the object and are readily available to the two statements in the move method when needed.
The
216
Table 11.9
Listing 7 (p. 217) contains essentially the same code that was written into the update method of the
earlier module mentioned above (p. 207) . In this case, however, all of the complexity has been encapsulated
into the Sprite01 class and replaced by a single call to the edgeBounce method in the update method
of the program named Slick0200 . Thus, the program's update method is now much simpler.
That concludes the discussion of the update method for this program.
The thing that is new about the code in Listing 8 (p. 218) is the call to the
Sprite01 class. That draw method is shown in Listing 9 (p. 218) .
draw
method of the
217
Table 11.11
In this case, moving the call to the draw method of the Image class from the render method to
the Sprite01 class didn't do much to reduce the complexity of the program. However, that is because I
kept the draw method in the Sprite01 class very simple.
I could have made it much more capable and more complex by including additional functionality. For
example, I could have caused the draw method to call the drawFlash method (see Slick0160: Using
the draw and drawFlash methods 3 ) of the Image class when the life property value goes to zero. In
that case, only a silhouette of the dead sprite would be drawn in place of the actual image of the sprite.
That concludes the discussion of the render method.
11.7 Summary
In this module, you learned how to develop a sprite class from which you can instantiate and animate swarms
of sprite objects.
11.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
3 http://cnx.org/contents/c8d91157-8952-40b7-8cca-d15ae4f65214
218
219
/*Slick0200.java
Copyright 2013, R.G.Baldwin
This program shows a baseball coach being attacked by a
swarm of vicious ladybugs.
This program uses the class named Sprite01 to populate
the game window with 1000 ladybug sprites in different
colors with different sizes that fly around the game
window in different directions with different speeds.
Tested using JDK 1.7 under WinXP
*********************************************************/
import
import
import
import
import
import
import
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.Color;
import java.util.Random;
public class Slick0200 extends BasicGame{
//Store references to Sprite01 objects here.
Sprite01[] sprites = new Sprite01[1000];
//Populate this with a ladybug image later.
Image image = null;
//Populate these variables with the background
// image along with the width and height of the
// image later.
Image background = null;
float backgroundWidth;
float backgroundHeight;
//This object produces random float values for a
// variety of purposes.
Random random = new Random();
//Frame rate we would like to see and maximum frame
// rate we will allow.
int targetFPS = 60;
//----------------------------------------------------//
public Slick0200(){//constructor
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
//Set the title
super("Slick0200, baldwin");
}//end constructor
//----------------------------------------------------//
220
Table 11.12
221
/*Sprite01.java
Copyright 2013, R.G.Baldwin
An object of this class can be manipulated as a sprite
in a Slick2D program.
Tested using JDK 1.7 under WinXP
*********************************************************/
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Color;
public class Sprite01{
Image image = null;//The sprite wears this image
float X = 0f;//X-Position of the sprite
float Y = 0f;//Y-Position of the sprite
float width = 0f;//Width of the sprite
float height = 0f;//Height of the sprite
float xStep = 1f;//Incremental step size in pixels - X
float yStep = 1f;//Incremental step size in pixels - Y
float scale = 1f;//Scale factor for draw method
Color colorFilter = null;//Color filter for draw method
float xDirection = 1.0f;//Move to right for positive
float yDirection = 1.0f;//Move down for positive
int life = 1;//Used to control life or death of sprite
boolean exposed = false;//Used in the contagion program
//Constructor
public Sprite01(Image image,//Sprite wears
float X,//Initial position
float Y,//Initial position
float xDirection,//Initial
float yDirection,//Initial
float xStep,//Initial step
float yStep,//Initial step
float scale,//Scale factor
Color colorFilter)
throws SlickException {
this image
direction
direction
size
size
for drawing
222
Table 11.13
-end-
Chapter 12
12.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 dierent game engines written in
dierent programming languages as well.
The purpose of this module is to teach you how to use the Sprite01 class developed in an earlier
module titled Slick0200: Developing a sprite class 2 to write a predator/prey simulation program involving
thousands of sprites along with collision detection and sound eects.
1 This content is available online at <http://cnx.org/content/m45755/1.5/>.
2 http://cnx.org/contents/84c02677-f58d-45b7-811d-b91571187235
223
224
12.2.1.1 Figures
Figure
Figure
Figure
Figure
1
2
3
4
(p.
(p.
(p.
(p.
230)
234)
238)
242)
.
.
.
.
12.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
12.3 Preview
In an earlier module titled Slick0200: Developing a sprite class 3 , we encountered a baseball coach that
had been attacked by a swarm of vicious ladybug sprites. I promised you that we would later nd a way to
save the coach. That time has come.
In this module, I will explain a program that uses the Sprite01 class from the earlier module to produce
a simulation program with the output shown in Figure 1 (p. 230) , Figure 2 (p. 234) , and Figure 3 (p. 238)
.
A swarm of insects
Once again, the coach has been attacked by a swarm of 1000 insects. However, in this case, the ladybug
sprites have been replaced by vicious green beetle sprites.
Fortunately for the coach, a red predator beetle sprite with a taste for green beetles has come along and
is gobbling up green beetles as fast as he can collide with them. (According to the text at the top of
Figure 1 (p. 230) , 152 of the 1000 beetles had been consumed by the time the screen shot in Figure 1
(p. 230) was taken.)
3 http://cnx.org/contents/84c02677-f58d-45b7-811d-b91571187235
225
226
227
228
Table 12.1
Figure 2 (p. 234) shows the situation some time later when all but 173 of the green beetles had been
eaten. Note that the process of eating those nutritious beetles has caused the red beetle to gain some weight
in Figure 2 (p. 234) .
229
230
231
232
Table 12.2
Figure 3 (p. 238) shows the situation with only 36 green beetles remaining. Collisions between the beetles
is rare at this point, so quite a bit more time will probably be required before the red beetle can collide with
and eat the remaining green beetles.
233
234
235
236
Table 12.3
In the previous module, you learned how to develop a sprite class from which you can instantiate and
animate swarms of sprite objects.
In this module, you will learn how to use the Sprite01 class developed in the earlier module (p. 226)
to write a predator/prey simulation program involving thousands of sprites, collision detection, and sound
eects.
Two scenarios
237
A baseball coach is attacked by a swarm of erce green ying sprites. Fortunately, a red predator sprite
comes along and attacks the green sprites just in time to save the coach.
There are two scenarios that can be simulated by setting the variable named dieOnCollision (see
Listing 1 (p. 244) ) to either true or false .
In one scenario ( dieOnCollision = false) , the vicious green sprites become harmless blue sprites
when they collide with the red sprite. A screen shot of this scenario is shown in Figure 4 (p. 242) .
238
239
240
Table 12.4
In the other scenario ( dieOnCollision = true) , the green sprites are consumed by the red sprite
upon contact and are removed from the population. This is the scenario shown in Figure 3 (p. 238) .
In both scenarios, contact between a green sprite and the red sprite causes the red sprite to increase in
size.
If you allow the program to run long enough, the probability is high that all of the green sprites will have
collided with the red sprite and will either have turned blue or will have been consumed.
241
Slick0210
242
243
Table 12.5
ArrayList
There are two things that are new in Listing 1 (p. 244) . First there is the instantiation of an ArrayList
object in place of the array object used in the program in the earlier module.
The use of an ArrayList instead of an array provides more exibility in managing a collection of
Sprite01 objects. If you are unfamiliar with the use of ArrayList objects, just Google the keywords
baldwin java ArrayList generics and I'm condent you will nd explanatory material that I have published
on that topic.
Sound
The second new item in Listing 1 (p. 244) is the declaration of a reference variable of the Slick2D Sound
class. That variable will be used to hold a reference to a Sound object, that will be played each time
the red sprite collides with a green sprite.
Otherwise, the code in Listing 1 (p. 244) is straightforward and shouldn't require further explanation.
245) .
The only thing new in Listing 2 (p. 245) is the instantiation of the object of type Sound . As you can
see, the syntax for instantiation of a Sound object is essentially the same as for instantiating an Image
object.
Listing 3 (p. 247) calls the add method of the ArrayList class to add a red sprite to the beginning
of the ArrayList object. (Actually it add a reference to that object and not the object itself.)
You are already familiar with the constructor parameters (shown in Listing 3 (p. 247) ) for a Sprite01
object.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
244
245
Listing 4 (p. 247) uses a for loop and the value of the variable named numberSprites
1 (p. 244) ) to add 1000 green Sprite01 object references to the ArrayList object.
(see Listing
Listing 4 (p. 247) also sets the target frame rate and signals the end of the
init
method.
method is to use a for loop to process the red sprite against each of
the green sprites and to take appropriate actions when a collision between the red sprite and a green sprite
occurs.
The update method begins in Listing 5 (p. 248) .
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
246
The code in Listing 5 (p. 248) is mostly the same as code that you have seen before, so further explanation
should not be necessary.
The code in Listing 6 (p. 248) is new to this module. This code calls the isCollision method of the
Sprite01 class to test for a collision between the current green sprite and the red sprite.
What is a collision?
There are many ways to dene and implement collision detection in game and simulation programming.
In this program, a collision is deemed to have occurred if any portion of the rectangular redBallImage
overlaps any portion of the rectangular greenBallImage . (Even though these images appear to be
249) .
247
otherTop = other.getY();
otherBottom = otherTop + other.getHeight()*other.getScale();
otherLeft = other.getX();
otherRight = otherLeft + other.getWidth()*other.getScale();
Methodology
This method detects a collision between the rectangular sprite object on which the method is called and
another rectangular sprite object.
The methodology is to test four cases where a collision could not possibly have occurred and to assume
that a collision has occurred if none of those cases are true.
Given that as background, you should be able to use a pencil and paper along with the code in Listing
7 (p. 249) to draw some rectangles and understand how the code in Listing 7 (p. 249) works.
Although I can't guarantee that the method won't call a collision when no collision actually occurred, I
am pretty sure that it won't miss any collisions that do occur.
Process a collision
The code in Listing 8 (p. 250) is executed when the call to the isCollision method returns true.
Therefore, this code processes a collision only when one has occurred.
The code excludes collisions between the red sprite and itself, (which is an artifact of the algorithm) .
It also excludes collisions between the red sprite and blue sprites (if they exist) .
248
Although the code in Listing 8 (p. 250) is long and tedious, it isn't particularly complicated. It consists
mainly of calls to the accessor methods of the two sprite objects involved in the collision to modify their
property values in some way.
For example, near the top of Listing 8 (p. 250) , there is a call to the
sprite to change it to a blue sprite.
setImage
249
This is followed by a call to the setLife method to set the life of the (now blue) sprite object to 0,
but only if the dieOnCollision variable belonging to the object is true. Later on, all sprite objects with
a life property value of 0 will be removed from the population.
And so forth
I could continue down the page describing the calls to various other accessor methods, but that shouldn't
be necessary. The embedded comments should suce for the explanation.
Play a sound
Finally near the end of the code in Listing 8 (p. 250) , there is a call to the play method belonging to
Sound object referred to as blaster .
Each time there is a collision between the red sprite and a green sprite, the sound loaded earlier from the
le named "blaster.wav" is played.
Listing 8 (p. 250) signals the end of the for loop, but does not signal the end of the
There is one more task to complete before the update method terminates.
update
method.
property value
Explanation of an Iterator
The explanation of an Iterator is beyond the scope of this module. However, if you Google the keywords
baldwin java iterator , you will nd several tutorials that I have published on this and related topics.
Listing 9 (p. 251) signals the end of the update method.
250
Slick0210
12.7 Summary
In this module, you learned how to use the Sprite01 class from an earlier module to write a predator/prey
simulation program involving thousands of sprites, collision detection, and sound eects.
251
12.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
252
/*Slick0210.java
Copyright 2013, R.G.Baldwin
A baseball coach is attacked by a swarm of fierce green
flying insects. Fortunately, a red predator insect comes
along and attacks the green insects just in time to save
the coach.
There are two scenarios that can be exercised by setting
dieOnCollision to true or false. In one scenario,
the green insects become harmless blue insects when they
collide with the red insect. In the other case, they are
consumed by the red insect upon contact and removed from
the population.
In both scenarios, contact between a green insect and the
red insect causes the red insect to increase in size.
If you allow the program to run long enough, the
probability is high that all of the green insects will
have collided with the red insect and will either have
turned blue or have been consumed.
Tested using JDK 1.7 under WinXP
*********************************************************/
import
import
import
import
import
import
import
import
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.Color;
org.newdawn.slick.Sound;
import java.util.Random;
import java.util.ArrayList;
import java.util.Iterator;
public class Slick0210 extends BasicGame{
//Set the value of this variable to true to cause the
// sprites to die on collision and to be removed from
// the population.
boolean dieOnCollision = true;
//Store references to Sprite01 objects here.
ArrayList <Sprite01> sprites =
new ArrayList
<Sprite01>();
Available for free at Connexions
<http://cnx.org/content/col11489/1.13>
//Change this value and recompile to change the number
// of sprites.
int numberSprites = 1000;
253
Table 12.15
254
this image
direction
direction
size
size
for drawing
255
Table 12.16
-end-
256
Chapter 13
13.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 dierent game engines written in
dierent programming languages as well.
The purpose of this module is to teach you how to write a program that simulates the spread of a fatal
communicable disease within a population (a pandemic) .
257
258
13.2.1.1 Figures
Figure 1 (p. 264) . The disease has gained a foothold.
Figure 2 (p. 268) . The disease has spread into the population.
Figure 3 (p. 272) . The disease has receded after killing many in the population.
13.2.1.2 Listings
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
Listing
1
2
3
4
5
6
7
8
9
(p.
(p.
(p.
(p.
(p.
(p.
(p.
(p.
(p.
274)
276)
277)
278)
280)
282)
283)
285)
287)
.
.
.
.
.
.
.
.
.
13.3 Preview
In an earlier module titled Slick0210: Collision detection and sound 2 , you learned how to write a
non-trivial program involving thousands of sprites, collision detection, and sound. We will take that concept
considerably further in this module by writing a program that simulates the spread of a fatal communicable
disease within a population (a pandemic) and displays the results in animated graphic form.
Figure 1 (p. 264) shows the result of inserting a single infected sprite into a population of healthy sprites.
Healthy sprites are colored green and infected sprites are colored red.
By the time the screen shot in Figure 1 (p. 264) was taken, the disease had gained a foothold, several
other sprites had become infected, and eight of the original 1000 sprites had died, leaving only 992 live sprites
including the seven that are infected.
2 http://cnx.org/contents/7fd862dc-efad-463f-be-1a1276a4b698
259
260
261
262
Table 13.1
Figure 2 (p. 268) shows the situation some time later when the disease has spread considerably. By
this point, many sprites have become infected (and are infecting others) and only 763 of the original 1000
sprites are still alive including those that are infected.
263
264
265
266
Table 13.2
Figure 3 (p. 272) shows the situation much later. For the set of properties used to run this simulation,
the pandemic appears to be receding with 341 of the 1000 original sprites still alive.
267
268
269
270
Figure 3 . The disease has receded after killing many in the population.
Table 13.3
Later on, I will explain the properties that control the spread of the disease. Some sets of property values
produce results similar to those shown above where the disease gains a foothold, spreads for awhile killing
many sprites, and then recedes without killing the entire population.
Other sets of property values end up with all of the sprites having died.
Still other sets of property values end up with the disease being unable to gain a foothold and spread
beyond just a few individual sprites.
271
You have learned how to use a basic Slick2D game engine to create simulations involving thousands of
sprites, collision detection, and sound.
In this module, you will learn how to use what you have previously learned to write a relatively complex
(but somewhat simplied) simulation of a real-world pandemic.
If you were to study the characteristic of pandemics, you could probably upgrade this program to produce
a better model of a pandemic. For example, an interesting student project would be to allow healthy sprites
to reproduce when they come in contact based on a random probability function. This would allow the
population to be growing at the same time that it is dying o due to the disease. Of course, it may then be
necessary to deal with the eects of a population explosion.
The nal outcome is determined both by chance and by several factors including:
The
The
The
The
The actual values for the rst three factors for each individual are determined by a maximum value multiplied
by a random number between 0 and 1.0.
Experimentation
Instance variables are provided for all four of these factors. You can modify the values and recompile the
program to experiment with dierent combinations of the factors.
A good exercise for a student would be to create a GUI that allows the factors to be entered more easily
without having to recompile the program for purposes of experimentation.
Slick0220
272
273
Table 13.4
There is nothing new in Listing 1 (p. 274) , so there should be no need for an explanation beyond the
embedded comments.
276) .
274
The only new code in Listing 2 (p. 276) is the call to the setLife method at the end. In the earlier
module titled Slick0210: Collision detection and sound 3 , the life property of a sprite was always either 0
or 1. A sprite with a life property value of 0 was dead. A sprite with a life property value of 1 was alive.
3 http://cnx.org/contents/7fd862dc-efad-463f-be-1a1276a4b698
275
This program is more nuanced and uses values other than 0 and 1 for the infected red sprites. A value
of 0 still means that a sprite is dead. Any other positive value means that the sprite is sick and dying but
not yet dead.
The value assigned to the life property for this sprite is a random value between 0 and infectedSpriteLife . This is one of the property values that has an impact on the extent to which the disease spreads
through the population. The longer an infected sprite lives after becoming infected, the more healthy sprites
it will infect and the more aggressive will be the disease.
You can modify this value (see Listing 1 (p. 274) ) and recompile the program to experiment with
dierent values.
277) .
Listing 3 (p. 277) uses a for loop to add numberSprites (see Listing 1 (p. 274) ) healthy sprites to
the population. This is another property that has an impact on the spread of the disease. Everything else
being equal, the more sparse the population, the more dicult it is for the disease to get a foothold in the
rst place and the more dicult it is for the disease to spread if it does get a foothold.
Listing 3 (p. 277) also sets the frame rate to the value of targetFPS (see Listing 1 (p. 274) )
. Note that I slowed this program down to the standard movie frame rate of 24 fps (as opposed to the
typical 60 fps) mainly because I wanted to run the simulation more slowly. In other words, I wanted it to
be possible to see the disease spread through the population. Also, it is a fairly demanding program so it
may not run at 60 fps on some machines.
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
276
init
method.
The is nothing new in the code fragment shown in Listing 4 (p. 278) . The new code begins in Listing 5
(p. 280) .
Before getting down into the details of the code, I will give you a descriptive overview.
In the outer-most layer, the program uses a for loop to examine every sprite in the population looking
for red or infected sprites.
When it nds an infected sprite, it decreases the value of its life expectancy. Then it uses an inner for
loop to test that sprite against every sprite in the population looking for collisions.
If the infected sprite collides with another infected sprite, it ignores the collision and keeps searching the
population, looking for collisions with healthy sprites.
If the infected sprite collides with a healthy (green) sprite, it causes that sprite to become exposed to
the disease and plays a sound eect. (As you will see later, sprites that are exposed to the disease don't
When the infected sprite has been tested for a collision with every healthy sprite, four kinds of sprites
exist in the population:
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
277
1.
2.
3.
4.
A cleanup pass
An Iterator is used to make a cleanup pass through the population.
Exposed sprites are either converted to infected sprites or cleared of the exposure on the basis of a
random value that has a maximum value of probabilityOfInfection (see Listing 1 (p. 274) ) .
Dead sprites are removed from the population.
The code to accomplish all of this begins with the for loop in Listing 5 (p. 280) .
278
You should have no diculty matching up the code in Listing 5 (p. 280) with the verbal description
given above.
Iterator
279
280
Once again, you should have no diculty matching up the code in Listing 6 (p. 282) with the verbal
description given above.
281
13.7 Summary
In this module, you learned how to write a program that simulates the spread of a fatal communicable
disease within a population.
13.8 Conclusion
Although I may come back and add more modules later, for now, this will be the nal module in this
collection.
The objective of the collection was to explain the anatomy of a game engine. I believe I have accomplished
that objective and have also provided sample programs to illustrate the use of the game engine.
It is worth pointing out that BasicGame is not the only game engine architecture available with
Slick2D. The Slick2D Wiki 4 refers to BasicGame as a game container and indicates that several others
are available including:
282
The documentation also describes a class named StateBasedGame , which provides a dierent anatomy
than BasicGame . Bucky Roberts provides a series of video tutorials on state based games using Slick2D
at http://www.youtube.com/watch?v=AXNDBQfCd08 5
13.9 Miscellaneous
This section contains a variety of miscellaneous information.
Housekeeping material
Disclaimers: Financial : Although the Connexions site makes it possible for you to download
a PDF le for this module at no charge, and also makes it possible for you to purchase a pre-printed
version of the PDF le, you should be aware that some of the HTML elements in this module may
not translate well into PDF.
I also want you to know that, I receive no nancial compensation from the Connexions website even
if you purchase the PDF version of the module.
In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle
books, and placed them for sale on Amazon.com showing me as the author. I neither receive
compensation for those sales nor do I know who does receive compensation. If you purchase such
a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it
was made and published without my prior knowledge.
283
/*Slick0220.java
Copyright 2013, R.G.Baldwin
This program simulates the propagation of a fatal
communicable disease within a population.
A single infected sprite is introduced into a large
population of sprites. The disease is spread by physical
contact with an infected sprite.
You can watch as the disease either spreads and kills the
entire population or spreads for awhile, then recedes and
dies out. Infected sprites are colored red. Healthy
sprites are colored green. A sound is emitted (for drama)
each time there is contact between an infected sprite and
a healthy sprite.
The final outcome is determined both by chance and by
several factors including:
-The maximum life expectancy of an infected sprite
-The maximum probability of infection due to contact with
an infected sprite
-The maximum degree of mobility of both infected and
healthy sprites
-The population density of sprites.
The actual values for the first three factors for each
individual are determined by the maximum value multiplied
by a random number between 0 and 1.0.
Instance variables are provided for each of these factors.
You can modify the values and recompile the program to
experiment with different combinations of the factors.
A good exercise for a student would be to create a GUI
that allows the factors to be entered more easily for
purposes of experimentation.
Tested using JDK 1.7 under WinXP
*********************************************************/
import
import
import
import
import
import
import
import
org.newdawn.slick.AppGameContainer;
org.newdawn.slick.BasicGame;
org.newdawn.slick.GameContainer;
org.newdawn.slick.Graphics;
org.newdawn.slick.Image;
org.newdawn.slick.SlickException;
org.newdawn.slick.Color;
Available for free at Connexions <http://cnx.org/content/col11489/1.13>
org.newdawn.slick.Sound;
import java.util.Random;
import java.util.ArrayList;
284
Table 13.11
285
/*Sprite01.java
Copyright 2013, R.G.Baldwin
An object of this class can be manipulated as a sprite
in a Slick2D program.
Tested using JDK 1.7 under WinXP
*********************************************************/
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Color;
public class Sprite01{
Image image = null;//The sprite wears this image
float X = 0f;//X-Position of the sprite
float Y = 0f;//Y-Position of the sprite
float width = 0f;//Width of the sprite
float height = 0f;//Height of the sprite
float xStep = 1f;//Incremental step size in pixels - X
float yStep = 1f;//Incremental step size in pixels - Y
float scale = 1f;//Scale factor for draw method
Color colorFilter = null;//Color filter for draw method
float xDirection = 1.0f;//Move to right for positive
float yDirection = 1.0f;//Move down for positive
int life = 1;//Used to control life or death of sprite
boolean exposed = false;//Used in the contagion program
//Constructor
public Sprite01(Image image,//Sprite wears
float X,//Initial position
float Y,//Initial position
float xDirection,//Initial
float yDirection,//Initial
float xStep,//Initial step
float yStep,//Initial step
float scale,//Scale factor
Color colorFilter)
throws SlickException {
this image
direction
direction
size
size
for drawing
286
Table 13.12
-end-
INDEX
287
Keywords
do not necessarily appear in the text of the page. They are merely associated with that section. Ex.
apples, 1.1 (1) Terms are referenced by the page they appear on. Ex. apples, 1
A
B
C
D
F
G
M motion, 6(91)
O object, 7(125), 8(153), 9(165), 10(183),
11(201), 12(225), 13(259)
object-oriented programming, 7(125),
8(153), 9(165), 10(183), 11(201),
12(225), 13(259)
OOP, 3(33), 4(45), 5(65), 6(91),
7(125), 8(153), 9(165), 10(183),
11(201), 12(225), 13(259)
draw, 5(65)
frameworks, 2(15)
Game engine, 1(1)
game engines, 2(15)
Game interface, 3(33)
Game library, 1(1)
game loop, 4(45)
game programming, 3(33), 4(45), 5(65),
6(91), 7(125), 8(153), 9(165), 10(183),
11(201), 12(225), 13(259)
getDelta method, 3(33)
java, 1(1), 2(15), 3(33), 4(45), 5(65),
6(91), 7(125), 8(153), 9(165), 10(183),
11(201), 12(225), 13(259)
P
S
pixel, 5(65)
timing, 6(91)
transparent, 5(65)
ATTRIBUTIONS
288
Attributions
Collection: Anatomy of a Game Engine
Edited by: R.G. (Dick) Baldwin
URL: http://cnx.org/content/col11489/1.13/
License: http://creativecommons.org/licenses/by/3.0/
Module: "Slick0100: Getting started with the Slick2D game library"
By: R.G. (Dick) Baldwin
URL: http://cnx.org/content/m45726/1.9/
Pages: 1-14
Copyright: R.G. (Dick) Baldwin
License: http://creativecommons.org/licenses/by/4.0/
Module: "Slick0110: Overview"
By: R.G. (Dick) Baldwin
URL: http://cnx.org/content/m45728/1.3/
Pages: 15-31
Copyright: R.G. (Dick) Baldwin
License: http://creativecommons.org/licenses/by/4.0/
Module: "Slick0120: Starting your program"
By: R.G. (Dick) Baldwin
URL: http://cnx.org/content/m45732/1.3/
Pages: 33-43
Copyright: R.G. (Dick) Baldwin
License: http://creativecommons.org/licenses/by/4.0/
Module: "Slick0130: The game loop"
By: R.G. (Dick) Baldwin
URL: http://cnx.org/content/m45733/1.4/
Pages: 45-63
Copyright: R.G. (Dick) Baldwin
License: http://creativecommons.org/licenses/by/4.0/
Module: "Slick0140: A rst look at Slick2D bitmap graphics"
By: R.G. (Dick) Baldwin
URL: http://cnx.org/content/m45737/1.4/
Pages: 65-90
Copyright: R.G. (Dick) Baldwin
License: http://creativecommons.org/licenses/by/4.0/
Module: "Slick0150: A rst look at sprite motion, collision detection, and timing control"
By: R.G. (Dick) Baldwin
URL: http://cnx.org/content/m45738/1.4/
Pages: 91-124
Copyright: R.G. (Dick) Baldwin
License: http://creativecommons.org/licenses/by/4.0/
ATTRIBUTIONS
289
Learn about the anatomy of a basic game engine written around the Slick2D Java game library.
About OpenStax-CNX