home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 17
/
amigaformatcd17.iso
/
-screenplay-
/
shareware
/
graal
/
original_archives
/
graal2d.lha
/
GRAAL_Manual.text
< prev
next >
Wrap
Text File
|
1997-06-24
|
189KB
|
4,992 lines
1 Contents
=============
1 Contents
2 Introduction
2.1 Copyright Information
2.2 Credits
2.3 About the Manual
2.4 Release Info
2.5 Notation Conventions
3 (Finally:) The REAL Introduction
3.1 So, What Is GRAAL?
3.2 Other Tools of the Trade
3.3 The Things That Make a GRAAL
3.4 GRAAL Script Files
3.5 The graal.main Script
3.6 The .room Scripts
3.7 The .section Files
3.8 The .scene Scripts
3.9 The .ptrn Scripts
3.10 Running an Adventure
3.11 Loading, Saving and Quitting
4 Starting on an Adventure
4.1 Starting on the graal.main File
4.2 The Hero - What a Character!
4.3 Basics about Images and Bobs
4.4 The Images in the graal.main File
5 "A Room! A Room! A Kingdom for a Room!"
6 The Object Matter
7 Section Objects and BOBs
8 Camera! Action! Lights!
8.1 ACTION: statements
9 Using Exits
10 The DACT: Statements
11 Flags and String Variables
11.1 Flags
11.2 String Variables
12 Having a Chat
13 Multiple Characters and Inventories
13.1 Multiple Character Graphics
13.2 Character Objects
13.3 Switching Characters
13.4 Inventory Switching
13.5 Identifying Characters and/or Inventories
13.6 Characters Following Characters Around...
13.7 Helpful Conditions
13.8 Things to Consider
13.9 Space-saving Tip
14 Character and Graphics Design
14.1 Size
14.2 Colour
14.3 Pointer Shapes and Colours
14.4 Designing Animations
14.5 Complex animation patterns
14.6 Flipped images
14.7 All About 3D and Hotspots
14.8 Scaling the Characters
15 Cutscenes
15.1 Hop, Skip and Jump
15.2 No Breaks!
15.3 Nesting
16 Timer Events
17 Special Techniques or "How The Heck Did He Do That?"
17.1 The Load / Save Room.
17.2 Going into the Alley
17.3 Speaking In a Foreign Tongue
17.4 An Automated Room
17.5 The Art of Avoiding a Seagull
17.6 A Spitting Image
17.7 A Map Room
18 The On-line Monitor
19 Macros
19.1 Starting a Macro Recording
19.2 Saving a Macro
19.3 Playing a Macro
19.4 Restrictions to Macro Playback
20 "Productifying" Your Adventures
20.1 The Basics
20.2 The diskinfo.graal File
20.3 GREP
20.4 GPRO
20.5 GDC
21 The Editor
21.1 Introduction
21.2 System Requirements
21.3 Known Bugs & Irritating Facts
21.4 Creating a New Script
21.5 Working with the Editor
21.6 Creating a Report
21.7 The Parameter Editor
21.8 Icon Tooltypes
21.9 Editor Keyboard Shortcuts
22 Hints and Tips
22.1 Flags
22.2 Diverse
23 Questions and Answers
2 Introduction
=================
2.1 Copyright Information
--------------------------
GRAAL 2 is Shareware. If you like it and use it, register and make
me happy!
All rights to the GRAAL system remains with Performance
Software and is copyright © 1997 Per Thulin.
Users of GRAAL may use the system freely to distribute their own
graphic adventures, but are completely forbidden to use any of the
supplied example material - puzzles, characters, animations, or
scenes - in their own work. Quite simply, all material used in your
own GRAAL adventures must be your own!
The shareware version of GRAAL is not crippled in any way, but it
is not quite adapted for "professional" use, which is explained later
in this manual.
See the file Registration.form for details on how to register.
2.2 Credits
------------
GRAAL is coded in Amos Professional. You know it makes
sense... :) Also, let's not forget that Black Legend Craft 1 and
AMCAF extensions. They made things that much better!
The GRAAL Editor is coded in Blitz 2 Basic. You know it makes
even more sense... ;)
2.3 About the Manual
---------------------
This manual contains an awful lot of text. Don't be discouraged -
that is simply because each little GRAAL statement carries an
awful lot of power (and because I'm such a blabbermouth), and
some sophisticated initial definitions automate most of the
gameplay! Before you get totally discouraged, print out the
following files from the example disk(s):
graal.main
1.section
1.room
If you look at these files, and disregard the abundance of comment
lines starting with /*, you will quickly realise how precious little
GRAAL code is actually needed for the basics of an adventure, and
be able to read on with a lighter heart. Also remember that there is
an editor included making your GRAAL-coding life a lot easier - you
don't have to enter that many tricky parts manually, the editor can
help you.
The GRAAL documentation is divided into three main parts:
1. The latest .readme file - essential to all who wants to read
about the news in the latest version of the system.
2. This manual.
3. An AmigaGuide on-line reference (graal.guide), the definitive
authority on all GRAAL statements and commands.
If you want to play the provided "Olaf" demo AND build your own
Graphic Adventure, I strongly suggest you play the game first!
Because "Olaf" is used as an example throughout the tutorial, some
of the secrets of the demo is given away here. This is also a good way
of deciding whether this kind of stuff is what you want to spend the
rest of your life doing :-)
2.4 Release Info
-----------------
GRAAL 2.2 brings you the following features:
* A graphic adventure point'n'click interface along the lines of,
among others, the Indy games and Monkey Island
(Trademarks of LucasArts Ltd.).
* Automation of most of the controllable characters' walking,
talking, and general fiddling around.
* 32- or 64-colour (EHB) lowres, automatically scrolling
background screens, 320 to 640 pixels wide.
* 16-colour, hires, fully configurable command area, 640 pixels
wide.
* Any number of player commands.
* Features to handle "USE", "GIVE TO" and "GO TO"
commands.
* Room and section data swapped in and out of memory at
runtime to minimise the growth of permanent in-memory data
as the adventure grows. This gives you a virtually unlimited
number of locations (rooms), objects, images, dialogues, etc.
* Also automatically detects extra memory and uses this as
cache memory to avoid unnecessary disk access.
* Animated objects and characters.
* Pixel-perfect detection of objects.
* Side-view "simulated 3D" scenes with foreground, "middle",
and background objects.
* Dynamic depth-scaling of characters.
* A rather intelligent and easy-to-use dialogue system for those
totally silly discussions with sidekick characters we all have
come love so much.
* An equally intelligent and smart but perhaps a little more
difficult-to-grasp floor and path definition system - for defining
legal movement paths and automatic negotiation of obstacles.
* Cut-scenes with or without indicators. Nested cut-scenes are possible.
* Timer events.
* Functions for in-game clocks and dates.
* Built-in requesters for save/load and quit functions - or disable
them and design your own save/load and quit screens.
* Multiple character control.
* Multiple inventories.
* Soundtracker style music modules for background music.
* IFF and raw samples for sound effects.
* Run-time error checking (to a degree).
* GRAAL automatically detects if a GRAAL adventure is run
from diskette, CD-ROM, or hard disk, and adjusts disk
swapping and save/load routines accordingly.
* All tools included except an art/animation package and
(optional) sound sampler equipment.
* Diskette layout system for automatic copying and labelling of
distribution master diskettes.
* Dynamic on-line monitor and debugger for script testing, on-
the-fly temporary corrections, and examination of the game
status.
* Single-step trace mode for debugging.
The developer's registered version also gives you:
* Optimization and encryption of distribution files. The process
also locks all development functions (the on-line monitor,
break keys, etc.) so that they cannot be used by the player.
* Extra graphics files offering various "requester looks".
It does NOT give you:
* AGA (but on the other hand, a much broader customer base for
your games. Let's be kind to those ECS users out there! :)
2.5 Notation Conventions
-------------------------
In this text, < > denotes button gadgets and [ ] keyboard keys.
Furthermore, I have tried to print names of files and sections of
scripts in a special font:
file.name
Of course, those of you who only have the ascii manual will not
benefit from this. Register and order the manual! :)
3 (Finally:) The REAL Introduction
=====================================
Welcome to GRAAL. Maybe thy quest is over!
...or maybe it has just begun. Because, although GRAAL is a
powerful tool, designing a graphic adventure still needs an awful
lot of hard work from your side - all GRAAL does is take most of the
actual coding work out of the job and lets you get on with designing
the story, logic, backgrounds, objects, animated characters and
dialogue! Which, in itself, should keep you busy for quite a while.
GRAAL was mainly invented along with the 7-room demo of the
first ever GRAAL adventure "Olaf Longhair, Part I", delaying the
release of both, but ensuring that GRAAL really works on a full-
scale and rather advanced graphic adventure. Although maybe not
quite up to LucasArts standards, it proves that GRAAL can make
at least a budget-level game any day! And since this manual was
written parallel to the code that went into "Olaf" and GRAAL itself,
you should find everything of importance right here.
3.1 So, What Is GRAAL?
-----------------------
All GRAAL adventures consist of:
* The GRAAL driver program, which is the "adventure engine".
It is named GRAAL_2 in the development package. When you
use it to run a specific game, it is usually renamed to whatever
that adventure is called.
* GRAAL script files, containing the statements that make up
the adventure. There are different kinds of script files: One
graal.main file, .room files, .section files, .scene files, and .ptrn
files.
* IFF image files, depicting background scenes and object and
character "clip-art".
* A file called diskinfo.graal. This file contains, among other
things, the names of all the other files used in your adventure.
This file is used by GRAAL to locate files and handle disk
swapping in an intelligent way if your game gets so big it does
not fit onto one disk.
* Optionally, soundtracker music modules and sample banks.
3.2 Other Tools of the Trade
-----------------------------
If you don't have AmigaGuide (or Multiview - WB 3 and above), get
hold of it NOW. You'll need it to use the editor, and read the on-line
command reference.
You will not go far without a good paint program like Deluxe Paint,
Brilliance or Personal Paint to create all backgrounds, objects and
animations. An image processing program like Photopaint, Image
FX or ADPro is a good complement.
To take some of the work out of the backdrop scene creation, why
not use a modelling and rendering package? (Believe it or not, there
are some good ones that are freeware, even - POV-ray, for instance.
A sound sampler and software could also come in handy, as could a
scanner or digitizer. But hey, it's up to you. Or rather, your wallet.
3.3 The Things That Make a GRAAL
---------------------------------
Because there are a lot of things in the GRAAL system to keep
track of, and you need almost all of it to make the adventure work,
the manual will try to explain most of the stuff in the tutorial form,
followed by in-depth discussions on a number of the trickier
subjects and concepts. There is also an on-line command reference
in Amigaguide format, which is a necessary complement to this
manual, and which will be vital once you get hang of things in
general. Also, the Olaf 1 demo provides you with well commented
script files of all types. These demonstrate almost all major GRAAL
techniques. (Beware: READ THE COPYRIGHT NOTICE!)
But first, let's have a quick general look at the general structure of
a GRAAL game.
3.4 GRAAL Script Files
-----------------------
The GRAAL code needed to make an adventure tick is contained in
a number of script files. It is a compact language; if it wasn't for the
heavy commenting, they would not take up too much space at all!
There are different types of script files, each controlling a different
portion of the game. Their relationships form a tree- shaped
structure, like this:
There may be any number of .section files beneath the graal.main
file, and any number of .room files under each .section file.
(Although placed in the middle of the structure, the importance of
section files vary greatly depending on the design of your
adventure. In some cases, you may want to have only the one
section file, containing nothing at all! More about this further on.)
In all these script files there are three basic kinds of lines:
Comment lines - All comment lines must begin with the
characters
/*
which can be followed by any text, like in
/* This is a comment if ever I saw one!
Use comments a lot, because the GRAAL syntax is not particularly
reader-friendly, and what was clear in your mind when you typed
it in may seem like pointless rubbish a couple of weeks later - if you
don't have the comments there to remind you.
Hint: The GRAAL_Editor uses the first line of each script file to
explain its contents in file requesters, making it easier to find the
file you want. Therefore, always make the first line of each script a
comment, like this:
/* Short description of script contents
Empty lines - may be used as separators for improved readability.
Statement lines - each statement line contains a statement (or
keyword, if you will), followed by a colon, and one or more
parameters separated by semicolons. Like this:
statement: parameter1;parameter2;...;parameterN
In many cases, the parameters contained in a statement line are
conditions or commands, containing their own parameters.
Example:
ACTION: 4;IFRF 2=0;SAY I Can't do that;EXIT
In this example, ACTION: is a statement that comes into play when
GRAAL is checking a command input by the player. More precisely,
the ACTION statement in this example will be used if a sentence
using verb 4 (parameter 1) has been entered by the player. GRAAL
will then execute the commands SAY and EXIT, but only if the
condition IFRF 2=0 has been fulfilled first.
Note: There must be a space between the ":" and the parameters,
but there must be no spaces around the semicolons separating the
parameters! Also, there is no semi-colon after the last parameter in
a line.
Each statement in a script file may be up to 255 characters long.
The script files are case sensitive, so make sure all statement and
command names are written in upper case.
Any line in the three types of script files mentioned above that does
not conform to the rules will be spotted by GRAAL at run-time,
normally causing the execution of the adventure to halt with an
error message. Double-check everything, and use the GRAAL
editor for help with the parameter syntax and syntax checking!
3.5 The graal.main Script
--------------------------
"All right, but what do these different script files actually do?" I
hear you scream.
Good questions! The first, and in many ways the most important, is
the graal.main file. It is called that because that is what it must be
called - if GRAAL doesn't find a graal.main file in the current
directory, it will say so and terminate.
The graal.main file sets up everything that is common to the entire
adventure, such as:
* All basic aspects of the main character's behaviour - he's
certainly going to be around in the entire adventure!
* Where the adventure starts.
* The fonts to be used for the user interface.
* All the objects that can be carried anywhere in the game.
* All the characters involved in dialogues.
* All the actions the main character can take that are common
to all, or at least to most, locations.
3.6 The .room Scripts
----------------------
Once GRAAL has interpreted the graal.main file, it knows which
room file to look for first. All room files have the suffix .room
preceded by the room number, so the first room file used in the
adventure is very often called 1.room . (If you decide on a better
starting point for the adventure later on, you may of course tell
GRAAL to start in, for example, room 45 instead.)
Since GRAAL reserves memory for each possible room number
from 1 and up to the highest room number used, it is quite wasteful
to have "gaps" in the room sequence. If you have deleted some
rooms in the middle of the sequence, use the vacant numbers when
you add new rooms, thus minimising the gaps in the numbering
sequence.
The .room files do much the same for each adventure location or
"room" as the graal.main file does for the adventure as a whole.
They contain, among other things, the following:
* The name of the IFF file to be used as the background in the
Scene Area.
* Information about "clip-art" to be loaded in and used as
graphic elements and objects for this particular room.
* The dialogues that take place in this room.
* The objects that can only exist within this room.
* All actions that are specific to this room.
3.7 The .section Files
-----------------------
.section files are very similar to .room files. Their main purpose in
life is to make GRAAL more memory efficient. The basic idea is that
many graphic adventures are divided into logical sections, a section
being a number of connected rooms where the same objects can be
handled and a number of puzzles need to be solved before you can
move on to the next section. However, once you are through with a
section, there are a number of objects and images you will never use
again, and therefore they can be deleted from memory the freed
space can be used for the objects of the new section. Or, perhaps the
rooms of the section share a lot of graphics - like a labyrinth in a
system of caves probably would.
How you define sections is up to you, and you do not need to use the
concept at all if it is irrelevant. (In that case, just use section 1 for
all the rooms, and place no commands in the 1.SECT file - just a few
comment lines describing what the blazes you are up to, with a
couple of totally blank lines in between.)
3.8 The .scene Scripts
-----------------------
.scene files are known as cut-scene files, containing non- interactive
parts of the adventure (playing much like cartoon movies). They
can also be used as subroutines, saving you the work of re-coding
the same set of commands in a lot of places.
The cut-scene files are a little special (but simpler) than the
previous script files, and will be discussed later on.
3.9 The .ptrn Scripts
----------------------
.ptrn files are not scripts as such - they contain definitions of
animation patterns that would be too long to enter into the other
script files directly, or you wish to re-use in a number of different
places in your scripts - or all of the above. (For those of you familiar
with Amos Pro, the contents of the .ptrn files follow the AMAL
syntax exactly.)
3.10 Running an Adventure
-------------------------
At some point or other, you feel that the script files are ripe for
testing. This is simply a matter of trying to start the adventure by
running the driver program GRAAL_2, which must be placed in the
same directory as all the script and graphics files you refer to in the
game.
(You should, of course, run the syntax checker in the
GRAAL_Editor on all scripts first to get rid of all typing errors and
other such mistakes. This takes far less time than re-running
GRAAL_2!)
First, the GRAAL_2 program loads. Then, the GRAAL title screen
is shown. The progress indicator (the horizontal bar) indicates that
the contents of the graal.main file are being loaded and processed.
When the title screen disappears and the screen goes blank for a
moment, the system is working on the first .room script.
Most likely, you will get some error messages before everything
starts running smoothly. A GRAAL "run-time error" message will
appear in yellow text surrounded by a red border on screen, stating
the type of error, which room was currently loaded, and which file
was last accessed.
Note: This file may in some cases not be the actual culprit! For
example, If GRAAL has loaded a small cutscene file, executed it
and run into a problem in the calling script later on, it is still the
name of the completely innocent cutscene file that is shown, so take
this information for what it is.
Some problems may be of a less severe nature. In those cases,
GRAAL sometimes lets you decide whether to continue playing, or
exit the program (in which case it tries to clean up the memory just
as if you give the "Q"uit command when playing the game the
normal way).
Continuing after such a warning is not always safe: The error
almost certainly affects some aspect of the game. However, things
like flag value errors may often be corrected using the on-line
monitor (see the appendices).
Also note that in the error messages, the offensive statements and
commands are sometimes printed in a slightly different way from
how they appear in the script: This is because all RBOBn, SBOBn,
ROBJn and SOBJn references, which are relative numbers, are
translated directly upon loading to become absolute numbers. So if
your N_xxxxBOBS statement in the graal.main file decide that
ROOMBOBS start at image number 51, an erroneous statement
containing RBOB4 would actually show the number as "54" in the
error message. (Sorry 'bout that. Read on, and you will probably
understand what the heck I am talking about later.)
There will most likely always be some errors that are not trapped
properly, and the system may just "die on you". In those cases, try
to determine how far the loading process has actually gone, and
check the structure of YOUR scripts carefully against the Olaf 1
demo and the order in which things appear there! Also, resetting
your Amiga before trying again often helps - as always, there is a
certain amount of memory thrashing going on if you make a lot of
consecutive test runs.
For an overview of the features of the GRAAL_2 player interface,
read the "Olaf.guide" that contains instructions for the demo
adventure.
3.11 Loading, Saving and Quitting
---------------------------------
GRAAL has its own, built-in requesters and short-cut keys for the
standard tasks of loading, saving, and quitting a game. However,
you can easily disable those short-cut keys (with some statements
in the graal.main script) and design your own routines. Olaf
Longhair uses a special room where you can have a look at the
score, save and load games, and optionally quit the program. In the
demo, I have not disabled the short-cut keys, so you can choose
which way to quit, for example - the quick one or the impressive
one!
On the subject of loading saved games, note that saved game files
can only be used with the same GRAAL driver and adventure
version with which they were saved - each time you add or delete
objects, rooms and other stuff in the adventure, the saved game file
format changes, and renders old saved game files unusable. To
make the task of testing a little easier, have a look at the macro
feature ("Macros" on page 65).
4 Starting on an Adventure
=============================
I won't bother you with a lot of talk about how you must plan the
contents of your adventure, have a good storyline, so on and so
forth. If you don't that's not my fault, is it? I simply assume you
HAVE a story to tell, and that you are well aware of how graphic
adventures of this kind works - if you don't, you'd better play some
first. I will then show how you can do it all using GRAAL.
I won't even go into the basic idea behind my example adventure
"Olaf Longhair", because surely you have played the demo by now!
This tutorial concentrates on everything that makes the first four
rooms in Olaf Longhair tick - because once we have that much
going, almost everything follows along the same lines (or will be
pointed out separately).
The four rooms, in order of appearance, are:
1. The bar, where Olaf wakes up the morning after the night
before, and has an informative chat with the bartender.
2. The street outside the bar, where he bumps into a strange-
looking guy with an even stranger-looking animal.
3. The harbour, where he meets a foreign captain and deals with
a rather irritating seagull.
4. The shopping emporium of one Ali Harrod, Esq.
4.1 Starting on the graal.main File
------------------------------------
Look at the graal.main script now. To do it "the GRAAL way",
* Start the GRAAL Editor, which should be in the same
directory as the example files.
* Press right Amiga + "4" to automatically open a new window
in the editor and load the graal.main script there.
The GRAAL Editor with graal.main loaded into window no.2
The best way to start creating a new adventure is to take a
graal.main file that works, and alter it to suit your own needs. Using
the GRAAL editor, you can also choose to create a graal.main file
template, with comments and statements showing what is
mandatory and what is not. (This method can also be used for the
other script types.)
Here are some examples of statements that can be set almost
immediately. Other ones will be dealt with once we start designing
rooms, objects and characters for the adventure.
If you use the GRAAL Editor, you can read more about each
statement if you place the cursor in the statement name
somewhere and then press the [Help] key or click the <?> button.
NAME: "Olaf Longhair Goes East"
The name of my adventure is "Olaf Longhair Goes East". (The
quotes are not there because they enclose a string or anything - I
actually want them displayed on screen when the name of the
adventure is called up by pressing the [V] key during a game!)
VERSION: Demo 2.2
The adventure version number. This is especially useful to
guarantee that you don't try to load old saved game files when
testing a newer version of the adventure.
Then follows a lot of statements dealing with the player interface
layout, and numbers setting limits for how many images, objects,
and other things GRAAL can handle in your adventure. Basically,
the size of the comand area, the number of available commands,
their positions and appearance, the layout of inventory lists, and
dialogue alternative displays can all be adjusted to suit your needs.
Read the comments in the graal.main file, that's the best way to
learn about them. Many of these statements require graphic
images to be specified and positioned - more about graphics follows
below.
Fonts
"""""
Among the statements in graal.main, one thing worth a special
mention is the way GRAAL uses fonts.
The statements
MSGFONT: xen;8
COMFONT: garnet;9
TITLEFONT1: olaf;27
TITLEFONT2: times;14
each loads a font with a certain size and stores it in memory for
later use in the game. (For more information on what font is used
where, go to the on-line reference.)
To keep things easy to handle on the player side, we do NOT install
these fonts in the normal Workbench FONTS: drawer, but keep
them in a special FONTS drawer inside the drawer where all the
other game files reside.
This means all fonts you wish to use in the game must be copied to
this special "game fonts" drawer in your development directory.
The only trouble is that GRAAL needs to have its fonts drawer
"prepared" with the standard Amiga FIXFONTS command in order
to be able to load the fonts.
What this means is that whenever you change the fonts in the
drawer, you should run the standard Workbench "fixfonts"
program, with the logical assign FONTS: pointing to the game fonts
drawer. You do this in a CLI shell, and the commands used should
look something like this ("DH1:" below is a hard disk drive, and
"MYADVENTURE" is the path to your development drawer on that
disk):
> assign FONTS: to DH1:MYADVENTURE/FONTS
> fixfonts
> assign FONTS: to SYS:FONTS
The last command re-assigns FONTS: to the Workbench FONTS
drawer.
4.2 The Hero - What a Character!
---------------------------------
At this point, we will not get much further without bringing the big
star, our main character, the man, Olaf Longhair himself, into play!
One of the things GRAAL makes so easy to manage is the point and
click control of the main character - in this case, Olaf. GRAAL
controls what animation sequence is the correct one to use in all
standard situations, in which direction Olaf is heading, where in a
room he can actually place his feet, and so on.
Wonderful as all this may be, it doesn't relieve you of the
responsibility for the character design - in other words, before
GRAAL can do all this wonderful stuff, you must design the main
character and the animations used for his basic movements.
Basically, what we need now are some still images and animation
cels showing Olaf in various standardised poses. For "Olaf", all
these are placed in the IFF picture file "Olaf_Original.iff", which
you should take a look at now.
What the images portray are:
* Olaf walking towards, away, and sideways
* Olaf's front, back, and profile when standing still
* Olaf talking - the front, back, and profile views.
* Olaf manipulating things - also front, back and sideways
views, but for each view also in three "height" versions - for
objects high up, far down, or "in mid-air".
As you notice, the images of Olaf in the file are neatly and evenly
spaced. This makes it easier for GRAAL to "cut out" these images
and store them in its image bank later.
Also note that there are no separate images for the right and left
profiles - to make life a little easier, and less memory consuming,
the profile images will simply be flipped by GRAAL when a
reversed view is required.
We will need more images of Olaf during the course of the game,
but since they will only be used for special occasions, they are
loaded into memory only when they are needed and erased
afterwards. So "Olaf_Original.iff" contains all the "global" images
of our main character and favourite hero.
4.3 Basics about Images and Bobs
---------------------------------
We are going to talk a lot about stills, cels, animations and BOBs in
this tutorial, all concepts dealing with how an image is used.
A still is any image that is static.
An animation is any image that moves, and it does so by using a
number of slightly different stills replacing each other, called
ANIMATION CELS.
BOB is short for Blitter OBject. BOBs are well-known to Amos
programmers. They are, basically, the way GRAAL displays all
graphics on screen that aren't just backdrops: Objects, animated
characters, texts, and so on. BOBs can be put into the display and
deleted again without harming the backdrop picture. To achieve
this, the system must keep track of all the little graphic bits and
pieces by assigning each one used at any time with a BOB number.
To make it easier to keep track of the images used by the BOBs,
they are stored in a BOB image bank.
Any BOB may use any image (or vice versa, depending on how you
look at the world). For example, BOB number 44 may be used to
display a flower, held in image bank position 56, in one scene. In
another room or scene, the same BOB number 44 may be used to
display a knife, which is image 78 in the bank. Confusing? Just
keep this in the back of your head until we start discussing the
script file statements!
Since re-cycling is the word of the day, there is no difference in the
image types used for different purposes - all are stored in the BOB
image bank, and you may use the same image as an animation cel
in one situation and as a still image in another.
The BOB image bank, where we store all images, must be logically
divided into three sections:
1. Global BOB images are those that are kept in memory at all
times, for example all Olaf's basic movements, icons for global
objects, and command area graphics. The number of slots used
for these are defined with the N_GLOBALBOBS: statement.
Make an educated guess how many of these you'll need. "Olaf"
uses about 90.
2. Room BOB images are images that are only needed in a
specific room - as soon as the game switched to a new room, all
these images are erased from memory and replaced by the
graphics for the new room. The number of these is defined by
the N_ROOMBOBS: statement. When referred to in the
scripts, their numbers are always prefixed with RBOB:
RBOB5 means room BOB 5.
3. Section BOB images work the same way as room BOBs, but
for a section (collection of connected rooms) rather than a
single room. Their number is defined by the
N_SECTIONBOBS: statement. When referred to in the
scripts, their numbers are always prefixed with SBOB:
SBOB10 means section BOB image 10.
If you make a mistake when estimating the number of each image
category here, it is not the end of the world. These numbers can be
altered at any time later on.
4.4 The Images in the graal.main File
--------------------------------------
Back to the graal.main file now, to practice what was just preached:
N_GLOBALBOBS: 90
N_SECTIONBOBS: 30
N_ROOMBOBS: 70
This means that right now, we believe we need 50 global BOB
images, 30 for use in sections, and 70 for use in rooms. If we change
our minds later on, we can always change the numbers then.
Let's define the main character's images. The statement
CLPART: Olaf_Original.iff
tells GRAAL that following statements will grab images from the
picture file Olaf_Original.iff
BOBS: 10;11;1;1;31;47;32;0
tells GRAAL to grab 10 BOB images and store them in image slot
11 and upwards (slots 1-10 are reserved for system use,
remember?)
In the GRAAL editor, try this:
1. Put the cursor on the statement name "BOBS:".
2. Click <Edit parameters>.
3. Click <Area>.
4. The Olaf_Original.iff file appears with ten frames showing
which pieces of graphics will be cut out. The frames can be
moved, resized, and re-spaced. If you were to change the new
position with the Enter key (but don't do it now!), the
parameters of the statement reflects the changes you made.
See "The Editor" on page 74 for a complete description of the
editor.
More CLPART: and BOBS: statements follow upon this first one,
until all basic images we need have been loaded into the image
bank.
If you want to use multiple controllable characters, automatic
character scaling, or make the cingle controlled character
"clickable", you have to define a CHAR: statement for it. Each
CHAR: statement defines a controllable character, and because
parameters in CHAR: also set height, width, and other properties,
the above statements may seem a little useless and out-of-date. So
they are, but bear with me - they are left in for compatibility.
In my demo adventure, I do use character scaling, so let's define
Olaf with a CHAR: statement:
CHAR: 1;18;11;40;1;1;37;0;22;1.2
1;
means Olaf is character number one. There must ALWAYS be a
character number one if CHAR: statements are used at all!
18;
means that Olaf is object 18. We'll come back to defining objects
later - in this case, the object definition holds some important
information about Olaf, like which animation channel he will be
using.
We will not go into details about the other parameters here - read
all about it in the on-line reference.
(In older versions of GRAAL, there was no CHAR: statement, or
indeed a character object - instead, you had separate
CHARACTER_WIDTH:, CHARACTER_HEIGHT: and similar
statements to set the properties now dealt with in the CHAR:
statement.)
Anyway, on with it. We need to define some graphics concering
some standard movements and still images for our hero:
STILL_RIGHT: 14
STILL_LEFT: //14
STILL_BACK: 12
STILL_FRONT: 11
These statements tell which still images are to be shown when Olaf
is facing in the respective direction, doing nothing.
Wait a minute, what's that strange "//14" thing? Well, it's a
convenient way of re-using graphics. Any image number prefixed
with "//" will display the image flipped left/right, so you don't have
to create graphics for both views. Neat, eh?
Anyway, on with it.
PAUSE_RIGHT: 13
PAUSE_LEFT: //13
PAUSE_BACK: 12
PAUSE_FRONT: 11
These images are used when Olaf pauses after having gone in a
certain direction. If you wish, they may be set to exactly the same
values as the STILL_ images. However, as you see, Olaf uses image
13, a slightly more relaxed, forward-facing and "ready-for-input"
pose, for the right and left poses in these statements than in the
STILL_ statements.
You don't HAVE to make the left pose the flipped-over version of
the right pose - if you want to draw different images for each
direction, go right ahead. Also, if there is any risk of both views of
the same image being shown on screen at the same time, they
should be separate images! For more info, see "Character and
Graphics Design" on page 48.
So far, all we have done is specify still images. Now we enter into
the gruesome, yet strangely attractive world of animation:
WALK_RIGHT: A 0,(16,6)(15,6)(14,6)(17,6) ...
WALK_LEFT: A 0,(//16,6)(//15,6)(//14,6)(//17,6) ...
WALK_AWAY: A 0,(29,8)(30,8)(31,8)(30,8)
WALK_TOWARD: A 0,(26,8)(27,8)(28,8)(27,8)
And yes, AMOS Pro users will immediately give a cry of joy: It's
AMAL!
AMAL is AMOS Pro's animation language, and GRAAL uses the
same syntax for animations. So let's see what we have here:
"A 0," simply tells GRAAL to repeat the following animation
sequence indefinitely. (Stay calm - GRAAL will handle all starting
and stopping of standard character animations automatically.)
"(16,6)(15,6)(14,6)" and so on are the images and display lengths of
each animation cel. For WALK_RIGHT, first image 16 is displayed
for 6 frames (=screen updates), then image 15 is displayed for 6
frames, and so on. When the end of the list is reached, the
animation loops and starts over with image 16 again. As you see in
the WALK_LEFT statements, flipped images are used in
animations also - no problems. For more about animations, see
"Designing Animations" on page 49.
It's quite wise to use 6 frames as the smallest time space for any
image during background scrolling - 3 is possible and may work
well if you have a limited number of BOBs in each scene in your
adventure. However, if you paint on a large canvas so to speak, the
system will have problems fitting all graphic updates into a 3 frame
space and so the animation may become jerky. (6 isn't safe in all
situations, but it usually works and is a good compromise.)
TALK_MAP: 11;A 0,(20,18)(11,12)(20,12)(11,6)(19,12)
Not only walking is animated and automated in GRAAL - talking
is as well.
The animation to be used for speech in each situation is not
connected to a certain direction, but rather to what image is
displayed on screen at the time the character starts talking - The
above statement tells us to use this animation if the character is
facing forwards (image 11) when the speech starts.
As you see in graal.main, there are six TALK_MAP:s specified - all
STILL_ and PAUSE_ images are accounted for, which indeed they
must be for GRAAL automation of the speech to work in all
standard situations. And you can test for flipped images, too:
"TALK_MAP: //14; ...", for instance, checks if the image displayed is
the flipped version of image 14.
HANDLE_MAP: 11;A 1,(11,12)(36,1);A 1,(11,12)(34,1);A
1,(11,12)(35,1)
Standard "manipulation" or handling of objects are specified in a
similar manner - the animation to be used when a certain object is
handled depends on a) the previous character image on screen and
b) whether the object in question is placed high up, low down or in
mid-air - an animation sequence for each possible position is
supplied in the same statement, separated by semicolons.
Note that the last image in each sequence should be specified as
shown for only ONE frame - this is because a) the character will
stay in that position during the handling of the object anyway, and
b) we may wish to immediately do some other graphic tricks after
the HANDLE command has been given, such as placing an object
in the character's out-stretched hand. Specifying too long a pause
in these animation sequences would produce an unwanted pause in
the flow of the script.
To summarise, if the character is facing forward using image 11,
and suddenly is commanded to handle an object placed in mid-air,
(the cup in the "Constantinoplian" bar is a concrete example), the
middle animation sequence in the above statement, which is "A
1,(11,12)(34,1)", would be executed.
OK. That was a lot of hard work and tricky definitions to sink one's
teeth into, but guess what? We're done! We have actually
completed a large percentage of the animations needed for our hero,
and can get on with designing the adventure itself!
The statements we have defined above will be used and executed
time and time again throughout the adventure, and in a fully
automated fashion, too. But you control-freaks should not worry too
much: GRAAL contains enough script commands to enable you to
break away from the standard poses and animations in any given
special situation - if you are willing to take on the extra work and
extra coding in the scripts that is required.
5 "A Room! A Room! A Kingdom for a Room!"
=============================================
As you may gather from the heading of this chapter, we now quite
badly need a room or other location to move about in - having our
hero confined to a lot of abstract image and animation statements
in the graal.main file will not make anyone happy.
Let's start with room number one. Although the demo adventure
first goes through a couple of other rooms, these only make up the
introductory animation, that is where the real action starts.
Similar to how the main properties of the adventure is defined in
graal.main, the properties of room 1 is defined in the file 1.room.
Have a look.
The first statement we come across here is
UPDATE: 3;1
which sets the updating speed of the scene area. The higher the
numbers, the slower the screen updating, and the more graphics
GRAAL is capable to shift between updates. To keep animations
etc. from becoming jerky, the numbers must be set high enough to
cope with all graphics.
Actually, this only becomes a real problem when the background is
scrolling, so there are two numbers. The first is only used during
such scrolls. At all other times, the update rate is determined by the
second number. And in this room, the first number is completely
irrelevant, because the scene fits into the display without scrolling
- it is exactly 320 pixels wide. For other rooms, like the harbour,
UPDATE: is set to 6. (I have designed all of Olaf's animations to
work with the update range set in multiples of 2 or 3.)
Next, there comes a
SECTION: 1
statement, indicating that this room is part of section 1, as are all
the rooms making up Constantinople in this game.
Next, we need a background picture for the scene area. I prepared
the interior of this rather primitive bar in the file "1BG.IFF" using
the 3D modelling and rendering freeware program POV-RAY. The
gorgeous 24-bit image that was the result was then reduced to 16
colours, creating an image that is crude but suitably "cartoon-like"
for the purpose.
The background's 16 colour registers were then moved around and
combined with 16 standard colours used for Olaf and any other
common BOBs and images, whereupon i remapped the colours of
the 16-colour original in DPAINT. Now, all that remains is to tell
GRAAL to use this picture as the backdrop.
BACKDROP: 1BG.IFF
takes care of that.
The width of the backdrops may be from 320 up to 640, making for
excellent scrolling background scenarios (as shown in the
Constantinople main street and the Baghdad panorama, for
instance). The height is variable, but must be the same for all
rooms, and be set with the AREA_SIZES: statement in graal.main
Each time we enter a new room, Olaf must have a starting position
and pose. This is defined by the
START_POS: 1;13;20;115;L;1
statement. This not only indicates where Olaf starts, but whether
the background screen starts scrolled to the far left, far right or the
middle. (In this case, it's all the same, since the scene fits within the
screen width.)
Any number of starting positions may be defined for the same room
- great for those really awkward labyrinths!
GRAAL is not truly 3D - nothing shown on a computer screen ever
is - but uses a simulated 3D perspective. The bar in 1BG.IFF has a
floor, extending from the very bottom of the scene area and a few
lines up in the picture - if Olaf moves higher up in the picture, he is
also going further back in the room. The effect is demonstrated
more fully by the alley in the street outside the bar, which Olaf can
actually "walk into". To enhance the effect, GRAAL can also scale
the character or characters under your control automatically, so
the further up they go, the smaller they become. (However, this is
only done for rooms where it is needed, and only if you specifically
ask for it.)
Now, in order for Olaf to stay on the floor and not start climbing the
walls of the bar, we need some way of restricting his movement. We
do that using statements like
FLOOR: 1;16;114;304;119;1-1/2-2/3-3/4-4
Each such statement defines a rectangular part of the picture
where Olaf may place his feet. If there is more than one such
rectangle, each is defined by a separate floor statement, and all
floors must overlap with at least one other floor to enable Olaf to
find his way from one floor to another. The last parameter, "1-1/2-
2/3-3/4-4", describe how Olaf navigates between the four floors in
this room. See the FLOOR: statement in the on-line reference for
more information about this.
It wouldn't be much fun to have an adventure take place in only one
room (although such a thing IS possible - how about a "closed room
murder mystery"?). So the next statement,
EXIT: 1;7;66;12;112;10;113;Exit to\street
defines an exit from the bar. This creates a "clickable" rectangle on
the screen with some additional parameters describing the
properties of the exit. We will come back to the subject of switching
rooms further on.
So, now we have a background, an exit, and area to move about on,
and much more. Time to add some special graphics to the room to
spice things up a little.
CLPART: 1FG.IFF
is a statement telling GRAAL that we wish to grab some clipart
from the 1FG.IFF file to use as images in this room.
ROOMBOBS: ...
statements follow the syntax of the BOBS: statement we used in
the graal.main file. Every image grabbed with this statement
should later be referred to by a "room BOB image number", which
is a number proceeded by "RBOB". For example, RBOB3 means
room BOB image 3.
The images we grab as RBOBs are all used for objects and graphics
that are unique to this room, and are not much use outside it
(although you CAN grab clipart from the same 1FG.IFF file
anywhere you like in the game, of course).
Perhaps some of the clipart we just loaded is supposed to be pasted
into the scene without doing anything except being pretty. The
statements STATIC: and ANIM: are used for this purpose - which
one depends on whether the image should be static or animated.
We have two such static objects in the bar. One is the barrel behind
which Olaf appears. It has no other function except hiding Olaf at
the start of the game and being a general foreground object which
adds a bit of depth to the scene. The other is the wooden pillar, also
placed in the foreground.
That is the graphics department of room 1 over and done with.
6 The Object Matter
======================
You could, theoretically, spring Olaf loose in the bar now, but there
would be absolutely nothing to do - just an exit pointing to an
undefined room, floors to move about on - and a barrel to hide
behind! So far, there is not a single object to interact with!
The OBJECT: statement lets you define things that can be
manipulated in various ways. Every piece of your scene that
you need to hide, show, interact with, or move around,
should be defined as an object. (For graphics that follow very
simple, and don't move around, you may wish to use ANIM: or
STATIC: statements, or BOBON / PBOB commands.)
Just as with BOB images, objects are defined in various places
depending on where in the adventure they may appear - just in one
room, in a section, or in the entire adventure. Sticking with the
1.room file for the moment, you see some
ROOMOBJ: ...
statements here. They define objects which are never removed from
the bar, and never changed in any way: One of the barrels, the plate
of spam that Olaf refuses to touch, and so on. Room objects are a
great way of adding atmosphere, detail, and red herrings to a game
without wasting computer memory - from the players' point of view,
there is no way of telling whether an object is a room, section, or
global object. Only you know!
The policy in the tutorial is to leave details to the on-line reference
in graal.guide, but understanding the properties of an object is
rather vital, so we will examine one of the global objects present in
the bar closely. (The room objects are no good for this purpose, since
their use is severely restricted.)
In the graal.main file, locate the line
OBJECT: 16;piece of\paper;8;VIS;56;RBOB6;66;119;12;0;//14;with;PICK;0;8;47;LOW;WD;an;this;it
In the GRAAL Editor, you get a better view of the parameters if you
place the cursor on the word OBJECT: and then click <Edit
Parameters> to load the object into the Edit Parameters window:
An object loaded into the parameter editor
(more about that in the chapter about the GRAAL Editor).
This statement describes a piece of paper not actually used in the
demo portion of the adventure, but it serves to display the
properties of a typical object:
16;
means this is global object number 16.
piece of\paper;
is the name of the object. The backslash is replaced by a line break
when the name is shown in the scene area.
8;
is the room where the object first appears.
VIS;
means the object can be seen and handled. (NVIS means
"invisible".)
56;
is the BOB number (not the IMAGE number!) that will be used
when displaying the object.
RBOB6;
is the BOB image number which is used to display the object by
default. This could also be an animation sequence using the same
animation syntax as the TALK_MAP: etc. statements explained
previously.
But wait a minute! We use an RBOB image, obviously grabbed in
the 8.room file, to display a global object, which is obviously not tied
to that one room? Isn't this strange?
No, it actually makes sense. Room 8 is the only place where the
piece of paper will actually be SHOWN in that shape - when it is
used further on in the game, it will only be displayed using its
inventory icon. So this is a safe use of RBOBs!
66;119;
is the x and y position of the RBOBs hotspot.
12;0;
is the "character offset". When Olaf wants to handle the piece of
paper, he will walk to a position 14 pixels to the right and 0 pixels
above the object's hotspot.
Normally, we talk about the relative positions of the character's
and object's hotspots here. (See "All About 3D and Hotspots" on
page 52.) However, if you prefix the x value with a "W", for example
W8;0;
the x position refers to the edge of the character that is closest to
the object instead. That technique allows for multiple characters of
different widths more easily. However, if you only have one
character, or they look more or less the same, don't bother.
//14;
is the still image used to display Olaf once he has walked up to the
object. Since the object is to the left of him, he will face it using
image //14. And specifying the correct still image for each object is
vital: Should Olaf begin to handle the object after walking up to it,
the HANDLE_MAP sequence linked to image //14 will be used.
Should he start to talk, the TALK_MAP sequence linked to the
image will be used. But you need not worry about this, as long as
you specify the HANDLE_MAPs, TALK_MAPs and still images
used for object handling correctly!
with;
is a preposition. If a preposition exists, it is assumed that this object
can not be USEd on its own with the USE verb - it must be
combined with something else, and so the sentence line will read
USE PIECE OF PAPER WITH, and the system will wait for a
second object to be clicked. If this parameter is left blank, the object
will be used on its own.
PICK;
indicates that the object can be picked up (the condition IFPICK
returns TRUE). NPICK is used for the opposite.
Actually, you can easily override this parameter using script
commands - picking up objects marked NPICK, and making the
character refuse to pick up objects marked PICK. Still, this setting
means objects which rely on the global ACTION: statements
dealing with picking up and dropping will be handled in the right
way.
Also, there is no risk in making an object pickable even if it is
initially invisible (NVIS). If it cannot be seen, it cannot be accessed
by the player, and thus, the PICK status becomes insignificant...
(ALWAYS use NPICK for room objects, unless you make sure you
make the character drop the object again before he leaves the
room!)
0;
If the object is animated using an animation command (instead of
the single RBOB17 for this example), the animation channel must
be specified here. The range of possible values is 2-16, and as with
BOB numbers, the same number may not be used for two things
simultaneously. The piece of paper is not animated, and therefore
this parameter is 0.
8;
This is the object's "quick command", that is, the command issued
when the player points to the object and clicks the right mouse
button. Verb 8 is LOOK AT.
47;
This is the object icon used to show the object in the inventory:
Global BOB image 47.
LOW;
This is an important one for all objects which can be picked or
handled! It determines which of the "handle animations" Olaf will
use. Since the piece of paper is on the floor, the LOW animation will
be used. (Always place objects, or Olaf, using the character offset
co-ordinates so that one of the three positions can be used in a
natural way!)
DW;
This is an "attribute string" which can be used to determine some
general properties for the object. "D" stands for dead object, and
"W" for "wood". (A rather pointless attribute in this case. Basically,
it only tells us that it is softer than stone or steel!)
Attributes are used to make basic responses to some actions seem
more natural - you don't have to define separate replies to all
objects, but can specify a general response for all cases of Olaf
trying to use the small knife on objects made of wood, for instance.
You may also find an "abstract" class very useful - when Olaf
attempts to pick up the horizon, it enables you to respond with
some really insulting remarks! (Look in the graal.main script for
ACTION: statements containing IFTYPE tests to see how this can
be used.)
GRAAL is quite flexible in many ways, and there are a number of
GRAAL commands to alter many of the object's properties, such as
the name, visibility, location and so forth during the course of the
game. See the on-line reference for a complete list of commands.
Generally speaking, the statements in the script files set things up
- it is the commands contained in DACT:, LACT: and ACTION:
statements executed during gameplay that brings the whole thing
to life!
While we are at it, let us examine another, but more human, global
object: The bearded man / bartender.
So, what is the difference between a bearded man and some sheep
bones? Well, the bartender is animated using a default animation
sequence, as you see. This sequence also uses RBOB images, since
the bartender never leaves 1.room. Furthermore, the bartender can
not be picked up (there's a relief!) and uses animation channel
number 8 for the animation. His special attributes are "MV" -
meaning he's a male character and alive.
7 Section Objects and Bobs
=============================
There is a third class of objects involved in the bar scene, those
defined in the section file 1.section with the SECTIONOBJ:
statements. These are objects that only exist the very first time a
new section of the game is visited, and disappear again before the
section is exited. It is not that useful, but some of the objects in
Constantinople is of this kind - the magic flute, for example, which
disappears into the pawn shop before you can leave town.
You will probably find section BOB images (SBOBs) more useful
than section objects. These are grabbed in the section file the same
way RBOBs are grabbed in the room files, but with the
SECTIONBOBS: statement. Needless to say, they remain in
memory during the visit to the section, but disappear and are
replaced by other graphics the moment you walk into another game
section.
You are not obliged to use the section concept at all, especially if
your adventure is quite small. However, at least one section script
must exist, even if it just contains a comment saying "Not Used".
Then specify all your rooms as belonging to this "empty" section.
Okay, we have everything in place, except one VERY important
thing - the instructions telling Olaf to deal with the commands you
give him!
8 Camera! Action! Lights!
============================
8.1 ACTION: statements
-----------------------
All conditions and commands used to respond to the player's
actions are placed in ACTION: statements (leaving the dialogues
out of it for the moment).
ACTION: statements may appear in all three major types of script
file: .room, .section and graal.main.
The idea is that the ACTION: statements taking care of a certain
action is placed closest to the place where the action takes place. If
an action can only take place in one specific room, the ACTION:
statements for it are placed in that .room file. If the action is only
valid in a certain section, they are placed in the .section file. If it is
something that needs to be taken care of regardless of where it
appears, the graal.main file is the place.
In fact, almost every action should have some "safety net" in the
graal.main file - if no specific action is taken in the ACTION:
statements of the .room and .section files, the graal.main ACTION:
statements should at least make it look like Olaf understood what
you were trying to do! There is nothing more unrewarding than
clicking away at lots of things and have absolutely nothing happen.
Okay. So we write a lot of action statements containing commands
that makes Olaf walk, talk, and jump! But how does GRAAL know
when to use what actions?
Well, suppose we want to pick up the cup on the barrel in the bar.
Let's look at how that is performed in GRAAL, keeping in mind that
GRAAL always checks the .room file first, then the .section file, and
finally, if nothing else helps, the graal.main file. Each file is checked
from the top down to the bottom, which is very important to
remember in order to get the sequence of tests and commands right.
When the player has clicked PICK UP and the CUP, GRAAL starts
looking for appropriate ACTION: statements, knowing the number
of the verb (PICK UP = 2) and the object (the CUP is section object
3, referred to as SOBJ3).
The first parameter in each ACTION: statement is always the verb
number, and in 1.room, the first ACTION: 2;... statement that we
come across is
ACTION: 2;IFOBJ SOBJ3;ADDRF 0,20,1
IFOBJ SOBJ3 tells us to perform the rest of the actions if we
pointed to room object SOBJ3, and we did. What happens next?
Well, 1 is added to the value of room flag 20 for room 0. More about
flags later - suffice to say they are like variables in ordinary
programming languages, and this particular flag is used to hold the
player score in "Olaf". So you get one point for picking up the cup...
When we are done with the first ACTION: 2;... line, the next one
reads
ACTION: 2;IFOBJ ROBJ6;....
This is not a match, because the line is only relevant if we're trying
to pick up ROBJ6. Going through the rest of the ACTION: 2;... lines
in 1.room, we quickly discover that there are no more line concering
the mug there.
Switching to the 1.section file, let's see if we are more lucky. No, not
a single PICK UP command, actually. This is not so surprising,
since almost all objects start out in a certain room.
Well, why then wasn't there a command to really pick up the cup in
the 1.room file? Because, with the power of GRAAL, almost all
PICK UPs of any "pickable" object can be handled using a few
single ACTION: statements in the graal.main file - only objects
handled in special ways in room 1 need to have their actions in the
1.room file. Going on to the graal.main file, we find the following:
ACTION: 2;IFCARR;SAY I Already have it!;EXIT
IFCARR says that if the object we refer to is already in the
inventory, then let Olaf say "I already have it!". EXIT means no
more tests on ACTION statements will be done for our current
input: The sentence line will be cleared and Olaf is ready to try
something else.
However, SOBJ1 is NOT in our inventory yet, so we go on:
ACTION: 2;IFPICK;MOBJ;HANDLE;W 12;PICK;HANDLE -1;EXIT
Now behold the true power of the GRAAL. This is the stuff we have
been tormenting ourselves for all along the tutorial up to this point!
IFPICK;
If the object is "pickable"...
MOBJ;
Olaf walks to the default offset position next to the object (as
specified in the OBJECT: statement for the cup)...
HANDLE;
Olaf stretches out a hand according to the HANDLE_MAP:
animation...
W 12;
and waits for about 1/4 of a second...
PICK;
grabs the object (it disappears from the screen and enters the
inventory list)...
HANDLE -1;
lowers the hand again to the position it had before the
HANDLE command...
EXIT;
...and then we are done!
Now, if our object hadn't been "pickable", the ACTION: used by us
above are followed by a couple of "safety nets". (Remember, we
never get to these lines if the object has indeed been picked up - the
"EXIT" command sees to that.) One example of such a safety net is:
ACTION: 2;IFTYPE -;SAY That was rather far-fetched, wasn't it?;EXIT
IFTYPE -;
This checks if the referred object was an abstract object, like the
horizon in the Constantinople harbour. Since abstract objects can't
very well be picked up under any circumstances,
SAY That was rather far-fetched, wasn't it?;EXIT
makes Olaf "speak" this sentence using the talk-map corresponding
to his current position on the screen.
And finally, if the object happens to be un-pickable, but of another
type,
ACTION: 2;SAY I can't pick that up.;EXIT
gives a rather dull but to-the-point message to the player. Don't go
erasing ACTIONs in the supplied example graal.main file
altogether the first thing you do - a lot of these "safety net" actions
should be in almost any game, although you should of course alter
the wording and detailed behaviour to suit your own needs!
Special ACTION: Statements
""""""""""""""""""""""""""
The verb numbers corresponding to normal player input goes from
1 and upwards. Instead of an ordinary verb number, the following
can appear as the first parameter of an ACTION: statement:
0
(zero) - the verb number used for GO TO (that is, an exit has been
clicked. See "Using Exits" on page 34).
-1
Timer events. See "Timer Events" on page 57.
-2
Things to do after a LOAD or RESUME command. See "The Load /
Save Room." on page 58.
?
means any normal verb number from 1 and upwards will match
this statement. For example, you may have a room where no
ordinary actions should be possible. All player input (except exit
movements) could then be trapped in the room script with a single
ACTION: ?;EXIT
statement.
Repeating Verbs and Conditions
If the first parameter in an ACTION: statement reads
=
the verb number and initial conditions from the action statement
immediately above, saving you some typing if several statements
begin in the same way.
Example:
ACTION: 1;IFOBJ 2;IFOBJ2 21;MOBJ 21;SAY Here you go!;...
ACTION: =;RESP R,4,Thank you very much!;EXIT
The second line will actually be interpreted as
ACTION: 1;IFOBJ2;IFOBJ2 21;RESP R,4,Thank you very much!;EXIT
If only some of the initial conditions should be repeated, but a blank
space in between conditions. Here's the example once more, this
time repeating only the first condition:
ACTION: 1;IFOBJ 2; ;IFOBJ2 21;MOBJ 21;SAY Here you go!;...
ACTION: =;RESP R,4,Thank you very much!;EXIT
Now the second line will actually read
ACTION: 1;IFOBJ2;RESP R,4,Thank you very much!;EXIT
The method can also be used to repeat the initial part of DACT: and
LACT: statements.
9 Using Exits
================
Now that we are familiar with the general behaviour of ACTION
statements, it is time to explain how exits work.
As you may or may not remember, the EXIT: statement in the
1.room file defined a "clickable" rectangle on screen. However, we
never explained what happens when the player clicks the exit.
This is what happens: GRAAL interprets this as a very special
input sentence, with the VERB set to 0 and OBJ1 set to the number
of the exit. It then checks the ACTION statements just as if the
player had input a normal command. This is a typical ACTION
statement to take care of an exit command:
ACTION: 0;IFOBJ 1;MEXIT;CBOB 12;GOTO 2,1
0;
was the verb number indicating an "exit click".
IFOBJ 1;
tests if it was exit number 1 that was clicked.
MEXIT;
is a special command that can only be used in ACTION: 0;...
statements. It makes the main character move to the exit point
specified in the EXIT: statement (not to be confused with the EXIT
*command*, which is something completely different).
CBOB 12
Perhaps we wish the character to face the door before exiting.
GOTO 2,1
is a command specifying which room and entrance to go to. Voilà!
Of course, you are free to do whatever you like in these statements,
just like in any other ACTION: statement. You may manipulate the
way exits are interpreted to your heart's content!
10 The DACT: Statements
=========================
In each room file, there must be at least one DACT: statement. The
DACT: statements contain conditions and commands that are run
through each time the room is entered. The flow of control is the
same as for ACTION: statements: If a condition is not met, the rest
of that DACT: statement is disregarded, and if an EXIT command
is encountered, no more DACT: lines will be checked this time
around.
When GRAAL starts to run through the DACT: statements, all
graphics and objects are already loaded into their proper places.
However, the screen is still black - the light switch has not been
pushed yet, so to speak. This means you can do tests and move
things around using commands in the DACT: statements before
you let the player see the scene, which is very, very useful. Once you
are done preparing the scene, simply use a LIGHTS ON command
in a DACT: statement. When an EXIT command is encountered,
control is handed over to the player.
11 Flags and String Variables
===============================
In order to keep track of what is going on in your adventure, you
need a way to store information about the player's actions. In
GRAAL, there are two forms of variables that can be used to stora
information: Flags and string variables.
11.1 Flags
----------
Flags can hold integer numbers. There are 20 flags for each room
and 6 for each object. In reality, you can use any flag for any
purpose you like, but naturally it is most logical to keep
information regarding a certain room in that room's room flags,
information about an object in its own object flags, and so on. Also,
this is often most conventient - if you refer to the current room's or
object's flags, you don't have to specify the room or object number
in most flag-handling conditions and commands.
Since room 0 is never used as a location in the game, but it exists
as a "flag space", you can use room 0 flags to hold information that
pertains to the whole game.
There are commands to set, add, and subtract from flag values, and
conditions to test the contents in many different ways. Flags can
also be set to store in-game dates and times.
The flag values can also be printed in sentences by all text-
displaying commands - see the on-line reference for information
about how to do that.
11.2 String Variables
---------------------
In addition to the flags, there are 12 "global" string variables that
can hold text strings like the player name, or just snippets of text
you have to repeat in several text-displaying commands. There are
commands to set and test string variable contents, and there is also
a PROMPT command that asks the player for input. The PROMPT
command uses the dialogue area to display a prompt on the first
line and a text cursor on the second line. The player then enters the
text of his choice, and ends the input by pressing the Enter key.
Simple as that.
12 Having a Chat
==================
There are few things that breathe life into a graphic adventure the
way good dialogues do. Of course, in order to have a dialogue, you
need to have at least two people communicating. In this case, this
means our hero and another character in the game.
In the bar where the game starts, there is a bearded bartender who
is very likely to become the first person Olaf speaks to. Let's look at
how this is done.
First of all, any character involved in conversations must be
defined as an object using an OBJECT: statement - it can be a
global, section or room object. There is nothing special with the
definition: Just make sure the object is visible and placed in the
room where the dialogue takes place. Also, assign an animation
channel to it.
We need a way to make each "speaking partner" talk to the player-
controlled character, which is done by defining DLG: statements in
the graal.main file (below the OBJECT statements). Each DLG:
statement defines a set of rules for where and how the speech is
displayed, and an animation sequence for the speaking partner
talking.
DLG: 1;5;11;-20;A 0,(RBOB4,12)(RBOB6,24)...
1;
means this is dialogue speech definition number one.
5;
means that the appearance of the speaking partner is defined by
global object 5 (the bartender).
11;
is the colour used for the text displayed when the bartender speaks.
20;
determines how far above the bartender's head the text is
displayed.
A 0,(RBOB4,12)(RBOB6,24)....
is the animation used when the bartender talks.
Some speaking partners are probably fairly static, and then you do
not need more than one animation for the speech. However,
nothing prevents you from defining more than one DLG: statement
for the same speaking partner.
Now that we have two statements in the graal.main file, we move on
to the 1.room file, where the actual dialogue contents are defined.
A dialogue always starts when GRAAL encounters a DSET
command in an ACTION: or DACT: statement. It then shifts into
another mode, where the player's input is no longer a normal
command sentence, but only the number of a dialogue alternative.
GRAAL responds to the chosen alternative by going through LACT:
statements that correspond to the selected alternative, and does
not consider the ordinary ACTION: statements. Sooner or later,
GRAAL encounters an EDLG command in one of the LACT:
statements, which terminates the dialogue and switches the game
back to the normal input mode.
Let's begin from the beginning. When the player commands TALK
TO BEARDED MAN, the following ACTION line is performed:
ACTION: 5;IFOBJ 5;IFOF
1=0;MOBJ;SAY Hello;RESP R,1,Hello,yourself;
DSET 1,+3,+7,+9,+11,+12;EXIT
5;
the verb is TALK TO - we have a match
IFOBJ 5;
the object is the BEARDED MAN/BARTENDER - we still have a
match
IFOF 1=0;
Hello, what's this? It's a test of an object flag, a concept we have not
discussed earlier. Object flags are variables attached to each object.
There are six flags for each object, and each can have any
numerical, integer value. By assigning values to flags and testing
them, you can keep track of everything that has happened to an
object - it's up to you to decide what to use the flags for. In this case,
I have decided to use flag 1 for the bartender to see if this is the first
time ever we talk to him. All flags are initially 0, so this test - IFOF
1=0 - is true in our case. Before the dialogue is ended, the flag
values will be set to 1 to indicate that next time around, we should
resume the conversation in a slightly different manner.
OK, on with it:
MOBJ;
We move up to the bartender just like we move up to any object
before manipulating it.
SAY Hello; Say "Hello".
RESP R,1,Hello, yourself.;
This is the bartender's response. "1" means GRAAL will look up the
statement
DLG: 1;...
in the graal.main file to find out how the bartender should behave
when talking. "R" means the default bartender animation will
resume as soon as the talking is over.
So far, all statements have been performed with the game still in
the "normal" mode. Now comes the command which switches to
dialogue mode:
DSET 1,+3,+7,+9,+11;12
This command engages us in dialogue number one and tells
GRAAL to add the four dialogue alternatives 3, 7, 9, 11 and 12 to
the list of possible lines for Olaf to speak. Since this is the first
DSET statement ever to be performed for dialogue one, they will be
the ONLY four alternatives.
EXIT
exits the parsing of the TALK TO command, and leaves us to get on
with the dialogue - the player now has to select a dialogue line from
the dialogue area which has replaced the normal control area.
Hmm. Dialogue lines 3,7,9, 11 and 12. What are they? All the lines
are defined by LINE statements in the 1.room file. Let us take line
3 as an example:
LINE: 1;3;What is this place?;Where did you say I was?;
1;3;
means this is line 3 of dialogue 1
What is this place?;
This is the line appearing in the dialogue command area (where the
player can choose a line to say) when the alternative is previously
unused.
Where did you say I was?;
is the version that will appear if the alternative is "re-used". If this
second version is specified as a blank space only, the first version of
the sentence will always be used.
"one blank space"
The last semi-colon is followed by one, very important blank space,
which tells GRAAL there are no conditions attached to this
dialogue line.
To explain the concept of dialogue conditions, let's look at another
of the initially added lines, line 7. The definition of that LINE goes:
LINE: 1;7;Do you know anything about the ship in the harbour?; ;IFOF
2=1
First of all, notice there is no second version of this line. The
question will always look the same, regardless of how many times
Olaf puts it to the poor bartender.
Here, there is an additional condition that determines whether this
dialogue alternative is available to Olaf or not. Object flag 2 for the
bartender must be set to 1, otherwise the line will not appear in the
dialogue command area, no matter how many "DSET 1,+7"
commands are issued. However, once a DSET 1,+7 command has
been given, line 7 becomes a possible line: GRAAL will check object
flag 2 for the bartender each time the dialogue is re-engaged or
refreshed, and as soon as flag 2 becomes 1, the line will appear and
become available for Olaf to speak.
If you look through the lines, you will notice that only lines 3, 11
and 12 are unconditional. This means that if the first thing Olaf
does is engage in conversation with the bartender, only those two
alternatives will be visible. So what the player now sees in the
command area is:
What is this place?
My head hurts.
Could you help me, please...
However, if he trundles off to the harbour to look at the ship, and
only then returns to talk to the bartender, line 7
Do you know anything about the ship in the harbour?
is also available.
OK, back to our poor player, currently facing the task of choosing
a sentence to speak.
When the player clicks one of the alternatives, the corresponding
line number is sent back to GRAAL. Let's assume the player clicks
on
My head hurts.
This means the number "11" is returned. GRAAL now starts to
search for LACT statements starting with 1;11; - there had better
be one, or nothing will happen! Fortunately, there is:
LACT: 1;11;RESP R,1,That's probably because...;DSET 1,N11
This is a typical example of a simple response to a dialogue line.
The bartender speaks, and then another DSET command is given.
Because we already are in dialogue mode, this command only
"refreshes" the dialogue - that is, makes alterations to the current
set of valid alternatives. In this case, the adjustment is to take
away line 11 and tell GRAAL that it should never been shown
again. That's what "N11" means.
The alternative "Could you help me, please..." yields a similarly
unusable response, so assuming Olaf hasn't been out exploring the
town yet, he is now left with only one alternative - the line
What is this place?
The response to this one is a bit more substantial. The bartender
makes a long response - so long, in fact, that is does not fit into
one LACT statement with ease. Instead, there are two statements,
performed in sequence. When using this technique, remember NOT
to put an EXIT or DSET command at the end of the first statement,
because that would interrupt the process and prohibit the second
statement from being executed!
In the process, the bartender - if he is still named "bearded man" -
reveals his identity. Therefore, there is a
NAME bartender;
command, renaming object 5 "bartender" if it has not been done
already.
The response ends with DSET 1,+1,+2,+5. This means that three
more possible alternatives will be added to the set of lines available
to Olaf, all of which are unconditional. The current alternative -
line 3 - also remains, but now appears in its alternative form
"Where did you say I was?". This makes the conversation a bit more
believable, since you usually rephrase your questions when you feel
you need to repeat them.
One of the added alternatives, line 1, is an "end-of-conversation"
alternative. When Olaf says "Thank you very much", the bartender
answers "Don't mention it.". Then,
EDLG;EXIT
is performed, which switches the game back to normal input mode.
As you se in the LACT statement, object flag 1 for the bartender is
set to 1 with a SETOF (set object flag) command to indicate that if
we TALK TO the bartender again, it is a resumed conversation -
the initial "hellos" will be expressed a bit differently.
This concludes the basic tour of the features available in GRAAL
1.0, but stay tuned: Below are a lot of hints and tips about how to
use the power and special techniques of GRAAL to their full
potential.
13 Multiple Characters and Inventories
========================================
In the dialogues described in the previous chapter, the "speaking
partners" were little more than ordinary objects, animated to make
them look and act like human beings (or wizards, hobbits,
monsters... take your pick).
You can also offer the player true control over more than one
character. GRAAL keeps track of each character's location. There
are also multiple inventories, so that each character may have its
own inventory.
Up to four alternate characters and four inventories can be used.
(The Olaf Longhair adventure demo does not use multiple
characters. Get hold of "The GRAAL Herald, Issue 2" -
GraalHerald2.lha - which contains a mini-demo showing off these
and other 2.1+ features.)
13.1 Multiple Character Graphics
--------------------------------
To make the multiple character feature feasible, each character
uses the same animation patterns, sequences and default still
images as the main (default) character. The only thing that differs
between the characters are the image numbers being used.
This means that we still only need one set of "default graphics"
statements in graal.main. In other words, the
STILL_...
PAUSE_...
WALK_---
HANDLE_MAP: ...
TALK_MAP: ...
statements are defined only for the main character, exactly the
same way as in single-character games. Also, the CBOB command
expects you to specify a BOB number for the main character, and
then automatically uses the corresponding image for the currently
controlled character instead, and the same goes for the IFCBOB
condition.
All images used in these statements should have numbers close
together so as to form a "block" of graphics in the image bank,
describing all default poses of the main character. This block
should be placed as low as possible in the image number series. For
example, the main character graphics may consist of 30 images,
which we need to store in image numbers 11 to 40. Something like
/* Clipart file containing all graphics for the main character
CLPART: main_character.iff
/* The BOBS: statements below grab 3*10=30 images
BOBS: 10;11;...
BOBS: 10;21;...
BOBS: 10;31;...
in graal.main should take care of that.
Now, for each extra controllable character, an identical "graphics
block" must be loaded in a similar way. Ideally, these blocks are
placed directly above the main characters graphics, like this:
CLPART: second_character.iff
BOBS: 10;41;...
BOBS: 10;51;...
BOBS: 10;61;...
would place the graphics for the second character in slots 41 to 70.
Note: The image numbers used for alternate characters MUST be
higher than those for the main character graphics!
Now, as you have already guessed, the images contained in the two
block must match each other: If image 11 shows the main character
facing forward, image 41 MUST show the second character facing
forward, and so on.
13.2 Character Objects
----------------------
In normal, single-character adventures, the main character is not
an object in itself - that is why no name appears when you move the
mouse pointer over the main character in the scene area. However,
when you have multiple characters each one must be defined by a
global object before we can start to put any "character-switching
functions" into the game.
First, define a global object for each character. It's nice if the main
character is object number 1, and the second character object 2 and
so on, but this is not at all necessary as we shall see later on.
You MUST abide by the following rules for the character objects:
* Each one must have a unique BOB number not used for
anything else in the parts of the game where the character can
appear.
* Each one must have a unique animation channel, not used for
anything else in the parts of the game where the character can
appear.
* They should all be VISible.
* They should all be NPICK (not "pickable").
Apart from this, they are defined pretty much like any other type
of object.
Now, we need to tell GRAAL that there are multiple controllable
characters in the game, and define some more properties for them
that cannot be deduced from their respective OBJECT: definitions.
This is done with CHAR: statements:
CHAR: no;object;stimg;eimg;floor;colour;height;text_offset;width;speed
no
is the character number. The main (default) character is always
number 1, and if CHAR: statements are used at all, there MUST be
one for character number 1!
object
This is the object number of the object defining the character, as
discussed earlier.
startimage;endimage
These parameters define the first and last image number of the
"image block" containing all default character graphics.
startfloor
This one may seem a little odd. Each character's starting position
in the game is defined by the room and x/y parameters of the
OBJECT: statement, but we also need to know what floor in the
room contains that point, which is a piece of information not
available in the OBJECT: statement.
colour;height;text_offset;width;speed
When using a only one controllable character, all these things are
set in separate statements.
Examples:
CHAR: 1;1;11;40;2;11;40;10;20;1.2
Character 1 is global object 1, occupies image slots 11-40, and starts
out on floor 2 - the room and exact position are specified in the
object definition.
Furthermore, it uses text colour 11, is about 40 pixels high, has an
extra 10 pixels above its head to the place where related text is
displayed, is 20 pixels wide, and walks at a speed of 1.2. (This is one
of the very few floating point numbers used in GRAAL!)
CHAR: 2;20;41;70;1;4;0;30;30;1.5
Character 2 is global object 20, occupies image slots 41-70, and
starts out on floor 1 - once again, the room and exact position are
specified in the object definition.
It uses colour 4, its height is set to 0 which makes the mouse pointer
point to its feet, the text is displayed 30 pixels higher up than that,
it is 30 pixels wide and uses a walking speed of 1.5.
Note that if your various controllable characters are of different
heights, it is probably a very wise thing to set the height to 0 as in
this example, otherwise offsets from objects and the mouse cursor
will look very strange indeed.
Using a Character Object with a Single Character
Perhaps you want to manipulate your character using commands
that requires it to be clickable in the scene area. Even if you only
have one character in your game, you can still specify an object for
it and connect it with a CHAR: 1;... statement. Then the mouse
pointer will now recognise the character and display its name in the
scene area. also, if you wish to use the automatic 3D scaling feature
for the character, a CHAR: 1,... statement is required.
13.3 Switching Characters
-------------------------
Proper BOBS:, OBJECT:, and CHAR: statements - that is all that
is needed in your graal.main file to make your game multi-
character. However, we still need a way of switching between the
various characters.
Well, here it is. Switching between characters is r-e-a-l-l-y easy - in
fact, I can't think of a single way to make it any easier. The
command to use is simply
SWITCH character
* If the characters are visible in the current screen, you won't
see the change, apart from the fact that the next time you click
in the scene area, the new character moves instead of the old
one.
* If the characters are in different rooms, GRAAL will simply
jump to the room where the new character is currently located
- the first time you switch to a character, this is of course the
room and position specified in that character's OBJECT:
statement.
* If the characters are in the same room, but the one you switch
to is "off camera", the scene area will scroll the character into
view.
The SWITCH command must always come last in a command
sequence, followed by an EXIT command.
13.4 Inventory Switching
------------------------
Now, you probably want each character to have its own inventory.
Normally, this means the SWITCH command should be preceded
by an inventory command:
INVENTORY 2,U;SWITCH 2
would switch to inventory 2 (and update the command area to show
the change), and then also immediately switch to character 2.
Note: The inventory switching is handled completely separately
from the character switching, and there is no law that says
character 1 must use inventory 1 and so forth. This is because you
may want to switch inventory lists for other purposes than
switching characters!
Another note: The default inventory is inventory 1. (There's a big
shock for you... :)
To make an object start out in an inventory rather than in a room,
you use a special form of room number in the OBJECT: statement
room parameter. Simply type an "I" followed by the inventory
number:
I2
will place the object in inventory 2.
PICK, GET, and PUT commands always work with the currently
selected inventory. To place things in another inventory than the
currently selected, you must use the PUT command specifying the
inventory in a similar way to the OBJECT: statement room
number:
PUT 4,U,I2
would move object 4 to inventory 2. The parameter "U" indicates
that the move is made from the current inventory, since U means
we wish to update the inventory display to show the change.
Technically, each inventory is a room number, calculated by
1000 - inventory number = inventory room
which means inventory 1 is actually room 999. This concept works
as long as you don't have more than 990 rooms in your game, and I
really don't think you do...
13.5 Identifying Characters and/or Inventories
----------------------------------------------
You may well wish to have some way of knowing which character is
currently selected. There is a COMGR command that can paste an
image anywhere in the command area (although you should take
care not overlay the inventory list or any other areas used by the
system, of course). Simply create a global image containing the
name, symbol or portrait for each of the possible characters /
inventories, then COMGR the proper one onto the command area
when switching.
13.6 Characters Following Characters Around...
----------------------------------------------
If you have a game with two controllable characters it is very likely
that, from time to time, you will want one of them to follow the
other one around. As long as all movements by the currently
controlled character is generated either by the player clicking in
the scene area, or by the CMOVE command, this is quite simple to
achieve. The command
FOLLOW character,startx,starty,followx,followy
will cause the specified character to follow the one under player
control around.
This continues until a SWITCH command switches the control to
another character, or you give a
FOLLOW OFF
command.
The parameters following the character specification deals with
where the following character will position itself in relation to the
current character.
Generally speaking, it will strive to always stop "behind" the
controlled character.
startx,starty
After a FOLLOW command has been given, any GOTO command
moving the controlled character to a new room will cause the
following character to go there, too. startx specifies the number of
pixels between the characters. It is the Left/Right/Middle
parameter of the START_POS: statement that determines whether
the following character will be to the left or the right of the
controlled one. Thus, it should always be a positive number;
GRAAL determines the actual sign. starty should normally be a
small, negative number.
followx, followy
These number work about the same way as startx and starty,
except they determine the offset between the characters after
having walked around in a room. Both numbers should always be
positive: GRAAL "knows" where to place the following character in
most cases.
Note that when the controlled character goes next to a floor
boundary, the following character probably ends up a few pixels off
that floor, depending on your offset settings. There are two things
to remember about this:
* You may want to adjust the floor sizes in some rooms to
prevent the following character from "climbing the walls".
* Normally, if control is switched to the following character, it
will be treated as if it had been placed on the same spot as the
previously controlled character. Normally, having a character
move from a spot outside the floor system results in very odd
movement paths, but in this special case, the slight
misplacement of the character will be taken care of
automatically. However, if a SHOW or OMOVE command has
been issued for the character's object between the last "follow"
and the switching of control to it, GRAAL expects you to
correctly specify the character's current floor using
SETFLOOR instead (once control has been switched to it).
13.7 Helpful Conditions
-----------------------
To help to determine what the scene looks like, a couple of
conditions have been added primarily for multiple character
games:
IFCHAR character
is TRUE if the current character under player control is the
specified character.
IFHERE object
is TRUE if the specified object is in the room. Note that the
parameter is the object number and not the character number -
because this may also come in handy for other objects apart from
characters.
13.8 Things to Consider
-----------------------
Unfortunately, there is no collision detection between characters.
From time to time, they will seem to "walk through" each other on
screen. The only thing you can do about it is try to minimize the
problem by carefully thinking about character placements and floor
layouts.
13.9 Space-saving Tip
---------------------
If you have a need for different controllable characters in different
sections of the game, you can save a lot of chip memory by letting
them share the same space in the image bank. Just put CLPART
and BOBS commands in the appropriate section files (and also in
ACTION: -2 statements to make sure the correct set is loaded after
loading a saved game).
14 Character and Graphics Design
==================================
Well, fellow adventurer, by now you are a proficient GRAAL user.
I hope. Anyway, welcome to the first master class, where we will
look at some of the central GRAAL concepts a bit more closely.
This chapter deals with designing your main character and
planning your graphics, something that must be done with some
thought and consideration - although small adjustments are easy to
make at any stage during the game development, things like the
character size influence every other piece of graphics you create, so
beware!
14.1 Size
---------
Get a suitable character size, keeping the backgrounds in mind -
they are 120 pixels high, and in lowres, so you must use lowres
when designing too - otherwise your hero will look rather fat on the
screen! I should think a character between 40 and 60 pixels high
would be about right. Below 40 and there is not much room for
detail at all, more than 60 and the scenes start to feel cramped
because the character takes up too much space. Also, bigger
graphics takes more processing power. In addition, the more pixels
you have to animate, the more chances you have of making a bad
job of it! Really, I am not kidding. Small can be beautiful
sometimes.
Naturally, how you want the backdrops to relate to the main
character is also a factor - is he a small guy in a big, cruel world, or
an ace detective always moving around in cramped Victorian
tunnels and Baker Street studies?
14.2 Colour
-----------
Use only some of the available colours for your character, and make
it a good spread of useful colours, because these colours will have to
be the same in all scenes!
Colours not used for portrayal of the main character, or frequently
occurring objects, can change according to the current scene - the
more colours you have left to play with, the more variation you can
bring to the backdrops.
Note: The first three colours more or less have to be as follows:
Colour 0 should always be used ONLY for transparent areas in
BOB images. Colour 1 SHOULD be a rather bright white, colour 2
MUST be black!!
Here's a tip: When working with a background or clip-art picture in
a paint program, set colour 0 to something strange to distinguish it
from "usable" colours, but always set it back to black before saving,
or the borders around the adventure scenes when running the
adventure may become coloured in ways that we don't want! If you
don't follow this advice, you surely will make the mistake of using
colour 0 as the black colour in spots of the graphics, whereas it will
be transparent when used in the game - and vice versa!
Note: Despite the fact that you should only use some colours for the
character, always create the graphics with a palette using the same
number of colours as your backdrop pictures.
14.3 Pointer Shapes and Colours
-------------------------------
The shape of the two mouse pointers used in GRAAL can be
changed in graal.main by using the ARROW_CURSOR: and
CROSSHAIR_CURSOR: statements.
The new pointer shapes are simply images stored in the image
bank like any other, but they have some special properties:
* They must be four colours only, and colour 0 is transparent.
* Colours 1, 2, and 3 of the pointer shape will be mapped to
colours 17, 18, and 19 of the backdrop palette. If you want the
pointer to always have the same colours in the scene area,
these colours must be the same for all backdrop pictures.
If there was a way to alter these palette numbers I would, but there
isn't, so I can't. So there. This means that you may want to plan
ahead and decide the following colours for all scene are graphics,
once and for all:
0 Black (transparent. Do NOT use this for the black parts of the
backdrop itself!)
1 White
2 Black (Use THIS for the black parts of the backdrop picture!)
17 Pointer colour 1
18 Pointer colour 2
19 Pointer colour 3
14.4 Designing Animations
-------------------------
The following poses must be designed for the main character:
* The stills to use for front, back and "sideways facing left" still
poses.
* The animations for walking towards, away, and sideways right
to left.
* The animations for talking corresponding to the front, back
and side stills. (Open and close the mouth in different ways,
move the head slightly, etc.)
* The animations or stills used for handling objects (picking up,
handing over, etc.), also corresponding to the three "main
stills" previously mentioned, but in three different heights for
each still - High, Middle and Low, depending on whether the
object is located on the floor, high up or on a table or
something else in "mid air".
The reason you don't have to make separate animations and images
for right and left is that you can mirror one image to point in the
other direction using a simple trick described further on. This saves
memory as well as time spent in paint programs!
To get the animation smooth, it should be designed to work with
frame updating taking place every 6th vertical blank. This may
sound like nonsense to you, but what it means is that you can
switch the animation cel every six 50ths of a second, which equals
six frames displayed on a PAL TV system (or 60ths of a second on
an NTSC system).
Actually, too many animation cels for a certain movement may not
necessarily add that much to the game anyway. Olaf uses only 5
cels for a basic walking movement, each cel being shown for 6 50ths
of a second.
So, now you should have you basic animations designed. Good.
First, test them against some different backdrops that you think
will be representative for the game in your excellent paint program.
Then, satisfied that your character basically looks OK, you should
now design a "dummy room" in GRAAL, place some "dummy
objects" in that room that will force your character to use all his
newly learned physical skills. Then, give him a good work-out.
14.5 Complex animation patterns
-------------------------------
Some times, we may need more complex animations for an object or
character. For example, the captain in room 3 of the Olaf demo
walks back and forth aboard his ship, bends down to fix things, and
occasionally, also loses his hat! The AMAL animation language
used by GRAAL allows us to achieve this, but the code needed is
longer than will comfortably fit into a statement line in GRAAL.
Therefore, ANIM:, OMOVE:, SHOW:, and OBJECT: statements all
accept animation pattern specifications that look like this:
...PTRN n...
which tells GRAAL to go look for the animation code in a file called
n.ptrn. Here is part of the pattern file for the captain's movements
as described above:
/* The captain's standard movements for room 3
/*
S:
A 15,(RBOB6,6)(RBOB5,6)(RBOB4,6)(RBOB7,6)(RBOB8,6)(RBOB7,6)(RBOB4,6)(RBOB5,6)
M 20,0,70 M 20,10,150 M 98,-6,200
A 1,(RBOB4,100)
M 0,0,100
A 3,(RBOB9,72)(RBOB10,128)
M 6,0,1
M 0,0,499
A 1,(RBOB4,50)
M -6,0,1
M 0,0,49
A 15,(//RBOB6,6)(//RBOB5,6)(//RBOB4,6)(//RBOB7,6)(//RBOB8,6)(//RBOB7,6)(//RBOB4,6)...
...
A 1,(//RBOB4,500)
M 6,0,1
M 0,0,499
J S
The pattern contains three things:
* Labels and jumps to labels
* Animation commands (A...)
* Movement commands (M...)
S: is simply a label allowing us to repeat the entire sequence of
commands indefinitely by jumping back to the S: label from the
very end of the commands sequence with the J(ump to) S command.
The rest of the script is made up of "blocks" where we first specify
an animation sequence, and how many times it should be repeated,
and then one or more movement commands that decide how the
object is to be moved during that animation.
In the M(ove) commands, the first number is the number of pixels
to move left or right (negative numbers = left), the second is the
number of pixels to move up or down (negative numbers = up), and
the third is the number of frames the movement should take. Note
that only the M(ove) commands control the timing of the program.
If one or move M(ove) commands before the A(nimation) command
has run out of frames to display, the program still moves on to the
next A(nimation) command. This means that:
In most cases, the total number of frames that the A(nimation)
command takes should match the number of frames the
corresponding M(ove) command(s) will take.
This way, the entire animation will keep in sync.
To specify a "still image" in the middle of the pattern, do like this:
A 1,(RBOB4,100)
M 0,0,100
Here, RBOB4 is shown for a hundred frames, and during that time,
the M 0,0,100 command keeps it still, because it is told to move
nowhere (0,0).
14.6 Flipped images
-------------------
As discussed in the section on image definitions in the graal.main
file, you can easily "flip" an image left/right by prefixing the
number with two slashes ( // ). However, there is a catch: You
cannot safely use both the normal and the flipped image on screen
at the same time - unpredictable results will occur if you do so!
The rule is, if you run the risk of having the same image in both the
original and the flipped version on screen at the same time, you
have to make the flipped version into a proper image in the image
bank, with its own image number.
14.7 All About 3D and Hotspots
------------------------------
GRAAL rooms are usually displayed in a "simulated 3D"
perspective (although top-down views can be achieved). This
basically means that the things slightly higher up the picture seem
"further away" than the things towards the lower end of the
picture. Take the harbour in "Olaf" as an example: When Olaf
walks towards the water and the edge of the quay, he's actually
only moving a number of pixels up the screen - there is no such
thing as "away", because the screen can never really be anything
but 2D.
This simple fact allows us to play with foreground and background
objects. Anything placed towards the bottom of the screen will,
generally speaking, be "in front". I'm talking about objects as well
as STATIC: and ANIM: images now, mind you - everything drawn
directly onto the background picture will naturally always be part
of the background!
So, as a rule anything lower down goes "in front" of anything
further up, but that's not necessarily the way we want people to
perceive things - take the mug on top of the barrel in the bar, for
instance. Looking only at the placement of the images of the mug
and the barrel, the mug should logically be partly hidden by the
barrel, because it is further up the picture. It's not. Instead, it looks
like it is placed ON the barrel, which is what we want. Also, when
Olaf walks behind the barrel, he must also walk behind the mug -
if the mug is on the barrel but Olaf seems to be walking in front of
the mug but behind the barrel, everything becomes hideously
unrealistic.
The answer to this problem? It's simply a matter of setting each
image's hotspot correctly. The hotspot is the point of each image
that will actually be placed at the x and y coordinate specified when
displaying the image.
Each image has its own hotspot, and it is normally set when the
image is loaded with a ...BOBS: statement (the last parameter -
look it up in the reference). The GRAAL default is to place the
hotspot at the middle of the bottom edge of the image - you might
say at the "foot" of the image. This is normally very appropriate,
especially so for people and living objects. But you can place the
hotspot anywhere you like - if you specify a value other than the
default, the hotspot will be offset in the y direction that number of
pixels from the top edge of the image. Both negative and positive
values are allowed.
Study the ROOMBOBS: statement for the mug image in room one,
compare that to the mug's x and y position in the OBJECT:
statement in graal.main, and you will see that the hotspot is placed
well below the actual image, making it the "frontmost" object in the
bar.
The hotspot of an image can also be altered using the HOTSP
command - this is used in some cutscenes dealing with the ship in
the harbour, to switch the depth-placing of the sail. This is because
the captain first walks behind the sail, but when summoned
ashore, he suddenly has to go in front of it! The solution? Just alter
the sail's hotspot...!
14.8 Scaling the Characters
---------------------------
Starting with GRAAL 2.2, the characters under player control can
be automatically scaled to match the simulated 3D perspective in
your backdrop. (You should only use this in rooms where you really
need it, because the scaled images never look as good as the
original-sized ones.) It is demonstrated in room 2 of the demo
adventure, where Olaf gets a lot smaller when walking into the
alley.
To begin with, the 3D scaling process relies on the information
about graphics stored in the CHAR: statements in graal.main. So
even if you only have one controllable character, you have
to create a global object and a CHAR: statement for it, as
discussed in "Multiple Characters and Inventories" on page 42.
After that, the process is a simple one: At the very start of a room
script, put a
3D:
statement. (See the on-line reference for details).
Each parameter in the 3D: statement defines a vertical line on
screen, and above each line, the character will be a little smaller
than below it. If the character is below the first line, it will retain
its original size as drawn by you. If the character is above the last
line, it is at its minimum size (25%, that is, half the height an half
the width).
The 3D scaling works with the SAY, MOBJ, HANDLE, CMOVE,
CBOB and CPOS commands, and the IFCBOB condition. This
means you shouldn't use OMOVE or SHOW to move or animate
controllable characters, unless you know exactly where in the room
the animations will be used and can make them according to that
size. If you handle more than one controllable character in the same
room, you probably need to use the SWITCH command a lot so you
can animate each character with the above commands rather than
relying on OMOVE and SHOW.
By setting some of the "scaling lines" outside the scene area, you
can force GRAAL to only use one or two of the scaled sizes. I have
used this in 7.room, where Olaf is only shown in the minimum size,
because all the scaling lines are put below the displayed scene area.
Note 1: If you use the BOBS command to load a new set of global
images that make up the graphics for one of your characters, you
will have to issue the MAKE3D command afterwards to recreate
the scaled versions of the images as well.
Note 2: If you use the FOLLOW command (see "Characters
Following Characters Around..." on page 46), take care to lay out
floors and paths so that the following character always ends up the
same size as the controlled character. Otherwise, it usually looks
plain ugly.
15 Cutscenes
==============
CUTSCENES are simply script files (suffixed with .scene) that
contain nothing but commands. That's right - no conditions, and no
statements! This means lines should NOT start with ACTION: or
anything like that - just fire away with the command name in
column one of each line! You can include several commands on the
same line just like in ACTION: statements as long as you separate
them with semi-colons.
Depending on the command used to start the cutscene, the
command area either disappears completely, has a special "cut-
scene icon" overlaying part of it, or remains totally unaffected
(although still unusable until the cutscene has ended). You may use
this to alter the degree of "movie-feel" the cutscene invokes.
Cutscenes that are so short that the player hardly notices anything
special happening control-wise should NOT mess with the display
of the command area.
The immense usefulness of cutscenes may not be apparent at first,
but you will soon find out that you use quite a lot of them - because
in addition to being used for "movie scenes", they are also very
handy whenever you have a sequence of GRAAL commands that
you need to use in a lot of different places. In these cases, cutscenes
can act the way procedures or subroutines do in ordinary
programming languages. In those cases, you must make sure the
entire cutscene is executed, and you probably don't want to show
the cutscene indicator to the player. It's easy enough - just read on!
The logic of cutscenes ought to be a fairly simple subject, since there
are no conditions allowed in them. In practice, two things require
you to think very carefully about designing your cutscenes: The
"skip" function (pressing the [Esc] key to jump past a cutscene) and
nested cutscenes.
15.1 Hop, Skip and Jump
-----------------------
Normally, a cutscene consists of two parts: The main part at the
top, always containing ALL the actions in the scene, and the FINAL
section at the end.
The FINAL section is ONLY used if the [Esc] key was pressed
during execution of the main part. It must duplicate all statements
necessary to set the scene exactly the same way it would have been
set if the main part had been run through completely. Remember,
you never know exactly where in the flow of the main part the
player decides to press [Esc] and breaks out of the action!
15.2 No Breaks!
---------------
In some circumstances, for example when you use cutscenes as
"subroutines" as discussed above, you may not want the skip option
to be in effect. In this case, start the entire cutscene with the
cutscene command NOBREAK, which disables the [Esc] key for the
duration of the cutscene. If a cutscene starts with NOBREAK, you
don't need a FINAL section in it.
15.3 Nesting
------------
Now, to complicate things even further, cutscenes may be nested in
up to three levels - that is, you can execute a cutscene within a
cutscene from within a cutscene!
"Why on earth would I want to do that?" you ask. Well, a good
example is the harbour scene in room 3 of "Olaf". There are a
number of occasions when Olaf needs to interact with the captain,
calling him ashore time and time again. The captain's going ashore
and aboard can not be handled as simple PTRN sequences, because
he, the ship itself, and the sail need to be rearranged in various
ways to make the captain go behind the sail, in front of the sail but
behind the gangplank, etc.
Therefore, the captain going ashore is played using one cutscene,
the going aboard in another (well, actually two, depending on
whether his hat is secured with the rubber band or not). These
cutscenes are then used from within, or in conjunction with, a
number of others specifying what is going on when the captain
comes ashore to talk to Olaf.
Let us call the first cutscene the "master scene" and those called
from within that "sub-scenes". Now, what we have to watch out for
is this:
If we press [Esc] at the very beginning of the master scene, or
indeed anywhere before the last sub-scene, this means some of the
sub-scenes will not come into play at all. However, the contents in
each sub-scene may affect how the game should be set up at the end
of the master scene.
To conclusion is that the FINAL section of the master scene also
must include all statements that are present in the FINAL sections
of the relevant sub-scenes. Let's look at Olaf and the captain again,
when Olaf tries to use the dictionary on the captain and gets it all
wrong. This is depicted in CUTSCENE 13 structured like this:
1. First, CUTSCENE 2 is called as a sub-scene to make the
captain come ashore.
Note: Sub-scenes should always be called with parameter ,F or
,NF to stop the cutscene indicator symbol flickering on the
screen. The master scene should be called with parameter ,S
or N because when it's finished, the whole scene is finished.
2. Then, Olaf tries to speak hindi or something like that, fails
miserably, and is knocked down.
3. While Olaf is still on the ground recovering, CUTSCENE 3 is
invoked to put the captain back aboard the ship.
4. Once the captain is back aboard, Olaf gets up and notes that
the whole endeavour wasn't particularly successful.
5. The FINAL section of the master scene CUTSCENE 13 then
needs to contain the following: The commands from the FINAL
section of CUTSCENE 3, because those make sure the captain
is back in place aboard the ship, and some commands to put
Olaf back on his feet in the right position. We do NOT have to
bother about anything in CUTSCENE 2, because the captain's
coming ashore does not have anything to do with how things
look after the master scene is finished.
16 Timer Events
-----------------
GRAAL contains a number of functions that can make things
happen at regular or irregular intervals more or less independent
of the movements of your controlled character.
First, you use a DOAFTER command to set one of three "timer
devices" to go off after a certain period of time (and this can also be
a random amount).
Next, you specify a number of ACTION: -1;... statements, because
each time a timer reaches zero, it goes through the list of ACTION:
-1;... statements to see if it should do anything. (Each timer - there
can be up to three running at the same time - uses its own "fake
object number", so you can use IFOBJ conditions to see what
statements belong to which timer if you have several running
simultaneously.)
The timer will go on repeating itself, until you issue a CANCEL
command for it. If you want the time between the timer events to
change continuously, you should end each ACTION: -1,... command
sequence with another DOAFTER for the same timer, specifying
another random interval.
The timer device called "0" is a little special. It doesn't check the
time elapsed since the DOAFTER command, but rather how long
the player has been inactive. You can use this to trigger "stall
anims" (like the one in "Simon the Sorcerer", where Simon puts on
his headphones when nothing happens).
Normally, the cursor will flicker during execution of the ACTION:
-1;... statements, because as always the player can't do anything
while a command sequence is being executed. However, if the timer
events are performed very quickly, you can use a TCURS OFF
command to stop the cursor from disappearing.
One of the uses for a timer is the concept of in-game date and time.
GRAAL contains a number of commands and layout statements to
set, advance, check, and automatically display the date and time,
even on an analogue clock face with hands for the hours and
minutes. (These things are displayed in special, reserved sections
of the command area.)
There is more on each of these subjects in the command
descriptions in the on-line reference.
17 Special Techniques or "How The Heck Did He Do That?"
=========================================================
This is a walk-through of some of the particularly clever stuff in the
Olaf script files. I hope this proves that I have tried not only to solve
a limited set of specific problems when writing GRAAL, but
provided a set of commands that are flexible enough to allow even
the nearly impossible to be done without an endless array of
"novelty gadgets".
17.1 The Load / Save Room.
--------------------------
GRAAL has some dull, built-in requesters for saving, loading and
quitting games, but the demo adventure shows how you can
customize these features using a special room.
The room is called by clicking verb 10, which is represented on
screen by a diskette icon. Because the load/save room should be
available everywhere, the code for jumping to it is in an
ACTION: 10;...
statement in graal.main, containing the following:
* We set a flag to remind ourselves about the missing command
area - see below.
* Next, we need to issue a MARK command - this is absolutely
essential. Not only do we need it to get back to the same place
when backing out from the load/save room, but we actually use
the MARKed data when saving the game! (We can't just SAVE
directly in the load/save room, because then we would save -
the load/save room position!)
* The next one may seem a little odd: We issue an EDLG
command. This is because from GRAAL 2.2, you can call load/
save routines from within a dialogue, and if we were in
dialogue mode, we need to get out of it in order to access the
buttons and stuff in the load/save room. (When you load a
saved game, the correct mode is automatically switched on
again.)
* Because we will not need the command area in the load/save
room, we hide it with a COMAREA OFF command.
* After all of this, we jump to room 40, which is the load/save
room. Study the code to see how IFNOTSAVEDISK is used to
ensure we have a place to save the game, and how IFEXISTS
is used to check for existing, saved games and to alter the
appearance of the save/load buttons and game slots according
to what's available at each moment.
Now, if we back out from the load/save room, we'd like the
command area back in place, thank you very much. Well, the
"backing out" is handled by either a LOAD or a RESUME
command, and both makes GRAAL look through the ACTION: -2...
statements. So, all we have to do is have such a statement checking
the flag we set earlier, and issue a COMAREA ON command to put
the command area back where it belongs. (In Olaf, some rooms
don't use the command area at all, so we also have an extra flag, set
in each room, to test if we should do a COMAREA ON or not when
loading a saved game.)
Note: If you have designed your own save/load/quit functions, you
could disable the ordinary short-cut keys for the standard
requesters in the finished version of the game. You do this by
putting a couple of DISABLE_... statements in the graal.main
script. Or, you could define your own save/load commands, pointing
to your newly designed room, and map the standard short-cut keys
(S/L/Q) to these commands. You do not necessarily have to put the
"clickable areas" for these commands inside the command area
visible to the player - if you put the areas off the screen with some
coordinates like 500;500;501;501, you force the player to use the
short-cut keys to access those commands.
Finally, remember that it is up to you to keep track of whether the
command area is displayed or not every inch along the way - saving
a game whilst the command area is not shown requires
mechanisms to check out how it should be after each and every
loading of a new game position.
17.2 Going into the Alley
-------------------------
In room 2, there is an example of how an un-named exit can be used
to cover an area and make special things happen when the player
tries to direct his character to go there. In this case, the back of the
alley is covered with an un-named exit. When the player clicks the
alley for the first time, Olaf moves there and makes a comment
about how very uninteresting it is. Then, a room flag is set, and the
exit is hidden. From there on, the alley is just an ordinary part of
the scene, and Olaf may walk in and out of the alley any number of
times without anything special happening.
The alley also demonstrates a typical use of the 3D scaling function
- the way the 3D: statement is set up in 2.room, GRAAL uses 3 of
the available character sizes to display Olaf, depending on how far
into the alley he has gone.
17.3 Speaking In a Foreign Tongue
---------------------------------
The conversation with Rajah Singh on the quay is rather special -
you are forgiven for thinking a special font is being used to display
the foreign language spoken by Rajah. However, this is not the
case. Instead, I have combined a "blank" RESP command with
BOBON and BOBOFF commands. Have a look in the 3.room file:
First, the "foreign language" was "typed" in an ordinary picture
(3FG.IFF) using DPAINT.
Then, the "words" were grabbed as RBOBs using ROOMBOB:
statements.
Rajah's responses to Olaf dialogue lines are as follows:
1. First, a BOBON command is used to display the RBOB with
the "foreign language".
2. Immediately upon that, a RESP command displaying nothing
but blank spaces is used to make Rajah Singh "speak". The
number of blank spaces determines the time it takes to
execute the RESP command.
3. After that, a BOBOFF takes away the strange text again.
Simple, eh? No need to construct an entire font (and no need
for another GRAAL command to handle that font!).
17.4 An Automated Room
----------------------
As you may have noticed, you can never get into normal game mode
in Ali Harrod's shop - As soon as you walk in, you end up in dialogue
mode, and when you end the dialogue, you are immediately
transported out of the boutique. This is thanks to the DACT
statements, where the programmer can grab control and keep it for
as long as he likes! Have a look in 4.room - there is not a single run-
through of DACT statements not ending with a DSET... EXIT
combination, forcing the player into dialogue mode. Therefore,
there are no ACTION: statements either.
This technique is useful in a lot of circumstances - many times, it
relieves you of having to think up a lot of elaborate ideas for a room
where you really don't want the player prowling around.
17.5 The Art of Avoiding a Seagull
----------------------------------
As long as the seagull in the harbour is sitting on the pollard, Olaf
steers well clear of it when walking about. He simply walks where
the room file FLOOR: statements say he can move!
However, as soon as the seagull is scared off, Olaf is free to
approach the pollard and pick up the feather. This is made possible
by two FLOOR and one NFLOOR command executed in the
cutscene where the seagull takes off (4.scene).
Having chased the seagull away, one problem remains: The next
time we re-enter the room, we want things to be the way they are
now, and not according to how they are set up in the room file
statements.
A room flag comes to the rescue here - it allows us to "remember"
the seagull status between visits to the room.
Room flag 1 for the room (room 3) is used - as long as it is zero (the
initial state), the seagull is on the pollard. As soon as the bird is
scared off, we set the flag to 1 with a SETRF 1=1 command in the
cutscene. This room flag is tested in a DACT: statement - if it is set
to 1, the bird is moved to the roof of the shed, and the default floor
definitions are changed exactly the same way as in cutscene 4.
Remember, as long as the LIGHTS ON command has not been
used, the scene remains black and we can move anything we want
around without the player being aware of what is done!
17.6 A Spitting Image
---------------------
The spitting llama on offer by Ali Harrod is composed of two
animations, because I decided a single one would be too large.
Instead, the llama itself is one animation, and the "spit" is another,
very small one, animated by an AMAL "Move" command.
The movement of the llama and spit animations are synchronised -
the llama being displayed on top of the spit. (Well, almost
synchronised. If you leave the llama sequence on and walk away for
a quarter of an hour, you will notice that things have become a little
strange when you return. But who could keep away from the game
that long, anyway? And if you don't like it, you can always make
one big animation of the whole thing!)
17.7 A Map Room
---------------
I had planned on only delivering the first four rooms with GRAAL,
but ended up giving you seven. The reason is some quite interesting
techniques were used in room 5, which may come in handy.
Room 5 is an outline map of the East, showing the towns of
Constantinople, Gurgan and Baghdad. The thing is, there is no
Olaf, and nothing to do except watch a short cutscene and, when
revisiting, point to one of the three towns. Also, this room does not
use the command area at all - instead, the scene area itself takes up
more space, and the command area is hidden.
Olaf was done away with by a simple CHAR OFF command in a
DACT: statement - nothing strange about that (once you read the
on-line reference). Remember that the main character will always
be made visible when entering a new room, unless you put it away
again with CHAR OFF.
Because we don't need the command area for this room, each GOTO
command leading into this room from other rooms is preceeded
with a COMAREA OFF command. (See the load/save room above
for more about hiding the command area.) In the room itself, a room
flag for room 40 (the save/load room) is set to indicate the status of
the command area (shown or hidden) - this flag is used in the save/
load procedures, as described in "The Load / Save Room." on
page 58.
We need to make sure the command area is replaced when entering
a new room. The only rooms Olaf can go to from room 5 is room 6
and room 7, so in each of these, a COMAREA ON command in the
DACT: statements prior to LIGHTS ON restores the command
area. (Keep the COMAREA ON commands close to LIGHTS ON to
make sure the command area disappears/re-appears in sync with
the scene area.)
By now, we have ensured the map, and ONLY the map, is shown on
screen. The only thing the player can do in room 5 is to point to one
of the three exits placed just over the towns on the map.
I have chosen to display the exit names for the towns in the normal
fashion when the mouse cursor moves over them, although I might
just as well have put a blank space instead of names in the EXIT
statements. The names of the towns are written on the map itself,
and it shouldn't have taken the player too long to figure out where
to click, anyway.
18 The On-line Monitor
========================
GRAAL's on-line monitor is a great help when things go wrong in
your scripts. It allows you to examine flags and other information
"on the fly", and also make temporary corrections. This helps to
lower the number of times you have to restart GRAAL during the
tests. (Naturally, the monitor cannot be called up from an
encrypted game unless there is a DEBUG: statement in
graal.main.)
To invoke the monitor, simply press the [G] key. The monitor
window pops up, covering the lower part of the screen.
Here's a description of what it contains:
Information lines
At the very top are two lines of general information showing
* The current room.
* The last starting position used.
* The current floor.
* Whether the character is (should be) visible or not.
The information in line two is mainly of interest in multiple-
character games:
* The number of the character currently under player control.
* The number of the inventory currently used.
* The number of the character following the controlled character
(if any).
Command field and < <- Execute > button, message field
In this text field, you can type any valid GRAAL command, and
then make GRAAL execute it with the < <- Execute > button next
to the field.
These are the commands your are likely to use most:
* GOTO to jump to another room (or reload the current one).
This command also automatically closes the monitor and thus
replaces the old (2.0) monitor's < <- GOTO > button.
* SETOF and SETRF to set flags.
While GRAAL takes care of your request, the text * executing * will
be shown in the message field at the very bottom of the window. If
it goes OK, the text
* OK * is shown. If GRAAL couldn't make sense of what you typed,
the text
* error * is shown instead. Make sure you get the syntax correct -
often, any mistakes will make the dreaded GRAAL run-time error
screen appear.
Some rules:
* You can only enter one command at a time.
* You cannot enter conditions.
* All input is automatically converted to upper case.
* You can use ROBJ, SOBJ, RBOB and SBOB references.
* While anything is possible, not everything is smart or even
relevant at all times. Commands you probably don't want to
execute from the monitor include SAVE, LOAD, MARK,
RESUME and others that re-arrange a lot of stuff in GRAAL.
< Back to GRAAL > button
This button quits the monitor. Remember that some changes you
attempt in the monitor may require re-loading the current room to
take effect, in which case you should end the monitor session by
executing a GOTO command instead.
List buttons
There are three buttons to list important information:
* < Object List > shows a list of all objects - numbers, locations
and flag contents.
* < Room List > shows the contents of all room flags for all
rooms.
* < Inventories > shows a list of the contents of each inventory.
< Trace > button
This is a toggle button, deciding whether the single-trace debug
mode is active or not.
Click once to activate. The trace console will open at the top of the
scene area. Then click < Back to GRAAL> and provide GRAAL with
some input.
As soon as GRAAL starts working on an input sentence, all
conditions and commands about to be executed are shown in green
in the trace console. For each command, you have to press a
keyboard key to continue through the script. The full stop key is a
good choice, because it also allows you to skip the pauses caused by
commands like SAY and W(ait).
The text colour in the trace window changes from green to red while
the command is being executed. An empty trace window means
GRAAL is waiting for more player input.
GRAAL with the trace console active. Here it waits for us to
acknowledge the next action - loading a sound sample for the bell.
Note: In the trace console, object and image references are NOT
converted back to ROBJ, RBOB, etc. references. For example,
SBOB1 will show up as number 61 or something like that.
To deactivate the trace mode, call up the monitor again and click <
Trace > once more.
The trace mode can also be activated and deactivated from within
scripts with the TRACE ON and TRACE OFF commands.
19 Macros
===========
Macros allow you to record a sequence of player input selections,
store them in a file, and play them back later.
The primary use is for testing - being able to play the same
sequence of events back over and over again, and having it done
automatically, makes testing a whole lot easier. They are especially
useful for running through parts of the game which are really
"finished", but still need to be tested from time to time to check that
no alterations you have made to other parts of the game affects
them, or when changes to scripts means you cannot use old saved
game files to put you in the desired part of the game.
The macro functions only work in development mode. In encrypted
games, they are not available unless there is a DEBUG: statement
in graal.main.
19.1 Starting a Macro Recording
-------------------------------
1. Start the game. Load a saved game, or go to the position from
which you want to start the macro recording by playing the
game in the normal way.
2. Press the [R] key. A message telling you that macro recording
is activated is shown very briefly in the scene area.
3. From now on, every command you execute, and every exit or
dialogue line you choose, will be recorded to memory.
19.2 Saving a Macro
-------------------
1. When you have reached the point where you want the macro
to stop, press the [R] key again.
2. A dialogue box pops up, asking for a macro file name. The
name you type will be suffixed with the text ".macro"
3. Click the "Save" button. The macro file is now stored in the
development directory.
19.3 Playing a Macro
--------------------
1. Put the game is in EXACTLY THE SAME POSITION as when
you started the macro recording.
2. Press the [P] key. A dialogue box appears, asking for the
macro file name. Type the name - you do not have to enter the
".macro" part.
3. Click the "Load" button.
4. The contents of the macro are now re-played before your very
eyes. Sit back, watch, and enjoy!
5. You may abort the playing of the macro at any time by
pressing the [Esc] key between commands.
Tip: Before playing a macro, you may want to put the text display
at maximum speed by pressing the [ I ] key a number of times first.
19.4 Restrictions to Macro Playback
-----------------------------------
The original timing of the player input is not preserved in the
macros. When a macro is played back, execution of the next
command starts as soon as the previous one is finished. This means
macros are not suited for recording parts where the timing of player
input is critical. In other words, if you are using the GRAAL timer
functions, stop to think before you record macros.
Changing the N_GLOBALBOBS:, N_SECTIONBOBS:,
GLOBALOBJS: or SECTIONOBJS: statements offsets the image
and object numbers, and previously recorded macros will stop
working. That's a very good reason to set them reasonably high
right from the beginning.
20 "Productifying" Your Adventures
====================================
20.1 The Basics
---------------
While developing your adventure, you have all the required files in
one, big, happy development directory. When you need to distribute
your finished work (or test versions) to other people, problems
arise:
1. You only want to distribute the files needed for the adventure -
not the GRAAL docs, utility programs and temporary work
files which you probably also have in the development
directory.
2. If the game should be playable from diskettes, you need a way
to tell GRAAL which files are on which diskette, and you
probably want to duplicate some frequently used files onto all
the game diskettes.
3. Perhaps you want to encrypt and compress the files, saving
disk space and making it very much harder for players to find
the solution by cheating.
This is how to go about it:
1. You put the information about which files belong to the
finished game, and which diskette(s) they should be placed on,
in the diskinfo.graal file. Use the GREP program (described
below) to help you out.
2. This step is optional and can only be done by registered users:
You run the GPRO program, which uses the diskinfo.graal file
to copy all the required files from the development directory to
a test directory (which must also be on hard disk). This makes
it possible to test if all required files really were specified
correctly in the diskinfo.graal file before making diskettes. It is
during this step that GPRO also offers an option to encrypt
and compress selected files.
3. You run the GDC program - either from the development or
the test directory depending on whether you did step 2 above -
which uses the diskinfo.graal file to copy the game files to
diskettes. It also formats and labels each diskette so that
GRAAL knows what diskette names to look for when disk
swapping during play becomes necessary.
20.2 The diskinfo.graal File
----------------------------
GPRO and GDC rely on a "diskinfo" file to tell them which files
should be copied, and which diskette each file is meant to end up
on. A diskinfo file must contain the following:
On line 2 (and nowhere else): The common part of the delivery
diskette volume name, for example
MYADVENTURE_DISK
When GDC does its stuff later, the diskettes will then be labelled
MYADVENTURE_DISK A MYADVENTURE_DISK B
and so on.
Below line 3: The names of all the files, grouped according to
delivery diskette. Each file name is on its own line, preceded by the
diskette suffix and a space. For example:
A 1.room
means the file 1.room is delivered on MYADVENTURE_DISK A.
Remember: The files should be grouped according to volume, and
the groups should be sorted alphabetically, starting with
everything on diskette A.
You may have as many comment lines and empty lines in between
the file entries as you like.
The following stuff should ALWAYS be on diskette A:
1) GRAAL_2 *
The main program. It does not have to be called GRAAL_2 - rename
it to anything you want your adventure called.
2) FONTS *
A special entry which copies the entire fonts: drawer in your
development directory.
3) graal.main
The graal.main file
4) diskinfo.graal *
5) The picture files for the command and dialogue areas (if you
don't specify DEFAULT, in which case the graphics included in the
GRAAL_2 program itself are used).
6) The resource file for requesters (suffix .rsb). If you use the
DEFAULT, no entry is needed - it's already in the GRAAL_2
program itself.
The asterisk (*) after some of the file names tells GPRO not to
compress and encrypt these files (see below). Apart from the files
above, always mark all user documentation and icon (.info) files
with asterisks in the same manner!!
20.3 GREP
---------
Once your adventure becomes reasonably big, you may find it a bit
difficult to keep track of all the files you use.
The GREP program starts by inspecting the graal.main file, and
from there it goes on to find all references to all files used by your
adventure.(This, of course, requires that a proper START_ROOM:
statement exists in graal.main, otherwise it will not find all the
information.)
GREP creates a report over what files are used where, and also
gives you helpful suggestions regarding the contents of your
diskinfo.graal file and some of the statement settings in graal.main.
This information is saved in a file called graal.report.
You can start GREP in two ways:
* From the shell: Switch to the development drawer, type "run
GREP".
* From the Editor: Select the "Create Report" option in the
GRAAL menu. The resulting file will automatically be loaded
into a new window in the Editor.
20.4 GPRO
---------
The GPRO program is used to copy the files that make up your
adventure (the ones that should go on the delivery diskette) from
the development directory (which can be a right old mess) to a test
directory, containing only what is needed to run the adventure.
You should test the adventure thoroughly in the test directory,
making sure everything is included, before making the delivery
diskettes. (GDC is automatically copied from development to this
test directory by gpro, because you need it there to make the
diskettes.)
This program is only available to registered users (in other words,
it needs the personal keyfile to work). Unregistered users are
confined to copying the game files directly onto the delivery
diskettes from the development directory using GDC, and then
testing the diskettes.
Starting GPRO
"""""""""""""
GPRO runs from CLI only. Open a shell, and switch to your
development directory. Then type "RUN GPRO". (Don't forget the
"RUN" bit, or GPRO may lock up during the copying process!)
GPRO now checks if there is a valid graal.key file in the directory.
If not, it will say so, urge you to register GRAAL, and terminate.
The user interface is as follows:
Encrypt:
< > Yes: Compress and encrypt files not marked by an asterisk in
the diskinfo.graal file. See "Compressing and encrypting"
below.
< > No: Do a normal file copy.
Simulation: < >
Click this if you just want to test the contents of the diskinfo file.
The Copy function will just "go through the motions", showing what
would happen if you had been copying for real.
Diskinfo:
You can choose the name of the diskinfo file to use here. You can,
for example, have one diskinfo file for demo versions and one for
"live" versions in your development directory. (I use this facility to
produce a GRAAL delivery from the "Olaf" development directory,
which normally produces only the "Olaf" game itself.)
Note that the selected file is renamed "diskinfo.graal" (the default
name) in the destination directory, and therefore, "diskinfo.graal"
is the name that should ALWAYS be used when referring to the
diskinfo file IN the diskinfo file!
Destination:
The name of a hard disk directory, which, by the way, must exist
already.
GPRO saves the names of the last diskinfo file and destination
directory in a file, and so remembers the settings until the next
time it is used.
Status bar
A green stripe shows how far the copying has progressed.
Message field
A text shows what is currently going on during the copy operation.
Copy and Exit buttons
Really... you'll just have to find out for yourself!
Compressing and encrypting
""""""""""""""""""""""""""
Almost all files can be compressed and encrypted during the
copying process. There are two benefits to this: You save disk space,
and both graphics and text files are rendered unreadable to your
users except through the GRAAL_2 program.
The following files/diskinfo entries should NEVER be compressed
during copying:
GRAAL_2 icon files documentation files graal.key diskinfo.graal
To make sure a file is never encrypted, just put a space and an
asterisk after the file name in the diskinfo.graal file, for example:
A Disk.info *
A GRAAL_2 *
A GRAAL_2.info *
Of course, you may want to compress GRAAL_2 to save disk space,
but do so before the final copying process, and use a utility that
creates a self-decompressing executable file (like PowerPacker or
CrunchMania).
Note that encrypted games ALWAYS require the keyfile to run, so
include an entry for the keyfile (on diskette A) in the diskinfo file
when you produce the final, encrypted master diskettes.
The compression routine puts the emphasis on speed rather than
efficiency. On average, 30%-40% less space is used by a compressed
adventure.
The percentage gained varies greatly with the structure and
complexity of the files. Some examples:
120K tracker module gained 42%
24K complex bg picture gained 20%
12K simple clipart picture gained 54%
24K script file gained 50%
48K IFF sample w. "silent" parts gained 38%
GRAAL games with compressed files require up to 200K or so extra
RAM space to do their job. Running a reasonably large adventure
thus takes a little more than 1,5MB...
On fast machines, I perceive a performance increase running
compressed games, but perhaps that's only my imagination... It's
not unreasonable, though, that the reduced disk access more than
makes up for the unpacking time.
On slow machines, the unpacking time becomes more noticeable,
and running a GRAAL game on an unexpanded 68000 machine
with no memory cacheing can be a nuisance. To help out a little,
consider NOT compressing and encrypting long sound samples,
and perhaps you could leave the tracker modules alone, too.
Because the tracker modules are probably the biggest files you
have, this will also save some working space (perhaps a 100K or so).
20.5 GDC
--------
GDC is the program that copies the game files to the final delivery
diskettes. You MUST use this program to prepare the diskettes.
However, GDC is not intended for making copies of the game. Just
use GDC to make the "master diskettes", and then use some proper
diskette copying software for the copies.
Note: ALWAYS wait for disk activity to finish completing before
responding to any prompt telling you to switch diskettes or that
the copying procedure has finished!
If you have run GPRO, the GDC program was copied to the test
directory automatically, and you should run it from there.
If you don't have access to GPRO, you run GDC directly from the
development directory.
GDC runs from CLI only. Open a shell, and switch to the
appropriate directory. Then type "RUN GDC". (Don't forget the
"RUN" bit, or GDC may lock up during the copying process!)
Format radio buttons
To prepare the diskettes, and label them properly, GDC first
formats each diskette. This can be done quickly, if the diskette has
been preformatted, or in the normal fashion, in which case the
previous formatting status of the disk is not important.
Check Sizes button
This is normally done automatically when you start GDC.
The "gauges" or "meters" labelled A, B, and so on, are updated to
show how much space is used on each disk. If you have specified too
much for a certain volume in the diskinfo file, the top of that meter
turns red to show that you must edit the diskinfo file and re-
distribute the files to make it all fit. (We're talking standard DD
diskettes here, of course.)
If you have left GDC running while editing the file, you could use
the button to re-calculate the space requirements. On the other
hand, it might be a good idea to exit the program, make sure you
update the right file in the right place, and only then re-run GDC...
Status bar
When you press Copy, each diskette meter in turn is gradually
emptied, and this line starts growing instead to show how far the
copy operation has progressed.
Message field
If anything goes wrong, this is where you will get told.
Copy and Exit buttons
Once more, pretty obvious...
You don't need more than 18 diskettes, do you? Please! Tell me you
don't!
EXTREMELY NICE TIP: It's good practice to keep the
diskinfo.graal file updated during development. Start GDC now
and then to see if the distribution of files seem about right with
respect to the space requirements... Also, use GREP to check that
the diskinfo.graal information is correct.
21 The Editor
===============
21.1 Introduction
-----------------
This is a neat little (well, growing bigger all the time, actually)
editor, making life in the GRAAL script-writing lane much easier
than it otherwise would be.
At first, you may find the concept behind it all slightly confusing.
While other "user-friendly" games development systems opt for
point-and-click control of everything, storing the results away in
cryptic databases, GRAAL is basically made up of ASCII scripts
that can be created using any text editor. While this means more
typing and requires a deeper understanding of what's going on, it
also has some definite advantages. It means greater flexibility in
your creations, a better overview, and a total freedom when it
comes to documenting the scripts via comment lines. And the
GRAAL editor steps in to bring you the best of the "point'n'click
world", too. It makes the typing of the scripts a lot easier, and you
will not want to be without it.
In short, the editor spares you from annoying things such as trying
to remember what script does what, what the parameters of that
"OBJECT:" statement mean, and what the coordinates of your last
6 FLOOR: and PATH: definitions actually looks like on screen. The
end result is the same as you would get with any other editor,
though - ASCII script files with lists of GRAAL statements and
commands.
In addition, the GRAAL editor has the following advantages:
* It handles multiple scripts in multiple windows
simultaneously, with easy switching, copying and pasting
between them.
* It is connected to the on-line reference, giving help on
statements and commands.
* It keeps track of used and unused room, section, scene, and
ptrn numbers.
* Although many features are GRAAL-related, it is perfectly
possible to use this editor to edit any kind of ASCII text file.
You will probably find it a good alternative. Enjoy!
The editor handles files up to 5000 lines long. (If you have GRAAL
scripts that long, you are probably in need of professional help :-)
21.2 System Requirements
------------------------
This editor needs Workbench 2.0 or better to work.
amigaguide.library v. 34 or later must be in your LIBS: drawer. (This
can be found for free on Aminet.)
On AGA machines, the editor screen "clones" your Workbench
setting by default. If you have a hi-res Workbench, it uses a hi-res
screen; with a Productivity Workbench, it opens in Productivity
mode... you get the picture. Just make sure that your Workbench is
at least 640 pixels wide, and everything should operate smoothly.
(The screen mode can be customised using the tooltypes in the
GRAAL Editor icon - see the end of this chapter.)
On non-AGA machines, a normal hi-res, non-interlaced screen is
always used.
Also note that the editor must be placed in your game development
library on your hard disk for all file fetching routines to operate
without problems. The GRAAL.guide file should also be placed in
the same directory.
21.3 Known Bugs & Irritating Facts
----------------------------------
* A block marked for editing and contained in a single screen
line is sometimes not properly highlighted on screen.
However, the copy/cut/delete functions still work.
* Adding lines to the end of the file in Overstrike Mode doesn't
work properly.
* If you use a 68030 or better processor, you may have to turn
CPU caches off before using the Editor. Otherwise, graphics in
the graphical editing functions may not display properly and
make you unnecessarily confused. The way to switch off caches
is to open a CLI shell, and type
CPU NOCACHE NOBURST
21.4 Creating a New Script
--------------------------
Since the editor expects to be placed in your GRAAL development
directory, it checks for a graal.main file in the current directory at
start-up - without such a file, you don't really have much of a
development environment!
If there is no graal.main file, the editor asks if one should be
created. If you answer "yes", a template for such a script will be
created in the editing window (which makes up the main part of the
editor display).
You can also use the "New" option in the "Project" menu to create a
new file. The "New" option has six suboptions. The first one,
"empty", just opens a new, empty editing window on top of the first
one. The editor handles up to ten script windows simultaneously,
and you can switch between them quite easily with the "Select
Window" option in the "Edit" menu (or [Amiga>+[W>).
The suboption "graal.main" creates a graal.main script template,
as discussed above.
The last four suboptions, ".room", ".section", ".scene", and ".ptrn"
creates a template for the specified script type. Before the template
is shown, a requester pops up showing a recommended script
number - this number is the first number not already occupied by
any of the existing scripts. You can change it if you wish, but
remember that it's a waste of space leaving unnecessary gaps in the
number sequences.
The requester also has a gadget for a short script description - you
should enter a meaningful description of the room, cutscene or
whatever here. This comment is placed in the first (comment) line
of the script, and you will see why it's so useful is a very short
while... in the next section, as it were!
21.5 Working with the Editor
----------------------------
Loading Existing Scripts
""""""""""""""""""""""""
Just like the "New" option, the "Load" option, also in the "Project"
menu, has the same selection of suboptions as the "New" option.
(The only difference is that "empty" is called "general" here.)
"Load general" brings up an ordinary file requester.
"Load graal.main file" loads the graal.main straight away - not
much use asking for its name, because it's always the same.
"Load .room file" and so on brings up a list requester showing the
numbers and descriptions (see above) of all existing scripts of the
desired type, neatly sorted in ascending order.
Most of the time, you probably want to open a script in a new
window, which is why you should use the "Load Another" option
instead. It looks exactly like the "Load" options, but in this case, the
suboptions have keyboard short-cuts ([amiga>+[3-8>). Learn to use
them, as this is the quickest way to open scripts.
Note: .scene files with a space in the name will not be properly
treated by the loader. Simply put, do not use spaces in file names.
The Templates and the Syntax Checker
""""""""""""""""""""""""""""""""""""
Some statements in the templates have suggested parameters
already filled in but in most cases, there is no point in giving a
suggestion because the correct parameters are very much up to
yourself. You can see this quite easily:
1. Create a new .room script, making the editor give you a room
script template.
2. Now press the button marked "Syntax". This will make the
editor check the script in the current window for syntax errors,
and it will not be very long before it comes upon a statement
with no parameter filled in. It then displays an error message
telling you about the problem, and it also marks the statement
where the error occurs.
The syntax checker is a great help, but it does not find every
possible error. This is what it does:
* It checks the names of all statements.
* It checks that all mandatory statements are in place.
However, note that some statements may depend on others to
work, and this is not checked by this function. Be particularly
careful with graphics, and make sure the correct CLPART:
statement is in effect in every situation requiring CLPART
pictures!
* It checks the number of parameters for all statements (except
for statements with a variable number of parameters).
* For all parameters that may consist of conditions, commands,
or both, it checks the name of each condition and command.
If any error is found, the offending statement / command is
highlighted, and the nature of the error is shown in a requester as
described above.
All this should make development a little less frustrating.
However, GRAAL itself checks a lot of other stuff too, and will still
throw runtime errors at you from time to time. Further
improvements will probably appear over time.
Note: The syntax checker uses the file name suffix to determine
what statements and commands are allowed - so it can only be used
in files following the GRAAL naming conventions. And it does NOT
work with .ptrn files.
Amigaguide Help
"""""""""""""""
If you place the cursor on a statement or command word and press
the HELP key, the amigaguide reference file graal.guide is opened
with the relevant topic displayed. (The small <?> button does the
same thing.)
Note that just like the syntax checker, the help function uses the
file name suffix to determine what statements and commands are
allowed - so it can only be used in files following the GRAAL
naming conventions.
Normal Editing Functions
""""""""""""""""""""""""
I will not bother you too much about the functions that you are
likely to encounter in any text editor. You should find the find &
replace options, and the other options of the "Edit" menu, quite
adequate for the job at hand.
Just a few words about useful keyboard keys:
[shift]+[down arrow]
[shift]+[up arrow] These keys scrolls the script one page at a time.
[shift]+[right arrow] Moves the cursor past the last character of the
line.
[shift]+[left arrow] Moves the cursor to the beginning of the line.
[control]+[right arrow] Moves to the next semi-colon of the line; that
is, to the next GRAAL statement parameter.
[Esc] Closes the current window.
[Enter] Exits a string gadget (for example, in the
Find window), or carries out a function (for
example, "Find" in the find window, once the
cursor is not in a string gadget any more).
Other available short-cut keys are all listed in the menus.
Marking Text Using the Mouse
""""""""""""""""""""""""""""
Apart from marking text blocks with [amiga>+[1> and
[amiga>+[2>, you can use the mouse:
1. Click the first character of the block.
2. Hold down a [shift> key and click the character immediately to
the right of the last character of the block. (Clicking the first
character of a line will mark the entire previous line.)
The Status Bar
""""""""""""""
Some useful bits of information are shown in the "status bar"
immediately above the editing windows:
* Cursor row (r) and column (c) position.
* Insert (I) or overstrike (O) write mode.
* Number of changes made since the last save. Note that some
"big" operations, like inserting a block of text, only count as
one change each!
* Time. The clock is only updated when you do something in the
editor, like moving the cursor.
<RUN> button
""""""""""""
The <RUN> button (which has a small GRAAL symbol on it) tries
to start the GRAAL driver as a separate process. By default, it
assumes the name of the GRAAL driver program is GRAAL_2. This
can be changed using tooltypes in the GRAAL Editor icon. (See the
end of this chapter.)
"Quick LOCATE" Buttons
""""""""""""""""""""""
To help you quickly locate those parts of a script file which are most
often edited, four buttons have been provided. For example,
clicking <ACTION:> takes you to the first occurrence of "ACTION:"
in the file.
Switching between Windows
"""""""""""""""""""""""""
When writing GRAAL scripts, you very often need to make changes
to two or more script files almost simultaneously. Fortunately, the
GRAAL editor really excels at this.
Use [amiga>+[w> to open a window containing a list of all currently
open editing windows and their contents. In addition, all windows
where unsaved changes exist are marked with an asterisk ( * )
before the window number.
Click on any name in the list, and that window will become active
and placed on top of the other windows. You can also use the cursor
keys and select a window with the [enter> key. In fact, the GRAAL
text editing functions have been designed to make as little use of
the mouse as possible - the keyboard is much faster once you get
accustomed to using all short-cut keys.
If you need to view more than one script at the same time, just
resize the editing windows and place them next to each other -
nothing could be simpler. (Though I must confess I don't use this
much myself - window switching is so much easier!)
21.6 Creating a Report
----------------------
The "Create Report" option in the GRAAL menu starts the GREP
program, provided it is in the development drawer. When the
program has finished, the resulting report (always called
graal.report) is loaded into a new window in the Editor for viewing
(and possibly some cutting and pasting as well).
The GREP program is described elsewhere in this manual.
21.7 The Parameter Editor
-------------------------
Instead of typing the parameters of all statements and commands,
separating them with ";" or "," characters, you can edit the
parameters in a window, with each parameter neatly contained in
its own string gadget.
This is how to do it:
1. Place the cursor on a statement or command - the actual
NAME, mind you, not on one of the parameters.
2. Press [right Amiga] + [E] or click the <Edit Parameters>
button.
3. A window opens, with all parameters neatly laid out in string
gadgets. The number of string gadgets available equals the
number of parameters. Repetitive parameters (surrounded by
brackets {} in the syntax description) only get one string
gadget. You could type the parameters there, but it's often
easier to do these in the normal editor "typewriter" mode.
The lead text for each gadget is taken from the syntax help - if it's
longer than 15 characters, the leftmost characters will not be
visible, which may look a little funny at times. Oh well...
The Parameter Editor window - this one with an OBJECT:
statement loaded.
Keyboard Short-cuts
"""""""""""""""""""
There are a number of short-cut keys to help you reach the different
parts and functions of the window. They can only be used when the
cursor is not in an input string gadget. That means after you have
entered text into a gadget, press [Enter] to exit the gadget to make
the short-cut keys available. Specifically:
* When you press the [Tab] key, the next string gadget
(following the last activated one) will be activated.
* When you press the [Enter] key whilst not in an active gadget,
or click <OK>, any changes you have made will be inserted
into the script file.
* When you press the [Esc] key or click <Cancel>, the changes
you've started to make will be forgotten, and the window is
closed without any alterations to the script.
* When you press [Help] or click <?>, the amigaguide help for
the current statement or command is shown. When you've
done reading up on the subject, press [Esc] to return to the
parameter window.
* The graphical editing functions have keyboard short-cuts [F1]
to [F7], as listed further on.
Optional Parameters
"""""""""""""""""""
Optional parameters are shown in blue. Consult the on-line
reference for information about when to use them (and not).
Cycle Buttons
"""""""""""""
If the button to the right of a string gadget is available, you can
press this to cycle through the valid alternatives for the parameter.
The contents of the gadget will change as you click the button
repeatedly.
UPPERCASE text entered by the cycle button should be kept as is.
Occasionally, a text in lowercase may appear, which you should
change to a proper value.
For example, if the text "obj" is shown as one of the cycle
alternatives, this means you should replace "obj" with a proper
object number.
Graphical Editing
"""""""""""""""""
A lot of parameters have to do with specifying co-ordinates,
positions and other stuff related to a backdrop picture. You very
sledom have to enter the values of these parameters manually -
instead, there are a number of special functions to let you do this
graphically.
If a statement or command contain parameters which can be edited
in this way, one or more of the special editing buttons beneath the
string gadgets will become available. They also have keyboard
short-cuts in the form of keys [F1] to [F8].
Usually, the editor finds the relevant backdrop picture and room
file to use automatically, but may occasionally ask you for a file
name when it cannot decide which part of the adventure you are
referring to.
Sometimes, the editor asks "Reload the object and image data?". If
you haven't altered any images, or switched rooms or anything
since the last time you used the graphical editing functions, you can
answer "no", which speeds up the process.
If the backdrop picture is one of the rooms in your game, all
previously defined objects placed in that room are also shown for
reference. In many cases, floors and paths are also shown, with
their respective numbers shown close to the center of the each floor
and path. If the backdrop picture is wider than the screen, use the
left and right cursor keys to scroll it.
Note: If objects overlap, the editor does not bother to sort them in
the proper order.
The details of all the "graphical editing" operations are explained
below, and there is also a brief help text on a screen directly below
the picture you are about to edit. Once you are done, press "Enter"
to save the changes, or "Esc" to cancel.
Important Tips
""""""""""""""
* Make sure all statements and commands specifying picture
file names, which help the editor choose the right file, are
entered as early as possible in the script-writing process.
* Remember that the editor mainly loads data from the files
saved to disk, not from unsaved versions of the files still in the
editor. Therefore, you should usually save changes before
going to the parameter editor.
* When selecting character images in multiple character games,
note that most character-related statements and commands
expect you to specify the image of character 1, which will be
replaced by the corresponding image for the currently
controlled character automatically. See "Multiple Characters
and Inventories" on page 42.
Now, a closer look at the "graphical editing" buttons:
<Area> [F1]
"""""""""""
An area or "frame" is a rectangle that can be moved around the
screen and re-sized. It is used to cut out clipart graphics, and for
specifying areas for exits, floors, and a number of other things.
To re-size, click and drag the bottom left corner (the little square)
of the rectangle. To move the rectangle, click and drag anywhere
else on the screen.
If you use this option to edit the cut-out frames for BOB images, you
will get a number of rectangles on screen corresponding to the
number of images to be cut out by the ...BOBS: statement. Use the
leftmost rectangle to re-size: all duplicate frames will also be re-
sized automatically. To alter the spacing between the frames, use
the up and down cursor keys.
Editing areas for a BOBS: statement. If you look closely, you may be
able to see the 10 cut-out frames on the second row of images in this
screen shot (it's easier in real life :).
<Position> [F2]
"""""""""""""""
This edits the position of an image, and possibly also the image
number.
If the previous position and image used are known, the object or
image will start out in its old position.
Click and hold the mouse button. Drag the mouse to move the
image to the desired location and release. (If it's an object, a copy of
the image will remain the object's previous position when you drag
the image.)
To select another image, use the up and down cursor keys.
To flip the image left/right, press the "x" key.
Note: When you save the changes with the "Enter" key, the selected
image will normally be placed in the "image" parameter. However,
if the "image" parameter previously contained an animation
sequence or a PTRN specification, it will NOT be affected. This is
to prevent a lot of hard work being undone by an over-smart
editor...
<Pastepos> [F3]
"""""""""""""""
This is exactly the same as editing an image position, except the
parameters specify the upper left corner of the image, not the
hotspot position. This is nothing YOU have to worry about - the
Editor will make the correct button available and also take care of
which co-ordinate goes where.
<Char.pos> [F4]
"""""""""""""""
Very similar to the previous two, but only available when editing
an object. This sets the main character's position relative to the
object, used in the MOBJ command. The image used for the main
character can also be altered. The same rules as for the object
positioning apply.
As from GRAAL 2.2, the Editor asks you if the character width
should be taken into consideration. Answering "yes" means GRAAL
will calculate the position of the edge of the character closest to the
object, rather than the center of the image. This is only a concern if
you have multiple characters with varying widths that can try to
manipulate the object.
<Line> [F5]
"""""""""""
This one edits the line for a PATH: statement. Each point on the
line (there may be up to 6 of them) has a "handle" in the form of a
small square. Just click within the handle and drag to move the
point to a new place.
To add a new point, press the "arrow up" key. The new point will be
inserted between the last and the second last point.
To delete a point, press the "arrow down" key. It is always the
second last point that is deleted.
<Ink> [F6]
""""""""""
This one's a little different. Many commands require colour
numbers to be specified, and this helps to pick the correct palette
index number directly from the palette of the relevant backdrop
picture.
When the picture is shown, a palette overlays the upper left corner
of the picture. The text above the screen tells you to click on a colour
- the "normal ink" colour for things like text displays, and the
"background ink", which is the colour most functions use to erase or
clean up unwanted parts of the picture.
The "highlight ink" colour is only used in the sentence display area.
It is the colour used when a completed sentence is highlighted
during command execution.
<File> [F7]
"""""""""""
Not a very graphical function, but this button can be used to select
a file name. If you have an AGA machine, the file requester that
pops up will show only files of certain types, depending on the
statement or command you are currently editing. For example, for
the BG_IFF: statement, only picture files will be shown; for the
TRACK command, only music modules will be shown. The filter
settings can be changed using the tooltypes in the GRAAL Editor
icon. See the end of this chapter. If it's a room file that is wanted,
the Editor always uses the special "load room" requester which also
shows the room descriptions.
<3D> [F8]
"""""""""
This one edits the position of the 3D scaling lines in the 3D:
statement. Just drag each line to its proper position along the y
axis. Each line has a box attached to the top - the box represents the
scale of the character, so the line with the smallest box should be
the one furthest up the picture, and so on.
Inserting New Statements or Commands Using <Edit
Parameters>
If you place the cursor on an empty line and use <Edit
Parameters>, a list requester pops up asking you if you wish to
insert a new statement. All valid statements (according to the
script type) are shown in the list. Select a statement with the up
and down arrow keys, or with the mouse. With a statement
selected, you can also click the <?> button or press [Help] to read
the amigaguide help for the statement.
Select the statement with [Enter], the <OK> button, or by clicking
it a second time with the mouse. A new line containing the
statement will be inserted at the cursor position, and the
parameter editor window is opened automatically.
Similarly, positioning the cursor on a line that has a statement, but
neither on the statement nor the existing command names, brings
up a requester asking if you wish to insert a new condition or
command. Be careful not to insert a new command in the middle of
parameters belonging to another command...
Note: .scene files can't contain statements. Therefore, it's always
the condition/command list that appears when using the <Edit
Parameters> function in an empty space.
21.8 Icon Tooltypes
-------------------
Some aspects of the Editor's operation can be changed using the
following tooltypes:
SCREEN=WB|NTSC|PAL
WB: The editor will open in the current Workbench screen
mode. NTSC: The screen opens in hires NTSC mode. PAL: The
screen open in hires PAL mode.
(Note: The SCREEN tooltype only works with AGA machines.)
GRAAL=name Sets the name of the GRAAL driver program being
started with the Editor´s <RUN!> button.
IMAGEFILTER=filter
Specifies which files should be shown by the file requester
when the FILE button in the Parameter Editor window is
used to find images. The default is
#?.iff|#?.pic|#?.i16|#?.i32|#?.i64
TRACKFILTER=filter
Specifies which files should be shown by the file requester
when the FILE button in the Parameter Editor window is
used to find music modules. The default is
#?.trk|#?.track|#?.mod|#?.sng
SAMPLEFILTER=filter
Specifies which files should be shown by the file requester
when the FILE button in the Parameter Editor window is
used to find samples for sound effects. The default is
#?.snd|#?.raw|#?.8svx
CHECKONSAVE=YES|NO
If this is set to yes, a syntax check will be automatically
performed as soon as you try to save a script file.
If an error occurs and you click the <Cancel> button in the
error report box, the file will not be saved. Clicking
<Continue> allows you to save the file with the errors in it.
PAINTAPP=path:name [arguments]
The path and name of a paint program, which can be launched
directly from the Editor's GRAAL menu. Some paint programs
may accept command line arguments and even a file name. In
this case, put {f} in the place of the file name - GRAAL will
then open a file requester, using the imagefilter specification,
before starting the paint application. (This works wonderfully
well with DPaint.)
21.9 Editor Keyboard Shortcuts
------------------------------
("a" means the key must be combined with the right [Amiga] key.)
a[3] Open new window & Load any file
a[4] Open new window & Load graal.main
a[5] Open new window & Load .room script
a[6] Open new window & Load .section script
a[7] Open new window & Load .scene script
a[8] Open new window & Load .ptrn script
a[S] Save
a[A] Save As
a[P] Print
a[?] About
a[Q] Quit
a[W] Select Window
a[I] Insert Mode
a[O] Overstrike Mode
a[F] Find
a[N] Find Next
a[R] Replace
a[1] Mark Block Start
a[2] Mark Block End
a[T] Top
a[B] Bottom
a[C] Copy
a[X] Cut
a[V] Paste
a[D] Delete Current Line
a[Z] Undo "Delete Current Line"
a[J] Stack windows
a[L] Tile windows horizontally
a[M] Tile windows vertically
a[K] Check Syntax
a[E] Edit Parameters
a[G] Launch GRAAL
a[H] Create and load GREP report
a[U] Launch paint program
[Shift] + [Left Arrow] Start of line
[Shift] + [Right Arrow] End of line
[Shift] + [Up Arrow] Page up
[Shift] + [Down Arrow] Page down
[Ctrl] + [Right Arrow] Next parameter ( ";" character )
[Help] Show Amigaguide help for current statement / command
[Esc] Close current window / requester
[Enter] Exit current input string gadget, or close requester and
execute function (depending on current situation).
[Tab] Activate next input string gadget (can only be done if previous
string gadget has been deactivated with [Enter] first).
[F1] Run GRAAL from Editing Window
[F2]-[F5] Quick locate buttons in Editing Window
[F1]-[F8] Editing buttons in Parameter Editing Window
22 Hints and Tips
===================
Here are some general hints and tips that may prove useful.
22.1 Flags
----------
* Avoid setting flags in cutscenes, if you have a choice. It's hard
to keep track of the games' status in the main script files if the
setting of flags is "hidden from sight" in the cutscenes. (And
forget I mentioned I've done just the opposite in a few places.
Do as I say, not as I do! :-)
* Since all variables have the initial value 0, it is good practice
to let that value represent the initial state of the object, room,
situation, etc.
* Use room flags for all things that relate to the scene as a
whole, rather than the flags of a particular object.
* Remember that ALL aspects of room objects and section
objects get reset as soon as you leave the room or section. You
can compensate for this using room flags to track room object
states, and then set the objects up in whatever way they
should be by using DACT statements.
* Use the room flags for room 0 as "global flags" pertaining to
the game as a whole. Room 0 is never used as a "real" room in
any adventure.
22.2 Diverse
------------
* During the development of a game, you often wish to start the
game in an odd location with the objects and flags required set
up in a special way. To keep your proper game scripts "clean",
set up a special testing room and call this as the
START_ROOM. Get objects and set flags using DACT:s, and in
the last DACT:, simply GOTO the location you wish to test.
* Keep a template containing comments for all the ACTION:
statements in a separate file, and copy it to the end of each
new room and section script. This way, you have a map over
what command has what number handy in all scripts.
23 Questions and Answers
==========================
Q: Anything I should think about when assigning BOB numbers to
objects?
A: Use numbers below 60. Make sure a BOB number is never used
for more than one thing at a time in the same room. Otherwise,
no: No information is connected to or "belongs to" BOB numbers
and their use, so there are no other fixed rules.
Q: What about animation channels then?
A: Same thing. Look up the reserved channel numbers in
graal.guide, and make sure you never try to use the same channel
for two things in the same room!
Q: What are the rules for room object use?
A: A room object can only exist in one room - therefore, it can never
be picked up or added to the inventory. Nor can you use its object
flags for very much, because they will be reset each time you exit
the room.
ROBJ references should only exist in .room files, never in .sect or
graal.main!
Q: What are the rules for section object use?
A: A section object only exists within one section, and preferably
disappears totally during the first visit to the section - otherwise,
you must keep track of how the objects have been handled via room
flags or such devices, if you happen to re-enter the section.
In other words, take particular care if your adventure is designed
in such a way that you can go back to, for example, section 1 from
section 2 - not only must you be sure that section 1 still looks okay
with respect to section object use, but also, the section 2 section
objects will suffer the same problems! Even if you haven't "solved"
section 2 yet completely, going back to section 1 will end your first
visit to section 2 and thus reset your section objects for section 2!!
SOBJ references should only be used in .room and .sect files, not in
the .main file.
Q: I need some very precise movement paths for my character in
some situations, and the floor system is not quite up to the job.
A: There are a couple of ways.
A) Try using PATH: statements.
These allow you to connect otherwise unconnected floors using
"twisting" paths. Read more in the room PATHS: statement in the
on-line reference.
B) Use an un-named exit.
When you specify an EXIT: with no description, GRAAL shows no
exit name in the scene area, nor does it put a "Go to ..." message in
the sentence box when the exit is clicked. That way the un-named
exit is just a "clickable area" in the scene area, and you can use
ACTION: 0;... statements for it to do anything you like.
1. Put an un-named exit over the destination on the screen your
character should reach using a special movement or animation.
2. In the ACTION: statements, use whatever commands you
need to transport the character to the destination point:
Perhaps first an ordinary CMOVE to the closest edge of the
actual floors, and then OMOVE 0... to make the final part (up
the ladder, down the hole, or whatever).
Note: Remember, if you move the character outside the normal floor
area, you are in a bit of trouble if he must also be able to return: If
you click outside your unnamed exit, the normal floor system will
try to move the character the normal way, and if it is no longer in
any floor area... well, problems arise. They can be dealt with,
though, using some careful planning. The easiest way is to make
sure the player does not get the opportunity of clicking anywhere
before the character is safely back on a legal floor again! Some
clever use of a number of un-named exits together with
SHOWEXIT and HIDEEXIT commands may do the trick.
Q: I have the need for menu-style pictures with multiple user
options.
A: Yes, why not indeed? Just use EXIT: statements with no name/
description to define the clickable areas needed on screen, and then
ACTION: 0;... statements to handle the player input.
Or, define room objects that are actually buttons.
Or, use the multiple inventories and put your menu selecting in a
special inventory, then access them with some special "select"
command.
There's more than one way to fling an otter...
Q: I want a way to show the player's score at any time!
A: The neatest (and quickest) way is probably to put a "SCORE"
button in the command area using the VERB_ZONE: and
VERB_TEXT: statements in the graal.main file. VERB_TEXT:
allows you to define "direct verbs", that is, commands that do not
wait for or use an object. If you define a verb "SCORE" and make
that a direct verb, you can then use a TEXT command to display the
score held in a flag (preferably a room flag for room 0 - as mentioned
elsewhere, these make excellent "global flags").
Q: I don't quite understand the FLOOR: statements.
A: The best description is in graal.guide. Make sure you read ALL
the information about FLOOR: and PATH: there - it's even got
some diagrams! Then look at one of the rooms in the demo
adventure to put theory to practice.
Q: I'm trying to run the GRAAL editor and GRAAL in parallel, but
changes I make to the scripts in the editor do not seem to take
effect, even though I'm sure I have saved them to disk.
A: Check this:
1. You must exit the room / situation where updates were made
and then re-enter to force a reload of the scripts in question.
Alternatively, use the "Go to" button in the on-line monitor,
which also forces a reload.
2. You must have MAX_CACHE: 0 in graal.main before starting
GRAAL for this. Otherwise, an old copy of the script file still in
memory will probably be used instead of your updated version.
3. Changes to graal.main NEVER take effect without restarting
the game.
Q: After playing a tune with the TRACK command, samples played
with the SAM command get caught in a loop!
A: Naughty you - you have probably used the undocumented MED-
module feature of GRAAL! It can play MED modules (MMD0 and
MMD1 formats), provided you have the file extension ".med" in the
module name. However, this causes the above bug in the sample
routines to appear - this is Amos's fault. I know there exists an
Amos bugfix or work-around for this, but I DON'T HAVE IT. If
anyone has seen it, mail it pronto, and the med support will be
made official!
Q: The command area behaves strangely - it doesn't go away when
I tell it to in CUTSCENE commands.
A: You have probably not put it back correctly in a previous
cutscene. All sequences of events that start with either
CUTSCENE ...,NF or CUTSCENE ...,F must end with an
equivalent CUTSCENE ...,N or CUTSCENE ...,S. ALWAYS restore
the command area before doing a DSET - it may seem the DSET
restores it for you after the dialogue has ended, but not really 100%.
This goes for the COMAREA command, too. COMAREA OFF is just
another way of saying CUTSCENE "blank file",NF, and
COMAREA ON is equivalent to CUTSCENE "blank file",N
Q: The song I'm playing with the TRACK command doesn't stop
after playing through once, but starts over in a weird tempo.
A: Unfortunately, the tracker "stop song" command 0FFE stopped
working with the tracker command set I started using in GRAAL
2.1. Fortunately, there is a way around this: At the very end of the
song, put a blank block, and have that block repeat itself by putting
a tracker "jump" command (0B..) in it.
Q: 1. A scaled character changes its size when it starts moving/
stops moving.
2. A character following the controlled character is not of the same
size!
A: You have been unlucky with the way the 3D scaling zones (in the
room 3D: statement) coincide with the FLOOR: settings. There are
a number of things you can try to make it all look nicer:
1. Make sure the 3D zone boundaries are not set too close to a
"character position" like EXIT: points, START_POS: points or
object-handling positions. This gets rid of problem 1.
2. Make sure each floor is within one and only one scaling zone,
and add some space for the following character´s y offset
around the floor edges as well. Then connect the floors with
paths. This should get rid of problem 2.