Some more or less unsorted implementation details. Some comments
are included in [].


1) Collectables
===============
A collectable is an object used once in each kart. It stores:
- a type (e.g. zipper)
- an icon (displayed in the gui)
- a number (how many of this items have been collected)
- can have a model (for missiles etc). 
The information about collectables is stored in several data files
(data/*.collectables, and data/*.projectiles). The mapping from
collectableType to data file is currently hard-coded in 
CollectableManager (look for initCollectableType and ict).

When a red herring is hit, Collectable::hitRedHerring for
the collectable being used in the current kart is called. When a
collectable is used, Collectable::use is called from PlayerKart::update
or AutoKart::update.

The collectables can have different styles, for example, in some tracks
they can look like a fish and in others like a box with a question mark. 
All herring models are stored in models/herrings and are loaded at the
start of the program. The only exception are the original fish models,
which are created within tuxkart. They can be specified by using the
special model names; OLD_GOLD, OLD_GREEN, OLD_RED, and OLD_SILVER.
The herrings to use are defined in herring style files in 
data/*.herring - for example:

(herring
  (gold   "goldcoin")
  (silver "silvercoin")
  (green  "OLD_GREEN")
)

This would use the new coin models for the energy boosters, but the
old green for bad collectables. Since no value is specified for
red herrings, the system default will be used. 
The program can load up to 4 different style. First of all it loads
the (hardcoded) defaults (which are the newly defined models in
models/herrings). Then it will a user specified model (using the
--herring command line option). Then it will load a herring file 
specified in the track, and if a grand prix is used, it will load
the grand prix specifications last. This means, that a grand prix
setting will overwrite a track setting, which in turn will overwrite
a user setting, which will overwrite the defaults. This way a grand
prix can specify a consistent style.

To create a new herring model:
1) create the model and put it in models/herrings
2) create a herring style file in data/*.herring,
   which specified for which to use the model.
3) Then either specify the name of the new herring style file
   on the command line option (which will then become your
   new default, since it will be loaded), or add it to a track
   or cup file in data (as  (herring "new-name-without-extension")

2) Projectiles
==============
Projectiles inherit from Moveables. The projectile_manager
maintains a dynamical list of unused projectiles (deletedProjectiles).
If a new projectile is needed (because of the use of a collectable):
- one projectile from this list will be used (and removed from
  this list) if one is available,
- otherwise a new one will created.
The new projectile is added to the list activeProjectiles, see 
ProjectileManager::newProjectile. When the projectile hits
something, the 'somethingWasHit' flag gets set. This flag
get tested after updating (i.e. moving) all projectiles from
ProjectileManager::update. In case of a hit, a new explosion
object is used (similarly from either a list of unused explosions
or created newly, see ProjectileManager::newExplosion), the
projectile is removed from the scene, and put in the dynamical
list of available projectils for later reuse (deletedProjectiles).
The speed and model of the projectile are taken from the
collectable_manager (who takes this information from the files
data/*.projectile).
[Note: this design is a little bit awkward, since not all 
collectables have/need speed. A more complicated implementation 
might make the ProjectileManager inherit from the CollectableManager,
... - but on the other hands, that makes (imho) all further handling
more complicated: e.g. depending on whether the collectable is
a missile or not, different managers have to be called ...]


3) Default parameters 
=====================
All default parameters (mostly physics related, including default
kart properties) are stored in data/physics.data, and managed by
PhysicsParameters, which has KartProperties as a base class, so it
can automatically store all kart data as well.
This class checks if all necessary parameters are defined, so 
missing data in data/physics.data will be detected.
To add another parameter:
1) add the parameter to data/physics.data
2) add a variable to PhysicsParameter.h
3) add a call to list->get to PhysicsParameter::getAllData
4) add an initialisation to PhysicsParameter::init_defaults
   (this value if possible should be <-99, since this is used
   to detect missing values. If this value should be a valid
   value for the new parameter, find something else and adjust
   the test in PhysicsParameters::load accordingly).
5) add a test to PhysicsParameters::load to see if this value
   was defined.

4) Menu handling
================
The ScreenManager contains the main event/redraw loop in its 
ScreenManager::run function. The next screen can be defined, which
means that the ScreenManager will delete the current screen, and
replace it with the next screen. The main loop for the 
ScreenManager can be aborted by calling ScreenManager::abort().

There are currently two screens:
- StartScreen
  --> background rendered image of tuxkart
- WorldScreen
  --> Handles the display of the actual race, but is also
      used when the race menu pops up
The screens are then mainly responsible for:
- drawing the actual screen (background image for StartScreen,
  race track, karts etc for WorldScreen)
- calling plibdrv.pollEvents (which manages all input)
- calling updateGUI to handle keyboard etc.
- swapping the display buffers

StartScreen
-----------
A gui-stack (gui/BaseGUI) is responsible for handling the
menus. StartScreen pushes GUI_MAINMENU on the guistack, which
is the first menu. When a choice is made, the next menu
(see BaseGUI the function updateGUI) is pushed on the stack.
The updateGUI function then updates the current gui.

When the main menu is finished, StartScreen::switchToGame
gets called, either from:
- start_tuxkart (profiling, quick start)
- gui/CharSel   (GrandPrix)
- gui/NumLaps   (all other racing modes)
switchToGame clears the guiStack and calls RaceManager::start(). 
There, a RaceMode object is created and start() gets called, 
where (after some setup) a new WorldScreen is created and set 
in the screen_manager.

If a race is over (or aborted), a new StartStreen is created
(see ::next() of all racing modes in RaceManager), and the
menu handling starts again.

WorldScreen
-----------
Similarly to StartScreen, WorldScreen::update gets called
regularly by the ScreenManager.


5) Physics
==========
The new physics (esp. new turning code) enables (well, soon)
karts to start sliding when driving too fast in too tight
curves. There are quite a few parameters which can and must
be tuned to get the right feeling. All these parameters
are stored in data/physics.data and can be changed with
any editor - no recompilation is necessary, but tuxkart
has to be started again for the new parameters to be used.
Here a short explanation on how the parameters interact 
with each other:
- Driving in straight lines
  The engine force is defined by 'engine-power', which
  results in a force pushing the kart forward. There are
  two forces countering this: rolling resistance (see
  roll-resistance), and air-resistance. Rolling resistance
  increases linearly with the velocity of the kart
  (speed * roll_resistance); while air resistance increases
  with the squared speed of the kart 
  (speed*speed*air_resistance). Rolling resistance is more
  important at lower speed, while air-resistance is most
  effective at higher speed (and it's ultimate responsible
  for the top speed of the kart).Therefore:
  - engine_power and roll_resistance determine how fast
    a kart can accelerate
  - engine_power and air_resistance determine the maximum
    speed of the kart.
  E.g., to make the kart accelerate faster, without changing
  the maximum speed: either decrease roll-resistance (the
  effect to the maximum speed can be neglected); or increase
  engine power and air resistance.
  Additional effects are the tire grip and the surface the
  kart is driving on: tire-force*tire_grip*surface_grip 
  is the maximum grip (tire-force = force on the tire, caused
  by the weight of the kart), and if the forward force is
  greater than the maximum grip, slipping occurs: the 
  effective force is reduced to 40% (arbitrary value), and
  skid marks are drawn.
- Turning
  Turning is implemented by computing two lateral forces 
  acting on the tires. These forces are caused by the 
  difference of the direction the kart is driving (velocity,
  which is a vector), and the direction the tires are 
  facing. This is called the slip angle. For example, 
  consider a kart driving in a straight line, when suddenly
  the steering wheel is turned left. At this time, the front
  tire will face in a different direction than the direction
  the kart is travelling, but the rear tire will still face
  in the same direction as the velocity. Therefore, a force
  will act on the front tires pushing them to the left, 
  while no such force acts on the rear tires. As a result of
  this, two changes take place in the kart:
  1) The force pushes the kart a bit to the left
     --> this is responsible for the centre of gravity
         to describe a circle
  2) this force causes a turning moment to the kart,
     causing the kart to rotate to the left.
  Notice that these two effects are to a certain degree
  independent: if the turning moment is too small (close
  to zero), the kart will be sliding to the left, but not
  actually face in the direction. If the turning moment
  is too big, the kart will rotate too much - not facing
  the direction of travel either.
  Later in the turn the behaviour is quite similar, except
  that the rear tires will (usually) face in a different
  direction than the velocity, causing a force there as 
  well. So the correct description is:
  1) The sum of the forces on the front and rear tire
     cause the centre of gravity of the kart to move
     sideways
  2) The difference of the two forces causes a turning
     moment on the kart.
  Well, that's somewhat simplified, since there are a
  few cos(alpha), sin(delta), ... happening, but that
  is enough to understand the parameters in the
  data/physics.data file. For more details see:
  http://home.planet.nl/~monstrous/tutcar.html
  This page is currently down :((
  Another recommended read is Ted Zuvich's "Vehicle
  Dynamics for Racing Games" (available on
  gamasutra, just google to find it). More information
  can be found online, search for slip angle, car
  physics, ...

  The slip angles for front and rear tires depend on:
  - steering angle (obviously only for front tires)
  - distance between tires and centre of gravity
    (and rotational velocity of the kart).
    The CoG is assumed to be in the middle of the kart, so
    this distance is wheel-base/2. The longer the wheel
    base, the longer the way the tires will move as
    a result of the kart rotation, the more lateral force
    will be produced.
  The force acting on the tires is then linearly dependent
  on the slip_angle:  slip_angle * corner_force
  (well, it's only linear for small angles, and the function
  Kart::NormalizedLateralForce will cap the values if the
  angle is too big). The acting force for the front tire
  is modified by cos(steer_angle) to compute the lateral 
  force on the centre of gravity from the lateral force
  on the tire.
  The sum of these two lateral forces causes the sideway
  movement of the kart, and the difference between these
  two forces multiplied by wheel_base/2 causes the turning
  moment or torque, which gets divided by the inertia of the
  kart to computer the rotational acceleration.

  To tweak these values, consider:
  - increasing the cornering forces for the tires will 
    result in larger forces to work on the tires
    --> the radius of the turn will be smaller, since the 
        force pulling the kart to the middle is bigger,
    --> the kart will rotate more, since the difference of 
        the two forces will be bigger as well.
  - increasing max_steer_angle will increase the force, but 
    at the same time decrease the later component for the 
    front tire (see cos(steer_angle) above)
    --> tighter curve, but less rotation of the kart
  - increasing the wheel base will increase the turning 
    velocity, causing more force
  - increasing the inertia will reduce the effect of the
    turning moment on the kart, resulting in less rotation,
    but the same pulling force causing the kart to go in
    a circle, so the kart will not 'oversteer'2

All those parameters are tightly coupled, and sometimes even
minor changes will result in big changes in playability, i.e.
the kart might suddenly only rotate on the spot, or hardly
turn at all. Testing and tweaking and tweaking and testing
is necessary.
 
6) Moving textures
==================
A texture can be marked as 'moving', creating an animation effect - for
example the lava in geekopeak. To do this, a new node must be added
into the models. I don't know how to do this in blender, the manual
way is:
Find the texture to be moved, and look up for the first previous
'OBJECT' statement (which is the begin of a node), e.g.:

OBJECT poly
name "rect.010"
texture "lava.rgb"
...

Before that insert a new node like, having a @autotex line:

OBJECT poly
name "wrapper"
data 14
@autotex y=0.1
kids 1
OBJECT poly
name "rect.010"
texture "lava.rgb"
...

The data line indicates the number of characters in the next line
(@autotex...) - including the '@'. The 'name' line is only inserted
to help finding the node in a dump of the track for debugging
purposes.

The possible parameters can be found in the file moving_textures.cpp
(function parseData).

7) Physical objects
===================
Similar to moving textures (above), part of the track can be declared
to represent a rigid body when bullet is used, i.e. this part of the
track will be following the physics rules, and can move around etc.
To do this, similar to moving textures, insert a node like:
OBJECT world
data 20
@physics cone mass=1
kids 1
at the beginning of a file (see roadcone, roadblock), or begin
with an "OBJECT poly" statement (instead of world).

Currently, only 'cone' and 'box' are supported. Additional parameters
can follow on the same line, but currently only 'mass=...'
is supported (which defaults to 1).

8) Track design
===============
This was  written originally by Steve Baker for TuxKart. Most of the
information contained here is still valid, though it might be good to
contact an experienced track designer on the supertuxkart-email list.

A TuxKart 'level' (a race track) is just a bunch of static 
models - perhaps just one if it's simple enough.

The model files can be in any format that PLIB's "SSG" library can
load - there are quite a few loaders now for a range of common
formats. I havn't tested many of them though and I suspect that some
of them are 'patchy' in implementation.

I've been using AC3D to model stuff for TuxKart - and the AC3D file
format is pretty well supported. 

RACETRACK MODELS.
-----------------
The race always starts at the origin of the model - with the players
facing due north. The karts start out spaced a couple of meters apart
- so make sure the track is wide enough! 

Karts are dropped onto the track - it's very important that the road
surface at X==0, Y==0 is slightly below Z==0. That may seem a nasty
restriction that I should fix - but think about what would happen if
you wanted to start the race inside a tunnel or something where there
were multiple layers of polygons above the origin...the program would
have no way to know which layer you wanted to start at. 

I've had to 'extend' the AC3D format a little by using the "Object
Data" field to contain the additional parameters. The TuxKart engine
knows how to do simple repetitive motion on either whole objects or
texture maps based on that data...eg, I have moving water and lava
streams by setting up a moving texture in the AC3D Object Data
field. There are various other similar extensions for 'model switched'
animations and such like. 

It would be easy to add other kinds of effects into the model in that
way.

Since most model formats allow for some kind of text field to be
attached to nodes in the database, this same technique should work for
other model formats - although we may need to get the authors of those
loaders to support the callback function that the AC3D loader uses to
tell the application program that this happened. 

IMAGE AND TEXTURE FILES:
------------------------
All 2D icons and texture maps have to be in either BMP or SGI 'RGB'
format. I greatly prefer the latter because BMP changes often and my
loader can't keep up. 

All images and textures have to obey the rules for OpenGL texture maps
- they must be even powers of two in size (ie the X and Y dimensions
must be 2,4,8,16,32,64,128,256,etc). You can have rectangular maps (eg
128x64). 

Whilst there is no limit to the size of a texture map or image - you
need to be aware that 3Dfx cards (which are VERY commonly used) cannot
cope with maps larger than 256x256. The map loader will downsize your
maps as necessary to make them fit - but beware that this will make
them fuzzy. 

3Dfx cards also have a limitation that maps must not have an aspect
ratio of more than 8:1 or less than 1:8. That's rarely a practical
limitation. 

Textures are ALWAYS MIPmapped and displayed using the highest quality
settings. 

Ideally, all the maps for one track should fit into texture memory -
and on early Voodoo-1 cards, that could be as little as 2Mb...of
course with a GeForce-2 you get something like 64Mb of compressed
texture memory - perhaps 100Mb. How much can you use? That's your
problem! 

COORDINATE SYSTEMS:
-------------------
I have chosen one 'unit' in the database to be one meter in the real
world - but since we don't really know how big Tux and his friends
are, this is pretty arbitary. Another way to think of this is that Tux
is one meter tall (that's just how big I think of him as being) - so
one 'unit' is one 'tux' high - which is one meter. Real world penguins
do get as big as a meter tall - but Tux is a 'Jackass Penguin' and
they only grow to about 30cm...however, if he was that small, it would
be hard to make levels because he ends up being too short to reach
furniture, door knobs, etc convincingly. 

I come from a flight-simulation background where we use the convention
that Z-is-up - so all my software works like that. However, the PLIB
loaders know that some modellers use Y-is-up and do the axis swap as
needed. Hence, in AC3D, Y-is-up - but in the game, your models will be
converted to Z-is-up. If you find this confusing, forget I mentioned
it - everything comes out OK automagically. 

RACETRACK MATERIALS:
--------------------
Another kind of effect comes from which texture map you use. I find
that model file formats don't tell me all I need to know about a
polygon.

For example - do you crash if you hit it? Yes - if it's a brick wall,
No - if it's a cloud of smoke. What is the coefficient of friction?
Different for Ice than for Concrete.

These things are listed in a 'Material Reference File' called
'data/materials.dat'. Since the default settings are generally what
you want, most textures needn't be listed in the material file. It's
really there for special materials such as those that make up the
'zippers'.

Hence, if you need an icy surface, you apply the texture "ice.rgb" and
when the model loads, I check that filename against my list of
materials in 'data/materials.dat' and note that "ice.rgb" is a
slippery material. This means that you can't re-use the ice texture
map for anything that isn't supposed to be slippery - but what the
heck...that's a really easy solution. It also allows me to add new
material properties without going back into every single model adding
that property into every single polygon. 

The format of 'data/materials.dat' is described in the file itself in
comments. Each material is on a line of it's own. Start with the
texturemap name in double-quotes, then follow a number of boolean or
numeric fields separated by spaces. 

An example of a line in this file is:

# TextureName        UVClamp Trans AlphaRef Light Friction Ign Zip Reset Collide
"lava.rgb"             N N     N      0.0     N     1.0     N   N    Y    Y


The fields (in order) are:

    * TextureName -- the name of the texture map - stripped of it's
      pathname. (All textures should be in the 'images' directory). 
    * UVCLAMP -- two booleans - the first indicates whether the
      texture coordinates should be clamped in the U direction - the
      second for the V direction. 
          o N N - repeats endlessly.
          o Y N - repeats in the V (ie Y) direction only.
          o N Y - or only in the U (ie X) direction.
          o Y Y - makes the texture not repeat at all. 
      If the polygon is larger than the map and the map is clamped
      then the edge texels of the map will be repeated endlessly. 
    * Trans -- True if the polygon or texture is likely to be
      transparent and therefore rendered with GL_BLEND enabled. 
    * AlphaRef -- the 'alpha clamp' value - pixels with an alpha less
      than this are not rendered. 
    * Light -- is 'lighting' enabled for this polygon? If not, the
      polygon will be drawn at it's full brightness and it'll glow in
      the dark. 
    * Friction -- the frictional coefficient. 1.0 is 'normal', larger
      numbers represent rougher surfaces, smaller are more slippery. 
    * Ign/Zip/Reset/Collide -- four booleans that describe the effect
      on the Kart of touching polygons made of this material:
          o Ign -- Ignore this polygon for the purposes of collision
            testing. 
          o Zip -- means that this is a 'zipper'. If a kart touches
            it, the kart will accellerate to high speed. 
          o Reset -- This material is "fatal" to karts - if you touch
            it then the rescue squad will come and hoist you away from
            it and up onto the track. 
          o Collide -- if no set for a horizontal surface, it means
            that a kart can drive on it - for a vertical surface,
            karts that hit it will only slow down a little and can
            'slide' along the polygons. If set, it means that any kart
            that hits this polygon will crash and drop to zero speed.  

THE 'LOCATION' FILE.
There is a 'data/xxx.loc' file (where 'xxx' is the name of your level)
that contains the location of each model file in (x,y,z) and (h,p,r) -
Heading, Pitch and Roll. 

It's convenient to have some objects automatically 'conform' to sit on
the terrain. If you wish to do that, then you can replace the Z
coordinate with a pair of curly braces '{}'...you can also leave out
either Pitch or Roll (using '{}') - and they will be computed so as to
position the object onto the underlying surface. 

Since objects are added to the scene in order, the track models needs
to appear earlier in the file than things you wish to conform to it. 

There are some models that are 'built-in' to the game engine - notably
the the various colours of herring. 

Comments can be placed into the '.loc' file by placing a '#' at the
start of the line. 

The easiest way to understand the '.loc' file format is to look at
some of those from existing levels - the format is easy enough. Here
is an example: 

#
# The track itself.
#
"bsodcastle.ac",0,0,0,0,0,0
#
# Two Zippers (clamped to the track)
#
"zipper.ac",-70,0,{},90,{},{}
"zipper.ac",-75,0,{},180,{},{}
#
# An advert for SuSE Linux
#
"susesign.ac",130,-40,5,-90,0,0
#
# A Gold (Yellow) herring
#
YHERRING,-45,-140
#
# Two Red herring
# 
RHERRING,29,-139
RHERRING,29,-141
#
# Two Silver herring 
#
SHERRING,20,80
SHERRING,120,-65
#
# Two Green herring
# 
GHERRING,25,70
GHERRING,30,70



THE 'DRIVE LINE' FILE:
----------------------
The second file you need is 'data/xxx.drv' - which is an ordered list
of 2D points that lie along the approximate centerline of the track -
starting at the start line, going all the way around the track and
ending again at the start line. 

The DRIVE LINE file is used for several things:

    * To tell the computer players where to steer.
    * To let me figure out how far around the 'lap' each player is. 
    * I also use it to generate a 'plan view' of the track with
      coloured dots for the players.  

Here is an example of a typical 'drv' file.

1.6556,-2.09912
-0.6416,15.1328
-7.5344,35.8112
-22.469,54.192
-40.8496,59.936
-59.2304,51.8944
-75.3136,33.5136
-83.3552,22.0256
-100.587,1.34728
-122.414,-8.99188


The simplest way to generate such a file is to load your track into a
suitable 3D modeller and digitize a 'polyline' (or 'line loop' or
whatever) around the track. Then delete all the other things in the
model and SaveAs to a separate file. Presuming your modeller can
export an ASCII format of some kind, you can easily hand edit the
points to delete the vertical coordinate and all the non-vertex data
from the file. 

You can test whether you got it right by loading the model and drv
file into TuxKart and driving Tux around the track. Observing the
planview as you go around will make it easy to tell whether you got it
right. 

The computer-controlled players have a hard time making it around
tight corners, so please try to have the drv file take a 'racing line'
through the turn to give them a better chance. 

KART MODELS:
------------
Right now, the Karts in TuxKart are pretty simple - just a plain rigid
model. That's going to have to change so the characters do stuff like
leaning into the corners, turning their heads, waving their fists (oh
- wait, none of them *have* fists :-) ...however, remarkably little of
that happens in MarioKart - and my first goal is just to be AS GOOD AS
MK64 - being better than it can come later! 

The Karts also need 2D icons for use in various parts of the game.

Have a look at the data/*.tkkf files for details.