How the Airstrike engine works: An incomplete introduction. Sprites The basic building block of Airstrike is the sprite type 'sprite_t'. Everything that moves, and some things that don't move, in the game are sprites. The sprites have some basic properties in common. They all have a position, a current animation, etc, but most importantly each sprite has a type, represented by the C type sprite_type_t. The type defines the behaviour of the sprite, and supplies is with animations etc. In C++ sprite_type_t would be the class, and sprite_t would be a general instance of this class. The sprite type, accessible via the .type member of sprite_t, defines how to create a sprite, what will happen if there is a collision with other sprites etc. Signals The sprite type also defines how the sprite will react to /signals/. The signal mechanism is used to communicate with the sprites in a uniform manner without knowing their exact types. Each sprite type may choose to catch any signals it likes, but there is never any guarantee that the signal will be caught. This mechanism is use to signal damage done to a sprite, for example. Only the 'important' sprites actually keep track of their internal damage, but the signal can be sent to any sprite in a safe way. The signals can be sent after some time, using the sprite_alarm() function. This is used for example to let the crashed biplanes remain for a certain time in the game before they are removed. In practice the signal system is also used to prevent excessive castings between the different type, and will hopefully be used to do network transparent communications in the future. Sprite groups Despite the niceness and generality of of the signal mechanism it is often convenient to keep separate types of sprites in different groups. This simplifies things, and minimizes unneccessary communication and collision detection. The C type sprite_group_t is used for this purpose. The groups are used for all major operations, like drawing and collision detection. Sprite reference counting Because pointers to individual sprites can be stored in many unlikely places, there is a reference counting mechanism to keep track of the sprites. When the reference count drops to zero the sprite is freed. This makes it very important to use sprite_aquire(), sprite_isvalid() and sprite_release() correctly. A sprite may be marked as dead using the sprit_kill() function, which means that is should be released by everyone that references it. This is done automatically when using sprite_isvalid() before accessing the sprite. See the code in sprite_types/biplane.c for an example of how to use these functions. Sprite type coding To create a new sprite type you should: 1) Make graphics for all its actions, add the pov files to the pov directory, with the corresponding makefile targets. See doc/animation.txt for some info about how to make animations. 2) Make sounds for it if needed. 3) Code the behavior by creating a sprite_type_t struct for the new type. Be sure to use the REGISTER_SPRITE_TYPE() macro, and place your code in a suitably named C file in the sprite_types directory. It will be picked up automatically by the makefile. 4) Implement some way for the sprite to appear in the game. Mechanics and dynamics The basic sprite_t function keeps track of position and velocity. For nice mechanics it is neccessary to have more properties, and there is a 'subclass' of sprite_t called mech_sprite_t, which have a lot of physical properties. The interaction between sprites of this type are handled 'automatically', and damage is distributed if impact velocities are too high. These sprites inevitably take up more memory and CPU, and they should only be used where accurate physics is important. In the current game this type is used for the biplanes, the balloons and the bombs. The functions for handling mechanics are located in mech.c, with support from support/maths.[hc]. The mechanics are far from done, and may do strange things in certain situations. The properties in mech_sprite_t are not all implemented, so beware! (and check the code). Game levels The level support is currently in its early stages, so currently there can only be levels of the same size as the display. In addition to the background image there is a special image which controlls the mask used for collision detection with the background. This is generally needed as the engine cannot know which parts of the background image belongs to the foreground. Alternatively the alpha channel could be used, but this makes things more complicated with Povray, for example. In the future the levels are going to be made up of separate elements and will possibly be larger than the screen. This is because it is not optimal to have a very large level in a single {sw|hw} surface. At this point there will also be a level editor. --Ulf