# The &kappname; Handbook

Thomas
Friedrichsmeier

    tfry@users.sourceforge.net

2001
2002
2004
Thomas Friedrichsmeier
&FDLNotice;
17/02/2004
0.9.01

&kappname; is a silly little game, based on what I remember of Spacetaxi for the C64.

KDE
kdegames
Taxipilot

## Introduction

&kappname; is just a silly little game. It's based on what I remember of the Spacetaxi-game on the C64. The objective is to pick up passengers waiting on a number of platforms and to drop them where they want to go. That's basically it. Please report any problems or feature requests to the author.

## The &kappname; Story

It is the year 4017 A.D. - or rather, that's the official date, but after that terrible desaster at the temporal power plant in New New Atlantis, which still serves as a popular excuse for being late on any occasion, nobody is quite sure about that anymore. However in the year 3999, scientists agreed that the year 3999 could not be off by more than some 787.3 years in the past or 543.7 in the future with a confidence of some 94% and hence took the temporal statistical mean. Since hardly anybody has too positive memories of temporal statistics in school, that settled it for the great majority of people, even some (assumed) two centuries after the desaster experiencing enough troubles in measuring medium time-intervals to be seriously worried about the exact year.

So - it's the year 4017 A.D. and for people in our time trying to understand 41st century mentality is somewhat comparable to stone age man trying to make sense of a commercial for internet banking. This might for us be a good enough explanation, why in a time when nobody can even remember who invented teleportation there exists such an utterly useless job as a taxi-pilot.

It is noteworthy though, that even under those 41st century people that ever came to think about this, there exist at least a few thousand completely different explanations for this fact, none of which being accepted by more than a handful of people. Most people do however agree, that this must have to do something with the taxi-pilots having done something very, very bad in a past or future life to deserve such a pitiful fate (this particular view is of course only held by those believing in some flavor of reincarnation, but the general direction of thought is widely shared).

To pick out just one of the especially absurd views: While it is once again becoming more and more en vogue on the segwitch-parties of the would-be-intellectual to claim that the world is really just the thing that we see, and we can - among the dozens of virtual realities - positely and correctly perceive one as the real one, there is a few people still insisting that the whole world is just a big computer simulation and so are all live-forms in it.

When the founder of this school of thought, her name now no longer being named, one day proposed, that actually, there might be a world outside the simulating computer, with some people actually steering the simulation - and yes, even taking the role of a taxi-pilot - just for fun ... ... well, anyway, her name is no longer being named.

## Using Taxipilot

&kappname; is a game, and really you shouldn't be reading the instructions, but simply play. But then, here is a short description of how to play. At some points this description is rather vague, saying "may or may not" and the like. This is due to the fact, that much of &kappname;'s behavior is configurable.

The arrow-keys (or whichever keys you chose in the Settings) allow you to accelerate into any direction. Most levels will also have gravity, that will generally pull you downwards. You may however also be pulled to or pushed away from certain points in many ways, few of which have to do anything with real-life physics.

Some taxis have fixed landing-flaps, while other taxis can draw in and out their landing-flaps. Obviously you can not land without your landing-flaps fully lowered. But then, some taxis are not able to accelerate left or right with the landing-flaps out. The default key to toggle the landing-flaps is currently 'F'. It is inactive for taxis with fixed flaps.

Passengers will appear from time to time. Land on the platform they wait on and wait unitl they have boarded the ship. The "Destination:"-display on the bottom of the window will tell you, where the passenger wants to go. While the passenger is waiting to be delivered, you will see the "Tip"-display counting down. This is how much the passenger will give you in addition to the regular fare. If the tip is negative, the passenger will not even pay the entire regular fare. But you will never be paid less than nothing for your services.

Passengers differ both in the amount of tip they will maximally give to you and in their impatience. The tip will count down faster for very impatient passengers.

The regular fare consists of a fixed base amount, which may differ from level to level and an amount that increases every time you accelerate. Therefore the fare is fairly based on your fuel consumption for the trip. In order to make money, you should be fast however and earn some tips.

Watch your fuel! When it's empty, you will no longer be able to accelerate. Most likely this means that you will crash very soon. You may fuel your ship on special platforms, which will generally, but not necessarily be platforms where no passengers ever appear or want to go to. Fuel does have a price, though, you can't refuel without money.

Some levels will have teleporters in them. Teleporters may take you to any other teleporter or nowhere at all. Teleporters need not work both ways and not the same way. Some teleporters may cost money. You can only use them, if you have enough funds.

In order to complete a level you have to do a number of "successful" deliveries, i.e. deliveries that you do get a non-negative tip for. So this is another reason to hurry. The number of "successful" deliveries required may differ from level to level. Upon completion of some levels, you will be awarded an extra ship (life).

### More &kappname; features

As of the time of this writing, &kappname; is still laking more high quality levels, graphics and sounds. You can help here. &kappname; is highly configurable and allows you to create your own game data without having to recompile. See the developers sections for details on writing your own levels.

## Command Reference

### The main &kappname; window

#### The Game Menu

Ctrln Game New

  Starts a new game

Ctrlw File Stop

  Aborts the current game

File Pause

  Pauses the game, without leaving it

Ctrlq File Quit

  Quits &kappname;

#### The Settings Menu

Settings Select Mission

  Lets you select a (different) mission

Settings Configure Key Bindings

  Lets you change the key bindings

Settings Configure Taxipilot

  Here you can tune a few performance settings in order to make &kappname; run as good as possible on your hardware. Also you can turn sound on and off.

## Enhancing &kappname;

&kappname; is still very limited. Although the number of levels and passengers is growing, there's still far too many - not to mention that many of the graphics distributed so far are rather bad. However, &kappname; allows you to configure a whole lot of things without having to dig through the code and recompile. This chapter describes the four types of XML-based configuration-files that currently exist, explaining how you can create your own levels and other game-data.

As more and more features have been added and will continue to be added over time, this documentation, too, is growing more and more complex. I try to explain all the possibilities, but chances are you will never need all of those at once. Therefore, don't get frustrated with this lengthy description - probably you can get a good start by looking at the configuration-files provided with the distribution and later check back in the documentation to find out what possibilities there are and what exactly one attribute or another does. Comments on how to make this documentation more readable are always welcome.

Version 0.3.0 introduced some sanity-checks on the configuration-files you write. Image-files are checked for being existent and readable, the parameters you can specify have been assigned upper and lower limits (for numeric attributes), that should be wide enough to allow everything that might make sense (please let me know, if they aren't) but hopefully catch a few mistakes. Default values will be assigned for missing or invalid parameters. These default values sometimes make sense, sometimes they probably don't - so look for debugging messages. Debugging messages are printed to stderr, using 5 levels:

    0: Error               These are critical errors meaning that &kappname; will not be able to proceed with the
                               configuration selected.
    1: Serious Warning     A default value was inserted that probably doesn't make a lot of sense
    2: Warning             (default level) A default value was inserted that probably makes sense,
                               but you should still better fix this.
    3: Info                A default value was inserted where you are explicitly allowed to omit
                               parameters, or other harmless messages.
    4: Translations        A string was translated, a string could not be translated, a translations-file was not found...
                               may generate a LOT of output, that will generally only be useful for translators.

You may change the debug-level using the commandline option --debug-level (level) to change the verbosity. If your configuration does not work and you can't figure out the reason, try setting debug-level to 3. The default debug-level is 2, and I'd consider it good style for the configuration files, that no debug messages are generated at this level.

Before distributing a (large) mission, you may want to start &kappname; with the option --thorough_check, which will make it parse all configuration-files belonging to the mission thoroughly once the mission is selected (as opposed to parsing only the information needed at that time). This should output any errors, without having to go through all the levels.

### Types of attributes used in configuration of &kappname;

Configuring game-data for &kappname; essentially consist of specifying values for a number of attributes. This section briefly explains the kinds of attributes and how they will be handled.

#### Boolean (yes/no) attributes

One type of attribute used by &kappname; is boolean values, i.e. attributes that turn on or off a certain behavior. Think of them as answers to yes/no-questions. These questions can be "answered" either with "yes"/"no" or with "true"/"false". Both variants have the same effect.

#### Numeric attributes

There are two different types of numeric attributes used in the configuration of game-data: integer values (i.e. whole numbers; e.g. "42") and decimal numbers (e.g. "2.345"). While it is always possible to specify an integer value where a decimal number is expected, this is not possible the other way around. Most of the time it should be pretty obvious, whether a numeric attribute should be and integer or a real number (e.g. you can't start out with 3.54 lives). In the examples given, however, I tried to write all decimal-parameters with a dot to make things clear.

Whenever numeric attributes are read, only a certain range of values will be allowed. Check debug-output to see, whether you violated such a boundary. Generally, the defined range of allowed values makes sense and prevents you from accidently specifying nonsense values. Sometimes, however, those boundaries may be too strict for your purposes - in that case, please contact me.

#### String (text) attributes

Some attributes allow you to specify a string/text. E.g. the name of the level is a string. There's little to be said about this kind of attribute, except for that strings can be translated.

#### Filenames and file-lookup

While filenames are essentially strings, it is important to understand, where &kappname; tries to find those filenames.

All files install to the subdir "taxipilot/game_data/" (config-files) or of the KDE-Standard-data-directory (for me that's "/usr/share/apps/"). Whenever you put in a non-absoulte path in your configuration files, &kappname; will first try to find those files in (or rather relative to) the directory where the selected mission-configuration files resides. If the files can't be found there, &kappname; will append the given filename to the path given above ("/usr/share/apps/taxipilot/game_data" or similar) and check, whether the file can be found there.

What this means practically, is that you should state the file-names of your configuration-files as relative to the directory where your mission-file resides. Now, if you want to use some configuration- or image-files of the distribution (e.g. you want to create an own level, but want to use the passengers and taxi provided), you specify those file-names relative to the default installation-directory. Therefore, &kappname; will first check in your mission's directory and then fall back to the files provided with the distribution. (What you can not do, however, is to have some files of one single animation in your mission-directory and some other files of the same animation in the installation-directory!)

You may also use absolute paths in your configuration files. These will be left untouched, but I'd recommend to do so only for testing purposes.

Hopefully, things will get clearer, when you read on. Otherwise, please contact me.

### How to specify animations

One of the most important components of the game data are animations, i.e. sequences of images that the sprites (e.g. the passenger) cycle through. At some places, you will only want a single (static) image instead of an animation, but most of the time, this is still an animation, internally.

Creating an animation involves two major steps. First of course you'll have to create the single images (frames) that are to be displayed one after another. I can't help you much with this step, but you need to take care of the following aspects: a) You will generally want the animations to have some transparent regions (otherwise all sprites would always cover a rectangular space), and therefore you'll have to save the frames in a file-format that supports transparency - PNG is most likely the best choice. b) The frames have to be saved individually as name0000.png, name0001.png, name0002.png and so on in the correct order. Be sure to place these files under images or a subdirectory below images (see section on filenames).

The second step is telling &kappname; all it needs to know about these animations, including the options to be used during playback. This step will be described in detail, here. Let's first have a look at the basic syntax to be used:

      <tagname file_pattern="path_to_animation/name_of_animation_%1.png" frames="4" />

First note, that of course you won't write "tagname" in your configuration-files, but rather use the appropriate tagname needed to identify, what exactly the animation is to be used for. Which name to use will be detailed in the appropriate sections of this document. The next two parameters, however will be the same for all animations, you use:

The "file_pattern"-attribute takes as parameter the filename-pattern of your animation. Note that the "%1" in the pattern will be replaced with 0000, 0001, ..., to read the first, second, ... frame of the animation (see the paragraph above on how to name the files of your animation). As an exception, if an animation only consists of a single frame (i.e. is a static image), you can directly specify the filename of that frame (without the "%1").

The "frames"-attribute is used to specify the number of frames in the animation. Like the above parameter, the "frames"-attribute may not be omitted.

One further parameter which always be used, but is not mandatory: "anim_frame_period" may be set to an integer number of milliseconds that each frame of this animation will be shown. E.g. if you specify

      <tagname file_pattern="name_of_animation_%1.png" frames="4" anim_frame_rate="200" />

that means, that the animation will be played at 5 frames per second (this does not influence the rate at which the sprite is moved, only the rate at which its image changes). If changes from frame to frame are small, you can set this parameter relatively high, and still get a smooth animation (with less drawing).

Finally you can always use the attribute alpha:

      <tagname file_pattern="name_of_animation_%1.png" alpha="true" frames="4" />

The meaning behind this parameter is this: Usually &kappname; will strip any alpha-channel it finds off the graphics. This is done for performance reasons and most of the time, you really don't need true alpha-blending. In those place where you do need true alpha-blending (for instance if you want to create a moving semi-translucent cloud), you'll have to explicitely specify 'alpha="true"' for that animation. Keep in mind, that alpha-blending really is a performance hog on slow machines. So try to keep objects with alpha-blending small.

Additionally, there is a number of parameters influencing animations, that can only be used in some places (refered to in those sections as "additional parameters"):

"anim_oscillating" is a boolean attribute, that specifies, whether the animation is simply to be played from first frame to last frame (anim_oscillating="false"), or whether it is to be played from first frame to last frame, and then played reverse back to the first frame (anim_oscillating="true"). This option is available in most places, except for animations for teleporting.

"anim_continuous" is a boolean attribute, that specifies, whether an animation is to be repeated over and over again. This is only possible for some few animations, and for some further, it is the only possible setting. As an example, the animation of a passenger walking, is always continuous, since it can not be predetermined, how far the passenger will have to walk. For moving objects however, you may freely chose, whether the animation will be played continuously or only once.

"repetitions" is a lot like the above attribute, but takes an integer number of times that this animation will be played. E.g. it may be used for animating a waving passenger. If the passenger is to wave five times, instead of saving each frame five times, you can specify repetitions="5" and only need each frame once. This option is available in more places than the above, but naturally can not be used in conjunction with anim_continuous="yes".

#### Textual "animations"

Wherever you can configure an animation, you may also fill in a (static) text instead. Most of the time, this does not make a lot of sense, but if, e.g. you want to move a text-message through the screen, you'd probably use such a text instead of creating an image containing that text. This way, you make life a lot easier to potential translators, and also save a few bytes on your harddisk. Creating such a text works as follows:

      <tagname text="Sorry, this is it,\nthis is the last level!" align="left" valign="top" font="helvetica"
        r="10" g="255" b="150" max_width="300" max_height="50" break="true" smooth="true" align_handle="true"
    	text_period="500"/>

First of all, note, that once again "tagname" only stands for whatever tag-name is appropriate for this place in the config (same as for the other animations). The first parameter should be relatively obvious. "text" is a takes as value the string that is to be displayed. If you insert a '\n' inside this text, this will be interpreted as a (forced) line break. Automatic breaking/wrapping of lines can be achieved by setting the "break"-parameter to true (by default lines do not get wrapped).

You may specify horizontal and vertical alignment using "align" and "valign". Possible values for these attributes are "left", "center", "right" and "top", "center", "bottom", respectively. Note that the vertical alignment-parameter will generally not have any effect if "align_handle" is set to false (see explanations for "align_handle" below).

The "font"-attribute specifies the name of the font to be used (please keep in mind, that non-standard fonts might not be available on the player's computer), the color of the text to be displayed is given in RGB color-scheme using the integer parameters "r", "g", and "b".

Next thing to explain is the size-parameters. Unlike you might have expected, the font-size is not given as point-size, but rather as maximum width ("max_width") and height ("max_height") in pixels of the rendered string. The reason is that the same point-size may result in greatly differing actual sizes of the text on different systems, that e.g. use different font-resolutions. Using "max_width" and "max_height" then, you specify a rectangular region that limits the text. &kappname; will always try to use a font-size as large as possible, but will never exceed the given boundaries.

That said, the "smooth"-attribute may affect, whether &kappname; will try to come as close to the given boundaries as possible, or whether it will limit itself to point-sizes that can be displayed smoothly. The results of this parameter are not quite predictible. There are systems, that will by themselves refuse to scale fonts that are not available in a given point-size (i.e. will only ever use "smooth" fonts) and there may be systems that are able to scale fonts smoothly. Either way, if you're mostly concerned about getting the text to display smoothly, you should set smooth="true". If however, you're most concerned about the exact region covered by the text, use smooth="false".

Last but not least, the "align_handle"-attribute specifies, whether the coordinates given for the text (esp. in the context of moving objects) are interpreted as the top-left corner of the rectangle containing the text (like it would be the case for any regular graphics-file), or whether the "handle" is placed according to the alignment-parameters. E.g. with align="center" valign="bottom" align_handle="true", the "handle" would be places on the bottom center of the text. Experimentation may help understand what I'm trying to explain.

The "text_period"-attribute specifies, after what time the animation will be considered "complete". Most of the time, this parameter does not have any effect, it only makes sense for such animations, where something happens when the animation is over, such as teleporting-animations. Again: Most of the time you can forget about this parameter.

### How to specify sounds

Different from animations, sounds are always defined in a tag of their own. The parent of the tag defines, what the given sound will be used for. All animations may have a sound, but sounds may also be defined in some other place (i.e. not directly related to an animation). The general syntax is then:

      <some_tag parameters_for_this_tag="something" ... >
        <sound file="path_to_sound/sound_file.wav" ... />
      </some_tag>

The "sound"-tag has only one mandatory attribute: "file" specifies the filename of the sound to be played.

At some placed however, two sounds may be specified using "file_a" and "file_b" as parameters. The second sound is used when an animation is played in reverse direction (e.g. the animation for the passengers teleporting is played forward for disappearing and reverse for appearing). Since generally it does not lead to the expected results to simply reverse the sound, too, in those cases you may specify a different sound to be played when the animation is reversed. At most places only one sound is needed and even at places where two sound would make sense, if you specify only one sound, that will be used for both directions of the animation. As always, having a look at the configuration-files in the distribution and their effects, may help clarify the matter.

There are four more boolean parameters, which may modify the way, the sound is played. Those parameters will only be read at places, where they make sense, however.

"continuous" specifies, whether the sound is to be played continuously. This makes sense, e.g. for the sound played while a passenger is walking, i.e. for continuous animations. It means, that the sound is looped over and over again, so you don't need to create a very long sound-file.

"repetitious" specifies, whether the sound is to be played again and again with every repetition of the animation (which obviously only makes sense for repetitious animations) in contrast to only once.

"interruptable" specifies, whether a sound can be stop in the mid of a playback-cycle, or only at the end of a playback cycle. E.g. whenever a sound is a verbal statement, it is probably better, not to interrupt it, while if it is just some noise, it may be better to interrupt it at the same time that the animation is interrupted.

"pitchable" only applies to passengers, which, as you will see may play back animations at varying rates. This attribute specifies, whether the animation too will be sped up accordingly, or whether it will not be pitched. In many cases, it is more sensible, not to speed up the sound, but try for yourself.

### Configuration of missions

A mission is a succession of levels, using a number of passengers and a particular taxi. To illustrate what I'm trying to say, you might define several missions, which differ in the sets of passenger-sprites they use (like one with aliens, one with normal human beings, one with your favorite cartoon-characters). More importantly, you can define which levels (see below) the player will have to go through and in which order, so you can easily reuse a level you or somebody else already created for a different mission. Furthermore you may specify a (set of) taxi(es), that will be used throughout the mission.

Most of the parameters to specify are filenames, so be sure to read the appropriate section. Let's have a walk through an example mission:

    <!DOCTYPE mission_data >
    <document author="Thomas Friedrichsmeier" title="Mission 1" startscreen="mission1_start_screen.png" version="0.9.0">

The "author" and "title"-attributes should be self-explanatory. The values in those attributes are shown in the credits on the start-screen (see below).

The startscreen-attribute specifies an image file that will be used as a sort of welcome screen to your mission. Please make sure, you leave some blank space (preferrably some dark color) on the bottom of this picture, since this is, where the credits will be shown.

The image will not necessarily have to be in png-format, of course. Most common graphics-formats should work.

The version-argument will be used by Taxipilot to determine, whether it can use the mission at all. Enter the version number of the version this mission was designed for (or the lowest version of Taxipilot, you have successfully tested the mission with). If you leave out this parameter, the mission will not show up in the list of available missions.

    	<abstract>
    Simply enter a short description of the mission here.
    	</abstract>

Here you can give a short description of the mission, which will be shown in the mission-selection dialog. Include information such as how many levels there are etc.

    	<initials ships="5" />

This simply specifies, how many ships (lives) the player will start out with.

    	<levels>
    		<data file="level1.level" />
    		<data file="level2.level" />
    		<data file="level3.level" />
    ...
    	</levels>

The levels-section simply lists all levels in the oder they are to be played. These are just plain filenames for the level-description-files explained below.

    	<passengers>
    		<data file="passenger1.passenger" on_start_screen="yes" start_screen_x="55" start_screen_y="420" />
    ...
    	</passengers>

The passenger-section is basically the same, the difference being to the order of specification is irrelevant, since passengers appear in random order (and probably more than once each) during the mission.

The additional parameters specify whether the passenger will appear on the startscreen and - if so - where. Use this to make the startscreen a bit more interesting. If you omit those parameters, the passenger will not appear on the startscreen. Regardless of this setting, the passenger will always show up in the credits, though.

    	<taxis fuel_capacity="1000" initial_fuel="800">
    		<taxi file="taxi1.taxi" on_start_screen="yes" start_screen_x="55" start_screen_y="55" />
    ...
    	</taxis>

In this section you specify which taxis will be used throughout the mission. Obviously you will need to specify at least one taxi. Further you need to specify, how much fuel will be available to the taxis in this mission. The smaller the "fuel_capacity", the more often the player will have to refuel. The more "initial_fuel", the fuller the tank will be initially. The "start_screen"-related attributes work the same way as for the passenger.

    </document>

#### Using different taxis/passengers in different levels

Passengers are usually selected at random from the list of passengers you supplied. In contrast, by default, only the first taxi you specified will ever be used throughout the mission. If you want to control, which passenger(s) and which taxi get used in a particular level, you will first have to assign your taxis/passengers and id:

    	<passengers>
    		<data id="passenger_a" file="passenger1.passenger" ... />
    		<data id="passenger_b" file="passenger2.passenger" ... />
    ...
    	</passengers>
    	<taxis fuel_capacity="1000" initial_fuel="800">
    		<taxi id="taxi_a" file="taxi1.taxi" ... />
    		<taxi id="taxi_b" file="taxi2.taxi" ... />
    ...
    	</taxis>

Then in the "levels"-section you can specify for each level, which passengers/taxis should be used:

    	<levels>
    		<data file="level1.level" taxi="taxi_b" passengers="passenger_a;passenger_b;passenger_c"/>
    		<data file="level2.level" />
    		<data file="level3.level" passengers="passenger_d;passenger_e" />
    ...
    	</levels>

You can specify for each level, which taxi to use (only a single taxi may be used in a level). If you omit the "taxi"-attribute, the default (first defined) taxi will be used in that level. The "passengers"-attribute allows you to give a ";"-separated list of passengers which might appear in the level. If you omit the "passengers"-attribute, all available passengers will be used in that level.

### Configuration of passengers

Passengers are the creatures you have to transport around. They are easy to configure, but a lot of work to draw. Essentially a number of animations and sounds are specified.

Let's look at the configuration:

    <!DOCTYPE passenger_data >
    <document author="Thomas Friedrichsmeier" title="Mr. Right">

The "author"- and "title"-attributes will again be shown in the credits for the missions, this passenger appears in.

    	<idle>
    		<data frames="4" file_pattern="passenger1_idle1_%1.png" repetitions="5" anim_oscillating="true" />
    		<data frames="4" file_pattern="passenger1_idle2_%1.png" repetitions="8">
    			<sound file="passenger1/idle2.wav" repetitious="true" />
    		</data>
    ...
    	</idle>

For a detailed description of the parameters, see the sections on animations and on sounds. As indicated in the example, the animation takes the parameters "repetitions" and "anim_oscillating" (see section on animations).

For sounds, the following attributes will be read: "repetitious" (default=false), "pitchable" (default=true), "continuous" (default=false), "interruptable" (default=false) (see section on sounds).

You may define as many idle-animations as you like, but at least one. If you create more than one, the animation will be picked at random. Use frames="1" and a static image, if you don't want any idle animations.

    	<walking speed="0.6" frames="14" file_pattern_left="passenger1_walking_left%1.png"
    				file_pattern_right="passenger1_walking_right%1.png" anim_frame_period="100">
    		<sound file="passenger1/steps.wav" />
    	</walking>

This is the animation used for the passenger walking. Note that two file-patterns, "file_pattern_left" and "file_pattern_right" are expected for the passenger walking to the left and to the right, respectively. Of the additional animation-parameters, only "anim_oscillating" can be used. The animation will always be continuos.

The "speed"-attribute is used to sync how many pixels the passenger-sprite is moved, while its frames are animated. Unfortunately, this parameter may be a bit awkward. It specifies the number of pixels, the sprites is moved per 50 milliseconds, while the animation itself may use a completely different frame-period (as specified by "anim_frame_period" (Of course, the timings differ for passengers differing in impatience, but the relation between "speed" and "anim_frame_period" is not affected by this).

The available sound-attributes are: "pitchable" (default=true), "continuous" (default=true), "interruptable" (default=true).

    	<teleporting frames="10" file_pattern="passenger1_teleporting%1.png">
    		<sound file_a="passenger1/appear.wav" file_b="passenger1/disappear.wav"/>
    	</teleporting>

This animation is used whenever the passenger is teleporting, i.e. once, when the passenger first appears on a platform (played reverse), second, when the passenger disappears into the taxi (forward), and two more times for reappearing and disappearing on the destination platform. No additional animation-parameters can be used.

Since this animation gets reversed for (re)appearing, two sound files may be specified, "file_b" being used for appearing. The available sound-attributes are: "pitchable" (default=true), "interruptable" (default=false).

    	<still frames="1" file_pattern="passenger1_still0000.png" />

This animation is played while the passenger is doing nothing, i.e. is visible, but not busy. Most of the time, you'll probably just want to use a static image here (as shown in the example), but if you like, you can also use a regular animation. The only additional animation-parameter that may be used is "anim_oscillating". The animation will always be continuous.

This "do nothing" animation may also have a sound (not shown in the example). The available parameters are: "continuous" (default=true), "interruptable" (default="true") and "pitchable" (default=true).

    </document>

You may not omit any of the above sections. You may always use frames="1", a constant "file_pattern", and no sound in order to create a very simple passenger, however.

#### Further passenger-sounds

There are a few optional tags, used for sounds, that are not directly related to animations. Those are (as of version 0.8.5):

    	<hello>
    		<sound file="passenger1/hello_taxi.wav" />
    	</hello>
    	<goodbye>
    		<sound file="passenger1/byebye.wav" />
    	</goodbye>
    	<die>
    		<sound file="passenger1/ouch.wav" />
    	</die>
    	<abandoned>
    		<sound file="passenger1/abandoned.wav" />
    	</abandoned>

These sounds are played when the passenger has appeared, when it leaves the taxi after delivery, when it dies, and when it get's abandoned (i.e. taxi takes off again, before the passenger has boarded), respectively. For all these sounds, the only additional attribute that will be read, is "pitchable" (default="true").

### Configuration of the taxi

The taxi is the central sprite on the screen. It is - so to speak - you, the player. Just like the passengers from a configuration point of view, it is mostly a collection of animations. One noteable difference is, that for all animations, "file_pattern_left" and "file_pattern_right" may be used. I.e. the taxi may look different, depending on whether it is going (or was last going) to the left or to the right. You may however also simply use the "file_pattern"-attribute for taxis or animations that look the same in both directions. For simplicity, the given examples will use animations that look the same in both directions.

An here it is:

    <!DOCTYPE taxi_data >
    <document author="Thomas Friedrichsmeier" title="AirCab 301" >

Once again, the "author"- and "title"-attributes will be shown in the credits for any mission that uses this taxi.

    	<still frames="1" file_pattern="taxi1/still0000.png" />

This is the animation (or in this case still image) the taxi is doing all of the time (if not doing idle-actions or teleporting). Of the additional animation-parameters, only "anim_oscillating" (default="false") may be used. You may also specify a sound for this animation. Available sound-parameters are "continuous" (default="false") and "interruptable" (default="false").

    	<idle>
    		<data frames="6" file_pattern="taxi1/idle1_%1.png" repetitions="2">
    			<sound file="taxi1/idle1.wav" />
    		</data>
    		<data frames="5" file_pattern="taxi1/idle2_%1.png" repetitions="3" anim_frame_period="100" />
    ...
    	</idle>

Even while flying, the taxi may do "idle"-animations. So obviously this term is not quite correct, but it's in analogy to the passengers' idle-animations (see there for more in-depth explanation). The available additional parameters are: "repetitions" (default="1") and "anim_oscillating" (default="false") for the animations and "repetitious" (default="false") for the sounds.

You may define as many idle-animations as you like, but at least one. If you create more than one, the animation will be picked at random. Use frames="1", a static image and no sound, if you don't want any idle animations.

    	<flying_left frames="2" file_pattern="taxi1/flying_left%1.png">
    		<sound file="taxi1/fly.wav"/>
    	</flying_left>
    	<flying_right frames="2" file_pattern="taxi1/flying_right%1.png">
    		<sound file="taxi1/fly.wav"/>
    	</flying_right>
    	<flying_up frames="2" file_pattern="taxi1/flying_up%1.png">
    		<sound file="taxi1/fly.wav"/>
    	</flying_up>
    	<flying_down frames="2" file_pattern="taxi1/flying_down%1.png">
    		<sound file="taxi1/fly.wav"/>
    	</flying_down>

The meaning of these should be easy to guess. They change your taxi's appearance when you accelerate with the cursor keys. These are not independend images however, but really these images are just draw over the taxi image (so it can continue doing it's idle-stuff). Technically these are a different sprite. Have a look at the animations provided in the distribution, if you can't see, what I'm trying to say.

By the way, hitting something with these "flying-animations" doesn't crash your taxi, that means they are not to be understood as part of the taxi itself. They are however harmful to the passenger.

The available additional parameters are: "anim_oscillating" (default="false") for the animations and "interruptable" (default="true") for the sounds. Both sound and animation are always continuous.

    	<teleporting frames="10" file_pattern="taxi1/teleporting%1.png" />

This is really the same as for the passenger. See there for details.

#### Landing flaps

    	<landing_flaps offset_x1="3" offset_x2="30" />

This tag was introduced in Version 0.4.2, and specifies the x-positions of the taxi's landing-flaps (Is this the correct term? The poles, you stand on when landed, is what I mean) relative to the left corner of the taxi-sprite. If you omit this tag, the very left and right pixels of your taxi will be assumed as the position of the landing-flaps. This may result in the taxi crashing, when landing close to the platforms edges, while it actually looks to the player like the taxi is properly standing on the platform. So you should really specify these attributes.

Starting with Version 0.4.3 you may also create taxis with moveable landing-flaps. For those, the landing_flaps-tag would look like this:

    	<landing_flaps offset_x1="3" offset_x2="30" moveable="true" frames="6" file_pattern="taxi2/flaps%1.png" blocking="false">
    		<sound file_a="taxi2/flaps_out.wav" file_b="taxi2/flaps_in.wav"/>
    	</landing_flaps>

Note that the offset-attributes do NOT change their meaning in this context. The flaps-image is always aligned top-left with the taxi-image. Have a look at taxi2 and its images. The boolean attribute "blocking" specifies, whether you can still accelerate left/right with the landing-flaps out (false, default, if you are able to do so), or whether left/right-acceleration is blocked with the flaps out.

For the sound, note once more, that two sound-files may be given (as shown in the example), one for moving the flaps out and one for drawing the in. The animation, however, will simply be reversed (same as for teleporting).

For direction-dependend animations (i.e. using "file_pattern_left" and "file_pattern_right"), you'll possibly also want to adjust the "offset_x1" and "offset_x2"-attribute according to the direction. Simply use "offset_x1_left", "offset_x1_right" etc., if the x-position of your landing-flaps changes with flying-direction.

    </document>

#### Ommissions

You may not omit any of the above sections. You may always use frames="1", a constant "file_pattern", and no sound in order to create a very simple taxi, however.

#### Further taxi-sounds

Just like with the passenger, while sounds are directly associated with animations, a few others are not. Those "global" sounds are (as of version 0.8.5):

    	<crash>
    		<sound file="taxi1/crash.wav"/>
    	</crash>
    	<land>
    		<sound file="taxi1/land.wav"/>
    	</land>

... which should be rather self-explanatory.

### Configuration of levels

A level is... well, I don't think I have to explain this. Let's have a walk through a sample config-file.

    <!DOCTYPE level_data >
    <document author="Thomas Friedrichsmeier" caption="Plain Level 1">

The "author"- and "caption"-attributes should be self-explanatory by now. Only thing is, that here you have to specify "caption" instead of "title" for historical reasons. The "caption" is also shown in &kappname;'s window-caption when the level is on.

    	<completion deliveries="5" extra_life="no" />

This specifies, that you will have to complete 5 deliveries successfully (get a tip for the delivery) in order to compelete this level. Upon completion of this level you will not be awarded an extra life.

    	<image background="level_background.jpg" foreground="level_foreground.png" />

Every level may have a unique background, specified like any other filename (this is not an animation!). Choose .png or any other file-format, QT supports, e.g. .jpg should be a reasonable choice most of the time. The background image is not solid/harmful, you can fly right over it. Make sure it doesn't look too much like the real level.

The level itself is first of all a simple image with transparancies. You can fly over the transparency, you can crash into everything else (+ land on the designated platforms, see below). For right now, the level-image has to have a solid frame. Currently there is not other mechanism of keeping the taxi inside the visible area.

You may want to have a look at the background- and level-images provided. It's really not that complicated. The only restrictions on the size of level- and background-images is that they should have the same size and should not be too large for a user with, say 800x600-screen-resolution to display (take into account the space the game-displays take up).

Starting with version 0.4.2 you may however also create oversized levels. The syntax is as follows:

    	<oversize visible_width="640" visible_height="480" initial_offset_x="0" initial_offset_y="0" margin="80" />

This specifies that the portion of the level that will be visible to the player is 640x480 pixels (your level should of course be bigger than that, if you use this option), you will initially see the top-left corner of the level, and finally "margin"-means the distance the taxi may have to any side of the visible area, before the level is scrolled.

    	<platforms>
    		<data y="265" passengers="yes" has_fuel="no" x1="94" passenger_base_x="190" x2="194" />
    		<data y="265" passengers="yes" has_fuel="no" x1="236" passenger_base_x="240" x2="356" />
    		<data y="355" passengers="yes" has_fuel="no" x1="116" passenger_base_x="120" x2="195" />
    		<data y="355" passengers="yes" has_fuel="no" x1="234" passenger_base_x="240" x2="337" />
    		<data y="389" passengers="yes" has_fuel="no" x1="420" passenger_base_x="425" x2="585" label="Residential area" />
    		<data y="71" passengers="no" has_fuel="yes" fuel_price="0.1000" fuel_step="3" x1="440" x2="540" />
    	</platforms>

This section defines, where you can land in this level. Note that you can't land in the void. &kappname; first checks, whether you collided yith the level-image, and only after that, whether this means you're landed. Make sure the landing-areas are really even, otherwise you might get "stuck" on them. The "label"-Attribute allows you to specify, what Spacetaxi will call the platform. If you omit the label-Attribute, the Platforms will will be numbered in the order of their definition, starting with 1 (and called "Platform <number>". It's your job to provided the user with information (in the level-image), which platform is which. Also don't forget to provide valid information about where the pilot can land. Therefore I'd recommend to explicitely label all platform in the level image.

You have to measure (2 or 3 pixels error won't harm) the y-coordinates of the surface of the platforms (y), and the x-coordinates of the left (x1) and right (x2) boundaries of the platform. Make sure the platform is large engouh to land on it (the taxi has to be compeletely within the boundaries). Of course you should be careful with these measures, to make sure the player can land everywhere, they expect to.

You may find the command-line-option "--highlight" useful during development. What it does is draw a (yellow) horizontal line from "x1" to "x2" at height "y". So this allows you to see, whether you really specified the platform-coordinates correctly.

The remaining parameters specify, whether there are passengers waiting on this platform (or demanding to be taken there) (passenger, default is "no"), if so, where exactly they appear / disappear on (passenger_base_x) (y coordinates are always right on top of the platform).

Furthermore, you can specify, whether you will get fuel on this platform (has_fuel, default is "no") and what the price of a unit of fuel is. I guess it is generally a good idea to keep passenger- and fuel-paltforms separate, but you don't have to.

"fuel_step" specifies, how fast the taxi will be fueled, i. e. how many units of fuel (see taxi-configuration) will be fueled up per unit of time (50 msec). "fuel_step" can take integer values from 1 (pretty slow) to 8000 (should amount to instant fueling to max for about any taxi). Personally I'd think values from 2 through 6 to be reasonable, as long as you don't want this "instant"-fueling effect.

    	<gravity base_gravity="0.0" horiz_gravity="0.0">
    		<data x="640" y="480" gravity="100" potential="2" />
    		<data x="0" y="0" gravity="100" potential="2" />
    		<data x="640" y="0" gravity="100" potential="2" />
    		<data x="0" y="480" gravity="100" potential="2" />
    	</gravity>

You have control over gravity far more than physics would allow. The simple parameters "base_gravity" and "horiz_gravity" specify the simple downward / sideward pull, you would expect in any game like this (independend of you current position). Start exprimenting with values around 0.005. Of course you may use negative values in order to reverse direction.

The following tags are "centers of gravity". Those allow you to make the force acting on the taxi depend on it's current position on the screen. Obviously you need to specify the location of the center of gravity. Next is a constant of gravity. Reasonable values (double) for this constant may vary dramatically depending on the following parameter. Use negative values to achieve a "pushing away". The parameter "potential" affords you a lot of control.

The allowed values and their effects are:

0: force does not depend on distance (but direction of force depends on direction)

1: force depends on plain distance

2: "physical gravity" - force is reverse of distance squared

4: "dangerous spot" - force is reverse of distance to the fourth power

There is no value "3"! You may have as many centers of gravity as you like, but I'm afraid, having real lots of them could slow down the game on old machines. You may of course omit specifying centers of gravity.

    	<teleporters>
    		<data x="100" y="100" destination="2" fare="0" factor_x="1" factor_y="1" frames="1" file_pattern="teleporter1.png" />
    		<data x="200" y="200" destination="3" fare="0" factor_x="-2.5" factor_y="-2.5" frames="1" file_pattern="teleporter1.png" />
    		<data x="400" y="200" destination="1" fare="1.50" factor_x="0" factor_y="0" frames="1" file_pattern="teleporter1.png" />
    	</teleporters>

Have a look at level 3 of the current distribution, if you want to know, what teleporters do. They may have unique animations (always continuous, only additional parameter allowed is "anim_oscillating", and of course they need to be placed on some coordinates. The other parameters are as follows:

"destination": Teleporters are numbered in the order of definition starting with 1. You can only teleport from a TP and only to another TP. This specifies the number of the TP, you will arrive at. If you want a TP to serve as an arrival-point only, set this value to "0".

"fare": Teleporting may cost money. This parameter specifies how much. If you don't have engouh money, the TP will be inactive. So make sure, vital TPs don't cost anything.

"factor_x", "factor_y": These parameters might be very nasty, they change the speed (and direction) when you arrive. Putting these values to 0 will obiviously stop the taxi. Putting them to large values might be very dangerous to the pilot.

Since generally, the active-region of a teleporter is determined by whether the taxi touches the teleporter, if you want to have an invisible teleporter (or one where the active-region does not correspond to the image), you will have to additionally specify the parameters "width" and "height" (in pixels). For an invisible teleporter, you could then specify a transparent 1x1-image. You may not omit the file_pattern-parameter, however. As a matter of fact, specifying a "width" and "height" for your teleporter, may save some resources, since in this case no collision-detection needs to be performed.

You may of course omit the teleporters-section, if you don't want any teleporters.

    	<tips min="10.00" max="30.00" />

This simply specifies the range of tips, passengers may start out with...

    	<fare base="5.40" step="0.050000" />

... while this parameter is used to control the taxi-pricing. "base" is the base-fare, "step" determines, how fast the fare will increase.

    	<initial_position x="50" y="50" />

Finally, this is, where the taxi starts out at in the level.

    </document>

#### Bringing life to your levels: Moving objects

Version 0.5.0 finally introduced support for moving objects in the levels. As of this version, there is still a lot to do, but also, a lot of flexibility is implemented already. And here is how that works:

    	<objects>
    		<object class="background" frames="5" file_pattern="some_object%1.png"
    				z="90" anim_frame_period="50" looping="yes" initial_vx="10" initial_vy="10" >
    			<path x="100" y="100" time="500" accel="linear" />
    			<path x="110" y="100" time="500" accel="abrupt" />
    			<path x="130" y="100" time="500" accel="linear" />
    			<path x="140" y="100" time="500" accel="linear" />
    			<path x="170" y="100" time="1500" accel="linear" visible="no" />
    		</object>
    		<object class="harmful" frames="10" file_pattern="another_object%1.png" looping="no" z="90" >
    			<path x="100" y="100" time="5000" accel="linear" />
    			<path x="100" y="300" time="5000" accel="linear" frames="5" file_pattern"animation_override%1.png" />
    			<path x="100" y="400" time="5000" accel="linear" />
    		</object>
    	</objects>

So first of all an objects may belong to different classes. Two basic classes are supported: Either the object is "harmful" i.e. you crash when you collide with it, or "background" i.e. it does not do anything to you, and is merely decoration. There is a number of special classes, which will be dealt with in the next section. Then of course, an object has an image or animation as described in the section on animations. The avaialbe additional parameters for the animation are: "anim_continuous" (default="false"), repetitions (default="1") and "anim_oscillating" (default=false). For moving objects, the ability to create textual "animations" might be especially interesting.

Of course, the animations may also have sounds, with the additional parameters "continuous" (default="false"), "repetitious" (default="false") and "interruptable" (default="false").

Further, you may specify the z-Position of the object. The higher the value, the closer is the object, i.e. it will cover objects with a lower z, when the two overlap. BTW, the taxi is at z="75", the level at z="50", passengers at z=40". Of course the object can not be behind the level's background, however.

An object may either be "looping" (going from A to B to C to A) or "bouncing" (going from A to B to C to B to A and then back). Note that this also affects the way that the last path-segment is treated. For looping objects, it will be taken as the way back, i.e. the first object above will be invisible for 1.5 seconds and return to the position 100/100 during that time. For bouncing objects, the way is the same in both directions, so here the last path-segment describes the way the object takes starting from the last key-position, until it reaches that same key-position again. So it will spend 5 seconds in the third path-segment and then go back to the second.

You may specify an inital speed for the object. This only has an effect, if the first segment of the path has accel="linear" given. See below.

Next we will have to specify the path of the object: Therefore we define key-frames, with starting-coordinates, time needed to reach next key-point (milliseconds), mode of acceleration, and whether it will be visible on the way (while invisible it is never harmful).

There are three possible modes of acceleration:

accel="abrupt": The object moves from the starting-coordinates of the current path-segment to the startin-coordinates of the next at a constant speed on a straight line. Therefore the speed and direction of the object may change abruptly with respect to the previous path-segment.

accel="linear": The object starts out with the speed and direction it had on the last frame of the previous segment of the path (or with initial_vx and initial_vy). It then uses just that constant acceleration that will make it arrive at the next key-position in the specified time. Most of the time this should give nice smooth movements.

accel="custom": The tough way, but of course the one with the most flexibility. If you specify accel="custom", you may also specify the parameters "vx" and "vy" (starting velocity (in pixels per second)), "ax" and "ay" (starting acceleration in pixels per second squared) and "dax" and "day" (change in acceleartion over time in pixels per second cube). Of course you don't have to specify all these. Any parameter you omit will be assumed to be zero. Therefore, if you omit "ax", "ay", "day", and "dax", you will get a movement with a constant velocity "vx" and "vy". Using this mode, it is entirely your responsibility to make sure that using these parameters, the object will reach the next key-frame in the specified time. If it does not, it will simply be put there, making the object jump. So this is for those who love maths. Even in this mode, if you specify a "bouncing" object, the way back will be exactly the reverse of the way forth.

Finally you can override the animation used in any path-segment.

I admit, this is quite complex already, but as always, you can start out with simple objects and slowly experiment with more difficult ones.

#### Everything's moving now: Special moving objects

Version 0.5.1 greatly extends the support for moving objects in the levels. You can now also define platforms, teleporters and centers of gravity to be moving objects. In order to do so, first of all you assign an identification label to the platform/teleporter/center of gravity (example for a moving teleporter):

    		<data ident="tp1" destination="2" fare="0" factor_x="1" factor_y="1" />

Of course now, you do not need to specify a (static) x- and y-position and also, you don't have to specify the animation parameters ("file_pattern" etc.). After all, the teleporter now is a moving object, that may change it's position and appearance.

Note: You may of course mix "normal" and "moving" teleporters in the teleporters' section.

Next, the teleporter needs to be tied to a moving object. You do this simply by declaring an object to be of class "teleporter" and having the same idenification label you used when defining the teleporter:

    		<object class="teleporter" frames="5" file_pattern="some_object%1.png"
    				z="90" anim_frame_period="50" looping="yes" ident="tp1" >
    			<path x="100" y="100" time="500" accel="linear" />
    			...
    		</object>

Everything else works the usual way. So, to sum it up, you define the parameters specific to a teleporter in the teleporters' section and those specific to a moving object in the object's section, then you tie both sections together with the "ident"-paramenter.

Note: The one thing that is different is, that x- and y-position-parameters for a (normal) static teleporter are interpreted to be the center of the image, objects' positions always refer to the top-left corner of the image!

For moving platforms and centers of gravity, the procedure is basically the same. What is left to be said is that objects tied to centers of gravity may either be defined with class="harmful center" or class="harmless center". Obviously, the two differ in whether the taxi can crash into them. Also obviously, the x- and y-position-parameters (in the definition of the center of gravity) are not interpreted for moving centers.

Moving platforms still take the "x1", "x2", "passenger_base_x" and "y"-paramenters. For moving platforms, those parameters are interpreted as relative to the top left of the image of the platform. The belonging moving object has to be classified as class="platform".

Finally, it needs to be said, that the "tying up" of platforms/teleporters/centers of gravity with moving objects fails, the object does not have the same "ident"-parameter, or if it is not classified appopriately. You can only ever tie up one of these functions with a single moving object, and you cannot tie several moving objects to one function.

As always, having a look at the configuration-files provided might help understanding the procedure.

#### Advanced level programming: Events and States

An arcade game of this sort, without doors and switches? Of course not! Version 0.7.0 introduces a framework for creating doors and switches and eventually many other things. Not everything that this framework allows for has been implemented yet, but new features are soon to follow.

Let me start by giving you a general overview of "events" and "states": A "state" is basically a variable which may either be on or off. E.g. you might have a state labled "door_open", which may either be on or off, and of course a door (a moving object) which will act according to this state (how to accomplish this will be described some paragraphs below).

The whole thing would of course be pointless, if the "door_open"-state would never change. Changing states is accomplished by events. Think of events as actions, which may be triggered when something happens. As of version 0.7.0, there is only one sort of objects, the "hot_area", which can fire events, but eventually platforms will be able to trigger events, when you land on them, when a passenger appears on them, teleporters, when you arrive at them...

So actually, opening a door is not all that easy to do: You need a moving object, that depends on a state, a state, which it depends on, an event, that changes the state and finally something to trigger the event. This framework does however allow for a maximum of flexibility. Let's have a more detailed look:

##### Syntax of "States"

The syntax for declaring a state is relatively straightforward. All state-declarations are grouped together in a "states"-tag and individual "states" are given a label ("ident") and initial value ("initial"):

    	<states>
    		<state ident="door_open" initial="off"/>
    		<state ident="some_other_state" initial="on"/>
    	</states>

##### Syntax of "Events"

Similarily events are grouped in an "events"-tag and of course also need a label. Events, generally, also change some state(s), which is accomplished via a "change"-tag:

    	<events>
    		<event ident="toggle_door">
    			<change state="door_open" to="toggle"/>
    		</event>
    	</events>

What happens in this example is, that the event, when triggered, changes the state "door_open" to is opposite value, i.e. to "on" when it was "off" and vice versa. Of course you may also specify to="on" (or to="off"), if you want your event to only open (close) the door.

This, however, isn't all there is to events. You may make the execution of your event depend on a condition. E.g. you might have a state "door_can_be_opened", which is to control, whether your "toggle_door"-event takes any effect. In the following example, if "door_can_be_opened" is "off", and the event "toggle_door" is triggered, nothing wil happen, because the condition is not met:

    		<event ident="toggle_door">
    			<condition>
    				<requires state="door_can_be_opened" to_be="on"/>
    			</condition>
    			<change state="door_open" to="toggle"/>
    		</event>

The "condition"-syntax is described in more detail, below. There may be only one condition-tag per event, but it may involve several states.

Events may also be associated to (single-shot) sounds:

    		<event ident="toggle_door">
    			<condition>
    				<requires state="door_can_be_opened" to_be="on"/>
    			</condition>
    			<change state="door_open" to="toggle"/>
    			<sound file="unlock_sound.wav"/>
    		</event>

Another thing, that can be done in events is to trigger some further events. E.g. you could have two doors, A and B, and you want door B to get shut, whenever door A gets opened, but not necessarily the other way around. You could accomplish this using the following two events:

    	<events>
    		<event ident="open_door_a">
    			<change state="door_a_open" to="on"/>
    			<child_event ident="close_door_b"/>
    		</event>
    		<event ident="close_door_b">
    			<change state="door_b_open" to="off"/>
    		</event>
    	</events>

What's left to say is that each event may have only one condition-tag and any number of "change"- and "child_event"-tags. When the event gets triggered, first the condition (if any) will be checked. If the condition fails, nothing will happen. If the condition is fulfilled, the event will process all "change"-tags in the order they are specified. Only after that all "child_event"s will be triggered in the order the appear in the config. Triggering means, that the "child_events" will each be processed fully one at a time. I.e. if you have an event A with child-events B, C and D, and C has child-event E, first A will be triggered, then B, then C, then E and only then D. (This is just to confuse you, probably you'll never need to know about it).

Note that events perform strict checking for recursions. If an event notices, that it is called again (from some child_event), before it has finished all its actions, it will ignore that call and output an error message. Whenever timers do get implemented, you will however be able to have a recursion with a certain delay between each cycle.

##### A closer look on conditions

Conditions are not all that complicated, but since they may appear in several places, they deserve a section of their own. A condition is really a sequence of "requires"-tags with all the specified "state"s required to be in the specified state. All "requires"-statements have to be fulfilled at once. They therefore constitue a logical AND.

    			<condition>
    				<requires state="has_key" to_be="on"/>
    				<requires state="can_handle_key" to_be="on"/>
    				<requires state="key_broken" to_be="off"/>
    			</condition>

##### Hot Areas

Starting with version 0.7.2 there are a number of other ways to trigger events besides "hot_areas". Those other ways will be discussed later, since "hot_areas" probably the most important way. Hot "area"s are rectangular regions on the screen (invisible by themselves) which can trigger events, if the taxi touches ("touch_event", stops to touch ("untouch_event"), enters ("enter_event") or leaves ("leave_event") this region. Note that hot-areas currently don't perform an exact check for these events, i.e. do no real collision-detection, but merely check, whether the bounding-rectangle of the taxi-sprite touches, enters, ... the area. I believe this is a reasonable compromise with performance. One helpful thing when creating levels with hot-areas is the commandline-option --highlight, which not only hightlights the platforms as mentioned above, but also oultines the hot_areas, so you can see, whether they are positioned correctly.

The following example should illustrate the syntax. Note that all hot-areas in a level are grouped in a single "hot_areas"-tag (analogous to events and states).

    	<hot_areas>
    		<area x1="558" x2="640" y1="0" y2="68" enter_event="unlock"/>
    		<area x1="0" x2="78" y1="320" y2="340" touch_event="toggle_left_door" untouch_event="toggle_left_door"/>
    		<area x1="0" x2="78" y1="354" y2="375" leave_event="close_all_doors"/>
    	<hot_areas>

##### Conditional behavior in Moving Objects

So far events and states have remained dry theory, with no visible results. The ultimate purpose of "states" is of course that they affect the behavior of objects in the game. Moving Objects are the first kind of objects that can have conditional behavior. You can add special actions to each path-segment, that will be processed at the end of that path-segment. Lets have a look at a concrete example:

    		<object frames="1" file_pattern="objects/door.png" class="harmful" z="1" looping ="true">
    			<path x="84" y="343" time="500" accel="abrupt"/>
    			<path x="0" y="343" time="50" accel="abrupt">
    				<stop>
    					<condition>
    						<requires state="door_open" to_be="off"/>
    					</condition>
    				</stop>
    			</path>
    			<path x="0" y="343" time="500" accel="abrupt"/>
    			<path x="84" y="343" time="50" accel="abrupt">
    				<stop>
    					<condition>
    						<requires state="door_open" to_be="on"/>
    					</condition>
    				</stop>
    			</path>
    		</object>

What this example is meant to accomplish is to have a door that will be in x-position 0 when the state "door_open" is "off", and in position 84 when the state is "on". In the example, the door will start out opened (at x 84) and move to closed from the first to the second-path-segment. Next, it will move all the way of the second path-segment, which actually simply tells the door to remain in place for a brief period of time. At the end of the second path-segment, however a "stop" is to be processed. This "stop" tells the object to simply wait without moving as long as the given condition is fullfilled, i.e. as long as "door_open" is "off".

If "door_open" happens to be "on" when the object finishes the path-segment, it simply moves on to the next segment, like it normally would. If "door_open" is "off" however, it will not continue to move until "door_open" changes to "on". It is important to understand, that the object will only ever stop at the end of a path-segment, never in between.

There are three more tag besides "stop" that version 0.7.2 supports: "freeze", "trigger" and "jump". "freeze" is used in exactly the same way as "stop" and does almost exactly the same thing (stop the object), but also stops any animation the object might have. "trigger" and "jump" will be discussed below.

A few things remain to be said about conditional movements. First, you may have wondered, why I specified four path-segments for really only two positions. The reason is that at the end of a path-segment, the object is generally some way before reaching it's target position. The next key-position will only be reached at the start of the new path-segment. Therefore, if you want very exact control over where the object stops, you should insert "dummy-path-segments", where no movement occurs. Second, you should note, that the "linear"-accel mode does not work as might be expected over a "stop". Rather, the object will come to an abrupt halt if it is to stop, and when released, starts with the speed it would have had, if there had been no "stop"-tag in between. This is because the movement-velocities are calculated beforehand, not during the game. Therefore, you should make sure not to introduce stops at points where the object would normally be moving very fast - that would simply look awkward. "jump"s, discussed below give you a neat way to circumvent this limitation.

The syntax for "jump"s is basically the same as for "stop"s:

    			<path x="0" y="343" time="50" accel="abrupt">
    				<jump target="5">
    					<condition>
    						<requires state="go_somewhere" to_be="on"/>
    					</condition>
    				</stop>
    			</path>
    			...

What a "jump" does, is that - if the condition is met - the object will continue it's movement at the specified "target". Target is the number of a path-segment for this object (path-segments are counted starting with 1). So in the above example, if the state "go_somewhere" is "on", instead of proceeding to the next path-segment, the object will continue it's movement at the fifth path-segment. Any further actions like "stop"s or other "jump"s that follow the "jump"-tag will be ignored, if the jump-condition is met. If it is not met, the "jump"-tag will simply be ignored.

It might not be easy to understand the "jump"-tag, but it is indeed very powerful, giving you the option of not only stopping an object, but making it move entirely differently. If you are familiar with a programming language that has GOTO-statements, it will probably help, thinking of "jump"s as GOTO-statements.

Two things remain to the said about jumps. First, &kappname; will not take them into account when doing path-calculations (when putting meaning to accel="linear" or accel="abrupt"), and instead calculate acceleration-rates as though the path would continue normally. In many situations it will therefore be adviseable to use accel="custom" for best results.

Second, when using "bouncing" objects, there will internally be twice as many path-segments than you specified (for the way back). You are allowed to address those in the "target"-attribute, making your object jump to a position on the way back. E.g. you might have an object going for A to B (path-segment 1) to C (2) to D (3) to E (4), then bouncing back to D (internal segment 5) to C (6) to B (7) to A (8). Now you could insert a jump between after 2 (when the object has arrived at C) with target="7". Then if the jump-condition is met, the object will jump to the path-segment taking it back form C to B, i.e. effectively return back before going to E.

Finally the "trigger"-action can be used to trigger an event, when the object arrives at a certain key-posiiton:

    			<path x="0" y="343" time="50" accel="abrupt">
    				<trigger event="do_something">
    					<condition>
    						<requires state="inform" to_be="on"/>
    					</condition>
    				</stop>
    			</path>
    			...

Here, after the object finishes the path-segment, the event "do_something" will be triggered. This might be useful for syncing the movement of several objects. As with all other types of actions, the "condition"-tag is mandatory.

As always, having a look at the level-files in the distribution might be more instructive than this document. Go ahead and try, e-mail me, if you experience problems or find bugs!

##### Further ways to trigger events

Version 0.7.2 of &kappname; introduced a number of additional ways of firing events.

###### Platforms

Platforms may signal four different events: (1) The taxis has landed on the platform (2) the taxis has taken off (3) a passenger appeared on the platform (3) a passenger has left the platform. Using these events is really rather straight-forward:

    	<platforms>
    		<data y="100" passengers="yes" has_fuel="no" x1="100" passenger_base_x="110" x2="140" label="Special platform"
    				land_event="do_something" take_off_event="do_something_else"
    				arrive_event="yet_another_event" leave_event="and_another_one" />
    		...
    	</platforms>

So this platform would fire four different events in the four above-mentioned cases.

###### Teleporters

Teleporters can trigger event, when (1) the taxi gets teleported away from this teleporter and (2) the taxi gets teleported to this teleporter:

    	<teleporters>
    		<data x="461" y="273" destination="2" fare="0" factor_x="0" factor_y="0" frames="1" file_pattern="teleporter.png"
    				arrive_event="open_door" leave_event="close_door" />
    		...
    	<teleporters>

###### Timers: Delayed events

Timers essentially behave like events and are defined and used in much the same way. The difference being that when triggered, the timer will not immediately do it's stuff (checking it's condition, then changing states and firing child-events), but rather wait for a specified period of time before doing so. Let's have a look at the definition of a timer:

    	<timers>
    		<timer ident="timer1" period="500" triggered_while_active="restart" loop_state="some_state" trigger_initially="true" >
    			<condition>
    				<requires state="door_can_be_opened" to_be="on"/>
    			</condition>
    			<change state="door_open" to="toggle"/>
    			<child_event ident="some_event_or_timer"/>
    		</timer>
    	</timers>

So first of all, you should note, that a timer takes all the attributes and tags that a normal event does. In fact it internally is an event, and whereever you are allowed to specify an event to be triggered, you could specify a timer in exactly the same way. The additional parameters for a timer are:

"period": The duration of the delay in msecs.

"triggered_while_active": Specifies, what will happen, when the timer is triggered, while it is already actively counting down. Possible values are (1) "ignore" (default), the timer will simply ignore the triggering and continue counting down (2) "restart", the timer will start over with the count-down (3) "stop", the timer will be stopped.

"loop_state": Here you may specify the name of a state, that controls, whether the timer behaves as a single-shot-timer, i.e. stops after it has finished it's countdown and done its actions or whether the timer starts over automatically. The default is to behave as a single-shot-timer, but if you specify a valid state, each time the timer finishes it's countdown, it will check the specified state and restart itself if the state is set to "on".

"trigger_initially": Controls, whether the timer will be triggered initially (when the level is started). Default is false/no.

##### Further ways to use states

Besides affecting the movement of moving objects, states may control a few other things:

###### Teleporters

States can be used to (de)activate teleporters, i.e. to control (1) whether the teleporter will take the taxi anywhere and (2), whether a taxi can be teleported to the teleporter:

    	<teleporters>
    		<data x="461" y="273" destination="2" fare="0" factor_x="0" factor_y="0" frames="1" file_pattern="teleporter.png"
    				arrive_state="state1" leave_state="state2" />
    ...
    	<teleporters>

So, if "state1" is "off", you can not teleport to this teleporter, i.e. all teleporters that have this teleporter a their destination will be blocked. If "state2" is "off", the teleporter itself is blocked, i.e. will not take you anywhere (but depending on "state1" you can still arrive on it).

###### Centers of Gravity

The attribute "active_state" allows you to specify a state that controls, whether the center-of-gravity is active (i.e. attracting or pushing away the taxi). This way, you can turn on and off centers-of-gravity:

    	<gravity>
    		<data x="320" y="240" gravity="200" potential="2" active_state="has_gravity"/<
    ...
    	</gravity>

## How to translate &kappname;

Translating the actual application should not be different from compiling any other application. However, since all the levels are defined in seperate file that are read at runtime (and may contain language-specific strings), you should provide translations for the strings in those files, too. Here's how to do so (version 0.7.1 and above):

Somewhere in cdp.cpp there is an i18n()ed string "en_US", that you will have "translate" to your language code (e.g. "fi" or "de"). Now, whenever &kappname; starts parsing a configuration file, it will try to find a translations-file with the language code as a filename-extension. I.e. when &kappname; reads the file "level1.level", and your language code is "fr" it will look for a file called "level1.level.fr" (in the same directory). If it doesn't find this file, all strings in "level1.level" will be used untranslated.

If &kappname; does find the translations file, it expects it to look like this:

    some string to be translated:::::translated version of the string
    another string that should be translated:::::translation for that one
    ...

I.e. you simply list those strings that should be translated, five colons and then the translated version. Order of the strings is irrelevant, but be sure to copy the left-hand-side (i.e. the not yet translated strings) exactly as they are, since otherwise &kappname; will not be able to match them to their translations. There is no need to translate strings, that are not shown to the user, or are the same in your language. If the translations-file does not contain a certain string of the configuration-file on the left-hand-side, the string will be used untranslated.

Although this is not exactly good style, there are a number of images that contain language-specific information (i.e. strings that are realized as graphics). Although of course, it's a lot harder to translate those, you can do so, by simply "translating" the filename of the image. I.e if the file "levelx.png" contains text, you could edit that image, save it as "levelx.fr.png" (leave the extension ".png" untouched!) and add a line

    levelx.png:::::levelx.fr.png

in the translations-file.

When done, you should test your translations, and especially have &kappname; parse all config-file thoroughly, to make sure you did not break anything (command-line option --thorough_check). In case you get unexpected results, try the command-line option --debug-level 4 , which will generate a lot of output, among other things listing all the strings &kappname; translated (or failed to find a translation for). A basic understanding of &kappname;s configuration files (see previous chapter) will probably help in deciding, which strings should be translated and which should not.

## Questions and Answers

&reporting.bugs; &updating.documentation;

Why aren't there any questions in this faq?

'Cause I haven't yet been asked any. Go ahead and contact me in person.

## Credits and License

&kappname;

Program copyright 2001, 2002, 2004 Thomas Friedrichsmeier tfry@users.sourceforge.net

Documentation copyright 2001, 2002, 2004 Thomas Friedrichsmeier tfry@users.sourceforge.net

Many data files (levels, graphics etc.) - and about all of the better looking ones - have been contributed by other people. Have a look at the respective configuration-files or the credits displayed on the startscreen for information on who created (and owns the copyright) on those. Also take a look at the Acknowledgments Section.

&underFDL;

&underGPL;

## A note to anybody who read the code

This is my first KDE-App. As a matter of fact, it is my first C++ or even object-oriented program. Actually it is my first program to ever really see the light of the world (although some small programs and scripts do good deeds in their niches).

So if you look at the code, there's probably a whole lot of silly things in there, not to mention, that the documentation could be better. Please don't blame me for it - give me a hand, show me how to do it right. I'd really appreciate your comments.

Some three months after I wrote the above two paragraphs, I might add that as the code keeps growing, inconsistencies keep creeping into the API. Also, while I trie to documentate each new function I create, I'm afraid some functions have changed in lots of little ways, without the API-documentation reflecting those changes. I've even been playing with the thought of rewriting some classes entirely. But then, if I had that time...

## Acknowledgments

I'd like to thank (in oder of addition):

- Josef Spillner for several helpful comments and suggestions early on

- Stefan Bruens for a number of bug-reports and useful suggestions, and for being the first person to contribute a level

- Joe Bolin for contributing some high quality graphics/levels and for many good suggestions

- Stefan F. Raab for contributing some high quality graphics/levels and testing

&documentation.index;