Leveleditor
In this chapter we discuss how to program a leveleditor
that can used in any arraybased game. An arraybased game might be a
Breakout clon, Boulderdash, PacMan or a Nibbles clone like our
game
Snakin,
where we
used this leveleditor too. Before you start reading this article
you should know something about arrays in Java (just basics),
a little bit about applet parameters, and of course you
should download the sourcecode at the end of the chapter!
Why do we need a leveleditor?
Even though the answer to this question might be clear I want
to write a few lines about it. To program a leveleditor and to
make your game work with any level build with this editor
is much harder and costs you much more time than to write a game
that has one or two static levels. But this is worth the price
if you want to program a game with many different levels. If
you programmed the game that way, that it works with a leveleditor,
then it costs you just a few minutes to add a new level. But if
you programmed your game just for static levels it will be hard
and maybe even impossible to add a new level. So the hard work
at the start of your game design was really worth the price! Well,
let's start with the real problem!
The basic idea
Before we find a solution to the problem of where and how to
define our levels, we have to think about something else. We have
to find a way to represent a level in our game.
Imagine the applet area with a grid over it. Next we place the
elements included in our level, (walls, stones, enemies...), in
the fields of this grid (just one element per field). This means
that the position of every level element is defined by the row
and the column number of the grid field in which the level
element is placed. The easiest way to represent such a two
dimensional matrix in Java is to use a two dimensional array.
So every level consits of a 2D array. This array holds the
different level elements and these elements can differ from level
to level. Everytime we read in our levels we will place different
level objects at different positions in our 2D array. Everytime
we want to draw our level to the screen we go through the array
and paint every object in it at the position in our grid which
is represented by the column and row number of the array. Using
this pretty simple idea we will now try to solve the problem of
where and how we want to define our levels so that it is possible
to fill the level array later.
Where and how will we define the levels?
We are programming applets so we have basicly three possibilities
where we can define the levels:
- In an external file
- In the source code of the game
- In the HTML - page of the applet (with help of applet
parameters)
The first and the second solution are for different reasons
worse than the third one. To read in an external file into an
applet is possible but not that easy, so we won't do it. To
define the different levels in the sourcecode is a good solution
if the player should not be able to take a look at a level
before he has reached it, for example if the goal of the game
is to find a way out of a labyrint. But you can't use this
solution if the player should be able to write a level by himself.
So there is just the third alternative left and we will use this
idea now in our editor.
So we will use applet parameters to define our levels. Every
applet parameter has a value and a name (for details see below)
and we can get the value of a parameter by calling the
getParameter(parametername) - method of the applet class. Then
the value of the parameter with the specific name is returned as
a string. Applet parameter can be defined between the opening
and the closing applet tag and look always the same just like:
<param name= "name of the parameter"
value="value of the parameter">
Well, now we know where we will write our levels, but we still
don't know what a level will look like. Ok, here comes my
solution. Every level we'll write will consist of 11 parameters:
3 information parameters that hold information about the author
of the level, the level description and the level name.
The other 8 parameters will represent the 8 rows of the level
array that represents our level in the example. The parameter
names will always look like this:
"Level" + "Levelnumber" + "_" + "Id". Id can have the values
"Author", "Name", "Comment" or "Line" + "Rownumber". The value
strings of the information parameters can have any length, the
values of the level defining parameters have to consist of a
string with length 10. Every character of the string represents
one level element, in our case, stones with different colors.
These colors/character pairs will be r = red, g = green, b = blue,
y = yellow and another character ":" that represents grid
fields in the level where no level element shall be placed.
So the names of parameters of different levels will look all the
same execpt for the levelnumber. Because of this structure of
the parameter names it is really easy to read in the different
levels using a while or a for loop, counting from 1 to the in
the "Levels_in_total" defined integer (for details see readLevel
- method further down this chapter). Now you can take a look
at a level, which can be read by the leveleditor:
// Start of the applettag including the normal applet information
<applet code = Main width=300 height=400>
// This line tells the editor how many levels are defined
<param name="Levels_in_total" value="1">
// These lines include the level information parameters
<param name="Level1_Author" value="FBI">
<param name="Level1_Name" value="Test Level 1">
<param name="Level1_Comment" value="My first try">
// This is the "real" level
<param name="Level1_Line0" value="rrrrrrrrrr">
<param name="Level1_Line1" value="bbbbbggggg">
<param name="Level1_Line2" value="r::rrrr::r">
<param name="Level1_Line3" value="yyyyybbbbb">
<param name="Level1_Line4" value="rrr::::rrr">
<param name="Level1_Line5" value="gggggyyyyy">
<param name="Level1_Line6" value="r::rrrr::r">
<param name="Level1_Line7" value="bgybgrybgy">
// End of the applet tag
</applet>
Class design of our editor
Now we'll start with the class design of our leveleditor, that
will make it possible to read in a level.
- LevelReader:
This class will read in a certain number
of levels defined in the "Levels_in_total" - parameter using the
getParameter(parametername) - method. For every level in the
HTML - file it will create an instance of the class Level
(see below), and stores this created level in an array of
instances of the class Level. Then the method readLevels(),
which is doing the job of reading in all the levels, returns
this array of Level instances to the calling class.
- Level:
This class saves the values of the information strings Author,
Levelname and description and holds the 2D array (stone_map)
with the level elements. As I've already said, this array saves
instances of the class Stone and, according to the definition
of the level, in different colors. Each stone "knows" its color
and its position in the grid. The class level has also a method
to paint the whole level to the screen.
- Stone:
This class holds the color and the position of the stone in the
applet area. The position (in pixel) is calculated in the
constructor of the class, using the information in which column
and row, the stone is placed in the stone_map array of the level
instance. A stone instance also has it's own paint method to
paint the stone in the right color and at the right position.
- Main:
This class holds an array of instances of the class level. A level
can be chosen out of this level array using the cursor keys and
then the chosen level is painted to the screen. This is just a
test class and has absolutly no meaning for the leveleditor.
- C_LevelEditor:
To make the leveleditor more flexible without needing to change
the sourcecode in general, all constant values (number of lines
in one level, number of columns in one level, grid size...) are
stored in the class C_LevelEditor. If you want to use more lines
in your level... you just have to change the values of the
corosponding constant. So this class holds some static constants
and nothing else!
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.