Introduction
Steps to making a game
Debugging
Making and loading images
Making a map and player
Making some bad guys
Fixing problems / debugging
Making some custom scripts
Tutorial 1
Tutorial 2
Introduction
Building a game in Zot isn't so difficult to do, but it can be
difficult to know just where to begin, especially with all that
dense documentation. But its really not so bad if you follow a few
simple guidelines...
- Start small; no one aims for Zelda day one -- instead you aim
for something small.. create a single room, get a player walking
around, and then fill it in and grow it and add more levels, etc.
- Whip up some quick artwork for map tiles, or pull some from an
existing Zot project, or pull some from a fansite for Zelda or
other popular game. You can look into BombZ for artwork for
some characters like Hudson's Bomberman, or Zot to the Past's
Link character of Zelda fame.. (these are copywritten images, but
no one should mind hacking around for learning sake.) ie: These images
are ready to use, and you can even pluck the sprite-descriptions
from the config.txt's of those gamelets, and be up and going
in no time.
- Start a config.txt file up in your favourite text editor (such
as Notepad, Textpad, or real text editor; its often a good idea to
just copy an existing Zot project (like ZInvaders!) directory and
modify its config file.. this way you start with something that
already works.
- Whip up a simple map, and set the engine to use it; suddenly
you can run Zot and see it in action! If you duplicated an existing
project, just copy its "tilemap" block in the config.txt and modify
it a bit and give it a new name, then start the "startmap" to the
newly named level.
- From there its just "filling in the gaps" -- make the map larger,
add some sprites, make them move around, add some more artwork, add
some audio... just grow the game.
Read on for some step by step instructions to what the parts of
a basic config.txt stand for.
Steps to Making a Game
Debugging
Debugging is something we all have to get through, so the trick
is to get good at it so you spend as little time possible
at doing it.
Debugging is finding out why something happens when you intended
another thing to happen, or finding out why the Zot engine is
crashing. The Zot engine tries "reasonably hard" to avoid
crashing, and tries to let you know when you're doing something
naughty. However, due to performance considerations, checking all
your work all the time would slow things down and so only so many
sanity checked are performed.. so you can crash the Zot engine
by configuring things all wrong. However, most of the time Zot will
not crash, and almost certainly Zot will give you a useful error
message. But in general, best to be careful.. if you feed Zot a
30x30 sprite, doesn't tell it to look for the sprite 400 pixels in ;)
Some handy techniques..
- Always develop, or at least test, your game on the desktop
versions of Zot, because logging is turned onto maximum there.
On handhelds, logging is disabled mostly since it coudl fill up
storage cards, or there may be no storage cards available, etc.
They'll pop up messages to the display, but the desktop is where
the zotlog lives, and the zotlog is the key to debugging.
- If something goes funny (Zot engine crashes, or sprite doesn't
show up *at all*, etc), then first thing to do is always
always Always check the zotlog.txt. On desktops,
this shows up in the Zot directory (not your game directory,
but the main Zot directory.) This is because it starts before
your game launches, logging away the attempt to launch.
The zotlog contains everything Zot thinks about -- as it loads
your config.txt each line is copied to the zotlog and any
actions or decisions made as a result are written there. Thus,
if the engine crashes during loading, you'll know exactly what
caused the crash by seeing the last entry. Or if a sprite doesn't
show up, look for the log entries for the sprite, or its image,
or its script, or other things effecxting it.. there will almost
certainly be some details.
Always do a search in the zotlog for ERROR lines (or once in awhile
WARN lines.) -- any important error will begin with ERROR, though
a lot of older runtime errors from earlier Zot versions will not
begin with ERROR, but all config.txt parsing error messages
definately begin with ERROR and thus are very very easy to find,
and are the problem most peopel will see.
Zotscript compile errors and warnings always show up in the
zotlog .. if a mob is just sitting there not walking around or the
like, you either didn't assign an AI module, or you assigned it
an AI and didn't fill in data or scripts right. If Zot tries to
compile a script and cannot do so due to scripting typos or errors,
then detailed descriptions of the errors will show up in the
zotlog!
On screen HUD -- if "ERROR" entries are sent to the log, then an
onscreen HUD will come up when it gets a chance, to let you know
that errors occurred and what some of them are. This isn't as
detailed as zotlog, but lets you know you should consult the
zotlog!
- Display to the screen -- you can post messages to the Zot
display with some variable-values for instance, so you can trace
what is going on. I will also add some zotscript functions to
log to zotlog, so that you can insert your own data to the log,
to let you see whats going on. Showing data ot the screen is a
huge help when things are working "more or less", but something
goes funny once in awhile..
Making and loading images
Look at these two images:
BombZ
ZInvaders
If you look carefully at the first, you'll notice that its made
up of a grid of squares (tiles), where each one is 16x16 pixels.
Furthermore you'll notice that most tiles are the same, though you
(as a player) tend not to notice if there is sufficient tile
variety. However, you can use larger tiles, or you can use
very large images. Looking at ZInvaders you'll notice the background
is one large image.. one great big tile. Internally, Zot always
works in terms of 16x16 tiles, but you don't have to.. you can
tell Zot to just deal with it for you. (Mind you, very large images
take up a lot of memory.)
What image file format?
Using The Gimp or Photoshop or the like, you'll know you can save
artwork in any number of formats, from .PNG to .GIF to .JPG to ...
anything. However, to keep things very specific and simple and to keep
the application size down for handhelds, Zot only supports a few
limited formats.. for now, PCX and TGA (Targa).
If you wish to do a non-alpha-blended image (tile, or static
artwork, or simple sprite with simple transparency), then PCX can be
ideal; always save in "8bpp", otherwise known as indexed 256-colour
images. This has a bad rap, but is actually a *very* versatile
colour scheme -- since it actually means that you get 8bits of colour
for each of red, green and blue, meaning its actually 24bpp colour,
but limited to 256 different colours.
Targa (.TGA) files can be 8bpp or 16bpp or 24bpp colour, and
also can have an "alpha channel" (degree of transparency on each
pixel.) Alpha channels slow things down a lot, but are fantasticly
powerful for special effects.. so some sprites should be TGA with
alpha, but most sprites and artwork should be TGA-no-alpha, or 8bpp
PCX. All tiles should be 8bpp PCX or TGA-no-alpha, since tiles are
drawn a lot and are *under* everything, so no blending.
How big to make them?
Tiles should always be multiples of 16 in each direction, such
as 16x16, 32x32, 48x48, 64x16, 16x48, etc etc. They can really be
any size, but most tiles should be small to keep them low on memory,
and ideally 16x16 since thats easiest to work with. However, for
large animated artwork or making things pretty some large artwork
is kocher -- consider an RPG, with lots of repeating floor tiles,
but a large fountain or table or bed in the middle of a room.
Sprites can be any old size pretty much, not restricted to
multiples of 16 pixels. ie: Could be 5x10, 21x32 or whatever.
Larger sprites are slower to render so you don't want too many, but
Zot is also pretty fast so you can usually have a lot of sprites,
for animation or enemies or the like.
ZInvaders artwork...
For ZInvaders I first nabbed some skyline photos I nabbed while
browsing around with Google of course; then a few people such as
Apex kicked in some samples and voila, the screenshot above.
For bad guys, I searched google for "ufo artwork" and did some
resizing in The Gimp, then filled all around the newly sized
ships with gray. (A special gray, RGB(123,123,123) means "transparent"
when its from an 8bpp PCX image). For the player I just re-used the
dude from BombZ (copy the pcx image file and the sprite definition
from BombZ). Look at the ZInvaders screenshot and you'll see
exactly what I'm talking about.
Making it all work in Zot!
Zot must have the images loaded into it, and you have to name
the images. This is done so that multiple sprites and tiles can refer
to the same image (or part of an image), saving memory. The image
section is one of the first things you put into the config.txt,
since you'll want to use the images in most subsequent sections,
and Zot loads the config in order.
image-list start
# background
background apex4832.pcx
#
# UFO's
ufo1 ufo1.pcx
ufo2 ship_1.pcx
ufo3 ship_4.pcx
#
# shots
shot1 shot_2.tga
#
# explosions
apexboom zinshee3.pcx
#
# bombz
bluebrick blbrick.pcx # basic 16x16 blue floor tile
skeefont fontaa.pcx
#
image-list end
Notice a few things..
- Comment lines begin with "#"; everything after the # is
ignored.
- Most lines are two words.. key and value.
- Images are "image name" and "filename" ... above you'll notice
that "background" is "apex4832.pcx"; after the image is loaded,
further objects will refer to this image as "background" and never
as "apex4832.pcx"
Making a map and player
After you've loaded up some images, I like to slap together
a map and get something going.
The first thing you need to decide is what to name the level
("Level1" will do :), as well as deciding the size of the level --
is it going to be wide, tall, square, whatever. Is it going to be
a 10x10 level (in terms of tiles, not pixels!), 20x20, 30x20, etc.
A Palm OS screen is usually 320x320 or 480x320; 320 pixels is
20 tiles (320/16=20!). If the level is 20x20 (320x320 pixels) then
it will be centered automatically on a zodiac (480x320 device) or
scroll on the GP32 (320x240 device).
So starting filling in the tilemap section..
tilemap Level1
width 20
height 20
tilemap end
The above is a square 20x20 (320x320 pixel) level, not yet
filled in.
Now we need some tiles to put into the map. I always define
a standard "floor" tile. Perhaps something like this...
tile .
name floor
image floorartwork
tile end
This little snippet can be between "tilemap" lines, or it can
be outside of the tilemap block. If it is inside the tilemap
block, it can only be used in that tilemap. If it is outside of
the tilemap, then it can be used on any tilemap. (The reason you'd
do it inside the tilemap is since a tile has a one character name,
such as "." above, that you can only make so many tiles. But if
you have some global tiles for all maps, and others on a per-map
basis, you're virtually unlimited.)
This tile is called "." (period), though by name it is "floor".
Most important is the "." and the artwork "floorartwork", which
must've been defined above. In our image case, above, it would have
to be called "background", say.
Now, given a tile, we can fill in the map. A boring map made up
of one tile, but a map none-the-less. You merely add "row" lines
and put the tile's identifier (the period) in a square...
tilemap Level1
width 20
height 20
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
row ....................
tilemap end
Notice how there are 20 periods across each row, and 20 rows.
There you go.. width and height are each 20, so due to width there
must be 20 periods across. Due to height, it must be 20 rows tall.
Thats it.. a level called Level1, that can be used!
Now just add a startmap line so Zot knows where to begin..
startmap Level1
Voila, you're almost ready to launch Zot! All we need now
is a player sprite, since Zot requires one...
Making some bad guys
Fixing problems / debugging
Making some custom scripts
Tutorial 1
First things first.. get the tutorial files; they're included
in Zot versions 046 or later, or you can download them
here.
The first tutorial is a very basic sample Zot config.txt; when
you run it in Zot, it'll run fully.. it'll give you a couple
suggestive errors, but it'll run fine and be a complete if very
basic gamelet.
There is no fancy zotscript going on here.. just basic
zot-config to get things going.
The annotated description is here:
First we need to load a couple of images for use as tiles for
the map. If we don't load them, the engine will supply us with
black tiles to get things running.
image-list start
blue blbrick.pcx
brown brbrick.pcx
image-list end
Second, we need to define a couple tiles. Again, if we refer
to a tile that doesn't exist the engine will supply us with a black
tile which isn't very useful, but it gets us going. Below we define
two tiles.. a tile called "." to use as a floor, using the blue tile
image defined above. We also define "W" to be a brown tile.. a
wall, say.
# define the tiles for use on floors in this config
tile .
name floor
image blue
tile end
tile W
name floor
image brown
tile end
Last we define a tilemap.. a floor map. First we tell the engine
that it is 20 wide by 15 high, and then we define all the 'rows'
(going across).. one "row" line for each height.. so we need 15
row lines. Each row line must be "20" tiles wide since we specified
that many. If you specify a character that is not defined as a tile,
such as "z" (since we only defined . and W), then the engine will
supply a black tile just to fill in the gaps.
# make up a floor based on all those tiles
tilemap MyFloor
width 20
height 15
row WWWWWWWWWWWWWWWWWWWW
row W...WW..W..W.......W
row W.W....WW....W..WWWW
row W.WWWW.WWWW..W.....W
row W.W.............WWWW
row W....WWWW..WWW..W..W
row W.WW...W........W..W
row W.W..WW...W..W.....W
row W....W..WWW.....W..W
row W....W..WWW.....W..W
row W....W..WWW.....W..W
row W....W..WWW.....W..W
row W....W..WWW.....W..W
row W....W..WWW.....W..W
row WWWWWWWWWWWWWWWWWWWW
tilemap end
Thats it.. thats all you need for a very basic game to get
up and going.
Well, thats not even true.. you could supply a completely
empty config.txt and it'll run all black :)
Tutorial 2
In this tutorial I will simply add a basic player sprite and do
enough setup that the engine will run everything with no errors, and
give us a working little game.
Commentary below is only about the new lines.. most of the
config is unchanged from the previous tutorial.
image-list start
blue blbrick.pcx
brown brbrick.pcx
person perso.pcx
image-list end
First, we tell the engine specifically which tilemap to begin
on; when you don't tell it, it just guesses the first map it can
find; if it cannot find any map, then it'll make one up that is
blank. Anyway, this "startmap" line just says which to start at
since of course most games include multiple maps.
# where to start?
startmap MyFloor
# define the tiles for use on floors in this config
tile .
name floor
image blue
tile end
tile W
name floor
image brown
option impassable
tile end
Next we decide to tell the engine where the player should
start; if we don't tell it, it'll guess and just plop the player
down somewhere. In this case we just define a tile, and give it
the option "option starthere".
tile @
name floor
image blue
option starthere
tile end
# make up a floor based on all those tiles
tilemap MyFloor
width 20
height 15
row WWWWWWWWWWWWWWWWWWWW
row W...WW..W..W.......W
row W.W....WW....W..WWWW
row W.WWWW.WWWW..W.....W
row W.W.............WWWW
row W....WWWW..WWW..W..W
row W.WW...W........W..W
row W.W..WW...W..W.....W
row W....W..WWW.....W..W
row W....W..WWW..@..W..W
row W....W..WWW.....W..W
row W....W..WWW.....W..W
row W....W..WWW.....W..W
row W....W..WWW.....W..W
row WWWWWWWWWWWWWWWWWWWW
tilemap end
Next is the real goods.. we start defining a sprite. The first
sprite we usually define is the player sprite, since the engine
likes to have a player. This is a special sprite that gets auto-made
by the engine. Any other sprite definitions are not automagicly
turned into "mobs" (created in the world).. you have to tell it to.
But a player is always created.
If you elect to use Zotscript to control the player yourself,
then some of the settings may not apply.
Some comments are in the below text on the right. Some things
to notice are that the sprite 'body' (the area used for impact
checking, such as bumping into walls or enemies) doesn't have to
be the same size as the sprite artwork. So you can define a tall
piece of artwork and a smaller body.. this way the 'head' of the
artwork could go onto the wall or tile above, but the 'body' could
still let the sprite walk down a small hallway. This is important
for making isometric-style displays.
sprite player # name the player sprite as 'player' always
# general stuff
ai player # use the special "AI".. 'player'
speed 2 # the speed to move the player at
option impassable # so things cannot walk through the player
order 3 # drawn on top of some other sprites/mobs
# location of body within sprite
width 16
height 13
offset_y 9
# artwork for sprite
image_width 16
image_height 24
# while standing still
anim_statedef still
anim_steps 1
Also notice that there is one "anim_statedef" definition; you can
define many states, so that the sprite artwork changes when its going
up or down or the like.. but you should always define a "still"
state, so that sprite knows what to look like when doing nothing.
Furthermore, when a sprite can't switch to another state it will
fall back to 'still'.