Fight Zone Technical Design Document Table of Contents Design Recap .................................................................................................................................. 4 Platform and System Requirements ................................................................................................ 5 3rd Party Technologies ..................................................................................................................... 6 DirectX 8.1 ................................................................................................................................... 6 FMOD .......................................................................................................................................... 6 MD3 & BSP ................................................................................................................................. 6 Game Logic ..................................................................................................................................... 7 Game Manager ........................................................................................................................... 7 Object Classes ............................................................................................................................ 7 Gladiator Class ............................................................................................................................ 8 Object Manager ........................................................................................................................... 9 Physics .......................................................................................................................................... 10 Motion ........................................................................................................................................ 10 Players: ................................................................................................................................. 10 Projectiles: ............................................................................................................................ 10 Data Types ............................................................................................................................ 10 Physics Loop ......................................................................................................................... 11 Collision Detection Overview .................................................................................................... 11 Collision Objects and Volumes ................................................................................................. 11 Players: ................................................................................................................................. 11 Projectiles: ............................................................................................................................ 11 Walls: .................................................................................................................................... 11 Methods of Collision Detection .................................................................................................. 12 Projectiles to players: ............................................................................................................ 12 Player to player: .................................................................................................................... 12 Players to walls and floors: ................................................................................................... 13 Collision Handling...................................................................................................................... 14 Player to player collisions: .................................................................................................... 14 Player to wall collisions: ........................................................................................................ 14 Players and explosion spheres: ............................................................................................ 15 Players and gravity fields: ..................................................................................................... 15 Grenades and lasers with walls: ........................................................................................... 15 Menus ............................................................................................................................................ 17 Interface ................................................................................................................................ 17 Implementation ..................................................................................................................... 17 Menu Skin Files .................................................................................................................... 17 Menu Functionality .................................................................................................................... 17 Interface ................................................................................................................................ 17 Implementation ..................................................................................................................... 17 UI Object Classes ................................................................................................................. 18 Button Base Class ................................................................................................................ 18 Transfer Button ..................................................................................................................... 18 Checkbox Base Class ........................................................................................................... 18 Selection Boxes Base Class ................................................................................................. 18 Edit Box ................................................................................................................................. 18 Dropdown Box ...................................................................................................................... 18 Image .................................................................................................................................... 18 Model .................................................................................................................................... 18 Graphics/Rendering ....................................................................................................................... 19 Core Structure ........................................................................................................................... 19 Interface ................................................................................................................................ 19 2D Images ................................................................................................................................. 21 User Interface ....................................................................................................................... 21 Page 1 of 128 Fight Zone Technical Design Document Particle Manager ................................................................................................................... 21 Special Effects ...................................................................................................................... 21 Models ....................................................................................................................................... 22 Player Models ....................................................................................................................... 22 Game World .............................................................................................................................. 23 Player Models ............................................................................................................................ 26 Item/Weapon Models ................................................................................................................ 26 Levels ........................................................................................................................................ 26 Textures .................................................................................................................................... 27 Required Art .............................................................................................................................. 27 Levels .................................................................................................................................... 27 Static Meshes ....................................................................................................................... 27 Animated Meshes ................................................................................................................. 27 MD3s ..................................................................................................................................... 27 2D Particle Sprites ................................................................................................................ 27 2D Images ............................................................................................................................. 28 Sound ............................................................................................................................................ 29 SoundMgr class Description ..................................................................................................... 29 Sound class description ............................................................................................................ 29 SoundBuffer class description ................................................................................................... 30 Handle class description ........................................................................................................... 30 Required Sounds ....................................................................................................................... 30 Music ..................................................................................................................................... 30 Sound Effects ........................................................................................................................ 30 Input ............................................................................................................................................... 32 Keyboard Input .......................................................................................................................... 32 Un-buffered Input .................................................................................................................. 32 Buffered Input ....................................................................................................................... 32 Mouse Input ............................................................................................................................... 32 Artificial Intelligence ....................................................................................................................... 33 Path-Finding and Obstacle Avoidance ...................................................................................... 33 Obstacle Avoidance Using Neural Networks ........................................................................ 33 Path-Finding Using a 3D Connectivity Grid .......................................................................... 34 Bot Upgrade Logic..................................................................................................................... 35 AI Agent Architecture ................................................................................................................ 36 AIBehavior ............................................................................................................................ 36 AICombat .............................................................................................................................. 36 What the bot can sense in the world ..................................................................................... 37 AIMovement .......................................................................................................................... 37 Artificial Neural Networks .......................................................................................................... 38 Finite State Machines ................................................................................................................ 39 The Condition and Transition Classes .................................................................................. 41 FSM State Objects (TFSMState) .......................................................................................... 42 The Finite State Machine Class (TFSM) ............................................................................... 43 Physics .......................................................................................................................................... 45 Motion ........................................................................................................................................ 45 Players: ................................................................................................................................. 45 Projectiles: ............................................................................................................................ 45 Data Types ............................................................................................................................ 45 Physics Loop ......................................................................................................................... 46 Collision Detection Overview .................................................................................................... 46 Collision Objects and Volumes ................................................................................................. 46 Players: ................................................................................................................................. 46 Projectiles: ............................................................................................................................ 46 Walls: .................................................................................................................................... 46 Methods of Collision Detection .................................................................................................. 47 Page 2 of 128 Fight Zone Technical Design Document Projectiles to players: ............................................................................................................ 47 Player to player: .................................................................................................................... 47 Players to walls and floors: ................................................................................................... 48 Collision Handling...................................................................................................................... 49 Player to player collisions: .................................................................................................... 49 Player to wall collisions: ........................................................................................................ 49 Players and explosion spheres: ............................................................................................ 50 Players and gravity fields: ..................................................................................................... 50 Grenades and lasers with walls: ........................................................................................... 50 Networking ..................................................................................................................................... 52 Basic Components .................................................................................................................... 52 Persist Manager .................................................................................................................... 52 Huffman Compression .......................................................................................................... 52 Latest State Compression..................................................................................................... 53 Connection Layer ...................................................................................................................... 53 Connection Manager ............................................................................................................. 53 Connections .......................................................................................................................... 53 Stream Layer ............................................................................................................................. 56 Stream Manager ................................................................................................................... 56 Stream................................................................................................................................... 57 Packet Chunks ...................................................................................................................... 58 User Packet Chunk Manager ................................................................................................ 60 Event Packet Chunk Manager .............................................................................................. 61 Ghost Packet Chunk Manager .............................................................................................. 62 Subsystems ................................................................................................................................... 66 Memory Manager ...................................................................................................................... 66 Interface ................................................................................................................................ 66 Implementation ..................................................................................................................... 66 Debugging Support ............................................................................................................... 68 Statistical Support ................................................................................................................. 68 Trace Manager .......................................................................................................................... 69 Interface ................................................................................................................................ 69 Implementation ..................................................................................................................... 69 Assertions .................................................................................................................................. 70 Resource Manager .................................................................................................................... 70 Interface ................................................................................................................................ 70 Creating Resource Types ..................................................................................................... 71 Implementation ..................................................................................................................... 72 Statistical Support ................................................................................................................. 73 Appendix A .................................................................................................................................... 74 The TRIBES Engine Networking Model ......................................................................... 74 Appendix B .................................................................................................................................... 91 UI Skin File Format.................................................................................................................... 92 Header Tag ........................................................................................................................... 92 Buttons .................................................................................................................................. 93 Check Boxes ......................................................................................................................... 96 Cursors.................................................................................................................................. 98 Drop Down Boxes ............................................................................................................... 100 Edit Boxes ........................................................................................................................... 107 Images ................................................................................................................................ 110 Key Links............................................................................................................................. 111 List Boxes............................................................................................................................ 115 Radio Buttons ..................................................................................................................... 123 Roll Overs ........................................................................................................................... 126 Text Displays ...................................................................................................................... 127 Page 3 of 128 Fight Zone Technical Design Document Design Recap In the future, a game has been invented that has caught the world’s attention. The game is titled “Fight Zone,” and it is the first televised game that allows the contestants to battle each other with real weapons to win fame and fortune. The game takes place in special arenas where killed players can be reconstructed instantly to continue the fight. The fighter with the most kills wins the game. Fight Zone is a first person shooter in which the player must utilize character customization to defeat opponents. At the beginning of every round, all players are given the option of upgrading weapon and armor components of their character to help with the arena battle ahead. All players start with three armor pieces. Each armor piece has its own strength. Once the strength of an armor piece reaches zero, then the piece is destroyed. From now on, that player will take life damage if the player is hit where the former armor piece was located. If any player reaches zero life, then that player is killed. Killed players must wait a short time while being reconstructed. Once fully reconstructed, players reenter play with full life, armor, and chosen upgrades. There are two main victory settings for Fight Zone: time limit, and kills. A time limit can be set, and the player with the highest number of kills when time runs out will win. A kill limit can also be set, which means the first player to reach the set number of kills will win. Weapon upgrades make the player’s weapon arsenal much stronger and much more deadly. The player also may utilize tactics and purchase status effecting mines that turn the battle to the player’s favor without causing direct damage. Armor upgrades are very useful to the player’s defense. However, each armor upgrade is attached to an armor piece. Therefore, if that piece gets destroyed, then the functionalities of that piece get destroyed along with it. In this manner, powerful defensive upgrades can be countered. The battle arenas are designed to give combatants a challenging play field. Hallways, ramps, walkways, platforms, and floating platforms offer strategic locations for ambush and recovery spots. Along with all these obstacles, camera bots will be traveling throughout the arenas to video the whole fight. Page 4 of 128 Fight Zone Technical Design Document Platform and System Requirements We will be developing Fight Zone in Windows 2000 Professional Edition, and will be given cursory testing in Windows XP, 98 and ME. Minimum System Requirements - Windows 2k, XP, 98 or ME - 64 MB of RAM - 600 MHz Processor or faster - 60 MB Hard Drive space - 16MB DirectX 8.1 Compatible 3D Graphics Accelerator Recommended System Requirements - Windows 2k, XP - 128 MB of RAM - 1 GHz Processor or faster - 60 MB Hard Drive space - 32MB DirectX 8.1 Compatible 3D Graphics Accelerator Page 5 of 128 Fight Zone Technical Design Document 3rd Party Technologies DirectX 8.1 Creator: Microsoft Available at: http://microsoft.com/windows/directx/ Usage: We are using DirectX Graphics to draw, and DirectInput for controls. DirectX is backwards compatible, so any later version will work as well. As of writing this document, Microsoft had just released version 9.0. FMOD Creator: Firelight Technologies Available at: http://www.fmod.org/ Usage: FMOD handles all of the low-level sound implementation in Fight Zone, including loading, playing, volume control, 3D calculation, and freeing. Our custom wrapper to FMOD imposes an additional layer of channel management to give us a little extra control over when and how particular classes of sounds are playing. As part of the wrapper, we've discarded certain aspects such as panning control and channel priority. We've created separate classes to wrap different parts of the FMOD functionality as follows: SoundMgr -> General system functionality Sound -> Sample/Stream functionality SoundBuffer -> Channel functionality MD3 & BSP Creator: Id Software Available at: http://www.google.com Usage: We are using the .md3 and .bsp file formats for our models and levels respectively. Id Software owns both of these formats, but they allow them to be used freely. The only restriction is that we cannot use their tools for a commercial product. While there is no official documentation of these formats, there is enough 3rd party documentation to figure it out. Page 6 of 128 Fight Zone Technical Design Document Game Logic Game Manager The game manager class is the main class that holds all information relevant to the game. The update function of the game class is in charge of calling all of the objects’ update functions as well as receiving input and drawing the objects. Class GameMgr Derived From [Nothing] This is the main game class that holds all pertinent information relating to the game and game objects. Data Description Time Scale This is a scalar value indicating that game time will be that much faster than real time. Error Message Current game error message to display. Version Number The current version of the game code. Main Window The main window to display to. World List A list of worlds currently available. World Index An index into the world list. World Name of the current world that is being played. Camera The current camera being displayed to the user. Players Array of all players in the game. Max players The maximum allowed number of players for this game. Num players The current amount of players in the game. Human player A pointer to the local player. Active Object The current object of the local player. Active Object Index The index value to the active object. Function Description Update The update function is in charge of updating all of the objects. The update function will first get all available input. Then, it will update all the objects by calling the object manager update. Draw Draw all objects in the current view plant. Initialize This function will set up all the data structures with their respective starting values. Uninitialize Any memory allocations that have been made will be cleaned up by this function. Start Server Sets up the game to be a server. Start Client Sets up the game to be a client. End Gameplay Quit the current game round. Initialize Round Perform all round specific initializations. Accessor functions All related accessor functions will be here as well. Description Object Classes There is a hierarchal tree structure of in-game objects. That structure is outlined below: In-game Objects o Animate Objects Gladiator Object Human Gladiator Page 7 of 128 Fight Zone Technical Design Document AI Gladiator Gunbot Object AI Gunbot Cambot Object AI Cambot Inanimate Objects Laser Object Plasma Shot Rocket Grenade Mine o Gladiator Class The gladiator class holds all information regarding a player and his attributes. Class Gladiator Class Derived From Animate Object The gladiator class holds all information about the player that the game will need to know about. Data Description Head Hor Offset Horizontal offset of the head from the torso. Head Ver Offset Vertical offset of the head from the torso. Torso Hor Offset Horizontal offset of the torso from the legs. Torso Ver Offset Vertical offset of the torso from the legs. CurHelmetArmor The current armor strength of the helmet. CurTorsoArmor The current armor strength of the torso. CurLegsArmor The current armor strength of the legs. CurLife The current life strength of the player. BallisticClipAmmo The amount of ballistic ammunition in the clip. BallisticStoredAmmo The amount of ballistic ammunition out of the clip. EnergyClipAmmo The amount of energy ammunition in the clip. EnergyStoredAmmo The amount of energy ammunition out of the clip. ExplosiveClipAmmo The amount of explosive ammunition in the clip. ExplosiveStoredAmmo The amount of explosive ammunition out of the clip. NumStasisMines The number of stasis mines the player has. NumEMPMines The number of EMP mines the player has. NumExplosiveMines The number of explosive mines the player has. Selected Weapon The currently selected weapon of the player. Current Secondary The weapon currently in secondary mode, if any. Weapon Animation Information Information relating to which animation should be playing for the player at this point in time. Hovering A Boolean used to determine if the player is hovering. Hover Capacity A value indicating how much hover energy is left in the hover pack. Upgrades Chosen An array indicating which upgrades the player has chosen for this round. Total Frags The number of kills that the player currently has obtained. Total Deaths The number of times that this player has been killed this game. Upgrade variables For quicker reference, specific upgrade variables will be stored here so as to not have to be recalculated each game Description Page 8 of 128 Fight Zone Technical Design Document Function Draw Update Spawn Attach Camera Get Collision Volume Accessor functions loop. Description Draws the player to the rendering scene. Updates the player’s attributes. Initialize all values to level-set stats. Attach the world camera to this player. Get the player’s collision volume. All related accessor functions will be here as well. Object Manager The object manager is basically a big container. It holds a list of all the objects in the game and all the players in the game. These objects also include UI objects for the menus and the HUD. Class Object Manager Derived From [Nothing] This is the manager that holds the object and player lists. Description A bool indicating that menus need to be changed. Name of menu to display. List of used objects. List of unused objects. List of objects that are in the game. List of collidable animate objects. List of collidable inanimate objects. List of non-collidable inanimate objects. List of UI objects. A list of all objects that are currently contained in the game. A list of all players currently in the game. Description The update function will go through all the objects in the game and all the players in the game and call the update function for each item. Draw InGame objs Draw all in-game objects. Draw first-person Draw all first-person specific objects. Draw UI Draw all UI objects. Accessor functions All related accessor functions will be here as well. Description Data Change Menus Menu File Name Used Objects Unused objects In Game objs Coll. Animate objs Coll. Inan. Objs Noncoll. Inan. Objs UI Objects Object List Player List Function Update Objects Page 9 of 128 Fight Zone Technical Design Document Physics Motion The following is a breakdown of the motion physics that will be applied to all moveable objects. Players: Moving player objects work under a force system, and so each contains a mass for determining inertia, momentum, etc. Directional input applies a new force to the player object, thus changing its acceleration and ultimately affecting the velocity. Player objects’ accelerations when moving are determined by their mass (due to inertia), which changes depending on the state of their armor. As they lose armor pieces, they become less massive and will accelerate faster, but will have a lower momentum at top speed. All player objects are constantly affected by gravity (note: in Fight Zone, gravity is less than Earth’s 9.8 m/s2), and so will take damage when falling from great heights. The damage is determined by the amount of force applied to the player upon impact. However, a player with an upgraded jumping ability can sustain higher forces when landing from a fall than a player without upgraded jumping. Players' hover-packs gently counter both upward and downward movement until their velocities reach 0 in the y direction. For example, if a player jumps and is moving up, the hover-pack, if activated, will gently slow their ascent until they are simply hovering. If a player is falling, the hover-pack applies a gentle force in the upward direction and slows their descent. Only walls and floors apply friction to moving objects. Projectiles: With the exception of grenades and mines, all projectiles completely ignore gravity. Furthermore, projectiles themselves do not have mass, and so do not apply forces to objects when striking them. However, projectiles that explode upon impact will impart forces on all objects within their explosion radii. This force can be represented by a line from the center of the explosion to the center of the object within the explosion radius. Regular bullets, fired from the machine gun or sniper rifle, do not have velocities. They instantly strike the first object that is in their line of would-be travel. Rockets, plasma balls, grenades, and lasers, however, have velocities and accelerations (even if the acceleration brings them to their maximum velocity instantly). Data Types Velocity: Velocity is stored as a vector that contains the direction of movement and the magnitude. Acceleration: Acceleration is stored as a vector that contains the direction of acceleration and the magnitude. Force: Force is stored as a vector that contains the direction of the force and the magnitude. Mass: Mass is stored as a float. Page 10 of 128 Fight Zone Technical Design Document Physics Loop The physics is handled in the following steps: 1) Input is taken and new forces are determined. 2) A new net force is calculated for each moving object, which yields a new acceleration and thus a new velocity for this frame. 3) Using the newly calculated velocities, all objects are checked for collisions. 4) When collisions occur, they are handled appropriately and objects are given new forces, accelerations, or velocities. They are then rechecked for more collisions during that frame. 5) Objects are moved along their final velocities to their new positions and are ready for the next frame. Collision Detection Overview Though a complex problem as a whole, collision detection is simplified in Fight Zone by separating all objects in the game world into two categories: dynamic and static objects. With this distinction, only two types of general collisions exist: 1) 2) Dynamic objects colliding with dynamic objects. Dynamic objects colliding with static objects. Obviously, a static object can never move into another static object, so collision between them is not checked. A problem that needs to be taken into consideration in every type of collision detection is two objects in the list may collide, but that doesn’t mean another object that will be checked later wouldn’t collide with one of them earlier. Therefore, a list of collisions must be kept so that if, for example, a bullet collides with a player at some time t0, and it collides with another player at time t1, the collision with the earlier time can be kept in the list and the other collision removed. Collision Objects and Volumes Players: Player objects utilize the following collision volumes: 1) Encompassing hit boxes for projectile collisions. 2) Spheres for player-to-player collisions, trivial rejections of objects that will never collide with players, and collisions with walls. Projectiles: In addition to player volumes, projectiles are treated as rays to simplify the calculations of detecting collisions between moving players and moving projectiles between frames. Walls: Naturally, walls are treated as planes. By using the vectors normal to the planes, calculating collisions, reflections, etc. becomes relatively simple. Page 11 of 128 Fight Zone Technical Design Document Methods of Collision Detection Projectiles to players: As noted above, projectiles are treated as rays. In each new frame, their origin becomes their location at the end of the previous frame, and their final destination becomes their origin plus their velocity vector. The first step in detecting collision between projectiles and players is to trivially reject any projectiles that will never collide with a given player. This is done by creating a sphere that encompasses a given player’s entire movement volume: Sphere around movement volume. Beginning of frame. End of the frame. Each projectile is checked with each player’s encompassing movement sphere. If a projectile passes through this sphere, there is a chance it could collide with the player object, and further calculations, listed below, must be carried out. Otherwise, if a projectile does not pass through this sphere, it is guaranteed that it will not hit the player. If a projectile passes through one or more of these spheres, it must then be checked for collision with the player’s actual hit box. The first step is to take the player’s velocity and subtract it from the projectile’s velocity. By doing this, the player can be treated as a stationary object, thus making the interpolation calculations much simpler. Then the ray must be checked for an intersection with any given face (plane) on the hit box. If a collision occurs, the remaining faces can be ignored. At this point, if a collision with a given plane has occurred, all that remains is to check the height of the collision to make sure it was within the player’s hit box. If a collision did not occur and a projectile passed through more than one player’s movement sphere, collision with those remaining players would still need to be checked. Player to player: Player to player collision is detected by creating a sphere around each player’s movement volume (see diagram above) and then checking to see if any two spheres overlap. If so, collision between the actual players must then be checked. The following diagram gives a 2D example of two circles that could potentially collide during a frame: Page 12 of 128 Fight Zone Technical Design Document A1 B1 Va * t Vb * t A0 B0 AB = B0 – A0 Using the vectors A(t) and B(t) such that A(t) = A0 + Va * t B(t) = B0 + Vb * t The distance between the lines of movement can be calculated by [ B(t) – A(t) ] * [ B(t) – A(t) ] The time of the first collision can be calculated by solving for t such that [ B(t) – A(t) ] * [ B(t) – A(t) ] = (Ra + Rb)2 where Ra and Rb are the radii of A and B. Expanding this out yields the quadratic equation: AB * AB + 2 * Vab * AB * t + Vab * Vab * t2 = (Ra + Rb)2 where: AB = B0 – A0 Vab = Vb – Va Because the equation is a quadratic, there may be: 1) No solution. 2) One solution (they bump at a single point) 3) Two solutions (the lower solution being when they first intersect, and the second being when they break apart). Players to walls and floors: Dynamic to static objection collision detection is handled by checking a player’s initial position and final position during any given frame to determine if he/she passes into/through a wall. This is accomplished by creating a sphere around each player object’s hit box and determining if that Page 13 of 128 Fight Zone Technical Design Document sphere intersects with any walls or floors. If so, the player is stopped from continuing in that direction, forced instead to slide along the wall. One problem that must be considered is collision with short walls, such as stairs, pipes on the floors, etc. Players should not be forced to jump over objects they normally wouldn’t think about stepping over or walking up. Therefore, when a collision with any wall occurs, the collision volume is lifted a certain amount and then retested against the wall for another collision. If the wall in question were the side of a stair, the player would then be above the stair and would move forward onto the top of the stair. If the wall was an actual wall, the player still could not move forward and thus would not be allowed to continue into the wall. Collision Handling Player to player collisions: When a player collides with a player, the resulting impact is treated as an elastic collision. That is, they bounce off at different angles and do not stick together. All players have a mass and velocity, so their momentum can be calculated by: Momentum = mass * velocity This momentum is used to determine the resulting angles of reflections, as well as the resulting velocities after the collision. Player to wall collisions: Like player-to-player collisions, player to wall collisions is effectively inelastic. However, the effect on the wall of a player colliding with it is ignored, as the amount a wall moves when struck is negligible, and so, because the wall doesn’t move, the player doesn’t get sent along some resulting vector with the wall. Instead, the player essentially slides along the wall, maintaining all of their previous velocity minus the portion that is normal to the wall: Wall Player Result: Wall Player Page 14 of 128 Fight Zone Technical Design Document Players and explosion spheres: When objects explode, they apply a force to all players within their radius. This force is added to the force vector of the players’ movement (mass * velocity). By dividing the mass, the player’s new velocity can be determined. Explosion spheres also affect destroyable objects such as grenades and mines. If any destroyable object is within the blast radius, it is instantly destroyed. The force in explosion spheres is constant along the entire radius, and furthermore, explosion spheres do not grow over time. They are instantaneous. Players and gravity fields: Gravity fields affect players by supplying them with a new acceleration towards the center of the field, which is represented by a sphere. While the pulling force is constant along the entire radius (thus making the acceleration constant for all objects caught within the sphere), players or objects caught right on the edge will, most likely, not make it to the center of the field before it ceases to exist. This creates the illusion of degrading strength as one moves further from the center of the field. Grenades and lasers with walls: Grenades and lasers share the characteristic of bouncing (reflecting) off of walls. Grenades are, however, affected by gravity, but the distance traveled is so small within any given frame that its curved path of motion can be accurately approximated by a single, straight line. Therefore, simple line to plane calculations will yield the resulting vector after the reflection: Result Normal Ray The resulting vector can be determined by first projecting the initial ray V onto the normal N (assuming N is normalized, result shown in blue): projNV = dot(V,N) * N Result Ray Page 15 of 128 Fight Zone Technical Design Document This projection is then subtracted from the original ray to get the difference (perpendicular to N, shown in red): Result Ray This perpendicular difference must then be doubled: Result Ray Finally, V must be subtracted from this doubled perpendicular difference (the entire red vector, result shown in green): Result Ray Page 16 of 128 Fight Zone Technical Design Document Menus Interface Any menu can be created explicitly by creating a new Resource<UITemplateResource> class. When creating this you pass in the menu template file to the constructor and it will load the menu and prepare it for drawing. Typically you will only do this on the base menu. Each menu after the base menu will be created from the previous menu. Implementation The implementation is as simple as parsing through and loading a menu file and parsing through and loading as many menu object files that are contained within the menu file. Menu Skin Files Menu skin files (.mnu) are the files that specify the objects for a menu. The format for these files is specified in the appendix. These files allow the user to customize the menus and/or hud to their exact desires. The user cannot create brand new objects, but can alter the appearance and placement of all objects. They may also change which menu an object appears on. Menu Functionality Interface The interface for menu functionality is all done behind the scenes. Once a menu is loaded, each button, text field, image or other UI object exists as an object in the world and is handled on it’s own. Implementation The base UIObject class will be derived from the BaseObject class that all objects in the game are derived from. It has the following functions: Function IsInView Draw GetPosition & SetPosition GetWidth & SetWidth GetHeigh & SetHeight GetAlignment & SetAlignment GetObjectImage & SetObjectImage GetObjectType & SetObjectType GetExtraInfo & SetExtraInfo Description This is a base object function. Will take in a camera and check if the object is in view. Returns a bool. Will pass out a list of vertices to draw to the renderer. Accessor functions for the position of the object. Accessor functions to change or get the width of the object. Accessor functions to change or get the height of the object. Accessor functions to change or get the alignment of an object Get or set the object image file for this menu object. The Object type. i.e. button, check box, list box, etc… Extra optional info that is context sensitive based upon the menu type. Page 17 of 128 Fight Zone Technical Design Document UI Object Classes These are the base types of objects that will be available. All menu objects will either be one of these base types or a new type derived from these. For example, a transition button is not derived from as it already has all of the functionality required for such a button, whereas a button object is always derived from. All of these types are derived from the UIObject base class. Button Base Class When the user clicks in, then releases this button, the button will perform it’s Activate function. Transfer Button When this button is pressed, a new menu file is loaded. This is not a base class, and no other buttons should be derived from it. Checkbox Base Class This button is used to change Boolean settings in the game. Selection Boxes Base Class This is a large box containing several strings for the user to choose from. This is used when the number of strings is known at compile time, or screen space is not an issue. Edit Box The edit box will be used for the user to input text, such as the player’s name or an ip address. Dropdown Box Clicking on this button expands a menu allowing the user to choose from a variable number of strings. This is used for items where the screen space is limited, or the number of strings is not known at compile time, such as screen resolutions. Image This object has no actual functionality. It exists only to display an image. Model Similar to the Image object, this exists only to display an .MD3 model. Page 18 of 128 Fight Zone Technical Design Document Graphics/Rendering Core Structure We will be using the part of DirectX 8 known as DirectX Graphics to display all portions of our game (henceforth referred to by its old name, Direct3D). We will also be using the DirectX 8 Utility library, as this provides many useful functions and structures such as vector and matrix classes, and texture loading. Interface The rendering engine will be encapsulated within the DisplayMgr singleton object, which exists in the dp namespace. This class may be accessed with the Get() function. While this class has many functions, only the most important will be detailed here. The DisplayMgr class relies on the use of three other classes, Camera, IndexBuffer and VertexBuffer. Camera The Camera class encapsulates all of the functionality required to view the world, including position, direction, field of view, and the generation of the required projection and view matrices. Function SetPosition, SetTarget SetFOV GetViewMatrix GetProjectionMatrix Reset MoveForward MoveHorizontal MoveVertical Description Both of these will take in a vector, such that the camera is located at the Position, and points toward the Target. The distance between these points is not important, but will be normalized internally. Sets the camera’s field of view to this angle in radians. This function takes in the address of a matrix, which it will then fill out with the appropriate view matrix, based on the internal data of Camera. This function takes in the address of a matrix, which it will then fill out with the appropriate perspective projection matrix, based on the internal data of Camera. Mostly used for debugging and possibly spectator modes, this resets the FOV and orientation of the camera to the default value. The position is not changed. This function will move the camera position forward (or backward, if the value is negative) This function will move the camera position sideways (also known as strafing). Positive values move in the +X axis direction. This function will move the camera position up and down. Positive values move in the +Y axis direction. VertexBuffer The VertexBuffer class encapsulates the required data structures for storing vertex data in a Direct3D-optimized form. As the vertices required for any given application may require different data, this class will also store the type of vertex. Function LockBuffer Unlock Buffer Description This will return a char* pointing to the existing buffer, with which the user can fill with vertex data. This is called when the user has finished filling the vertex Page 19 of 128 Fight Zone Technical Design Document SetShader buffer with data. While the shader is normally set to the vertex style, this function can be used if the user has created a vertex shader. When the VertexBuffer is created (see the DisplayMgr class description) the user must specify a vertex style and vertex size. This is a feature of DirectX that allows the user to create their own vertices with only the data they need. Here is a chart with the possible fields: The user can then create an array of the vertices, and memcpy() those into the VertexBuffer. It is important that the fields are in the order specified above, or they will not work correctly. To specify a field, the vertex style should be one or more of the following values logically OR’d together. D3DFVF_DIFFUSE D3DFVF_NORMAL D3DFVF_PSIZE D3DFVF_SPECULAR D3DFVF_XYZ D3DFVF_XYZRHW D3DFVF_XYZB1 through D3DFVF_XYZB5 D3DFVF_TEX0 through D3DFVF_TEX8 D3DFVF_TEXTUREFORMAT2 For more information on these, please consult the DirectX 8.1 SDK Help Files. Page 20 of 128 Fight Zone Technical Design Document Most access to the DisplayMgr class will use the following interface: Function Initialize Description This will take in an HWND. It will load the configuration file and initialize Direct3D, using the specified window. SceneBegin This will take in a const Camera reference, and will allow a scene to be rendered from the given camera position. SceneEnd This will flip the surfaces, displaying the scene. CreateVertexBuffer This will return a VertexBuffer* using the given vertex style and vertex count. Render This takes in a VertexBuffer*, the texture to use and a transformation matrix. This function then renders the vertex buffer to the screen. This function accepts a bool, and resets the device to either windowed mode or fullscreen mode. This is for use in WM_SIZE or similar messages. ToggleFullscreen 2D Images User Interface 2D images will be used for the HUD and Menu Systems. This is done by specifying the vertex style as D3DFVF_XYZRHW. This allows the user to specify screen coordinates for polygons on the screen. Particle Manager The particle manager will exist separately from other modules, and will be a singleton. Its sole function is the spawning, management, and destruction of groups of particles. The rendering process may be handled within the manager or particle class, or elsewhere if the Direct3D code is general enough to exist outside. Particle effects will be rendered using Direct3D. Specifically, it will be accomplished using ‘point sprite’ support, which is a hardware-accelerated method to easily specify billboarded quads by center points. The manager will accept a variable amount of input when the client wishes for particles to be spawned. A non-exclusive list of options is: particle size, amount of particles, texture, weight, force/velocity, and a random variance factor. Additionally some particles will just be drawn, and some will be drawn and have physical properties. The different types of particles the manager will handle so far are decals, billboards, and models. Special Effects The special effects we will demonstrate in the game are explosions, smoke, dynamic lightning, and possibly motion blur if time permits. At this time, the exact method of some of these effects is unknown, except through the use of Direct3D. These will be added if time allows. Page 21 of 128 Fight Zone Technical Design Document Smoke and explosions can be handled through the particle manager. Motion blur is simple enough to implement; just draw the object several times with a positional offset, and draw the versions behind the real object more transparently. Dynamic lighting will be researched when the time comes. Models Models will be drawn using Triangle Strips whenever possible. This method is highly optimized in most graphics accelerators, and allows the drawing of many triangles. 4 6 8 2 10 3 5 7 9 1 A sample Triangle Strip. For each additional triangle drawn, only one extra vertex is specified, and the last two vertices from the previous triangle are used. This also means that the vertex order is reversed every triangle. (The vertices are specified in a counter-clockwise order instead of a clockwise order, or vise-versa) However, this is all taken care of by the hardware. Player Models The Quake 3 MD3 model file format was used to represent 3D models graphically in Fight Zone. A player model requires 6 MD3 models; an armored and unarmored model for the head, torso, and legs. Upon calling the initialization function, pass the names of 2 directories where full player models, animation data, and texture data can be found; one for the armored model and the other for the unarmored model. Flags can be set for the head, torso, and legs to determine the armor state. This allows separated pieces of armor to break off. Class Q3Model Nothing This class stores information for a player model. Description Data Description Head model The unarmored head MD3 model Torso model The unarmored torso MD3 model Leg model The unarmored leg MD3 model Armored head model The armored head model Armored torso model The armored torso model Armored leg model The armored leg model Head armored If the head has armor on Torso armored If the torso has armor on Leg armored If the legs have armor on Torso animation data Torso animation data structure array Leg animation data Leg animation data structure array Current torso animation The current leg animation Derived From Page 22 of 128 Fight Zone Technical Design Document Current leg animation Head render Torso render Leg render Torso frame Leg frame Torso frame time Leg frame time The current leg animation The head render structure for D3D The torso render structure for D3D The leg render structure for D3D The current torso frame of animation The current leg frame of animation The frame time of torso animation The frame time of leg animation Game World The game world will be drawn primarily with Triangle Fans. A Triangle Fan is similar to a triangle strip, but the first vertex specified is used for all triangles in the fan. 3 2 4 1 5 6 A sample Triangle Fan. Triangle fans are used to draw n-sided polygons. While this is usually not as optimized as a Triangle Strip, it is more efficient than drawing single triangles. BSP-Tree Rendering Our levels will be rendering using a Binary Space Partition (BSP) tree. This tree repeatedly divides the world into halves based on convex polygon sets. Then, after the level is divided, each polygon set creates a list of all of the other sets that are visible from it. When the level is drawn, the BSP tree is traversed to find the camera’s location, then the current polygon set is drawn. The other visible polygon sets are then drawn in a recursive function. The polygons are sorted using the Z-Bufer Page 23 of 128 Fight Zone Technical Design Document In this screenshot from Quake 3, the player was standing on the X (the lines represent the player’s FOV), when the console command “r_lockpvs 1” was entered. This tells the engine to render the level as if the player were always located at that point, allowing the player to walk around the level and see exactly what parts of the level are being drawn. It is fairly clear that the rooms behind and in front of the player are being drawn, but the rest of the level is not being drawn. The level will be stored and drawn by the cWorld class. Class World Derived From [Nothing] Description This class stores and renders Quake 3 BSPs Description This is the vertex buffer containing all of the vertex data for the level. A list of all of the BSP nodes A list of all of the BSP leaves A list of all of the Potentially Visible Sets A list of lightmap textures A list of lightmap textures Description Determines if one cluster is visible from another cluster Finds which BSP leaf the given position is in. Renders a single face of a polygon set. Loads/Unloads a level. Data CVertexBuffer* Node List Leaf List Cluster List Lightmaps Textures Function IsClusterVisible FindLeaf RenderFace Load, Unload Lighting For lighting, we will be using the lightmaps included in the BSP file. These are stored as 128x128 arrays of 24-bit values. These are then converterd to textures. Page 24 of 128 Fight Zone Technical Design Document A screenshot of Quake 3, minus textures. A lightmap from Quake 3. Notice the light rectangle in the left corner of the light map? That is the lightmap for the outlined portion of the screenshot. The lightmap and the texture are multiplied together, which results in the texture appearing lighter or darker in different areas. ( TextureR x LightmapR ) / 256 = Displayed Red Value ( TextureG x LightmapG ) / 256 = Displayed Green Value ( TextureB x LightmapB ) / 256 = Displayed Blue Value While this may seem like an expensive computation, it is done in hardware with a second texture pass. Also, the light map shown above is at 150% normal size. This means that it does not take up very much texture memory. When it is rendered, it is stretched to fit the size of the polygon and bilinear filtering is used to smooth it out. Page 25 of 128 Fight Zone Technical Design Document Art Some of the file formats mentioned below are property of Id Software. This is a quote from John Carmack (From www.flipcode.com): "We do not legally protect the file formats, but you can't use any of the released tools, or tools derived from them (except the GPL'd Quake 1 tools) to generate content for a commercial venture. If you are writing everything yourself, no problem." While Fight Zone is not a commercial venture, we will be creating our content in 3D Studio Max and using exporters, which were not written by Id. Player Models Player models will be stored using Id Software’s .md3 file format. This format is extremely flexible, and has a large existing base of models that we can use for testing. If a player wishes, they will be able to use an existing Quake 3 model in our game, but we will not be including any. This format has the fortunate side effect of matching our damage system. Each model consists of a Head, Torso and Leg model, all of which are animated independently. This means that we will have 2 player models, one with armor, and one without. When a player loses a piece of armor, we will swap that part of the model for the unarmored version. The models should consist of no more than 1 texture per body part, (3 textures maximum) and have a total polycount of no more than 800. Higher polycounts may be allowed upon further development and testing of the graphics engine. Item/Weapon Models Since these models have no animations, we will be using Microsoft’s .X file format, which is easily exportable from 3D Studio Max. This format is extremely flexible, but we will only be using it to store vertex positions, texture mapping coordinates, and polygon normals. The exporter included with the DirectX SDK does not have all of the options we need, but there is an exporter made by Pandasoft that does. It can be obtained at: http://www.pandasoft.demon.co.uk/directx.htm. The polycount should be kept relatively low for these models, as there may be many on the screen at any give time. Each model should only have 1 texture. Levels Levels will be stored using Id Software’s .bsp format. While there are many versions of this format, we will be using the version used for Quake 3. The poly count here will vary widely, as the use of Potentially Visible Sets will limit the number of polygons that the engine will try to render. Therefore, both large and small levels will be easily rendered. Note: Both the .BSP file format and the .MD3 file formats make extensive use of “shader” files, which allow the creators to specify special effects to be applied to both models and textures. Due to the engine specificness and complexity of these shaders, we will not be implementing these unless time allows. Page 26 of 128 Fight Zone Technical Design Document Textures Textures are allowed to be in a wide variety of formats, but there are 3 main formats that we will be using. .BMP .JPG .TGA For images that are required to have a high level of detail. For bulk quantities of images. (i.e. Level textures) For images requiring alpha transparency. Textures should be 24 or 32 bit as required, and should attempt to be 256x256 pixels in size. If a different size is required, its dimensions must be a power of 2. Any textures not of this size will be stretched to the next power of 2 by the hardware. Required Art Levels We require 4 arena-style levels. The levels may share textures, and should be compiled into the Quake 3 .BSP file format. Static Meshes 3D Objects with no animations will be stored in Microsoft’s DirectX file format. Each model will consist of 1 model and 1 texture. Rocket Grenade EMP Mine Stasis Mine Explosive Mine Ammo Pack Third Person Sword Third Person Gun Cambot Animated Meshes The Animated meshes will be using the .md3 format, but not the associated skin and config files. Robot - Firing Animation First Person Sword - 3 Swing animations First Person Gun - Fire MD3s Armored Gladiator Unarmored Gladiator 2D Particle Sprites We will be tinting the Grayscale Explosion sprite to match the type of explosion. Bullet Sparks Laser Page 27 of 128 Fight Zone Technical Design Document Armor Shards Plasma Shot Smoke Grayscale Explosion Sprite 2D Images Explosion Mark Bullet Hole User Interface HUD UI Object Textures Instruction Booklet Art Box Art Page 28 of 128 Fight Zone Technical Design Document Sound SoundMgr class Description The sound manager is a class designed as a wrapper around the functionality of FMOD, a third party audio library. The class, like the other manager classes, is implemented as a singleton since only one instance is necessary per instance of the application. The sound manager, as the center of the audio functionality has several responsibilities. When the application is launched, the sound manager is responsible for initializing the FMOD system. The most important aspect of initialization is that software channels are allocated at this time for use throughout the lifetime of the application. While the game is running, the primary interaction with the sound manager is requesting a handle to a sound. These handles are used primarily to start playback of a sound, but they also allow other types of configuration for individual sounds. Besides handling sound requests, the sound manager will handle external requests for volume change, switches between 2D and 3D sound, and updates of the listener position when 3D sound is active. Internally, the sound manager will be busy interacting with the sound class. Every time a sound is requested that does not exist already in memory, the sound manager loads the sound into a Sound object. These sound objects are kept in a list inside the sound manager. This list is used to determine whether or not a sound is already loaded when a request comes in. The sound manager also keeps a list of all of the channels and their status. Whenever an object asks to play a sound, the corresponding Sound object must get a free channel from the manager to pass into the playback function from the FMOD library. While FMOD has default channel management built in, another level of management is necessary to make sure static samples, looping samples, and streams are properly controlled when particular system events occur. The sound manager has a limited cast of supporting classes: the Sound class, the SoundBuffer class, and their corresponding handle classes. Sound class description The sound class is the class directly managed by the sound manager. Sound objects act as wrappers to the sample and stream handles received from FMOD. The Sound object maintains a reference count based on how many handles it has active. When all handles referring to a given Sound object pass out of scope, that Sound object asks the sound manager to destroy it. The Sound object has two basic interactions with objects outside of the sound system. First, the Sound object contains the functionality for actually playing a sound. When an object calls the play method of the Sound object, the Sound object retrieves a free channel from the sound manager and calls the play function from the FMOD library. Upon playing, the Sound object creates a SoundBuffer object and returns a buffer handle to the user. The initial properties of playback for a given sound are also set through the Sound object. Through the SetDefaults method, an object can alter the default looping, volume, panning, and priority for a sound. Just as the sound manager maintains a list of Sound objects, the Sound class has a built-in list to track buffers. The Sound object uses this list upon its destruction to make sure that any buffers that it has created are destroyed. Since the Sound class retrieves free channels from the sound manager for the SoundBuffer objects that it creates, it is also responsible for informing the sound manager that a channel is free when the SoundBuffer is destroyed. Page 29 of 128 Fight Zone Technical Design Document SoundBuffer class description The SoundBuffer class contains the functionality to control a sound that is currently playing. This functionality is actually based around altering properties of the sound channel in which a sound is playing. In fact, the methods of the SoundBuffer class are slightly modified versions of the functions of the FMOD library, tied to the channel stored in the SoundBuffer object. The SoundBuffer class is necessary for changing the properties of a sound that is currently playing. As in the Sound class, the SoundBuffer class controls the volume and panning characteristics of a sound. In addition, the SoundBuffer class can be used to pause or stop a sound. Unlike the Sound class, which may have multiple handles out at a time, the SoundBuffer class has a one-to-one correspondence between its instances and its handles. But the SoundBuffer class is similar to the Sound class in that it asks for destruction when its handle goes out of scope, bringing its reference count to zero. Handle class description The handle classes, SoundHandle and SBufferHandle, are essentially copied from the Resource Handle class. These handle classes handle the reference counting for the Sound and SoundBuffer classes. All of the functionality of the Sound and SoundBuffer objects is accessed through their handle classes. Just as with the Resource Handles, the handles for the Sound and SoundBuffer objects can only have values assigned to them by the sound manager or the Sound object that created them. Required Sounds Music Music will be made by Austin Haynes. All of the music should have a very strong Techno Rock feel. We want one song for use as the game theme, and 4 other songs for general purpose. Sound Effects Sound Effects will be made by Mike Jones. All sounds with *’s are sounds that require multiple sounds to increase variation. Weapons Machine Gun Fire* Sniper Rifle Shot* Bullet Hit Wall/Armor* Bullet Hit Organic* Sword Swing* Sword Hit Wall* Sword Hit Organic* Rocket Launch Rocket Thrust Grenade Launch Grenade Bounce* Generic Explosion* Plasma Shot Single bullet firing from a machine gun. Large Caliber rifle shot Bullet ricochet sound Squelch sound Star Wars-style lightsaber sound. Electric fizzle sound Burning flesh + lightsaber sound Thoom! FFFFFFFfffffssssssshhhhhhhh! Fwoomp! Metallic Clank Kaboom Electric pulse with a hint of a thud. Page 30 of 128 Fight Zone Technical Design Document Plasma Explode Plasma Charge Plasma Big Shot Release Plasma Big Shot Explode Laser Shot Laser Hit/Bounce* Mine Drop EMP Explode Gravity Well Stasis Explode Electrical Discharge. Electronic buzz, looping Like Plasma Shot, only with more substance, and an electric crackle. Like Plasma Explode, but bigger Bwap! Bee-yyouun Clank BFG from Quake 2 Sucking sound Like an electric motor running down, (think the sound of a robot running out of energy) UI Click Button Roll-overs Button Title Screen Sound Umm.. Click? What ever you want Menu sliding on to screen, monitor powering up, etc. Gladiators Hit for Damage (Vocal)* Death* Jump* Footstep* Jetpack Ammo Pickup Armor Destruction Spawn Reloading Weapon Changing Ow, Ouch, Ungh, Eh, etc. AAAIIIIIIEEEE!!!!, UUUuuunnnnggggghhhhh Hgh!, Ungh, Hup! Single footstep sounds, Electric Hum Ka-Click Metallic Shattering Bshhhnn Clck-Shick, pause, Shick-Click, ka-click chkchkchk Cambots + Robots Thruster Hit for Damage* Death Misc. Announcer Sounds These sounds should be things like, “Game Over”, “Fight”, or “Did you see that shot?!”. These will be implemented as time allows. Page 31 of 128 Fight Zone Technical Design Document Input The input manager is built as a singleton class named “InputMgr” that exists within the “dp” namespace and can be accessed through the static member function of the class named “Get()”. For a source file to make use of the input manager, it must have “InputMgr.h” included. Keyboard Input Un-buffered Input To bind a key to a command, the InputCommand enum must first have the proper command defined. Once it is defined, all that is required is that the user call the Bind() function, which takes in the enumerated command and a Direct Input Keycode. (DIK code) To see if a command is pressed, the user only has to call the IsCommandOn() function, which takes in an enumerated command. This allows the rebinding of keys while being transparent to the rest of the program. Buffered Input For name and chat entry, we will use buffered input. Without buffered input, the player’s typing speed is limited by the framerate of the program. Buffered input allows characters pressed between frames of logic to register. Mouse Input Mouse input will be fairly simple, with GetMousePosition() returning a vector, and IsRightMouseButtonDown() and IsLeftMouseButtonDown() returning bools Page 32 of 128 Fight Zone Technical Design Document Artificial Intelligence Fight Zone will have computer-controlled players (bots) that will fight against other computercontrolled players as well as human controlled players. The bots will have 3 levels of difficulty: easy, normal, and hard. Path-Finding and Obstacle Avoidance In order to implement Obstacle Avoidance for our AI Agents, we will train an Artificial Neural Network (ANN) to avoid hitting walls and to explore the level (the level is the area where the game takes place). However, we would not want to let the ANN have full control of the bot’s navigation, so the level may be broken into a 3D grid that can store connectivity information. Let’s say a bot travels from one area to another, then it can be recorded that these two areas are connected. Using this information, the A* algorithm can be used to find a path from one location to another. Obstacle Avoidance Using Neural Networks Giving the bot some proximity sensors to detect distances to obstacles, as well as information about areas in the game that it has not visited, we may train the ANN to assists the bots in their navigation. Below there is a 2D illustration of a bot and it’s proximity sensors. Why should this technique be used? Neural Networks are good at finding complex solutions by using high-level parameters in the fitness functions. For example, suppose our fitness function gives low scores to bots that turn too much, hit too many walls, and scores higher for bots that explore more of the level. Using a genetic algorithm, we can evolve the good performers and over time should get a good solution to the problem. Page 33 of 128 Fight Zone Technical Design Document The complexity of real-time obstacle avoidance should be considered. Can we find an algorithm to achieve this goal? Using the sensor data and the connectivity graph, can we get good looking bot movements for wandering, fleeing (from opponents), and chasing states? If we can, then the Neural Network solution should not be used. Otherwise, a Neural Network solution may be followed. Path-Finding Using a 3D Connectivity Grid What is the Purpose of Path Finding? Assuming that the bots can wonder around the level, what would path finding be used for? In Fight Zone, there are no power-ups to collect, so finding weapons or armor is not a priority. However, when an opponent is killed it drops its ammo. It would be desirable for the bots to be able to efficiently find their way to that ammo given its world position. Another time when path finding would be desired is if the bot wants to reach the location of an annoying sniper or a particular location in the map where there has been lots of fighting. Many games have used waypoints for path finding, usually placed in the level by the level designer. In considering the techniques to use in this game, a solution that would require no human waypoint placement was desired. However, human placement of waypoints may be considered if the following solution is found to be inappropriate. The Grid We can break up the level into a 3D grid of cells in the same way that a 2D side-scrolling game can be divided into a 2D grid of tiles. Within these cells, a certain number of waypoints can be placed. The purpose of doing this is to create a connectivity graph to be used for path finding. As the bots travel around the level, they can fill in this connectivity chart as they travel from one area to another. Let us look at a 2D example of this. The picture above illustrates some of the advantages and disadvantages of using such as system. Some of the disadvantages are that some obvious connections might be missed, such as Page 34 of 128 Fight Zone Technical Design Document the two black waypoints. One way to fix this problem would be to add more waypoints. This would help to a certain extent, with a downside being that the amount of memory to hold this information would increase. Another solution would be to consider more than straight lines for connections. If a bot reaches one of the black waypoints from the other, then a connection may be recorded. When a bot needs to find a path using these two waypoints, then it should be able to sense the wall in between them and find a way around it. Memory Considerations A major concern when considering such a data structure is the amount of memory that it would require. An efficient way to store all of this information must be found in order for this solution to be practical. We can take advantage of the uniformity in the waypoint layout in order to reduce the memory size. Lets assume that the world above is 75x75 units. Each cell is a 25x25 unit in area. Each waypoint is a certain known offset into the cell. Using this information, the position of each waypoint can be determined at runtime. For example, let’s say that a bot is at position (48, 23). Dividing each number by 25 we figure out that it is in cell (1, 0). From there we can calculate the closest waypoint to the bot. A single waypoint’s connections can be encoded using a maximum of 2 bytes. One byte can represent connections to the waypoint located to the north, south, west, or east from the perspective of the waypoint (going out of the waypoint). A bit with zero would indicate that there is no connection available, and a one would represent a valid connection. The other byte would indicate if the connection has been examined. Knowing if a connection has been examined would not be necessary if the level was preprocessed, therefore reducing the memory requirements by half. It is easy to see how to extend this to 3D, in which only two more connections would be considered (along the extra axis). Preprocessing the Level While the connectivity determination could be done dynamically at runtime as the bots explore the level, it would probably be best to do some preprocessing of the level. Preprocessing the level would reduce the runtime complexity in terms of memory, as well as eliminate the need to completely learn the environment at runtime. A simple line segment intersection could be used during the preprocessing stage (with considerations such as jump height), and the bots could update the connectivity graph as they find complex connections at runtime. The updated connectivity could be saved at the end of the game, so it is more accurate the next time the level is played. Further thoughts Information such as popular fight zones, as well as locations where the bot has scored kills or been killed, may also be associated with this world representation. For example, grid cell (x, y, z) may be considered a popular fighting spot. Such information should be stored in a separate data structure that relates to a particular area in the grid. Bot Upgrade Logic In Fight Zone, certain aspects of the weapons and armor can be upgraded. When it is time to upgrade, if the bot has been loosing then it should redistribute its upgrade points in an attempt to be better prepared for the next battle. By keeping certain information such as what piece of the armor was destroyed first, the bot will decide what to upgrade based on that information. Page 35 of 128 Fight Zone Technical Design Document AI Agent Architecture AIBehavior The top level AI class is the AIBehavior class. The AIBehavior class has instances of the AIAnimation, AICombat, and AIMovement classes. AIBehavior uses the other classes to carry out the functions of the main AIAgent state machine. The different behaviors of the AIBehavior class will be managed using a Finite State Machine. Some of the behaviors that the AIBehavior class are: Searching: This is the initial state of the agents. In this state, the agent will look for an opponent to engage in combat. Combat: This behavior will be used when the AIAgent is fighting another agent. Control of the agent will be passed over to the AICombat object. Retreat: If the AIAgent is taking to much damage, it might decide to retreat. In this behavior, the AIAgent will try not to flee from combat. Following/Chase: If the agent’s opponent tries to flee from combat, the AIAgent may try to follow the opponent in order to try and score a kill. class AIBehavior enum BEHAVIOR { SEARCHING, COMBAT, RETREAT, FOLLOW, }; void Update( ); //determines the current actions of the agent BEHAVIOR GetBehavior( );//returns the current behavior AICombat The AICombat class takes care of the fighting functionality of the computer-controlled characters. When the AI agents are engaged in combat, the AIBehavior class passes control to the AICombat class. A Finite State Machine that takes care of different combat states is implemented in the AICombat class. Some of the combat states that will be implemented are: Camp: The agent waits in a hidden location and waits for opponents. When the opponents show up, the agent shoots at it from the hidden location. Joust: The AIAgent tries to get behind its opponent and shoot it from behind. Circle Strafe: The AI moves in circles around its opponent while firing. Flee and Ambush: The computer controlled character runs from its opponent and waits behind a corner waiting for the opponent to follow it. When the opponent shows up, the AIAgent will fire at it. class AICombat enum COMBAT_STATE { CAMP, JOUST, CIRCLE_STRAFE, FLEE_AND_AMBUSH, }; Page 36 of 128 Fight Zone Technical Design Document void Update( );//determines the current combat actions COMBAT_STATE GetCombatState( ); Choosing When to Miss or Hit an Opponent One of the differences of the different difficulty agents is their chance to hit or miss while shooting. The AI agents in Fight Zone will use a formula to determine if they should attempt to hit their opponent or miss with their shots. Different factors with values between 0 and 1 (where 1 means that the agent should hit and 0 means the agent should miss) are multiplied out to get a final value between 0 and 1 (the output value starts at 1). At that point a random number is picked. If the number is higher than the computed value then the AI should attempt to miss, otherwise the AI should attempt to hit its opponent. Factors that will be considered include AI skill, distance to opponent, relative velocity, and AI behavior state. What the bot can sense in the world In order for the bots to be able to fight, they need to know what is happening in the world. Sight A Line Of Sight algorithm will be needed to determine what opponents are visible. Hearing It will be desirable for the bots to be alerted of nearby sounds. If footsteps sound effects are implemented in the game, then the bots should be able to be notified of nearby footsteps. More importantly, nearby gunfire should be reacted to, especially if it was aimed at the bot. This functionality could probably be accomplished by letting the bots know of any gunfire within a certain distance of it. AIMovement The AIMovement component of the AIBehavior class takes care of moving the AIAgent around the game world. One of its functions is to encapsulate the path finding and obstacle avoidance components of the game. The AIMovement class does not determine where to move, only how to get there. Below is the prototype of the AIMovement class: class AIMovement //This function calculates the path to the new position and starts //moving the AIAgent. void MoveTo( VECTOR v //the position to move to ); //The StopMovement function makes the agent stop moving. void StopMovement( ); void TurnToAngle( VECTOR v //direction to turn to ); Turns the agent in the direction of the VECTOR v; Page 37 of 128 Fight Zone Technical Design Document void MoveInFormation( FORMATION _f, //the type of formation const Agent& _agent //the opponent ); Move in the specified formation relative to the specified Agent. enum FORMATION{ STRAIGHT, //move in a straight line CIRCLE, //move in a circular direction STRAFE, //strafe to the sides }; Artificial Neural Networks When using ANNs, some way of teaching it is required. One way to evolve the neural network is by using Genetic Algorithms. A Genetic Algorithm class that performs the operations of reproduction (picking two parents), crossover (merging two parents to produce offspring), and mutation (randomly changing the offspring) will also need to be implemented. class Neuron { //number of inputs to neuron int m_numInputs; //weights vector<double> m_weights; public: Neuron(int num_inputs); }; class NeuralLayer { //number of neurons in this layer int m_numNeurons; //vector of neurons vector<Neurons>; NeuralLayer(int num_neurons, int inputs_per_neuron); }; class NeuralNet { int m_numInputs, m_numOuputs, m_numHiddenLayers, m_numNueronsHiddenLayer; vector<NeuronLayer> m_layers; public: vector<double> GetOutput( ); void LoadWeights(vector<double>& w); vector<double> GetWeights( ); Page 38 of 128 Fight Zone Technical Design Document }; Below a prototype of the minimum requirements for a Genetic Algorithm: class GeneticAlgorithm { vector<NeuralNet>& Reproduce(vector<NeuralNet>& n); NeuralNet CrossOver(NeuralNet& mom, NeuralNet& dad); void Mutate(NeuralNet& n); }; Finite State Machines What is a Finite State Machine (FSM)? A FSM is a collection of states. An FSM state defines the current behavior of the AI character, as what has to happen to go to another state. A transition is a condition, and an output state to transition to when the condition is met. Conditions can be defined as a variable, a boolean function, and a value to be compared against. Below is a visual example of a finite state machine that could be used to model the behavior of one of the AI bots in the game. The FSM states are shown by rectangles. Transitions are shown as circles with arrows pointing to an output state. Inside of a transition is a condition. Another way to visualize a state machine is in a tree structure: Page 39 of 128 Fight Zone Technical Design Document -FSM { -State_N { -Transitions_N { -Condition { -Variable -Function -Value -Output State } } -Transition_N+1 { ... } } -State_N+1 { ... } } } Using the FSM tree structure, the file format can be defined as follows: [STATE_NUMBER] STATE = STATE_NAME CONDITION_NUMBER_VARIABLE = FSM_VARIABLE CONDITION_NUMBER_FUNC = FSM_FUNCTION CONDITION_NUMBER_VAL = VALUE OUTPUT_STATE_NUMBER = OUTPUT_STATE_NAME Ini files (also know as configuration files) are used for the FSM file format, since they are easy text based and easy to load. The above FSM can be defined as follows: [STATE_0] STATE = SEARCHING CONDITION_0_VAR = DISTANCE_PLAYER CONDITION_0_FUNC = LESS_THAN CONDITION_0_VAL = 40 OUTPUT_STATE_0 = COMBAT [STATE_1] STATE = COMBAT CONDITION_0_VAR = HEALTH CONDITION_0_FUNC = LESS_THAN CONDITION_0_VAL = 25 OUTPUT_STATE_0 = FLEE [STATE_2] STATE = FLEE CONDITION_0_VAR = ENEMY_STATE Page 40 of 128 Fight Zone Technical Design Document CONDITION_0_FUNC = EQUALS CONDITION_0_VAL = ATTACKING_ME OUTPUT_STATE_0 = COMBAT CONDITION_1_VAR = HEALTH CONDITION_1_FUNC = GREATER_THAN CONDITION_1_VAL = 50 OUTPUT_STATE_1 = SEARCHING [STATE_3] STATE = CHASE CONDITION_0_VAR = STATE_TIME CONDITION_0_FUNC = GREATER_THAN CONDITION_0_VAL = 10 OUTPUT_STATE_0 = SEARCHING In order to achieve less predictable behavior from the bots, a Fuzzy State Machine extension to the following state machine class will be developed. The Condition and Transition Classes The FSMCondition and FSMTransition class definitions come directly from the FSM file format. We will look at the FSM state class further along in this paper, but for now remember that the FSM state class will have a collection of FSMTransitions that it will use to determine if there needs to be a state change based on an input into the FSM. Below are C++ classes for the FSM transitions and conditions: class FSMCondition { public: //the type of variable for this condition FSM_VARIABLES variable; //the comparison function FSM_FUNCTIONS function; //the value to compare against int value; }; class FSMTransition { //condition to be evaluated FSMCondition m_condition; //the state to transition to FSM_STATE_NAME m_outputState; public: bool ConditionFulfilled(int value) { switch (m_condition.function) { case NONE: return true; case EQUALS: return m_condition.value == value; case GREATER_THAN: return m_condition.value < value; case LESS_THAN: Page 41 of 128 Fight Zone Technical Design Document return m_condition.value > value; default: return false; } } }; The ConditionFulfilled( ) function is used by the FSM state class when evaluating state transitions. ConditionFulfilled( ) compares the input value against its own condition value using the condition function. When it returns true, it is indicating that there should be a change of states in the state machine. FSM State Objects (TFSMState) template <class T> class TFSMState { //std map of state transitions TransitionMap m_transitionsMap; FSM_STATE_NAME m_stateName; public: //constructor – initialized with the state name CFSMState(FSM_STATE_NAME state_name); FSM_STATE_NAME GetName() { return m_stateName; } //add a state transition, used during load time void AddTransition(FSMCondition condition, FSM_STATE_NAME output_state ); //look for an FSMTransition in the map that //matches the input condition variable, and // evaluate the transition. Return the output //state FSM_STATE_NAME TestCondition(FSMCondition condition); //sets the functions associated with this state void SetFunctions(T* pInstance, PMemFunc pOnEnter, PMemFunc pOnUpdate, PMemFunc pOnExit); //calls the OnEnter, OnExit, or OnUpdate functions //using the pointers to member functions void OnEnter(); void OnUpdate(); void OnExit(); }; The TFSMState::AddTransition( ) member function takes a FSMCondition, along with the output state, constructs an FSMTransition from them, and adds the new FSMTransition to the transition map. Page 42 of 128 Fight Zone Technical Design Document The TFSMState::TestCondition ( ) member function takes an FSMCondition as an argument, matches up the input condition’s variable member with one of the FSMTransitions in the transition map, and calls the FSMTransition’s ConditionFulfilled( ) function. If FSMTransition::ConditionFulfilled( ) returns true, then CFSMState::GetOutput( ) returns the output state of the transition, otherwise it returns the ID of itself , indicating that no change of states is necessary. TFSMState::SetFunctions( ) is used to store pointers to member functions that will be called when entering, exiting, and updating a state. The first parameter is the this pointer of the class who owns the functions, and the other parameters are the respective callback functions. The Finite State Machine Class (TFSM) The FSM class is the only FSM-related class that the client needs to use. Below is the partial definition for the TFSM class: template <class T> class TFSM { //map containing all states of this FSM StateMap m_statesMap; //name of current state FSM_STATE_NAME m_currentState; //adds a new state to the state machine void AddState( State new_state ); public: //calls exit function for current state ~TFSM( ); //adds a set of OnEnter, OnUpdate, and OnExit //functions for a particular state void AddStateFunctions(T* p_instance, FSM_STATE_NAME state_name, PFUNC p_OnEnter, PFUNC p_OnUpdate, PFUNC p_OnExit); //test the input condition for a state change. If //there is a state change, the corresponding //OnEnter( ) and OnExit( ) functions are called. //Returns the name of the output state FSM_STATE_NAME EvaluateTransition(FSM_VARIABLES var, int val); //Executes the OnUpdate( ) function for the active //state void ExecuteStateMachine( ); //returns the enum value of the active state FSM_STATE_NAME GetCurrentState(); //Instantiates an FSM as define by input file void LoadStateMachine(LPCSTR file_name); }; Page 43 of 128 Fight Zone Technical Design Document The AddStateFunctions( ) method is used to set the OnEnter, OnExit, and OnUpdate functions for the state specified in the second parameter. This function would be called, after loading the state machine, for every state that the FSM wishes to handle. The EvaluateTransition( ) function handles input to the FSM. It takes a FSM_VARIABLE and a value as the input to the state machine. This variable/value pair represents what is currently going on in the game. This is passed along to the active state’s TestCondition( ) function, where the state determines if a state transition is necessary. The last member function listed, LoadStateMachine( ), loads the finite state machine logic from an external data file. When loading the state machine from a file, one can instantiate a local TFSMState, add transitions to it by using the TFSMState’s AddTransition( ) function, and pass it by value into the AddState( ) function, where it will be copied into the TFSM’s map of TFSMStates. Page 44 of 128 Fight Zone Technical Design Document Physics Motion The following is a breakdown of the motion physics that will be applied to all moveable objects. Players: Moving player objects work under a force system, and so each contains a mass for determining inertia, momentum, etc. Directional input applies a new force to the player object, thus changing its acceleration and ultimately affecting the velocity. Player objects’ accelerations when moving are determined by their mass (due to inertia), which changes depending on the state of their armor. As they lose armor pieces, they become less massive and will accelerate faster, but will have a lower momentum at top speed. All player objects are constantly affected by gravity (note: in Fight Zone, gravity is less than Earth’s 9.8 m/s2), and so will take damage when falling from great heights. The damage is determined by the amount of force applied to the player upon impact. However, a player with an upgraded jumping ability can sustain higher forces when landing from a fall than a player without upgraded jumping. Players' hover-packs gently counter both upward and downward movement until their velocities reach 0 in the y direction. For example, if a player jumps and is moving up, the hover-pack, if activated, will gently slow their ascent until they are simply hovering. If a player is falling, the hover-pack applies a gentle force in the upward direction and slows their descent. Only walls and floors apply friction to moving objects. Projectiles: With the exception of grenades, all projectiles completely ignore gravity. Furthermore, projectiles themselves do not have mass, and so do not apply forces to objects when striking them. However, projectiles that explode upon impact will impart forces on all objects within their explosion radii. This force can be represented by a line from the center of the explosion to the center of the object within the explosion radius. Regular bullets, fired from the machine gun or sniper rifle, do not have velocities. They instantly strike the first object that is in their line of would-be travel. Rockets, plasma balls, grenades, and lasers, however, have velocities and accelerations (even if the acceleration brings them to their maximum velocity instantly). Data Types Velocity: Velocity is stored as a vector that contains the direction of movement and the magnitude. Acceleration: Acceleration is stored as a vector that contains the direction of acceleration and the magnitude. Force: Force is stored as a vector that contains the direction of the force and the magnitude. Mass: Mass is stored as a float. Page 45 of 128 Fight Zone Technical Design Document Physics Loop The physics is handled in the following steps: 6) Input is taken and new forces are determined. 7) A new net force is calculated for each moving object, which yields a new acceleration and thus a new velocity for this frame. 8) Using the newly calculated velocities, all objects are checked for collisions. 9) When collisions occur, they are handled appropriately and objects are given new forces, accelerations, or velocities. They are then rechecked for more collisions during that frame. 10) Objects are moved along their final velocities to their new positions and are ready for the next frame. Collision Detection Overview Though a complex problem as a whole, collision detection is simplified in Fight Zone by separating all objects in the game world into two categories: dynamic and static objects. With this distinction, only two types of general collisions exist: 3) 4) Dynamic objects colliding with dynamic objects. Dynamic objects colliding with static objects. Obviously, a static object can never move into another static object, so collision between them is not checked. A problem that needs to be taken into consideration in every type of collision detection is two objects in the list may collide, but that doesn’t mean another object that will be checked later wouldn’t collide with one of them earlier. Therefore, a list of collisions must be kept so that if, for example, a bullet collides with a player at some time t0, and it collides with another player at time t1, the collision with the earlier time can be kept in the list and the other collision removed. Collision Objects and Volumes Players: Player objects utilize the following collision volumes: 3) Encompassing hit boxes for projectile collisions. 4) Spheres for player-to-player collisions, trivial rejections of objects that will never collide with players, and collisions with walls. Projectiles: In addition to player volumes, projectiles are treated as rays to simplify the calculations of detecting collisions between moving players and moving projectiles between frames. Walls: Naturally, walls are treated as planes. By using the vectors normal to the planes, calculating collisions, reflections, etc. becomes relatively simple. Page 46 of 128 Fight Zone Technical Design Document Methods of Collision Detection Projectiles to players: As noted above, projectiles are treated as rays. In each new frame, their origin becomes their location at the end of the previous frame, and their final destination becomes their origin plus their velocity vector. The first step in detecting collision between projectiles and players is to trivially reject any projectiles that will never collide with a given player. This is done by creating a sphere that encompasses a given player’s entire movement volume: Sphere around movement volume. Beginning of frame. End of the frame. Each projectile is checked with each player’s encompassing movement sphere. If a projectile passes through this sphere, there is a chance it could collide with the player object, and further calculations, listed below, must be carried out. Otherwise, if a projectile does not pass through this sphere, it is guaranteed that it will not hit the player. If a projectile passes through one or more of these spheres, it must then be checked for collision with the player’s actual hit box. The first step is to take the player’s velocity and subtract it from the projectile’s velocity. By doing this, the player can be treated as a stationary object, thus making the interpolation calculations much simpler. Then the ray must be checked for an intersection with any given face (plane) on the hit box. If a collision occurs, the remaining faces can be ignored. At this point, if a collision with a given plane has occurred, all that remains is to check the height of the collision to make sure it was within the player’s hit box. If a collision did not occur and a projectile passed through more than one player’s movement sphere, collision with those remaining players would still need to be checked. Player to player: Player to player collision is detected by creating a sphere around each player’s movement volume (see diagram above) and then determining if any two spheres overlap. If so, collision between the actual players must then be checked. The following diagram gives a 2D example of two circles that could potentially collide during a frame: Page 47 of 128 Fight Zone Technical Design Document A1 B1 Va * t Vb * t A0 B0 AB = B0 – A0 Using the vectors A(t) and B(t) such that A(t) = A0 + Va * t B(t) = B0 + Vb * t The distance between the lines of movement can be calculated by [ B(t) – A(t) ] * [ B(t) – A(t) ] The time of the first collision can be calculated by solving for t such that [ B(t) – A(t) ] * [ B(t) – A(t) ] = (Ra + Rb)2 where Ra and Rb are the radii of A and B. Expanding this out yields the quadratic equation: AB * AB + 2 * Vab * AB * t + Vab * Vab * t2 = (Ra + Rb)2 where: AB = B0 – A0 Vab = Vb – Va Because the equation is a quadratic, there may be: 4) No solution. 5) One solution (they bump at a single point) 6) Two solutions (the lower solution being when they first intersect, and the second being when they break apart). Players to walls and floors: Dynamic to static objection collision detection is handled by checking a player’s initial position and final position during any given frame to determine if he/she passes into/through a wall. This is accomplished by creating a sphere around each player object’s hit box and determining if that Page 48 of 128 Fight Zone Technical Design Document sphere intersects with any walls or floors. If so, the player is stopped from continuing in that direction, forced instead to slide along the wall. One problem that must be considered is collision with short walls, such as stairs, pipes on the floors, etc. Players should not be forced to jump over objects they normally wouldn’t think about stepping over or walking up. Therefore, when a collision with any wall occurs, the collision volume is lifted a certain amount and then retested against the wall for another collision. If the wall in question were the side of a stair, the player would then be above the stair and would move forward onto the top of the stair. If the wall was an actual wall, the player still could not move forward and thus would not be allowed to continue into the wall. Collision Handling Player to player collisions: When a player collides with a player, the resulting impact is treated as an elastic collision. That is, they bounce off at different angles and do not stick together. All players have a mass and velocity, so their momentum can be calculated by: Momentum = mass * velocity This momentum is used to determine the resulting angles of reflections, as well as the resulting velocities after the collision. Player to wall collisions: Like player-to-player collisions, player to wall collisions is effectively inelastic. However, the effect on the wall of a player colliding with it is ignored, as the amount a wall moves when struck is negligible, and so, because the wall doesn’t move, the player doesn’t get sent along some resulting vector with the wall. Instead, the player essentially slides along the wall, maintaining all of their previous velocity minus the portion that is normal to the wall: Wall Player Result: Wall Player Page 49 of 128 Fight Zone Technical Design Document Players and explosion spheres: When objects explode, they apply a force to all players within their radius. This force is added to the force vector of the players’ movement (mass * velocity). By dividing the mass, the player’s new velocity can be determined. Explosion spheres also affect destroyable objects such as grenades and mines. If any destroyable object is within the blast radius, it is instantly destroyed. The force in explosion spheres is constant along the entire radius, and furthermore, explosion spheres do not grow over time. They are instantaneous. Players and gravity fields: Gravity fields affect players by supplying them with a new acceleration towards the center of the field, which is represented by a sphere. While the pulling force is constant along the entire radius (thus making the acceleration constant for all objects caught within the sphere), players or objects caught right on the edge will, most likely, not make it to the center of the field before it ceases to exist. This creates the illusion of degrading strength as one moves further from the center of the field. Grenades and lasers with walls: Grenades and lasers share the characteristic of bouncing (reflecting) off of walls. Grenades are, however, affected by gravity, but the distance traveled is so small within any given frame that its curved path of motion can be accurately approximated by a single, straight line. Therefore, simple line to plane calculations will yield the resulting vector after the reflection: Result Normal The resulting vector can be determined Ray by first projecting the initial ray V onto the normal N (assuming N is normalized, result shown in blue): projNV = dot(V,N) * N Result Ray Page 50 of 128 Fight Zone Technical Design Document This projection is then subtracted from the original ray to get the difference (perpendicular to N, shown in red): Result This perpendicular difference must Ray then be doubled: Result Ray Finally, V must be subtracted from this doubled perpendicular difference (the entire red vector, result shown in green): Result Ray Page 51 of 128 Fight Zone Technical Design Document Networking The networking model has been designed to send only data that is needed by the remote application and to pack it into a small and efficient size for transfer. It will allow selective data to have a guaranteed transfer, and selective data to be given different priority levels. This functionality is created through a layered system of managers and a secondary thread that result in the creation each packet with dynamic layout based on the current needs of the application. The model itself is based upon the Tribes networking model, but it is simplified and/or changed in many places due to the different networking and game play requirements of Fight Zone. The Tribes networking model is described in Appendix A. Basic Components The following components are made use of by the layers of the networking model, but are not considered to be part of one of the layers. Persist Manager The persist manager allows the program to provide ID’s to polymorphic object types. By making use of these ID’s, the networking model can communicate which types of objects it is sending so that the other application can determine what kind of functionality to wrap around the data. Object types get registered in the persist manager at run time through a templatized function. It maintains an internal vector of typeid’s and allocation functions. Based on the number of types it has to store, it will be able to determine the number of bits required for an ID in memory. The ID (in the calculated number of bits) will be stored in the lowest bits of the returned value. The persist manager can also allocate new objects of a given type when supplied with the type’s persist ID. Huffman Compression Huffman compression will be used to compress all packed strings. The compression works by assigning bit patters to each allowed character. Characters that appear more frequently will be given shorter patterns than less frequent characters are given. Note that this means that the longer patterns cannot be an extension of a shorter pattern (i.e. if we have a ‘010’ we cannot have a ‘0101’) because it could then not be determined which pattern to use when decoding the string. In many implementations of Huffman compression, the tree is generated based on the content of the text being transferred. The custom tree is then transferred with the text and will be able to provide the maximum compression for the data. This networking model differs in the fact that it is designed for the transfer of short strings and thus sending the tree with the data has a good chance of canceling out all of the data’s compression. To solve this problem, there will be a constant tree of patterns that will match up with a generic character frequency in the English language (i.e. vowels will have fairly short patterns, and letters such as ‘Q’ and ‘Z’ will have longer patterns). This generic tree will then be used for compressing and decompressing all strings. Page 52 of 128 Fight Zone Technical Design Document Latest State Compression Some data sent between applications is sent over and over to make sure that both are synched up with the latest state of the data. This can be a wasteful use space because certain portions of the data might not change between each send. To optimize this situation, the sender only needs to send data that has changed since the last time it updated the receiver. By adding state flags at the start of the data, we can accomplish this task. The flag list is just a sequence of bits. Each bit corresponds to a given piece of the data. Different data types will have a different number of flags and different meanings for them. When a bit is set, that means that the corresponding portion of the original data has changed and is being sent in the compressed version. If the bit is not set, it means that the portion of the original data has not been included in the compressed version because it hasn’t changed. Connection Layer The connection layer is the lowest level of the networking model. It interacts with the actual networking API interface, which will be Winsock 2.2 in our case. The API is abstracted so that it can be easily changed at any point in time if needed. The connection manager is also the only part of the networking model that functions partially in a secondary thread. Connection Manager The connection manager is a singleton class at the base of the networking model. It can be used to create and destroy connections to remote applications (which it will then track internally). The manager can also be used to get low level networking information such as the local machine’s IP address. When the first connection (input or output) is made, the manager will initialize the networking API. When the final connection (input or output) is destroyed, the networking API will be uninitialized. On the creation of the first input connection, a secondary thread for receiving network input will be created and on the destruction of the final input connection, the secondary thread is stopped. Connections Connections can only be created through the connection manager. The connections actually maintain the SOCKETs that are retrieved from the network API. Three types of connections can be made. General input connections are used to receive packets from any IP address. Single input connections are used to only receive packets from a specified IP address. Output connections are used to send packets to a specified IP address. Connections also make use of packet IDs when sending and receiving packets. By supplying each packed with a unique ID, the connections can communicate notifications about which packets have been received. These notifications can then be used by the stream layer to confirm that certain pieces of information are sent when needed. General and Single Input Connections Function Description Lock Before making any use of the connection, it must be locked. This function will block until the connection can be locked. This makes the connection thread-safe. Unlock After using the connection, it should be unlocked. This makes Page 53 of 128 Fight Zone Technical Design Document Set the max input packet size the connection thread-safe. The input packet size of the connection will determine the largest packet size in bytes that the connection will be able to receive. This value includes the overhead that the connection places around the packet. The function will return the number of bytes that the user can read from the connection. This is equal to the packet size submitted minus the size of the overhead that the connection needs to put around the packet. This function will cause the connection to reallocate its input buffer size to equal the new maximum packet size. Get the max input packet size Read Packet The connection will be able to remove packets at an early stage that are too large by using the max input packet size. This function will return the current set max input packet size. It will be used for debugging purposes and to inform the user of the application what the current settings are. This function is supplied with a packet to fill in with any information that the connection has read from the socket. The connection strips off the header information that was wrapped around the original data and writes it to the packet that needs to be filled in. If the data received is too big for the packet to fill in, the function returns failure. To avoid this, the packet should be greater than or equal to the size in bytes returned the previous time that the max input packet size for the socket was set. The function will also return failure if there was no data to receive that fit the requirements for the socket or if the API failed. On a successful read, the function will return (through a parameter) the ID of the received packet. The stream can then use the ID to determine what kind of notification should be returned about the packet. Read Notification Output Connections Function Set the max output packet size After the information has been returned, the function will set the connection back into a state where it can read in more data from the socket when it can. Pops a notification of its FIFO notification queue (that receives input from the remote application) and returns it. If there are no notifications available, failure is returned. Description The output packet size of the connection will determine the largest packet size in bytes that the connection will be able to write. This value includes the overhead that the connection places around the packet. The function will return the number of bytes that the user can write to the connection. This is equal to the packet size submitted minus the size of the overhead that the connection needs to put around the packet. Page 54 of 128 Fight Zone Technical Design Document This function will cause the connection to reallocate its input buffer size to equal the new maximum packet size. Get the max output packet size Write Packet The connection will be able to remove packets at an early stage that are too large by using the max input packet size. This function will return the current set max output packet size. It will be used for debugging purposes and to inform the user of the application what the current settings are. This function is supplied with a packet to send that must be less than or equal to the size in bytes returned the previous time that the max output packet size for the socket was set. If the packet does not meet the size requirements, the function will automatically return failure. Otherwise, the function will wrap the supplied packet in any needed header information and will then send it out through the API. If the API returns a failure, the function will also return failure. Because the connection manager maintains the input connections in the secondary thread, they have to be thread-safe. To accomplish this, the connection has “Lock()” and “Unlock()” functions that must be respectively called before and after using the other functions. When writing packets, the connection adds header information that the remote application’s connection will understand. The first piece of information in the header is the ID of the packet being created. This ID is incremented for every packet. Note that this means the counter will eventually overflow and return to zero, but if the counter goes to a large enough value before looping, there will be no chance of confusion between the similar IDs. Internally, connections store a queue of notifications to send to the remote application. Every time a packet is sent to the remote application, notifications are taken from the head of the queue and added to the notification portion of the packet header. In addition to the queue of notifications to send out, the connection stores a queue of notifications that is has received from incoming packet headers. The stream layer can then request the notification at the head of the list when it wants. The connection manager is given private access to the connection and it can gain access to the connection’s private “Update()” function. When a connection updates, it first checks if it currently has an unread packet in its input packet buffer. If the information currently stored in the buffer has not been read from the connection, it does nothing so that the information is preserved. If the information can be overwritten, the packet will check if there is any incoming data on the SOCKET. If there is data to read that it can fit into the packet buffer, it will read it in and mark the buffer as being back in the unread state until a successful “Read()” is called. Notifications consist of a packet code and one of the following types: In Order – the packet was received in the requested order Out of Order – the packet was not received in the requested order The connection’s knowledge of packet structure is as follows. Packet Overhead Layout (total 32 bits): bit offset - length - Name: Description Page 55 of 128 Fight Zone Technical Design Document *1st byte* 00 - 7 ID: ID of this packet 07 - 1 - flag1: if the packet has three notifications {IF flag1 == 1} *2nd byte* 08 - 7 ID1: notification ID 15 - 1 - code1: notification code *3rd byte* 16 - 7 ID2: notification ID 23 - 1 - code2: notification code *4th byte* 24 - 7 ID3: notification ID 31 - 1 - code3: notification code {ELSE} *4th byte* 24 - 1 - flag2: if the packet has two notifications 25 - 7 - unused: unused bits {IF flag2 == 1} *2nd byte* 08 - 7 ID1: notification ID 15 - 1 - code1: notification code *3rd byte* 16 - 7 ID2: notification ID 23 - 1 - code2: notification code {ELSE} *3rd byte* 16 - 1 - flag3: if the packet has one notification 17 - 7 - unused: unused bits {IF flag3 == 1} *2nd byte* 08 - 7 ID1: notification ID 15 - 1 - code1: notification code {ELSE} 08 - 8 - unused: unused bits {END IF} {END IF} {END IF} Stream Layer The stream layer builds the dynamic portion of the packets that is sent down to the connection layer. It also handles what notifications should be sent, and decides what should be done based on the notifications it receives. This allows it to make certain chunks of the packet guaranteed and received in the correct order when needed. Stream Manager The stream manager is a singleton class that manages a list of all streams in existence. It stays in existence for the entire application and controls the existence of the secondary thread and the connection manager. When the first stream is created, the secondary thread and connection manager are initialized, and when then final stream is destroyed, the secondary thread and connection manager are also destroyed. Page 56 of 128 Fight Zone Technical Design Document The stream manager provides a public interface that consists of getting access to the streams though handles, and updating the manager. When the manager is told to update, it will update all of the streams it is maintaining. Stream Streams are the most functionally complicated part of the networking model because they have to decide what information should be sent per packet, and make sure that some information reaches the remote application successfully in a particular order. It also has to tell the remote application about what it is receiving. On the creation of a stream, it creates a connection for the IP address and port number that it has been supplied. A pointer to the connection is stored in the stream for its entire lifespan. On destruction, the connection is also destroyed. Between construction and destruction, the stream manager updates the streams as needed. Updating consists of reading and writing packets and notifications to and from the connection. When a stream builds a packet to send out through its connection, it needs to create it out of packet chunks. Packet chunks can be divided into the following three main types. User These packet chunks transmit information relative to the input that is being received from the user of the application. Input chunks are transferred with an unreliable, soonest possible, and guaranteed-lateststate delivery. Event These packet chunks transmit information relevant to the application status such as rounds starting and ending, or chat messages. Event chunks are sent with a reliable and guaranteed-order delivery. Ghost These packet chunks transfer state changes of individual objects that need to be synced up between this application and the remote application. Ghost chunks are sent with a prioritized and guaranteedlatest-state delivery. The packet chunk types are derived from a base packet chunk class that forces each packet chunk to be able to “Pack()” itself into a compressed format for transfer and “Unpack()” itself for use after transfer. Each packet chunk also need to have a persist ID that is retrieved from the persist manager. This allows the remote application to determine what kind of derived packet chunk it is actually reading in. In every stream, there are three managers (one for each of the main packet chunk types). When a packet is being created, the stream first asks the input packet chuck manager to fit any data into that packet that it wants to send. The input chunks always have top priority on packet space because they need to get to the remote application as quick as possible for synchronization purposes. The stream asks the event packet chunk manager to fit any data into the packet second. Events aren’t sent often, and when they are sent they are important and must be received in order, which may require resending at times, so they get second priority on packet space. Finally, the ghost packet chunk manager is told to fill in the remaining packet space with ghost object information. The ghost manager will then determine what state updates it should send based on what is important for the remote application to know. When the stream requests for the packet chunk managers to fill in their respective parts of the packet, it also lets them know the ID of the packet that they are filling in. This ID can then be tracked internally in the managers to compare it with notifications received about the packet later. The packet chunk managers inform the stream of how much data they used in bits after they are Page 57 of 128 Fight Zone Technical Design Document done. When the packet is finished being built, its total size is rounded up to the nearest byte, and it is sent down to the connection layer for transfer. In addition to sending packets to the connection layer, the stream also has to read them in from the connection layer. The stream receives packets from the connection in the same format that it supplies them to the connection (a combination of packet chunks ordered by packet chunk type). The packet is first handed off to the input chunk manager, event chunk manager, and ghost chunk manager in order. Each of these managers reads in packet chunks with persist IDs that match its chunk type. After reading in its packet chunks, it returns how many bits it read in so that the stream can tell the next chunk manager where to start. The event manager also returns a notification code in addition to the number of bits that say whether or not this packet has been received out of order. Only the event manager needs to do this because no other chunk types ever need a guaranteed order of sends. The final task of the stream during an update is to manage the notifications. Processing notifications to and from the remote application is a fairly simple process. After receiving a notification code received from the event packet chunk manager (when it reads in a packet), the stream sends the notification down to the connection layer for transfer. The stream then asks the connection layer for any incoming notifications. All incoming notifications are then sent to the packet chunk managers for use. During a streams lifetime, its max input and output packet sizes can be set. These values will be passed down to the connection layer. The max output for one application should be less than or equal to the max input or the remotely connected application to insure that large packets are not ignored. The process of synching these values up is left to the user of the networking model. It is suggested that guaranteed event chunks are used to do so. Streams can also be supplied with incoming and outgoings packet rates (milliseconds per packet). Packet rates do not need to be sent down to the connection layer. When the stream is updated, it will check if it is time to perform any actions with the connection layer based upon its packet rates. The user can also ask the stream for how long it has been since it has successfully read a packet from the connection. This information can then be used to determine timeouts. Packet Chunks Packet chunks exist within the packet chunk managers that exist in each stream. The chunks from each manager are then combined into an entire packet of data within the stream. The hierarchy of packet chunk types is as follows. Class Packet Chunk Base Derived From [Nothing] Description This is the virtual base class that all other packet chunks types are derived from. Description This is the ID received from the persist manager for the derived class that corresponds to the data in this packet chunk. This ID is set on construction. Description This function will return all of the information within the packet and pack it into its compact size for network transfer. This function will take a packed version of the packet chunk and fill the class with its unpacked version. Data Persist ID Function Pack Unpack Page 58 of 128 Fight Zone Technical Design Document Class User Packet Chunk Derived From X direction Y direction Z direction X position Y position Z position X velocity Y velocity Z velocity Move forward Move backward Move left Move right Jump Crouch Hover pack Shoot Weapon ID Packet Chunk Base This class stores information about input changes that have been made by the user. Description List of bits corresponding to each value in the packet chunk for use with the latest state compression algorithm. The x component of the view direction vector The y component of the view direction vector The z component of the view direction vector The x component of the position The y component of the position The z component of the position The x component of the velocity The y component of the velocity The z component of the velocity If the move forward button is pressed If the move backward button is pressed If the move left button is pressed If the move right button is pressed If the move jump button is pressed If the move crouch button is pressed If the move hover button is pressed Boolean variable determining if pressed down ID number corresponding to the current weapon Class Event Packet Chunk Base Description Data State Mask Packet Chunk Base This is the base class that all event packet chunks are derived from. Description Data Description State Mask List of bits corresponding to each value in the packet chunk for use with the latest state compression algorithm. The first bit in the state mask of event packet chunks has a special meaning and does not correspond to a piece of data. If the bit is set, it means that the packet is a guaranteed packet. Previous Packet ID The ID of a packet that must have been received and handled previous to this one because of an event chunk that it contained. The state mask can turn of this information if this chunk does not require a previous packet to have been delivered. The first bit (the “guaranteed” bit) of the state mask must be turned on if this state bit is turned on. Note that if a single event chunk in a packet requires a previous packet to have been received, and the previous packet has not been received, then all event chunks within the current packet will be ignored. This prevents confusion about which chunks need to be resent by instead forcing all of the dropped chunks to be resent. Derived From Page 59 of 128 Fight Zone Technical Design Document Class Ghost Packet Chunk Base Derived From Packet Chunk Base This is the base class that all ghost packet chunks are derived from. Description A priority used to determine how important it is for the remote application to receive this information. Higher values mean that it is more important, and a value of zero means that it does not need to be sent. The priority is never sent when the chunk is packet for delivery. List of bits corresponding to each value in the packet chunk for use with the latest state compression algorithm. The ghost object ID is used as an index into the current list of ghosted objects that will then identify which ghost object this packet chunk’s information corresponds to. The ghost ID only needs to be turned on for packing when the remote application is being told to create a new ghost with the specified ghost ID. A flag that determines if the object is currently in scope. Description Data Priority State Mask Ghost ID In Scope User Packet Chunk Manager The job of the user packet chunk manager is to make sure input packets get to the remote application as fast as possible. It also makes sure that if the remote application misses any information, the latest state of that information will be given as soon as possible. This task is attempted by adding three input packet chunks to the packet on every update. The first input chunk corresponds to the changes in input chunk information since the last packet was sent out. The second input chunk is equal to the first input chunk added to the previous packet. The third input chunk is equal to the second input chunk added to the previous packet. All together it results in a record of the latest three input modifications. Note that this requires the input manager to maintain an internal list of three packet chunks. By sending the most current three input modifications, we get a much better chance of quickly recovering for information being lost due to dropped packets. For any input chunk information (which is very vital) to be lost, three packets must consecutively not make it to the remote application. If this happens, we still need to make sure that the remote application doesn’t miss out on any state changes. To handle this problem, the manager makes use of the packet IDs. When a new packet is sent out, the current input chunk that was shipped at the front of that packet is tracked with the packet ID by pushing it onto end of the internal input packet chunk list. When a notification is received (an “In Order” or “Out of Order”), it means that the remote application received the packet and thus it was processed. We then need to find any packet chunks in our internal list that were stored in that packet (chunks corresponding to the ID, the ID minus 1, or the ID minus 2) and remove them. Packet chunks with previous the previous IDs would still exist in the list if the previous packets that stored their information have not received any notifications. If the internal list of sent packet chunks starts getting much larger than three, it can be assumed that there is a good chance that the information in the packet chunk at the head of the list has been lost. To recover from the information never getting transferred properly, we store the state mask of the packet chunk at the head of the list and then remove it. I then loop through the state masks of the chunks behind it in the list and set our copy equal to the bit wise AND of our copy with the bit wise NOT of their values. This will result in us having a state mask that correspond to any state we were updating that have not been changed and resent after us. We can then Page 60 of 128 Fight Zone Technical Design Document perform a logical OR of our state mask with the state mask that will be used for the chunk to go into the next packet. Now, the next packet chunk will send the lost and unchanged information in addition to the information it was already updating. Event Packet Chunk Manager The job of the event packet chunk manager’s job is to make sure that event chunks reach the other application with specified requirements. Event chunks can request one of three different transfer modes. The first and simplest mode is to request that the chunk be sent without a guaranteed reception. The second mode requests that the chunk be sent with a guaranteed reception. The final mode request that the chunk be sent with a guaranteed reception and that it is remotely processed after a specified previous packet (which must have contained a guaranteed event chunk in it). When the manager is given a new chunk for transfer, it stores in a list of packets that need to be sent. When it comes time for the manager to decide what chunks from the list will be put in an outgoing packet, it places guaranteed ordered chunks first, normal guaranteed chunks second, and unreliable chunks third. After guaranteed chunks (ordered or unordered) are packed, they are pushed onto the back of a second list that will be used in a sliding window fashion. When the manager receives a notification that indicates an ordered delivery of a packet, it finds any chunks in the list (and any chucks that were supposed to be received before those chunks) of sent chunks that were delivered in the packet and removes them from the list. If the list of sent chunks gets too big, the manager will stop sending out guaranteed chunks from its list of chunks to send until the list of sent chunks reduces in size. If the packet chunk at the head of the list of chunks to send has been waiting for a notification for too long, we assume that it was dropped and insert it at the head of the list of chunks to send with the same required previous packet ID that it had before. Note that the packet may actually have been received and it was the packet’s confirmation that was dropped. If this is so, the remote application could receive this packet chunk twice. Because of this unlikely and unavoidable (without adding more overhead) situation, the process taken to handle event packet chunks should not be damaging to application flow if it is executed twice with the same information, In addition to the two internal lists that are used in the process of sending packets, there is an internal array of flags used in the process of receiving packets. The array is the same size as the maximum number of unique packet IDs and each element corresponds to the equivalent packet ID. The elements are used to flag what packet IDs have been received in order. The array starts off indicating that no packets have been received in order. Every time a packet is received in order, its corresponding flag will be changed. As is, this method of tracking presents a problem of running into old data when the IDs loop. To handle this, we store an ID number corresponding to the “highest” packet ID we have received. At construction, this number is zero. When a new packet is received, we perform a check to see if the new ID lies somewhere in group of elements (equal to the size of half the array) directly after the element corresponding to the current highest ID. Note that this may require overflowing the check from the end of the array to the begging at times. If the new ID does exist in the specified group, then we set the “highest” ID equal to the new one. We then set the values of the group of elements (equal to the size of half the array) after the element corresponding to the new ID to indicate unordered receptions. This process will result in the elements of the array that will be used in the soon future to have been cleared out for use. When the manager receives a packet to strip event chunks from, it first unpacks the chunks one by one and places them in a list. As it fills the list of incoming chunks, it builds a second list of any previous packet IDs that these chunks are requiring. If it finds out that one of the required previous packets was not received properly (by indexing into the array of successfully received packets), it deletes the chunks that it just read in, and returns a notification that the packet was Page 61 of 128 Fight Zone Technical Design Document received out of order. On the other hand, if either there were no required previous packets or the requirements were met, it returns a notification that the packet was received in order. After receiving a packet in order, the manager marks the packet ID as having an ordered reception in the internal packet ID array. It then loops through the chunks in the order that they were packed, creates the appropriate derived event chunk using the persist manager and the supplied persist ID, and tells it to “Unpack()” the data. Ghost Packet Chunk Manager The job of the ghost packet chunk manager is to guarantee that the remote application is guaranteed to be receiving the latest state of objects at all times. It also needs to make use of supplied priorities to determine which order to send the different chunks. Each ghost packet chunk refers to an object that is being ghosted. The process of ghosting objects requires a concept of scope. When a remote application requires knowledge about a given object, that object is considered to be in scope for the remote application. When an object enters scope for a remote application, it can then be ghosted in the stream associated with that application. When an object leaves scope for a remote application, the ghost (if it has one) is removed. Only a limited number of objects can be ghosted at once in a ghost manager. Each ghost chunk has a unique ghost ID that is synchronized between the connected applications. The maximum number of unique IDs determines how many objects can be simultaneously ghosted. Inside the ghost manager is an array of pointers to ghost packet chunk bases that is equal to the maximum number of ghost IDs. The indexes of the array will correspond to the ghost ID of the chunks that their respective elements point to. If no ghost chunk with that ID exists, the pointer will be set to NULL. When a ghost is created for an object, the ghost chunk manager will request that the object supplies it with an allocated ghost chunk that is filled out. This consists of giving the ghost chunk a pointer to the ghosted object, setting its state mask bit to all ones, and updating all of its data members. The ghost manager also request for the object to give the ghost chunk a priority level. The priority level of ghost chunk determines how important it is for the remote application to receive the update. Chunks being created for the first time should be set to the second highest possible level. The ghost chunk manager will then search for a free ID in its ghost chunk array and set the new chunk up with the free ID. If there are no free IDs, it will find the chunk with the lowest priority. It does this by checking the end of an internal list of pointers to the active ghost chunks that is sorted by priority. If the new chunks priority is higher than the priority of the found chunk, the found chunk is destroyed and replaced with the new one. If the new chunk has a lower priority, it is deleted and not used. After the new chunk is set up with its ID in the array, it is inserted into the sorted priority list. If its priority is equal to the priority of another chunk in the list, it will be inserted behind the other chunk. When a ghost chunk is destroyed, the ghost ID will be pushed onto the end of a list of ghost chunks that the remote application needs to delete. It is then removed from the priority list if it existed in it, and the element in the array of ghost chunks that pointed to it is set to NULL. Also, if any references to its ghost ID exist in the list of sent ghost chunks, the corresponding elements of the list are removed. It is then deleted from memory. When it comes time to fill in an outgoing packet with ghost chunks, deletion messages from the list of ghost chunks that the remote host needs to delete are added until there are no more to send, or until the packet is full. The deletion messages are then removed from the list of deletions to send and pushed onto a list of sent deletions with their corresponding outgoing packet IDs after they are packed. Page 62 of 128 Fight Zone Technical Design Document Once the list of chunks to delete is cleared out, the ghost manager starts to traverse the prioritized list of chunks to send from highest priority to lowest priority. It first checks if any of the ghost IDs in the list of sent deletions match the current chunk’s ghost ID (we don’t have to check the list of deletions to send because it is guaranteed to be cleared at this point). If it does, it means that the remote application has not yet removed the previous ghost that had the same ID, and this chunk is skipped over for now. When we come across a chunk that does not have a ghost ID equal to one of the chunks that is in the process of deletion, it is first packed into the outgoing packet. Then a record of its ghost ID, state mask, and the ID of the outgoing packet are pushed onto the end of a list of sent chunks. Finally, the chunk is removed from the prioritized list (it will still be in the ID based array of chunks) and its priority is set to zero. This process is then repeated on the rest of the chunks until either the packet is full or there are no more chunks that can be sent. When a notification is received (ordered or unordered), all elements in the sent list of packets to delete corresponding to the notification’s packet ID are removed. If a deletion remains in the sent list for too long, it can be assumed that it was dropped. We then push its ghost ID onto the front of the list of ghost chunks that need to be remotely deleted. It will then be retransmitted on the next send. If only the notification was dropped, and the ghost chunk was remotely deleted the first time (i.e. the remote application will be told to delete the chunk twice), there will be no adverse effect. After the sent list of deletions is handled for the notification, the ghost chunk manger will traverse the list of sent ghost chunk records. When a record is found corresponding to a ghost chunk that was sent in the notified packet (this is checked for using the packet ID), the record is removed from the list. If a record remains in the sent list for too long, it can be assumed that it was dropped. The ghost manager now has to ensure that the remote application gets the dropped data. First, the manager makes a copy of the dropped chunk’s state mask. Then, the records of chunks, which were sent after the dropped chunk, are looped through. If it finds a chunk sent for the same ghost ID, it will set its state mask copy equal to the bit-wise AND of the copy with the bit-wise NOT of the found record’s state mask. This is done for each found record, and results in the clearing of state mask bits, which correspond to any data that the dropped record sent and was then later overwritten by another packet chunk. The manager’s state mask copy is now a true record of the information that the remote application needs. The next step is to get a hold of the packet chunk matching the ghost ID of the lost packet by indexing into the array of packet chunks. By setting the state mask of the packet chunk equal to the bit-wise OR of the its state mask with the manager’s modified copy of the dropped state mask, the chunk will automatically resend the lost data when it is its turn to be packed. If the chunk currently has a priority of zero, it means that it is not in the priority list of chunks to pack. To fix this, a new priority for the ghost is requested from the object it is ghosting, and the chunk is inserted into the priority list. Note that it was assumed that the ghost object we went back and modified was not a different object than the one the dropped packet corresponded to (i.e. it has since been deleted and replaced with another object). This can safely be done because all references to a ghost chunk’s ghost ID in the sent ghost chunk list are removed when it is deleted. In addition to adding and deleting objects with changing scopes, the ghost packet chunk manager also has to update the objects that are currently in scope. When the array of existing chunks is looped through, each chunks scope is checked. If the object ghosted by the chunk has left the scope of the remote application, then the ghost chunk is deleted as was earlier discussed. On the other hand, if the object ghosted by the chunk has remained in scope, the manager will request for an update from the object. This requires the manager to supply the object with a reference to its ghost chunk. The object then finds any data that has changed, sets the new values of the data, creates a state mask from it, and sets the ghost chunk’s state mask equal to the bit-wise OR of its generated state mask with the ghost chunk’s state mask. This will add any new updates to any previous updates that have not been sent. It must be done in this manner because the ghost chunk can actually get updated more than once before it is sent. This Page 63 of 128 Fight Zone Technical Design Document happens when it has stayed in the priority list for a loop without being sent. Remember that only one instance of the ghost exists in the manager at any one point in time. It is always pointed to by the array of chunks, and only pointed to by the priority list when necessary. When the object update’s the packet, it will also return whether any changes were made to it. If the packet has been changed, then the manager will ask the object for the packet’s current priority level. If the priority level has changed, the chunk is removed from the priority list (if it currently existed in it), and is then reinserted into the priority list with its updated priority. If the packet was not changed during the update, the chunk is left alone. When it is the ghost manager’s turn to read in a packet, it strips its packet chunks out one by one and processes each one before reading in the next. The first chunks it handles will be deletion chunks. The respective ghost chunks will be deleted from the internal tracking systems, and the objects that they point to will also be deleted. For the rest of the chunks, the ghost manager will first check to see if its supplied ghost ID is in use. If it is in use, the chunk residing at that ID is told to “Unpack()” the next part of the packet. If it is not in use, the ghost packet chunk manager must use the persist manager and the chunk’s persist ID to generate the appropriate derived ghost class and store it at the supplied ID. The virtual “Unpack()” function is then called to read in the data from the packet and handle it. Server vs. Client The server and the client both use the same parts of the networking model, but each one uses it in a unique way to create a clean and efficient server to client architecture. Clients will create one stream for joining the server. After the server is joined, a second stream for talking to the server will be created (the first stream is kept alive for rate and size updates). The server will start with a single stream that clients will connect to for joining the server. After a client has joined the server, the server will create a new stream for connecting directly to the client. The join stream is set to have a constant low packet size and constant low packet rate. There is no need to synchronize the rate and size of this stream between the server and client because they are predetermined constant values. On the other hand, the other streams do need their rates and sizes synchronized, and guaranteed event chunks are used to do so. The server and client will be given output and input rates and sizes that are configurable by the user of the application. The client application will want to use its entire outgoing size and rate if possible. The server will want to distribute its entire outgoing size and rate between the connected clients. The server and client will exchange their configured values every time that they are modified (note that the server will not tell the client its total available rate and size, but only the portion allotted to that connection). This exchange is performed on the join stream, which has a constant rate and size, because the normal stream’s new setting might cause the remote application to ignore its packets due to in invalid size. When an application (server or client) receives rate and size values from a remote application, it compares its output rate and size with the remote input rate and size. It then updates its out put rate and size to be less than or equal to the remote input rate and size it does not already meet these requirements. Client packets are almost always contain input chunks to tell the server about what the client user is doing. It will sometimes also contain event chunks for chat messages, user information messages, disconnection messages, and notifications that it has finished loading a level. Server packets use move chunks to tell the client what the server says he or she has been doing. The server uses event chunks to send game progress information such as levels ending and starting, scores, round times, chat messages, and disconnection messages. The server also sends out ghost chunks for objects that it considers in the scope of the client player. It will generally determine objects to be in scope when they are in the clients view or are about to enter the clients Page 64 of 128 Fight Zone Technical Design Document view. The priority of the ghost chunks increases with how dangerous the ghosted objects are to the client player. For example, projectiles heading toward the player will have a higher priority that projectiles moving away from the player. Page 65 of 128 Fight Zone Technical Design Document Subsystems Memory Manager The memory manager provides the application with efficient memory allocations, and useful memory debugging features, while at the same time making use of an almost transparent interface. It also guarantees allocations to be successful if you are sure that you will not exceed the size of the heap that is initially allocated. Interface The memory manager is built as a singleton class named “MemoryMgr” that exists within the “dp” namespace and can be accessed through the static member function of the class named “Get()”. For a source file to make use of the memory manager, it must have “MemoryMgr.h” included. The interface to the memory manager is kept transparent for the most part. The global new and delete operators are overloaded to take in any extra information that the memory manager requires per allocation. The preprocessor is then told to replace the regular syntax for calling new with the new one throughout the application. This results in the user being able to code allocations as he or she normally would and if the memory manager’s header file is included, his or her code will be updated appropriately. One line of code that gives the memory manager a size to create its heap at must always be added to the application in order for the memory manager to compile. The static size variable in the memory manager must be defined at the global scope with the following line. const unsigned long int dp::MemoryMgr::m_InitialSize = [heap size in bytes]; Where [heap size in bytes] is replaced with the number of bytes the application wants to request for the heap. If the user is making use of STL containers in his or her code and wants the allocations made by those container to make use of the memory manager, a custom allocator needs to be supplied to the container template parameters. The allocator to use “MemoryMgrAllocator” is defined in the memory manager’s header file. A problem arises of declarations can become very long and tedious when supplying this extra template parameter. The header file “MemoryMgrSTLDefs.h” is provided to help solve this problem. This header file contains templatized structures corresponding to each STL container that makes use of allocators. Within each of these structures is a type definition that is constantly referred to as “type”. The following examples display potential uses of the header file. dp::list<int>::type myList; dp::list< dp::vector<float>::type >::type myListOfVectors; Implementation At the core of the memory manager is a large memory heap that should in theory be able to hold all memory allocations at any given time during the application’s life. The memory within the Page 66 of 128 Fight Zone Technical Design Document heap is organized into a list of memory blocks. Memory blocks can take one of the following four types. Block Type HEAD TAIL FREE USED Description The head block only exists once at the start of the heap. It is used as the starting point when traversing through the heap. It also ensures that all used and free blocks will have at least one block before them. The tail block exists once at the end of the heap. It is used to determine when we have reached the end of the heap during traversals. It also ensures that all used and free blocks will have at least one block after them. Free blocks contain memory that is available for use by new allocations. Used blocks were once free blocks. They currently hold memory that has been allocated by the user. They will return to free blocks on deletion. Each block type has the same amount of overhead in the following format. Bytes 4 4 Name Block Type Data Size Data Size Data 4 Total Size Description The block type identifier. An unsigned integer corresponding to the size of the data portion of the memory block in bytes. This portion of the memory block is of variable length and is described by the rest of the block sections. The data size of HEAD and TAIL blocks will always be zero. In theory useful data could be added to those block types for statistical purposes if desired. An unsigned integer corresponding to the size of the entire block in bytes (overhead size plus data size). Every time a FREE block is created, it is inserted into a binary search tree within the memory manager that sorts the FREE blocks based on their size. This tree can then be used to efficiently find the best-fit free block for memory allocations. After the initial creation of the heap, there is a HEAD block at the start and a TAIL block at the end with a FREE block in between that fills up any available space. The binary search tree of FREE blocks will now contain one node. When an allocation is made, the binary search tree of FREE blocks is used to find the smallest FREE block that still contains enough free space to store the allocation. If it is large enough, the selected free block is then split into a USED block large enough to hold the allocated memory and another FREE block. If it is not large enough, it is just changed into a USED block. Note that this could result in the used block having some extra, unused memory allocated for it. A pointer to the data portion of the block is then returned to the user. When an allocation is freed, the USED block that contains the allocation is located. Based on the status of the blocks before and after the USED block, one of four actions is taken. Each action will have to remove and insert nodes into the binary search tree of FREE blocks appropriately. 5) If the previous block is a FREE block and the next block is not a FREE block, one large free block is created containing the previous block and this block. 6) If the next block is a FREE block and the previous block is not a FREE block, one large free block is created containing the next block and this block. Page 67 of 128 Fight Zone Technical Design Document 7) 8) If the next block is a FREE block and the previous block is a FREE block, one large free block is created containing the previous block, the next block and this block. If the next block is not a FREE block and the previous block is not a FREE block, this block is just turned into a FREE block. All USED blocks and FREE blocks must contain a data size that is a multiple of sixteen bytes. This will help prevent memory fragmentation by resisting the occurrence of blocks being created that contain a much greater memory overhead than their data size. If a block is allocated without making use of the memory manager or if the memory manager’s heap no longer contains a free block large enough to hold the current allocation, it is allocated normally without use of the memory manager. The memory manager will then assume that when deletions are requested outside of its heap that they are deleting external blocks that it previously allocated. It will delete these blocks normally. Debugging Support The memory manager provides the ability for the user to have a traversal of all the memory blocks done that will check to see if everything is in order and that no memory has been overwritten by accident. The memory manager also can be output to a stream at anytime returning information about each block stored in the heap, the count of FREE blocks, and the count of USED blocks. By globally defining DP_ENABLE_MEMORY_MANAGER_DEBUG in the preprocessor, the memory manager is set into a debugging mode where extra debugging information tracked at a performance loss. In debugging mode, the memory manager will track the file names and line numbers that allocations were made on, and it will fill the data portion of memory blocks with debug patterns. An extra section is added to the block layout after the block type and before the data size. This extra section stores a string of a constant length that stores information relevant to the block. If it is a USED block, the file name that the allocation was made on and the line number of the allocation is stored in the string. If it is a HEAD, TAIL, or FREE block, then its block type is indicated in the string. These strings will then be used when outputting the memory manager to a stream, and make it much easier to understand what is going on in the heap when looking at the actual data stored in memory from within the IDE. When blocks are initially created, their data will be filled with a pattern based on the block type. FREE blocks are filled with the hex value 0xE, USED blocks are filled with the hex value 0xA, and all other blocks are filled with the hex value 0xB. This is again useful for making a memory dump easier to view and understand. Statistical Support By globally defining DP_ENABLE_MEMORY_MANAGER_STATS in the preprocessor, the memory manager will track certain statistical information as memory is allocated and freed. This information will then be printed when the memory manager is output to a stream, and can also be accessed though accessor functions of the memory manager. The memory manager will track the following extra statistics for access at any point in time. Page 68 of 128 Fight Zone Technical Design Document - Current number of FREE blocks Current number of USED blocks Current total data space available in all of the FREE blocks in bytes Current total data space used in all of the USED blocks in bytes Maximum number of FREE blocks at one point in time during the application’s life Maximum number of USED blocks at one point in time during the application’s life Minimum total data space available in all of the FREE blocks at one point in time during the application’s life Maximum total data space used in all of the USED blocks at one point in time during the application’s life Trace Manager The trace manager encapsulates all of the streams used for tracing debug information. The trace manager can be turned on by globally defining DP_ENABLE_TRACE in the preprocessor. Interface The trace manager is built as a singleton class named “TraceMgr” that exists within the “dp” namespace and can be accessed through the static member function of the class named “Get()”. For a source file to make use of the trace manager, it must have “TraceMgr.h” included. Near the start of the application, after the main window is created, the “InitializeWindows” member function of the trace manager must be called to prepare the output windows for tracing to. Three output windows will be created at this point: the Progress Window, the Warning Window, and the General Window. To trace text to these windows, the user will make use of the following macros. - TRACE_PROGRESS( output ) - TRACE_GENERAL( output ) - TRACE_WARNING( output ) The output value passed to the macros should be a value that can be used as valid output to a stream. The following examples show possible uses of the macros. TRACE_PROGRESS( "Sample output\n" ); int myInt = 0; TRACE_GENERAL( "My int = " << myInt << std::endl ); Implementation The trace manager contains three “StreamOutputWindow” objects as members. The “StreamOutputWindow” class is derived from “std::ostream” and contains a window within it. All text that is output to the stream will get printed to the window. If the trace manager is not enabled, the tracing macros will define as nothing. If the trace manager is enabled, the macros will output their values to the appropriate streams. Page 69 of 128 Fight Zone Technical Design Document Assertions By globally defining DP_ENABLE_ASSERT in the preprocessor, assertions will be turned on. When assertions are not enabled, the ASSERT( Boolean value ) macro will define to nothing and when they are enabled, it will define to the standard “assert” function. Resource Manager The resource manager provides a single location to maintain a list of all the resources loaded from files into memory. It will then manage the sharing of resources and will be able to determine when they can safely be released. Interface The resource manager is built as a singleton class named “ResourceMgr” that exists within the “dp” namespace and can be accessed through the static member function of the class named “Get()”. For a source file to make use of the resource manager, it must have “ResourceMgr.h” included. The first and simplest interaction that is made with the resource manager is requesting a max size with the “SetRequestedMaxSize” function. This function takes a value representing the maximum size in bytes that you would like the loaded resources to take at any given time. The requested max size starts at zero bytes by default. Note that this is a requested size and is there for not guaranteed. This means that if all the resources needed in memory at a given time will exceed the requested max size, the requested max size will in fact be exceeded. The requested size allows resources that were once in use to stay in memory if there is still space for them (i.e. with the unused resources loaded, the requested maximum is not exceeded). This will allow the resource to be quickly loaded if it is needed again before any other needed resources cause the resource manager to free it. The requested max size can also be changed during any point in the application’s life span. When adding a resource, the resource manager can be given a file with or without directory information relative to the search directory. The resource manager will first search the base directory (where the application is installed) and then search all directories under the base directory if the file cannot be found there. In order to add a resource, the user must know the resource type (resource types are explained below) and the file name. After adding the resource, the resource manager will return a handle to the resource that the user may use to interact with it. If the resource fails to load, an invalid resource handle will be returned. The user may check if the resource handle is invalid by either comparing the resource handle with the Boolean value “false” or by applying the not operator (!) to the handle and checking if it evaluates to the Boolean value “true”. If the user receives a valid handle, dereferencing the handle will return a constant reference to the actual resource. The following example demonstrates a possible use of adding a resource assuming that a resource type named “ImageResource” exists with const functions “GetWidth()” and “GetHeight()”. dp::ResourceHandle<ImageResource> myImage = dp::ResourceMgr::Get().AddResource( dp::Resource<ImageResource>("myImage.bmp") ); if( myImage ) { Page 70 of 128 Fight Zone Technical Design Document int width = myImage->GetWidth(); int height = (*myImage).GetHeight(); } It is never necessary to directly tell the resource manager to free resources that you have added. The handles are able to determine when to free the resource based on when they go out of scope. On the other hand, it may sometimes be in reason to request that resources are freed for optimization purposes. If the user specifies a requested max resource size, once all of the handles to a resource go out of scope, the resource manager may decide to keep the resources loaded and not used if it does not exceed the requested size. If the user knows that the resource will never be used again, it can tell the resource manager to free a specific resource. The resource manager will return failure if the resource was still being reference, and success if the resource was removed or already didn’t exist. The following example demonstrates a possible use of freeing a resource assuming that a resource type named “ImageResource” exists. if( dp::ResourceMgr::Get().FreeResource( dp::Resource<ImageResource>("images/myImage.bmp") ) == false ) { // the resource is still being used } The resource manager also supplies a second, more general function for freeing resources. The “FreeUnusedResources()” function will remove any resources that are in memory and not in use. At anytime, the resource manager can be output to a stream. It will supply the list or resources loaded in memory, the requested max size, the current size, and the current resource count. The user can also get the requested max size, and the current size of memory in bytes that all of the loaded resources are using. Creating Resource Types The user must create all resource types that the application will need. For every resource, the user will create a data structure to encapsulate the loaded resource, and a function for loading the resource from file. The first step is to create a class that has members to hold all the information needed that will be loaded in from the file. Users of the resource type should never modify the data in the resource class because multiple parts of the application could have handles to the same resource. To prevent this, resource handles always dereference to a const version of the class which means that all functions that the user will use to interact with the resource must be const functions. All non-const functions will only be useful for setting data members when loading the resource. To write the function for loading a resource, the “Load()” function for the templatized “Resource” class must be defined. It is recommended to design the resource type class so that it has no knowledge of the file it was loaded from, and to encapsulate all of the file interaction in the “Load()” function. When writing the “Load()” function, the templatized resource class provides the user with the file name to load from through the “GetFileName()” function, and a pointer to the specified resource type named “m_DataP”. If the load function is successful, it should allocate its data type and set “m_DataP” to point to the allocated memory. The allocated memory will be freed when the resource is unloaded. Page 71 of 128 Fight Zone Technical Design Document If the “Load()” function fails to load the resource, it should delete any allocated memory (and set “m_DataP” back to NULL if its value was changed), and return zero to indicate failure. On success, the function should return a fairly good estimate (if not exact) of how many bytes the loaded resource is taking up in memory. This size includes the allocated resource type class and any memory allocated by the resource type class. If the resource type class contains resource handles within it, the size of the resources that those handles point to should not be added to the size of this resource. The following example demonstrates a possible layout for the “Load()” function assuming that a resource type named “ImageResource” exists. unsigned { // // // // // // // // // // // } long int dp::Resource<ImageResource>::Load() open the file set m_DataP = new ImageResource read the file into the ImageResource close the file if there were any problems delete m_DataP set m_DataP = NULL return 0 else there were no problems return size of (*m_DataP) + any extra memory allocated within (*m_DataP) Implementation At the highest level of the resource manager is the “ResourceHandle” class. The resource handle is a templatized class that takes a template parameter of a resource type. Resource handles internally maintain a pointer to a resource class for the resource type that defaults to NULL indicating an invalid handle. Public users can only create invalid handles, but can set an invalid handle equal to a valid one to create a copy of the valid handle. Only the “ResourceMgr” class has access to the private members of the “ResourceHandle” class, and therefore only the resource manager can create valid resource handles. As valid handles are created and destructed, they add and remove references to the resources that they point to. The middle layer of the resource manager is made up of the “Resource” class and the “ResourceBase” class that it is derived from. The “ResourceBase” class is a virtual base class (it cannot be instantiated). The resource base states that all classes derived from it must have the appropriate load and unload functions. It also maintains a reference count that tracks how many handles are pointing to it. The “Resource” class is templatized and adds one new member to the “ResourceBase” class that is a pointer to the resource type that is given as a template parameter. The “Load()” function (which was derived from the base class) is declared, but not generically defined. It must be explicitly defined for each resource type that is created to perform the specific task, which should result in allocating memory for the data pointer in some form or another. The “Unload()” function is defined, and will delete the allocated memory for the data pointer if it is not NULL. At the bottom layer of the resource manager is the “ResourceMgr” singleton class. This is the class that is publicly used to add and remove resources. When a resource is added, the resource manager strips down the file name so that it has not directory information and then searches all subdirectories under the directory that the executable was run from for the file. Once found, it will set the file name in the new resource class to the file name it found with a full directory path. On Page 72 of 128 Fight Zone Technical Design Document the back end, it maintains a list of “ResourceBase “ pointers. These pointers can now point to an actual derived resource class and treat them generically with their “Load()” and “Unload()” functions. When loading and unloading resources, the resource manager will track the current amount of memory used and will attempt to stay under the requested max size. Statistical Support By globally defining DP_ENABLE_RESOURCE_MANAGER_STATS in the preprocessor, the resource manager will track certain statistical information as resources are loaded and unloaded. This information will then be printed when the memory manager is output to a stream, and can also be accessed though accessor functions of the resource manager. The resource manager will track the following extra statistics for access at any point in time. - Current number of loaded resources Maximum number of loaded resources at one point in time during the application’s life Maximum size in bytes of memory used by loaded resources at one point in time during the application’s life Page 73 of 128 Fight Zone Technical Design Document Appendix A The TRIBES Engine Networking Model or How to Make the Internet Rock for Multi-player Games by Mark Frohnmayer and Tim Gift Mark.Frohnmayer@Dynamix.com Tim.Gift@Dynamix.com Page 74 of 128 Fight Zone Technical Design Document Abstract This paper discusses the networking model developed to support a "real-time" multi-player gaming environment. This model is being developed for TRIBES II, and was first implemented in Starsiege TRIBES, a multi-player online team game published in December '98. The three major features of this model are: support for multiple data delivery requirements, partial object state updates and a packet delivery notification protocol. Overview Starsiege TRIBES supports two modes of play: single player or multi-player over a LAN or the Internet. The multi-player mode supports up to 128 human or AI controlled players in a single game. Performance over the Internet drove the design of the networking model. The model supports low end modem connections and is designed to deal with low bandwidth, high latency and intermittent packet loss. The model deals primarily with the delivery of data and a key concept is the classification of delivery requirements. All data is classified into one of several requirement categories and the design of each component in the model centers around meeting those requirements. We organize transmitted data as follows: 1. Non-guaranteed data is data that is never re-transmitted if lost. 2. Guaranteed data is data that must be retransmitted if lost, and delivered to the client in the order it was sent. 3. Most Recent State data is volatile data of which only the latest version is of interest. 4. Guaranteed Quickest data is data that needs to be delivered in the quickest possible manner. The networking model is divided into three major components as shown in Figure 1: 1. A Connection Layer that deals with notification and delivery of packets between client and server. The features of this layer along with a stream class provide the general infrastructure on which the other layers are built. 2. A Stream Layer which provides packet stream management. This layer employs five stream managers to deal with events, object mirroring, input move management, static data and string compression. Each of the five stream managers provides different data delivery guarantees. 3. A Simulation Layer which manages all objects in the simulation. A full description of this layer is outside the scope of this article but several items are relevant: the advancement of time, object scoping and client prediction. Though Starsiege TRIBES employs a client-server connection model, only a few of the stream managers are asymmetrical. Nothing Page 75 of 128 Fight Zone Technical Design Document prevents this model from being used in peer-to-peer or multiserver architectures. Simulation Layer Ghost Manager Move Manager Datablock Manager Event Manager String Manager Stream Layer Stream Manager Connection Manager Connection Layer Platform Packet Module Figure 1 Persistent Objects Though polymorphic object persistence the networking model, it is a feature large percentage of data transmission objects and the polymorphic nature of the type and content of the data from is not an integral part of that is used extensively. A is done using persistent the objects used to hide the networking code. Each class that is declared persistent registers a "class representative" (ClassRep) object with the Persist manager and is assigned a unique Class ID. The ClassRep is used by the Persist manager to construct objects of the type it represents. By mapping assigned Class IDs to ClassReps the Persist manager can construct any persistent object given its class ID. This construction by Class ID along with virtual read and write methods provides basic polymorphic IO. Writing an object into a stream is a two step process. First its class ID is written, then the object's virtual write method is invoked. Reading an object involves reading the Class ID, constructing the object using the Persist manager, and then invoking its virtual read method. In this way both the object's class, and the data it reads and writes are hidden from the stream managers. Connection Layer The Connection layer provides transmission of packets between host machines and is divided into two modules, a platform packet module and the Connection manager. The platform packet module provides basic connectionless unreliable packet delivery, Page 76 of 128 Fight Zone Technical Design Document currently implemented using standard UDP sockets. The Connection manager provides a virtual connection between two hosts and while it does not provide delivery guarantees, it does provide packet delivery status notifications. This notification guarantee is very important to the architecture; a packet layer that supports only guaranteed or non-guaranteed packets would not be sufficient to support the four basic data delivery modalities outlined above. How each delivery mode is handled is delegated to a higher level -– the connection manager only guarantees the correct notification of a sent packet's status. I.e., if a packet is notified as dropped it was either dropped or delivered out of order (and subsequently dropped), and if a packet is notified as delivered, it has been delivered. The Connection manager notifies the Stream layer of the status of each packet in the order that they were sent. An overview of this relationship is shown in Figure 2. Dropped packets are never re-transmitted by the Connection manager; the Stream layer, and its associated managers, handle all data guarantee mechanisms. Since packets are never retransmitted, they are freed immediately after transmission. Stream Manager Packet Data Packet Notify Event Delivery Status Packet Data Connection Manager Packet Address Data Packet Address Data Connection Layer Platform Packet Module Figure 2 The Connection manager employs a sliding window protocol in order to track the delivery of packets. When the window is full, transmission stops until an Acknowledgment is received. Acknowledgment of packets is only used to advance the window and generate notification events. This protocol imposes an average overhead of 3 bytes per packet. Page 77 of 128 Fight Zone Technical Design Document Though not part of the protocol, an important feature of the architecture is bit-packing provided by a custom bit stream class. This class provides bit level read and write functions, including read/write functions for: a single bit, variable length integers, variable length normalized floats, and Huffman compressed strings. All packet data, including the header and the sliding window protocol, are accessed through this stream. These packing features are used extensively and virtually all data is transmitted using the smallest number of bits possible. Examples of bit packing using the bit stream. Writing into the packet: if (stream->writeBool(updateDamage)) { // Uses 1 bit stream->writeInt(mDamageState, 2); // Uses 2 bits if (mDamageState != Dead) stream->writeInt(mDamageLevel,6); if (stream->writeBool(mRepairActive)) stream->writeInt(mRepairRate,4); } The matching read method: if (stream->readBool()) { mDamageState = stream->readInt(2); if (mDamageState != Dead) mDamageLevel = stream->readInt(6); mRepairActive = stream->readBool(); if (mRepairActive) mRepairRate = stream->readInt(4); } Stream Layer The Stream layer is comprised of a Stream manager and the Event, Ghost, Move, Datablock and String managers. The Connection manager deals with the frequency of packet transmission as well as packet size and stream manager ordering. The individual stream managers deal with the packing and delivering of data including the various guarantee mechanisms. The String manager, dealing primarily with the compression of string data, is not covered in this article. The Stream manager allocates and transmits packets to its counterpart on a remote host. To control bandwidth, each Stream manager has a packet update rate and size. These parameters are set by the remote host’s Stream manager and represent the amount of data it’s capable of receiving. Clients connecting to a dedicated server set these values to represent the bandwidth of their Internet connection. If a client is connecting to an ISP with a 28.8 modem then it could set a rate of 10 packets per second with a size of 200 to produce about 2K of data per second. The client may change these parameters on the fly in response to changes in line quality. To control its own out-going bandwidth, Page 78 of 128 Fight Zone Technical Design Document the server imposes a maximum bandwidth per client based on its own connection quality. Packets are allocated by the Stream manager and filled by the Move, Event, and Ghost managers. Since the opportunity to write into the stream is given to the managers in a fixed order, this order forms a fixed priority among them. Once the requested packet size is exceeded or all the managers are done, the packet is handed off to the Connection manager for transmission. Figure 3 shows an example packet. Packet 1 Header Stream Manager Data Move Move Manager Data Event 1 Event 2 Event Manager Data Event 3 Ghost State 1 Ghost Manager Data Ghost State 2 Figure 3: Example Packet When a packet is delivered to the Stream layer for reading, it simply hands off the packet to each stream manager in the same fixed order and each manager is responsible for reading the data written by its counterpart. The Stream manager also provides a Transmission Record for each packet that it constructs (shown in Figure 4). When a stream manager stores data into a packet, it stores information regarding that data in the Transmission Record. When a Connection manager Notify Event occurs for a packet, the Transmission Record for that packet is processed by the Stream, Event and Ghost managers, and is used to provide delivery guarantees. Since the Connection manager always produces Notify Events for each packet in the order they were sent, the Transmission Records are stored in a simple FIFO. Event Stream Manager The Event Stream manager is responsible for providing guaranteed and non-guaranteed delivery of event objects from one host to another. Guaranteed events are also guaranteed to process in the order they were sent. A sliding window is used to track the status of events. All window management is performed using the Transmission Records. Page 79 of 128 Fight Zone Technical Design Document When the Event manager is given a packet to write into, it pops events off its outgoing queue and writes them into the stream until either the packet size is exceeded, the queue is empty, or the event window is full. Events are persistent objects and are written using the methods discussed earlier. Once events are written into a stream, they are linked together and attached to the Stream manager’s Transmission Record. When the Stream manager is notified of a packet’s status, the Transmission Record for that packet is passed to the Event manager. If the Connection manager signals the successful delivery of the packet then the events attached to the record are deleted and the sliding window updated. If the Connection manager signals non-delivery then the events associated with the lost packet are simply pushed onto the head of the event queue for retransmission. Transmission Record 1 Next Record Event List Ghost List Event 1 Next Event Event 2 Next Event TR2 Event 3 Next Event TR3 Figure 4: Transmission queue including record with events When the manager is given a packet stream to read, it unpacks and constructs all the events. If the event is marked as guaranteed, it is added to an ordered queue used to provide ordered processing. Processing either happens immediately upon receipt (for non-guaranteed events) or as the ordered queue is advanced. Since neither the transmitting nor the receiving Event managers store delivery status information into the packet stream, this protocol imposes very little overhead above that already imposed by the Connection manager, normally 3 bits per packet and 1 bit per event. If a packet is dropped an additional 7-14 bits per packet may be written. In packing, delivering and guaranteeing Event objects, the Event manager provides a fundamental service used by many other subsystems in the TRIBES II engine. Since events are packed, Page 80 of 128 Fight Zone Technical Design Document unpacked and processed using virtual functions and the Persist manager, the Event manager itself has no knowledge of the type or contents of these events. An example of a simple event: class Signal: public Event { enum { SignalBits = 4, }; U8 signal; public: Signal(U8 s) { guaranteed = true; signal = s; } void packData(Bitstream* stream) { stream->writeInt(signal,SignalBits); } void unpackData(Bitsream* stream){ signal = stream->readInt(SignalBits); } void process(NetConnection* ps){ printf("Recieved signal %d from host %s", signal,ps->getObjectName()); } }; Ghost Stream Manager The Ghost manager provides two key functions: the "ghosting" of objects from one host to another, and the transferring of state information between the original object and its ghost. A ghost is a copy of an object persisted and transmitted to a remote host. An object may only have one ghost per Ghost manager (and thus per remote host), but may be ghosted by several Ghost managers at once (to different clients, for example). Ghosts are created using a form of guaranteed delivery also used to support partial state updates between an object and its ghost. State data is considered volatile and transferred using a "Most Recent State" algorithm. Since ghosting an object involves network overhead, the ghost manager does not ghost all objects in the simulation, but instead has a concept of "scope." Objects may come in and out of scope for a manager for a number of different reasons (this process is managed in the Simulation layer). When an object comes into scope, its ghost is transferred to the remote host; when an object goes out of scope its ghost is deleted. While an object is in scope, state data is transferred between the object and its ghost and is updated at a rate based on its priority and state mask. The manager also supports the notion of "ghost always" objects, which are always in scope. When a new object comes into scope, the object is tagged with a Ghost Record containing a Ghost ID and a State Mask. The Ghost ID Page 81 of 128 Fight Zone Technical Design Document is assigned from a limited range and is used by the local manager to address ghost objects on the remote host. The remote Ghost manager maintains a dictionary, which translates Ghost IDs into local ghost objects. When the manager transfers information from an object to its ghost, its Ghost ID is embedded in the stream so that the remote manager can properly deliver the data. The Ghost Record’s State Mask represents state data that an object is interested in transferring and is the heart of the "Most Recent State" algorithm. Each bit in the State Mask represents a class dependant set of related data, or state, that will be transferred. An object may represent its position and velocity as one state bit, changes in rotation as another, and possibly a change in animation state as a third. (TRIBES simulation objects typically have upwards of 20 state flags.) Each state is tracked and transferred independently of the others, providing the ability to perform partial updates of an object’s total state. When the ghost manager is given a packet to fill by the stream manager, it performs two basic actions. First, it builds an update list which includes every object with a status change or non-zero State Mask. This update list is ordered first by status change, then by object priority. Status changes include the transferring or deleting of ghosts from the remote host; an object's priority is a value assigned by the Simulation layer as part of the scoping process. Next, the update list is traversed in order writing the Ghost ID, status and object state information into the packet until the packet is filled or the list is empty. For each object that contains data in the stream, a transmission structure is constructed containing the status change requested and the State Mask. This structure is attached to the Transmission Record for the packet as shown in Figure 5. The State Mask bits in the Transmission structure represent the state data written into the stream by the object. Transmission Record 1 Next Record Event List Ghost List Object 1 GTR1 Next Record State Mask [111] Object 2 GTR2 Next Record State Mask [101] Next Object TR Next Object TR TR2 TR3 Object 1 GTR3 Next Record State Mask [010] Next Object TR Figure 5: Transmission queue including ghost transmission records for objects 1 & 2 Page 82 of 128 Fight Zone Technical Design Document When a ghost manager receives a packet, it reads each set of Ghost ID and status flags in order. If a status indicates a new ghost, the Persist manager is called to construct the object and the new ghost is entered into the Ghost ID dictionary. If the status change is a deletion request, the ghost object is obtained from the dictionary and deleted. If there is no status change, the packet contains only state data. The ghost object is obtained from the ID dictionary and its unpack method is called with the current packet bit stream. Which state mask bits were used by the source object to pack data is not transmitted to the ghost. The object is responsible for encoding such information into the bit stream. The guarantee of object state information happens as follows; State Mask bits represent state changes, so if an object's position changes, it sets its "position state" bit in the State Mask. If there are multiple managers ghosting this object, the bit is set in the Ghost Record related to each manager. This set bit now represents state data that the Ghost manager needs to transfer to the object's ghost. When the manager is filling a packet, objects with a non-zero State Masks are asked to write into the packet stream given the current mask for that Ghost manager. In the example of the "position state", the object writes its current position. At this point the State Mask represents which states were written into the packet, and the mask is stored in a transmission structure which is linked to the Transmission Record. Once this is done, the State Mask is cleared. If the packet is notified as lost, then the State Mask for each object which had data in that packet is updated to include lost bits. State bits are only considered lost if no subsequently-sent packet contained the same state bit for that object. Since we guarantee only the latest state, if a later packet has already been sent with a later version of that state, then this requirement has been met and no other action takes place. In Figure 5, if the packet for Transmission Record 1 is lost then bits [101] for object 1 and 2 are considered lost; whereas bit [010] for object 1 is not, because GTR 3, a later update, has that bit set. If a lost bit is added to an object's State Mask, then that state will get re-transmitted at the next opportunity. Status changes, such as object construction and deletion, are handled in a similar fashion. Example of state masks: An object's position changes and it sets its Position State bit to true. The ghost manager decides to pack the object's state and calls the object’s pack method with the state mask. The object sees that the manager wants to transmit its position and writes its current position into the packet bit stream. The manager stores the state mask containing the Position State bit in the notification structure for that packet and the State Mask is then cleared. Page 83 of 128 Fight Zone Technical Design Document First possibility: the packet is delivered and the state has been successfully transferred. The object's position has not changed since the packet was sent and the State Mask is still 0 so no further action takes place. Second possibility: the packet is not delivered and in the meantime the object's position has not changed. The packet is notified as lost. Since no packets have been sent with new Position State data for the object, the Position State bit is set in the object’s State Mask. In this case the same position will get resent the next time the object is packed. Third possibility: the packet is not delivered, but in the meantime, the object's position has changed. Before notification of non-delivery, another packet was already sent with the latest position. In this case, the manager knows that Position State data has already been retransmitted and the loss of the state is ignored. This is possible because the Ghost manager only guarantees that the latest version of the state data is transferred and not any particular version or copy of that state. In this example, this is exactly the behavior we want -- the position information contained in the lost packet is stale and we don't want to retransmit it. Unless the second packet is notified as lost, we also don't want to re-transmit the current position, as it hasn't changed since the second packet was sent. Fourth possibility: the packet is not delivered, and in the meantime, the object's position has changed. But the position change was recent and no second packet has been sent yet. Since no new packets have been sent with Position State data for the object, the object's Position State bit is set by the Ghost manager. The object will have already set the bit itself, so this will not change the object’s behavior. The next time the object is packed it will write its current position, not the position sent in the lost packet. Similar to the third possibility, the position data lost in the dropped packet is never re-sent. Like the Connection manager, Event, and other stream managers, a server will have a Ghost manager for each client connected to it. If there are several Ghost managers ghosting an object, the object will have a Ghost Record for each manager. Each manager will have a different Ghost ID and State Mask for that object representing the state of that object on its remote host. When an object sets one of its state bits, it updates the State Mask for every Ghost manager currently ghosting it and each manager tracks and updates state information independently. This process of tracking state masks and guaranteeing the delivery of state information between object and their ghosts is a key feature of TRIBES networking. Game simulation objects rely almost exclusively on this mechanism to transfer information. Page 84 of 128 Fight Zone Technical Design Document Move Stream Manager The Move manager guarantees "soonest possible" delivery of client input moves to the server and "soonest possible" delivery of control object state data. A sliding window is used to track the delivery of moves and also to synchronize move processing between control objects and their ghosts. This manager is asymmetrical in that moves are only sent from a "client" connection to a "server" connection and Control Object state data from server object to client ghost. Input moves are used to control simulation objects such as vehicles, cameras, and players. Input is gathered on the client by an Input Manager, which collects a move every 32 milliseconds. Moves consist of x, y and z translations, yaw, pitch and roll rotations as well as an array of trigger states. These moves are delivered to objects by the Move manager and are the sole means of user controlled object movement. The Move manager, similar to the Event and Ghost managers, writes information into every packet stream allocated by the Stream manager. Unlike the other managers, it makes no use of the Transmission Record or the Connection manager's notification system. Instead, the Move manager provides "soonest possible" delivery of moves to the server by writing moves into every packet sent. Each move is transmitted three times in consecutive packets. Each packet transmitted from the server contains the last move received, which the client uses to advance a sliding window of outstanding moves. If the window becomes full, the client simulation is halted until the server advances the window. If 3 packets are dropped in a row then any moves unique to those packets are lost. In Starsiege TRIBES, every move in the current window was transmitted in every packet guaranteeing 100% delivery of all moves, but this was sometimes the cause of a negative feedback loop. A dropped packet would increase the size of the next packet by widening the sliding window and causing more moves to be transmitted. On low bandwidth Internet connections the increased packet size could exceed the connection's bandwidth, causing more packets to be dropped. Though this means moves are no longer guaranteed delivery, the client responds better when large numbers of packets are dropped. Losing moves can cause the client and server control object to get out of sync which may produce a momentary “warping” for the client. The Control Object for a client is the object that receives the current move being produced. Both the Control Object on the server and its ghost on the client receive every move. Control Objects have two major requirements that differentiate them from other objects. The first is the deterministic processing of moves. Both the original server object and its ghost are given moves generated by the player and both, given the same starting state, must produce the same end state. The second is that the control object must be able to transfer its current state on Page 85 of 128 Fight Zone Technical Design Document demand. Though Control Objects are ghosted, and thus can transfer information using the ghost State Mask, the Move manager provides a separate "Soonest possible" delivery of a Control Object's state to its ghost. This state information is similar but not identical to information transmitted through the Ghost manager. State information sent to a ghost is normally limited to that needed to render the object, or to reasonably predict its motion. Control Object state information must include everything needed to deterministically process input moves. "Soonest possible" delivery of this control state information is achieved by having the Control Object write its current state into every packet sent from the server. This combination of state transfer and deterministic move processing is used to keep the Control Object and its ghost synchronized, and to allow the client to predict the motion of the control object ahead of server updates. Delivering moves and Control Object state updates as soon as possible along with client prediction of move processing allows smooth and immediate response to player input, while providing full validation of all player moves by the server. Datablock Stream Manager The Datablock manager provides "latest state" delivery of datablocks from the server to the client. Datablocks are objects which contain relatively static data and the manager guarantees delivery only of the latest state at a very low frequency. Like the Ghost manager, the Datablock manager is asymmetric, and datablocks are only transmitted from server to client. The most common use of datablocks is to transmit initialization or reference data for ghosts. Datablocks are copied to the client in a stream of guaranteed events. Since datablocks are considered static they are not updated during the normal course of a session, but only at fixed times such as when first connecting to a server or during a map change. A global “last modified” key is used to track changes to datablocks. Each time a datablock is modified it is assigned the current value of this key, after which the key is incremented. The manager keeps the highest key value transmitted to its remote host. Since the manager only guarantees "latest state", if a Datablock is modified several times between updates, this information is lost to the client. Further, since the changes to datablocks are low in frequency, the Ghost manager’s overhead of partial state updates is not necessary –- a changed datablock is retransmitted in its entirety. Unlike the other Connection stream managers, the Datablock manager does not write into, or read from the packet bit stream produced by the Stream manager. Updates are invoked directly from the scripting language and involve looping through all the existing datablocks and transmitting every datablock with a modified key greater than manager's key. The actual transfer of datablocks is performed by sending guaranteed Datablock Events using the Event manager. A Datablock Event contains the datablock Page 86 of 128 Fight Zone Technical Design Document object to transmit, and the datablock is packed as part of the event. As an example, the Vehicle class has an associated VehicleData Datablock class. The Datablock class contains numerous vehicle property attributes such as shape, maximum speed, maximum acceleration, suspension properties for wheels, etc. When a Vehicle object is constructed, it is assigned an instance of the VehicleData Datablock. Each instance of the VehicleData Datablock represents a different set of attributes describing a different type of vehicle such as a tank, scout, transport, etc. The Vehicle class itself represents the instance of that vehicle type in the simulation and provides all the code and dynamic attributes necessary to simulate the vehicle. Server Client VehicleData Datablock Instance with static vehicle attributes VehicleData Datablock Copy of static vehicle attributes Vehicle Class Object Datablock Dynamic vehicle attributes Vehicle Class Ghost Datablock Dynamic vehicle attributes Figure 5: Vehicle Datablock relationship mirrored on client The advantage of this separation of static attribute data and instance data is that Datablocks are normally only transmitted to the client once at connect time. When a Vehicle object is ghosted to the client (a process that can happen often) it sends only its datablock's ID along with other dynamic data relevant to the ghost. This results in huge savings in bandwidth, while still providing the flexibility of defining static attribute data on the server. As shown in Figure 5, the client will mirror the same relationship of Vehicle instance to VehicleData datablock. Since datablocks are only transferred at times when the simulation is effectively stopped, more bandwidth is available and datablocks can contain more information than would normally be possible. This also means the Datablock manager imposes no extra overhead to the bitstream during the normal course of simulation. Simulation Layer Page 87 of 128 Fight Zone Technical Design Document The Simulation layer performs a number of functions of which only a few are relevant to a discussion of the networking model. These are the advancement of time, scoping for the Ghost manager, and client side prediction. Advancement of simulation time is centered on the processing of moves. Moves are gathered every 32 milliseconds, and the simulation is advanced in 32 millisecond increments with a move for each increment or tick. All objects on the client and server are advanced in the same manner and if a Move manager is not controlling an object, then it is passed NULL moves. Though client objects are advanced in fixed increments, the elapsed time between frames may not fall on even increments. To present a smooth view, especially on a machine with a high frame rate, time is always advanced to the beginning of the next interval, and ghost objects maintain backwards interpolation information which is used to "tween" frames between ticks. Objects on the server are never rendered so they do not have to perform this function. Simulation objects must be scoped and prioritized for the ghost manager. Scoping is the process of determining which objects on the server are relevant to a particular client. In the simplest sense, this means all objects that are potentially visible to a client from that client's current control object. This form of scoping is performed using a spatial database maintained by the simulation. When an object is determined to be in scope, the object itself determines its own priority based on information such as current ghost state mask, distance from the scoping object, projected radius (using the scoping object’s view frustrum parameters), relative velocity, animation state and interest modifiers (projectiles that are moving towards the client are more interesting than vehicles, vehicles are more interesting than items, etc.). There are two forms of client side prediction in this model. First is the Control Object move prediction performed by the Move manager. This is by far the more complicated and provides the foundation for controlling and predicting objects such as players, vehicles, turrets and cameras. The other is prediction performed by non-controlled ghost objects such as projectiles, items, etc. This level of prediction is left entirely to the objects themselves and no supporting structure is provided. An example of a prediction strategy is that provided by the Item class, one of the simpler objects. This object is driven entirely by the physics of the environment and does not process input moves. By simply simulating normally the ghost will correctly predict interaction with all static objects. If a dynamic object is hit on the server, then its ghost state mask is set to transfer its latest position and velocity. When the client ghost receives an update from the server, it interpolates its current position smoothly to the server's updated position and continues from there. More complex strategies are used by the vehicle and player classes, which have to deal with predicting movement from other clients. Page 88 of 128 Fight Zone Technical Design Document Summary By classifying data according to its delivery requirements and organizing the stream managers to efficiently meet those requirements, the Tribes II networking model attempts to make optimal use of available bandwidth. In combination with dynamic object scoping and prioritization of partial object state updates, the TRIBES II engine allows smooth visualization of large virtual environments over low bandwidth connections, even when a substantial number of objects are visible to a client. Though the model provides a solid foundation for network traffic, it is not sufficient to simply provide a fast reliable connection between hosts; there will always be bandwidth and latency issues to contend with. Not covered in this article are: choices made when deciding which object behavior should be managed by the server and which by the clients, which object state information to transfer, how to organize object partial states, how to prioritize object state changes relative to each other, which compression algorithm to use, and how to perform client side prediction of Control Objects. All of these can have a dramatic effect on perceived network performance. This model was first implemented in Starsiege TRIBES, which shipped in December of ‘98. The updated implementation in TRIBES II has the following improvements: 1. Reorganization and simplification of the Connection and Stream layers. 2. Better packet header compression for the Connection manager’s notification protocol. 3. A reduction in the number of times moves are re-transmitted to avoid negative feedback loops due to increased packet size. 4. Better data compression by individual objects. 5. The addition of the String manager, which provides high order compression for repeatedly transmitted character strings (not discussed in this article). Several modifications to the model have been considered, and though they will not be implemented for TRIBES II, are worth exploring. These include: 1. Variable production of packets by the Stream manager. Updates are currently produced at a constant rate dictated by the Stream manager’s bandwidth settings. Packets could be produced as soon as data is available for transmission or data priority reaches a given threshold. 2. Asynchronous Connection processing on the server. All Connection managers are currently processed at the same time on the server in a single thread. The server architecture could be changed to support a primary simulation thread with a separate thread for each client. This would provide the Connection and Stream managers with lower latency communication with their remote host as well as provide better support for multi-processor hardware. Page 89 of 128 Fight Zone Technical Design Document 3. The addition of new stream managers, including a multiplexing audio stream manager. TRIBES II will support voice using a simpler approach. 4. Dynamic allocation of server bandwidth. Bandwidth on the server is currently set at a fixed per client. The server could be modified to adjust its per client bandwidth based on the number of connected clients. 5. Determine a method of automatically and effectively calculating the available bandwidth on a connection. Bandwidth settings are currently set manually by a client. Acknowledgments Though several of the ideas presented here are unique to TRIBES, others have been assimilated from other sources over countless years of reading and the authors, being too lazy to research their sources, would like to thank everyone in one sentence. Page 90 of 128 Fight Zone Technical Design Document Appendix B UI Skin File Documentation Page 91 of 128 Fight Zone Technical Design Document UI Skin File Format UI skin files consist of a tag based file format that is slightly similar to HTML. The files consist of tags and comments. The tag format is as follows: < [TagName] [ParameterList] > Tags start with the ‘<’ character and end with the ‘>’ character. These characters open and close the tag respectively. After the opening the tag, the tag name is supplied. The tag name is a string of characters that is an ID corresponding to the functionality that the tag represents. The parameter list follows the tag name. Each parameter in the list is separated by white space. The parameter format is as follows: [ParameterName] = "[ParameterValue]" The parameter name is a string of characters that is an ID corresponding to what the parameter value represents. If an invalid parameter name is specified, the parameter will be skipped over. If a parameter name is not specified, it will be given a default value. All text in between tags in the file will be skipped over and can be used as space for putting comments. Header Tag The header tag determines where the actual skin starts. All text above the header tag (no matter what it contains) will be skipped. Tag Name Parameters Name Width Height FightZoneSkin Description This determines what resolution width you are building the skin at. The images will be scaled appropriately to the resolution that the user runs at in the game. This determines what resolution height you are building the skin at. The images will be scaled appropriately to the resolution that the user runs at in the game. Default Value Undefined Undefined Page 92 of 128 Fight Zone Technical Design Document Buttons Hit Box The hit box is the portion of the screen that interacts with mouse for detecting the different actions and image states. Parameters Name Description Default Value HitBoxPosX Undefined X position of the top left corner of the hit box on the screen in pixels relative to (0, 0). HitBoxPosY Undefined Y position of the top left corner of the hit box on the screen in pixels relative to (0, 0). HitBoxWidth NormalImgScrnWidth Width of the hit box in pixels relative to the skin width. HitBoxHeight NormalImgScrnHeight Height of the hit box in pixels relative to the skin height. Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Name Description Default Value ImgFileName Undefined Default image file name. ImgScrnPosX 0 Default image X position in pixels on the screen relative to HitBoxPosX. ImgScrnPosY 0 Default image Y position in pixels on the screen relative to HitBoxPosY. ImgScrnWidth ImgWidth Default image width in pixels on the screen relative to the skin width. ImgScrnHeight ImgHeight Default image height in pixels on the screen relative to the skin height. ImgFilePosX 0 Default image X position in pixels in the file relative to (0, 0). ImgFilePosY 0 Default image X position in pixels in the file relative to (0, 0). ImgFileWidth ImgWidth Default image width in pixels relative to the file width. ImgFileHeight ImgHeight Default image height in pixels relative to the file height. ImgWidth Default image width (on screen The width of the image file and in the file) in pixels relative to the file width and screen width. ImgHeight Default image height (on screen The height of the image and in the file) in pixels relative to file the file height and screen height. Page 93 of 128 Fight Zone Technical Design Document States The images representing each state can also be specified uniquely. This can be done by inserting the state name directly in front of (no white space) any of the default image parameters. This will then override that parameter for this state’s image. States Name Description Normal Button is not being interacted with, but can be used. Disabled Button is unable to be used. MouseOver When the mouse is over the hit box. MouseDown When the mouse is over the hit box and pressed down. Tag Names The following tag names can be used with the button object parameters. Buttons Name Description Additional Parameters ButtonLink Transfer to a different menu Target – File name of when clicked. the skin file to transfer to when the button is clicked. JoinServer Join the currently selected Target – File name of server. the skin file to transfer to when the button is clicked. MaxPlayersDecrement Decrease the maximum None number of players allowed in the game. MaxPlayersIncrement Increase the maximum None number of players allowed in the game. NumBotsDecrement Decrease the number of bots None that will be playing in the game. NumBotsIncrement Increase the number of bots None that will be playing in the game. RefreshLANServers Update the list of available None LAN servers on the network. StartGame Start the game as a server. Target – File name of the skin file to transfer to when the button is clicked. Spawn Spawn in the game with Target – File name of current upgrade settings. the skin file to transfer to when the button is clicked. AddArena Add the selected available None arena to the list of arena’s to play. Page 94 of 128 Fight Zone Technical Design Document RemoveArena CycleHeadColorLeft CycleHeadColorRight CycleTorsoColorLeft CycleTorsoColorRight CycleLegsColorLeft CycleLegsColorRight ExitGame Remove the selected arena to play from the list of arenas to play. Cycle the local player’s head armor color to the “left”. Cycle the local player’s head armor color to the “Right”. Cycle the local player’s torso armor color to the “left”. Cycle the local player’s torso armor color to the “Right”. Cycle the local player’s legs armor color to the “left”. Cycle the local player’s legs armor color to the “Right”. Exit the entire Fight Zone program. None None None None None None None None Page 95 of 128 Fight Zone Technical Design Document Check Boxes Hit Box The hit box is the portion of the screen that interacts with mouse for detecting the different actions and image states. Parameters Name Description Default Value HitBoxPosX X position of the top left Undefined corner of the hit box on the screen in pixels relative to (0, 0). HitBoxPosY Y position of the top left Undefined corner of the hit box on the screen in pixels relative to (0, 0). HitBoxWidth UnselectedNormalImgScrnWidth Width of the hit box in pixels relative to the skin width. HitBoxHeight UnselectedNormalImgScrnHeight Height of the hit box in pixels relative to the skin height. Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Same as buttons. States The images representing each state can also be specified uniquely. This can be done by inserting the state name directly in front of (no white space) any of the default image parameters. This will then override that parameter for this state’s image. States Name Description UnselectedNormal Check box is not checked and is not being interacted with, but can be used. SelectedNormal Check box is checked and is not being interacted with, but can be used. Disabled Check box is unable to be used. UnselectedMouseOver Check box is not checked and the mouse is over the hit box. SelectedMouseOver Check box is checked and the mouse is over the hit box. UnselectedMouseDown Check box is not checked and the mouse is over the hit box and pressed down. SelectedMouseDown Check box is checked and the mouse is over the hit box and pressed down. Page 96 of 128 Fight Zone Technical Design Document Tag Names The following tag names can be used with the check box object parameters. Check Boxes Name Description Additional Parameters MouseLook None Toggle mouse look functionality. InvertAxis Toggle inversion of the mouse None Y-axis. Page 97 of 128 Fight Zone Technical Design Document Cursors Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Name Description Default Value ImgFileName Undefined Default image file name. ImgScrnPosX 0 Default image X position in pixels on the screen relative to the mouse X position. ImgScrnPosY 0 Default image Y position in pixels on the screen relative to the mouse Y position. ImgScrnWidth ImgWidth Default image width in pixels on the screen relative to the skin width. ImgScrnHeight ImgHeight Default image height in pixels on the screen relative to the skin height. ImgFilePosX 0 Default image X position in pixels in the file relative to (0, 0). ImgFilePosY 0 Default image X position in pixels in the file relative to (0, 0). ImgFileWidth ImgWidth Default image width in pixels relative to the file width. ImgFileHeight ImgHeight Default image height in pixels relative to the file height. ImgWidth Default image width (on screen The width of the image file and in the file) in pixels relative to the file width and screen width. ImgHeight Default image height (on screen The height of the image and in the file) in pixels relative to file the file height and screen height. States The images representing each state can also be specified uniquely. This can be done by inserting the state name directly in front of (no white space) any of the default image parameters. This will then override that parameter for this state’s image. States Name Description Normal Mouse is enabled and not pressed down. Disabled Mouse is disabled. MouseDown Mouse is pressed down. Tag Names The following tag names can be used with the cursor object parameters. Page 98 of 128 Fight Zone Technical Design Document Cursors Name Cursor Description Standard mouse cursor on the screen. Additional Parameters None Page 99 of 128 Fight Zone Technical Design Document Drop Down Boxes Hit Box The hit box is the portion of the screen that interacts with mouse for detecting the different actions and image states. Parameters Name Description Default Value HitBoxPosX Undefined X position of the top left corner of the hit box on the screen in pixels relative to (0, 0). HitBoxPosY Undefined Y position of the top left corner of the hit box on the screen in pixels relative to (0, 0). HitBoxWidth Width of the hit box in pixels ClosedNormalImgScrnWidth relative to the skin width. HitBoxHeight ClosedNormalImgScrnHeight Height of the hit box in pixels relative to the skin height. Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Same as buttons. States The images representing each state can also be specified uniquely. This can be done by inserting the state name directly in front of (no white space) any of the default image parameters. This will then override that parameter for this state’s image. States Name Description ClosedNormal Check box is closed and is not being interacted with, but can be used. OpenNormal Check box is open and is not being interacted with, but can be used. Disabled Check box is unable to be used. ClosedMouseOver Check box is closed and the mouse is over the hit box. OpenMouseOver Check box is open and the mouse is over the hit box. ClosedMouseDown Check box is closed and the mouse is over the hit box and pressed down. OpenMouseDown Check box is open and the mouse is over the hit box and pressed down. Page 100 of 128 Fight Zone Technical Design Document Selected Text The selected text settings determine how to display the text of the selected value. This text is always displayed. Parameters Name Description Default Value TextPosX 0 Default selected text X position in pixels on the screen relative to HitBoxPosX. TextPosY 0 Default selected text Y position in pixels on the screen relative to HitBoxPosY. TextSize HitBoxHeight Default selected text size in pixels on the screen. TextColor Default selected text color Undefined in ARGB format. This is easiest to specify as a hexadecimal value which will require a prefix of 0x before the hexadecimal number. DisabledTextColor TextColor Disabled selected text color in ARGB format. ClosedTextColor Default selected text color TextColor in ARGB format for when the box is closed. OpenTextColor Default selected text color TextColor in ARGB format for when the box is open. ClosedNormalTextColor ClosedTextColor Normal selected text color in ARGB format for when the box is closed. OpenNormalTextColor OpenTextColor Normal selected text color in ARGB format for when the box is open. ClosedMouseOverTextColor Selected text color in ClosedTextColor ARGB format for when the box is open and the mouse is over the hit box. OpenMouseOverTextColor OpenTextColor Selected text color in ARGB format for when the box is open and the mouse is over the hit box. ClosedMouseDownTextColor Selected text color in ClosedTextColor ARGB format for when the box is open and the mouse is over the hit box and pressed down. OpenMouseDownTextColor OpenTextColor Selected text color in ARGB format for when the box is open and the mouse is over the hit box and pressed down. Page 101 of 128 Fight Zone Technical Design Document Box The box is where the items open up. Parameters Name Description BoxPosX X position of the top left corner of the box in pixels on the screen relative to HitBoxPosX. BoxPosY Y position of the top left corner of the box in pixels on the screen relative to HitBoxPosY. Default Value 0 0 Item Hit Box The item hit box is the portion of the screen used for the mouse to interact with the items in the box. Parameters Name Description Default Value ItemHitBoxPosX 0 X position of the top left corner of the item hit box on the screen in pixels relative to BoxPosX. ItemHitBoxPosY 0 Y position of the top left corner of the item hit box on the screen in pixels relative to BoxPosY ItemHitBoxWidth ItemImgScrnWidth Width of the item hit box in pixels relative to the skin width. ItemHitBoxHeight Height of the item hit box ItemImgScrnHeight in pixels relative to the skin height. Box Images The box images are used to draw the box of items. Three images construct the box (top, item, and bottom). The image parameters are specified with positions as if there was only one item in the box, and the item image will be repeated appropriately (based on the item hit box dimensions) given the actual amount of images in the box. The bottom image will also be pushed down appropriately. Parameters Name Description Default Value BoxTopImgFileName Undefined Top image file name. BoxTopImgScrnPosX 0 Top image X position in pixels on the screen relative to BoxPosX. BoxTopImgScrnPosY 0 Top image Y position in pixels on the screen Page 102 of 128 Fight Zone Technical Design Document BoxTopImgScrnWidth BoxTopImgScrnHeight BoxTopImgFilePosX BoxTopImgFilePosY BoxTopImgFileWidth BoxTopImgFileHeight BoxTopImgWidth BoxTopImgHeight ItemImgFileName ItemImgScrnPosX ItemImgScrnPosY ItemImgScrnWidth ItemImgScrnHeight ItemImgFilePosX ItemImgFilePosY ItemImgFileWidth ItemImgFileHeight ItemImgWidth relative to BoxPosY. Top image width in pixels on the screen relative to the skin width. Top image height in pixels on the screen relative to the skin height. Top image X position in pixels in the file relative to (0, 0). Top image X position in pixels in the file relative to (0, 0). Top image width in pixels relative to the file width. Top image height in pixels relative to the file height. Top image width (on screen and in the file) in pixels relative to the file width and screen width. Top image height (on screen and in the file) in pixels relative to the file height and screen height. Item image file name. Item image X position in pixels on the screen relative to ItemHitBoxPosX. Item image Y position in pixels on the screen relative to ItemHitBoxPosY. Item image width in pixels on the screen relative to the skin width. Item image height in pixels on the screen relative to the skin height. Item image X position in pixels in the file relative to (0, 0). Item image X position in pixels in the file relative to (0, 0). Item image width in pixels relative to the file width. Item image height in pixels relative to the file height. Item image width (on screen and in the file) in pixels relative to the file ImgWidth ImgHeight 0 0 ImgWidth ImgHeight The width of the image file The height of the image file Undefined 0 0 ImgWidth ImgHeight 0 0 ImgWidth ImgHeight The width of the image file Page 103 of 128 Fight Zone Technical Design Document ItemImgHeight BoxBottomImgFileName BoxBottomImgScrnPosX BoxBottomImgScrnPosY BoxBottomImgScrnWidth BoxBottomImgScrnHeight BoxBottomImgFilePosX BoxBottomImgFilePosY BoxBottomImgFileWidth BoxBottomImgFileHeight BoxBottomImgWidth BoxBottomImgHeight width and screen width. Item image height (on screen and in the file) in pixels relative to the file height and screen height. Bottom image file name. Bottom image X position in pixels on the screen relative to BoxPosX. Bottom image Y position in pixels on the screen relative to BoxPosY. Bottom image width in pixels on the screen relative to the skin width. Bottom image height in pixels on the screen relative to the skin height. Bottom image X position in pixels in the file relative to (0, 0). Bottom image X position in pixels in the file relative to (0, 0). Bottom image width in pixels relative to the file width. Bottom image height in pixels relative to the file height. Bottom image width (on screen and in the file) in pixels relative to the file width and screen width. Bottom image height (on screen and in the file) in pixels relative to the file height and screen height. The height of the image file Undefined 0 0 ImgWidth ImgHeight 0 0 ImgWidth ImgHeight The width of the image file The height of the image file Item Text The item text settings determine how to display the text of an item in the box when it is open. Parameters Name Description Default Value ItemTextPosX 0 Default item text X position in pixels on the screen relative to ItemHitBoxPosX. ItemTextPosY 0 Default item text Y position in pixels on the screen Page 104 of 128 Fight Zone Technical Design Document ItemTextSize ItemTextColor ItemUnselectedTextColor ItemSelectedTextColor ItemUnselectedNormalTextColor ItemSelectedNormalTextColor ItemUnselectedMouseOverTextColor ItemSelectedMouseOverTextColor ItemUnselectedMouseDownTextColor ItemSelectedMouseDownTextColor relative to ItemHitBoxPosY. Default item text size in pixels on the screen. Default item text color in ARGB format. This is easiest to specify as a hexadecimal value which will require a prefix of 0x before the hexadecimal number. Default unselected item text color in ARGB format. Default selected item text color in ARGB format. Normal unselected item text color in ARGB format. Normal selected item text color in ARGB format. Unselected item text color in ARGB format for when the mouse is over the item hit box. Selected item text color in ARGB format for when the mouse is over the item hit box. Unselected item text color in ARGB format for when the mouse is over the item hit box and pressed down. Selected item text color in ARGB format for when the mouse is over the item hit box and pressed down. TextSize TextColor ItemTextColor ItemTextColor ItemUnselectedTextColor ItemSelectedTextColor ItemUnselectedTextColor ItemSelectedTextColor ItemUnselectedTextColor ItemSelectedTextColor Tag Names The following tag names can be used with the drop down box object parameters. Drop Down Boxes Page 105 of 128 Fight Zone Technical Design Document Name Description ArenaDifficultySelection Select the difficulty of the arena to play in. Select the bit depth of the video mode. Select the difficulty of the bots to play with. Select the connection speed for network packet transfer. Select the detail to render visual effects at. Select the resolution of the video mode. Select the detail to render textures at. BitDepthSelection BotDifficultySelection ConnectionSpeedSelection EffectsDetailSelection ResolutionSelection TextureDetailSelection Additional Parameters None None None None None None None Page 106 of 128 Fight Zone Technical Design Document Edit Boxes Hit Box The hit box is the portion of the screen that interacts with mouse for detecting the different actions and image states. Parameters Name Description Default Value HitBoxPosX X position of the top left Undefined corner of the hit box on the screen in pixels relative to (0, 0). HitBoxPosY Y position of the top left Undefined corner of the hit box on the screen in pixels relative to (0, 0). HitBoxWidth UnselectedNormalImgScrnWidth Width of the hit box in pixels relative to the skin width. HitBoxHeight UnselectedNormalImgScrnHeight Height of the hit box in pixels relative to the skin height. Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Same as buttons. States The images representing each state can also be specified uniquely. This can be done by inserting the state name directly in front of (no white space) any of the default image parameters. This will then override that parameter for this state’s image. States Name Description UnselectedNormal Edit box is usable, is not being typed in, and is not being interacted with by the mouse. SelectedNormal Edit box is usable, is being typed in, and is not being interacted with by the mouse. Disabled Edit box is unable to be used. UnselectedMouseOver Edit box is usable, is not being typed in, and the mouse is over the hit box. SelectedMouseOver Edit box is usable, is being typed in, and the mouse is over the hit box. UnselectedMouseDown Edit box is usable, is not being typed in, and the mouse is over the hit box and pressed down. SelectedMouseDown Edit box is usable, is being typed in, and the mouse is over the hit box and pressed down. Page 107 of 128 Fight Zone Technical Design Document Text The text settings determine how to display the editable text. Parameters Name Description TextPosX Default text X position in pixels on the screen relative to HitBoxPosX. TextPosY Default text Y position in pixels on the screen relative to HitBoxPosY. TextSize Default text size in pixels on the screen. TextColor Default text color in ARGB format. This is easiest to specify as a hexadecimal value which will require a prefix of 0x before the hexadecimal number. DisabledTextColor Disabled text color in ARGB format. UnselectedTextColor Default unselected text color in ARGB format. SelectedTextColor Default selected text color in ARGB format. UnselectedNormalTextColor Normal unselected text color in ARGB format. SelectedNormalTextColor Normal selected text color in ARGB format. UnselectedMouseOverTextColor Unselected text color in ARGB format for when the mouse is over the hit box. SelectedMouseOverTextColor Selected text color in ARGB format for when Default Value 0 0 HitBoxHeight Undefined TextColor TextColor TextColor UnselectedTextColor SelectedTextColor UnselectedTextColor SelectedTextColor Page 108 of 128 Fight Zone Technical Design Document UnselectedMouseDownTextColor SelectedMouseDownTextColor the mouse is over the hit box. Unselected text color in ARGB format for when the mouse is over the hit box and pressed down. Selected text color in ARGB format for when the mouse is over the hit box and pressed down. UnselectedTextColor SelectedTextColor Tag Names The following tag names can be used with the edit box object parameters. Edit Boxes Name Description Additional Parameters MaxUpgradePointsEntry Enter the number of upgrade None points allowed for distribution. PlayerNameEntry Enter the name of the local None player. RoundTimeEntry Enter the length in time None allowed per round. ScoreLimitEntry Enter the score limit win None condition for a round. ServerAddressEntry Enter the address of the None server to connect to. ServerPasswordEntry Enter the password of the None server to connect to. Page 109 of 128 Fight Zone Technical Design Document Images Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Name Description Default Value ImgFileName Undefined Default image file name. ImgScrnPosX Undefined X position of the top left corner of the image on the screen in pixels relative to (0, 0). ImgScrnPosY Undefined Y position of the top left corner of the image on the screen in pixels relative to (0, 0). ImgScrnWidth ImgWidth Default image width in pixels on the screen relative to the skin width. ImgScrnHeight ImgHeight Default image height in pixels on the screen relative to the skin height. ImgFilePosX 0 Default image X position in pixels in the file relative to (0, 0). ImgFilePosY 0 Default image X position in pixels in the file relative to (0, 0). ImgFileWidth ImgWidth Default image width in pixels relative to the file width. ImgFileHeight ImgHeight Default image height in pixels relative to the file height. ImgWidth Default image width (on screen The width of the image file and in the file) in pixels relative to the file width and screen width. ImgHeight Default image height (on screen The height of the image and in the file) in pixels relative to file the file height and screen height. Tag Names The following tag names can be used with the image object parameters. Images Name Description Additional Parameters Image Display a static image on the None screen. Page 110 of 128 Fight Zone Technical Design Document Key Links Key The key link allows the user to press a key to transfer between menus. Key links make use of the following key codes. /****************************************************************** * * DirectInput keyboard scan codes * ******************************************************************/ DIK_ESCAPE 01 DIK_1 02 DIK_2 03 DIK_3 04 DIK_4 05 DIK_5 06 DIK_6 07 DIK_7 08 DIK_8 09 DIK_9 0A DIK_0 0B DIK_MINUS 0C /* - on main keyboard */ DIK_EQUALS 0D DIK_BACK 0E /* backspace */ DIK_TAB 0F DIK_Q 10 DIK_W 11 DIK_E 12 DIK_R 13 DIK_T 14 DIK_Y 15 DIK_U 16 DIK_I 17 DIK_O 18 DIK_P 19 DIK_LBRACKET 1A DIK_RBRACKET 1B DIK_RETURN 1C /* Enter on main keyboard */ DIK_LCONTROL 1D DIK_A 1E DIK_S 1F DIK_D 20 DIK_F 21 DIK_G 22 DIK_H 23 DIK_J 24 DIK_K 25 DIK_L 26 DIK_SEMICOLON 27 DIK_APOSTROPHE 28 DIK_GRAVE 29 /* accent grave */ DIK_LSHIFT 2A Page 111 of 128 Fight Zone Technical Design Document DIK_BACKSLASH 2B DIK_Z 2C DIK_X 2D DIK_C 2E DIK_V 2F DIK_B 30 DIK_N 31 DIK_M 32 DIK_COMMA 33 DIK_PERIOD 34 DIK_SLASH 35 DIK_RSHIFT 36 DIK_MULTIPLY 37 DIK_LMENU 38 DIK_SPACE 39 DIK_CAPITAL 3A DIK_F1 3B DIK_F2 3C DIK_F3 3D DIK_F4 3E DIK_F5 3F DIK_F6 40 DIK_F7 41 DIK_F8 42 DIK_F9 43 DIK_F10 44 DIK_NUMLOCK 45 DIK_SCROLL 46 DIK_NUMPAD7 47 DIK_NUMPAD8 48 DIK_NUMPAD9 49 DIK_SUBTRACT 4A DIK_NUMPAD4 4B DIK_NUMPAD5 4C DIK_NUMPAD6 4D DIK_ADD 4E DIK_NUMPAD1 4F DIK_NUMPAD2 50 DIK_NUMPAD3 51 DIK_NUMPAD0 52 DIK_DECIMAL 53 DIK_OEM_102 56 U.S.) */ DIK_F11 57 DIK_F12 58 DIK_F13 64 DIK_F14 65 DIK_F15 66 DIK_KANA 70 DIK_ABNT_C1 73 DIK_CONVERT 79 DIK_NOCONVERT 7B DIK_YEN 7D DIK_ABNT_C2 7E DIK_NUMPADEQUALS 8D DIK_PREVTRACK 90 Japanese keyboard) */ /* . on main keyboard */ /* / on main keyboard */ /* * on numeric keypad */ /* left Alt */ /* Scroll Lock */ /* - on numeric keypad */ /* + on numeric keypad */ /* . on numeric keypad */ /* <> or \| on RT 102-key keyboard (Non- /* /* /* /* /* /* /* /* /* /* /* (NEC PC98) */ (NEC PC98) */ (NEC PC98) */ (Japanese keyboard) */ /? on Brazilian keyboard */ (Japanese keyboard) */ (Japanese keyboard) */ (Japanese keyboard) */ Numpad . on Brazilian keyboard */ = on numeric keypad (NEC PC98) */ Previous Track (DIK_CIRCUMFLEX on Page 112 of 128 Fight Zone Technical Design Document DIK_AT DIK_COLON DIK_UNDERLINE DIK_KANJI DIK_STOP DIK_AX DIK_UNLABELED DIK_NEXTTRACK DIK_NUMPADENTER DIK_RCONTROL DIK_MUTE DIK_CALCULATOR DIK_PLAYPAUSE DIK_MEDIASTOP DIK_VOLUMEDOWN DIK_VOLUMEUP DIK_WEBHOME DIK_NUMPADCOMMA DIK_DIVIDE DIK_SYSRQ DIK_RMENU DIK_PAUSE DIK_HOME DIK_UP DIK_PRIOR DIK_LEFT DIK_RIGHT DIK_END DIK_DOWN DIK_NEXT DIK_INSERT DIK_DELETE DIK_LWIN DIK_RWIN DIK_APPS DIK_POWER DIK_SLEEP DIK_WAKE DIK_WEBSEARCH DIK_WEBFAVORITES DIK_WEBREFRESH DIK_WEBSTOP DIK_WEBFORWARD DIK_WEBBACK DIK_MYCOMPUTER DIK_MAIL DIK_MEDIASELECT 91 92 93 94 95 96 97 99 9C 9D A0 A1 A2 A4 AE B0 B2 B3 B5 B7 B8 C5 C7 C8 C9 CB CD CF D0 D1 D2 D3 DB DC DD DE DF E3 E5 E6 E7 E8 E9 EA EB EC ED /* (NEC PC98) /* (NEC PC98) /* (NEC PC98) /* (Japanese keyboard) /* (NEC PC98) /* (Japan AX) /* (J3100) /* Next Track */ /* Enter on numeric keypad */ */ */ */ */ */ */ */ /* /* /* /* /* /* /* /* /* Mute */ Calculator */ Play / Pause */ Media Stop */ Volume - */ Volume + */ Web home */ , on numeric keypad (NEC PC98) */ / on numeric keypad */ /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* right Alt */ Pause */ Home on arrow keypad */ UpArrow on arrow keypad */ PgUp on arrow keypad */ LeftArrow on arrow keypad */ RightArrow on arrow keypad */ End on arrow keypad */ DownArrow on arrow keypad */ PgDn on arrow keypad */ Insert on arrow keypad */ Delete on arrow keypad */ Left Windows key */ Right Windows key */ AppMenu key */ System Power */ System Sleep */ System Wake */ Web Search */ Web Favorites */ Web Refresh */ Web Stop */ Web Forward */ Web Back */ My Computer */ Mail */ Media Select */ /* * Alternate names for keys, to facilitate */ DIK_BACKSPACE DIK_BACK /* DIK_NUMPADSTAR DIK_MULTIPLY /* DIK_LALT DIK_LMENU /* DIK_CAPSLOCK DIK_CAPITAL /* DIK_NUMPADMINUS DIK_SUBTRACT /* DIK_NUMPADPLUS DIK_ADD /* transition from DOS. backspace */ * on numeric keypad */ left Alt */ CapsLock */ - on numeric keypad */ + on numeric keypad */ Page 113 of 128 Fight Zone Technical Design Document DIK_NUMPADPERIOD DIK_NUMPADSLASH DIK_RALT DIK_UPARROW */ DIK_PGUP DIK_LEFTARROW keypad */ DIK_RIGHTARROW keypad */ DIK_DOWNARROW keypad */ DIK_PGDN DIK_DECIMAL DIK_DIVIDE DIK_RMENU DIK_UP /* /* /* /* DIK_PRIOR DIK_LEFT /* PgUp on arrow keypad */ /* LeftArrow on arrow DIK_RIGHT /* RightArrow on arrow DIK_DOWN /* DownArrow on arrow DIK_NEXT /* PgDn on arrow keypad */ /* * Alternate names for keys originally not */ DIK_CIRCUMFLEX DIK_PREVTRACK /* Parameters Name Description Key Takes in a direct input key code. The above table gives the key code values in hexadecimal format, which requires a prefix of 0x. Target File name of the menu to transfer to. . on numeric keypad */ / on numeric keypad */ right Alt */ UpArrow on arrow keypad used on US keyboards. Japanese keyboard */ Default Value Undefined Undefined Tag Names The following tag names can be used with the image object parameters. Key Links Name Description Additional Parameters KeyLink Link to another menu. None Page 114 of 128 Fight Zone Technical Design Document List Boxes Box The box determines the overall reference position for the list box. Parameters Name Description Default Value BoxPosX X position of the top left Undefined corner of the box in pixels on the screen relative to (0, 0). BoxPosY Y position of the top left Undefined corner of the box in pixels on the screen relative to (0, 0). BoxHeight Number of items the box Undefined can display without scrolling. Up Button Hit Box The up button hit box is the portion of the screen that interacts with mouse for detecting the different actions with the up button and image states of the up button. Parameters Name Description Default Value UpButtonHitBoxPosX X position of the Undefined top left corner of the hit box on the screen in pixels relative to BoxPosX. UpButtonHitBoxPosY Y position of the Undefined top left corner of the hit box on the screen in pixels relative to BoxPosY. UpButtonHitBoxWidth UpButtonNormalImgScrnWidth Width of the hit box in pixels relative to the skin width. UpButtonHitBoxHeight Height of the hit UpButtonNormalImgScrnHeight box in pixels relative to the skin height. Up Button Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Page 115 of 128 Fight Zone Technical Design Document Parameters Name UpButtonImgFileName UpButtonImgScrnPosX UpButtonImgScrnPosY UpButtonImgScrnWidth UpButtonImgScrnHeight UpButtonImgFilePosX UpButtonImgFilePosY UpButtonImgFileWidth UpButtonImgFileHeight UpButtonImgWidth UpButtonImgHeight Description Default image file name. Default image X position in pixels on the screen relative to UpButtonHitBoxPosX. Default image Y position in pixels on the screen relative to UpButtonHitBoxPosY. Default image width in pixels on the screen relative to the skin width. Default image height in pixels on the screen relative to the skin height. Default image X position in pixels in the file relative to (0, 0). Default image X position in pixels in the file relative to (0, 0). Default image width in pixels relative to the file width. Default image height in pixels relative to the file height. Default image width (on screen and in the file) in pixels relative to the file width and screen width. Default image height (on screen and in the file) in pixels relative to the file height and screen height. Default Value Undefined 0 0 UpButtonImgWidth UpButtonImgHeight 0 0 UpButtonImgWidth UpButtonImgHeight The width of the image file The height of the image file Up Button States The images representing each up button state can also be specified uniquely. This can be done by inserting the state name after the UpButton portion of the tag name of the default up button image parameters. This will then override that parameter for this state’s image. States Name Description Normal Button is not being interacted with, but can be used. Disabled Button is unable to be used. MouseOver When the mouse is over the hit box. MouseDown When the mouse is over the hit box and pressed down. Down Button Hit Box Page 116 of 128 Fight Zone Technical Design Document The down button hit box is the portion of the screen that interacts with mouse for detecting the different actions with the down button and image states of the down button. Parameters Name Description Default Value DownButtonHitBoxPosX X position Undefined of the top left corner of the hit box on the screen in pixels relative to BoxPosX. DownButtonHitBoxPosY Y position Undefined of the top left corner of the hit box on the screen in pixels relative to BoxPosY. DownButtonHitBoxWidth DownButtonNormalImgScrnWidth Width of the hit box in pixels relative to the skin width. DownButtonHitBoxHeight Height of DownButtonNormalImgScrnHeight the hit box in pixels relative to the skin height. Down Button Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Name Description Default Value DownButtonImgFileName Default image file name. Undefined DownButtonImgScrnPosX Default image X position 0 in pixels on the screen relative to UpButtonHitBoxPosX. DownButtonImgScrnPosY Default image Y position 0 in pixels on the screen relative to UpButtonHitBoxPosY. DownButtonImgScrnWidth DownButtonImgWidth Default image width in pixels on the screen relative to the skin width. Page 117 of 128 Fight Zone Technical Design Document DownButtonImgScrnHeight DownButtonImgFilePosX DownButtonImgFilePosY DownButtonImgFileWidth DownButtonImgFileHeight DownButtonImgWidth DownButtonImgHeight Default image height in pixels on the screen relative to the skin height. Default image X position in pixels in the file relative to (0, 0). Default image X position in pixels in the file relative to (0, 0). Default image width in pixels relative to the file width. Default image height in pixels relative to the file height. Default image width (on screen and in the file) in pixels relative to the file width and screen width. Default image height (on screen and in the file) in pixels relative to the file height and screen height. DownButtonImgHeight 0 0 DownButtonImgWidth DownButtonImgHeight The width of the image file The height of the image file Down Button States The images representing each down button state can also be specified uniquely. This can be done by inserting the state name after the DownButton portion of the tag name of the default down button image parameters. This will then override that parameter for this state’s image. States Name Description Normal Button is not being interacted with, but can be used. Disabled Button is unable to be used. MouseOver When the mouse is over the hit box. MouseDown When the mouse is over the hit box and pressed down. Item Hit Box The item hit box is the portion of the screen used for the mouse to interact with the items in the box. Parameters Name Description Default Value ItemHitBoxPosX 0 X position of the top left corner of the item hit box on the screen in pixels relative to BoxPosX. ItemHitBoxPosY 0 Y position of the top left corner of the item hit box Page 118 of 128 Fight Zone Technical Design Document ItemHitBoxWidth ItemHitBoxHeight on the screen in pixels relative to BoxPosY Width of the item hit box in pixels relative to the skin width. Height of the item hit box in pixels relative to the skin height. ItemImgScrnWidth ItemImgScrnHeight Box Images The box images are used to draw the box of items. Three images construct the box (top, item, and bottom). The image parameters are specified with positions as if there was only one item in the box, and the item image will be repeated appropriately (based on the item hit box dimensions) given the actual amount of images in the box. The bottom image will also be pushed down appropriately. Parameters Name Description Default Value BoxTopImgFileName Undefined Top image file name. BoxTopImgScrnPosX 0 Top image X position in pixels on the screen relative to BoxPosX. BoxTopImgScrnPosY 0 Top image Y position in pixels on the screen relative to BoxPosY. BoxTopImgScrnWidth Top image width in pixels ImgWidth on the screen relative to the skin width. BoxTopImgScrnHeight ImgHeight Top image height in pixels on the screen relative to the skin height. BoxTopImgFilePosX 0 Top image X position in pixels in the file relative to (0, 0). BoxTopImgFilePosY 0 Top image X position in pixels in the file relative to (0, 0). BoxTopImgFileWidth Top image width in pixels ImgWidth relative to the file width. BoxTopImgFileHeight ImgHeight Top image height in pixels relative to the file height. BoxTopImgWidth Top image width (on The width of the screen and in the file) in image file pixels relative to the file width and screen width. BoxTopImgHeight Top image height (on The height of the screen and in the file) in image file pixels relative to the file height and screen height. ItemImgFileName Undefined Item image file name. ItemImgScrnPosX 0 Item image X position in Page 119 of 128 Fight Zone Technical Design Document ItemImgScrnPosY ItemImgScrnWidth ItemImgScrnHeight ItemImgFilePosX ItemImgFilePosY ItemImgFileWidth ItemImgFileHeight ItemImgWidth ItemImgHeight BoxBottomImgFileName BoxBottomImgScrnPosX BoxBottomImgScrnPosY BoxBottomImgScrnWidth BoxBottomImgScrnHeight BoxBottomImgFilePosX BoxBottomImgFilePosY BoxBottomImgFileWidth BoxBottomImgFileHeight pixels on the screen relative to ItemHitBoxPosX. Item image Y position in pixels on the screen relative to ItemHitBoxPosY. Item image width in pixels on the screen relative to the skin width. Item image height in pixels on the screen relative to the skin height. Item image X position in pixels in the file relative to (0, 0). Item image X position in pixels in the file relative to (0, 0). Item image width in pixels relative to the file width. Item image height in pixels relative to the file height. Item image width (on screen and in the file) in pixels relative to the file width and screen width. Item image height (on screen and in the file) in pixels relative to the file height and screen height. Bottom image file name. Bottom image X position in pixels on the screen relative to BoxPosX. Bottom image Y position in pixels on the screen relative to BoxPosY. Bottom image width in pixels on the screen relative to the skin width. Bottom image height in pixels on the screen relative to the skin height. Bottom image X position in pixels in the file relative to (0, 0). Bottom image X position in pixels in the file relative to (0, 0). Bottom image width in pixels relative to the file width. Bottom image height in 0 ImgWidth ImgHeight 0 0 ImgWidth ImgHeight The width of the image file The height of the image file Undefined 0 0 ImgWidth ImgHeight 0 0 ImgWidth ImgHeight Page 120 of 128 Fight Zone Technical Design Document BoxBottomImgWidth BoxBottomImgHeight pixels relative to the file height. Bottom image width (on screen and in the file) in pixels relative to the file width and screen width. Bottom image height (on screen and in the file) in pixels relative to the file height and screen height. The width of the image file The height of the image file Item Text The item text settings determine how to display the text of an item in the box when it is open. Parameters Name Description Default Value ItemTextPosX 0 Default item text X position in pixels on the screen relative to ItemHitBoxPosX. ItemTextPosY 0 Default item text Y position in pixels on the screen relative to ItemHitBoxPosY. ItemTextSize TextSize Default item text size in pixels on the screen. ItemTextColor TextColor Default item text color in ARGB format. This is easiest to specify as a hexadecimal value which will require a prefix of 0x before the hexadecimal number. ItemDisabledTextColor ItemTextColor Disabled item text color in ARGB format. ItemUnselectedTextColor ItemTextColor Default unselected item text color in ARGB format. ItemSelectedTextColor ItemTextColor Default selected item text color in ARGB format. ItemUnselectedNormalTextColor Normal unselected ItemUnselectedTextColor item text color in ARGB format. ItemSelectedNormalTextColor ItemSelectedTextColor Normal selected Page 121 of 128 Fight Zone Technical Design Document ItemUnselectedMouseOverTextColor ItemSelectedMouseOverTextColor ItemUnselectedMouseDownTextColor ItemSelectedMouseDownTextColor item text color in ARGB format. Unselected item text color in ARGB format for when the mouse is over the item hit box. Selected item text color in ARGB format for when the mouse is over the item hit box. Unselected item text color in ARGB format for when the mouse is over the item hit box and pressed down. Selected item text color in ARGB format for when the mouse is over the item hit box and pressed down. ItemUnselectedTextColor ItemSelectedTextColor ItemUnselectedTextColor ItemSelectedTextColor Tag Names The following tag names can be used with the list down box object parameters. List Boxes Name Description Additional Parameters AvailableArenaSelection Select from a list of None arenas that are available to play in. SelectedArenaSelection Select from a list of None arenas that are selected to play in. LANServerSelection Select from a list of None available LAN servers to join. Page 122 of 128 Fight Zone Technical Design Document Radio Buttons Hit Box The hit box is the portion of the screen that interacts with mouse for detecting the different actions and image states. Parameters Name Description Default Value HitBoxPosX X position of the top left Undefined corner of the hit box on the screen in pixels relative to (0, 0). HitBoxPosY Y position of the top left Undefined corner of the hit box on the screen in pixels relative to (0, 0). HitBoxWidth UnselectedNormalImgScrnWidth Width of the hit box in pixels relative to the skin width. HitBoxHeight UnselectedNormalImgScrnHeight Height of the hit box in pixels relative to the skin height. Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Same as buttons. States The images representing each state can also be specified uniquely. This can be done by inserting the state name directly in front of (no white space) any of the default image parameters. This will then override that parameter for this state’s image. States Name Description UnselectedNormal Check box is not checked and is not being interacted with, but can be used. SelectedNormal Check box is checked and is not being interacted with, but can be used. Disabled Check box is unable to be used. UnselectedMouseOver Check box is not checked and the mouse is over the hit box. SelectedMouseOver Check box is checked and the mouse is over the hit box. UnselectedMouseDown Check box is not checked and the mouse is over the hit box and pressed down. SelectedMouseDown Check box is checked and the mouse is over the hit box and pressed down. Page 123 of 128 Fight Zone Technical Design Document Tag Names The following tag names can be used with the check box object parameters. Check Boxes Name Description Additional Parameters BallisticAmmunitionUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. BallisticMineUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. BallisticPrimaryUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. BallisticSecondaryUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. EnergyAmmunitionUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. EnergyMineUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. EnergyPrimaryUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. EnergySecondaryUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. ExplosiveAmmunitionUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. ExplosiveMineUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. ExplosivePrimaryUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. ExplosiveSecondaryUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. HeadProtectionUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. HeadScannerUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. HeadZoomUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. TorsoProtectionUpgrade Selects a level for the Value – Level of respective upgrade. the upgrade to select. Page 124 of 128 Fight Zone Technical Design Document TorsoHoverPackUpgrade Selects a level for the respective upgrade. TorsoSlashStrengthUpgrade Selects a level for the respective upgrade. LegsProtectionUpgrade Selects a level for the respective upgrade. LegsJumpStrengthUpgrade Selects a level for the respective upgrade. HeadRunStrengthUpgrade Selects a level for the respective upgrade. MouseSensitivity Selects a level for the mouse sensitivity. MusicVolume Selects a level of music volume. SFXVolume Selects a level of sound volume. Value – Level of the upgrade to select. Value – Level of the upgrade to select. Value – Level of the upgrade to select. Value – Level of the upgrade to select. Value – Level of the upgrade to select. Value – Level of mouse sensitivity to select. Value – Level of music volume to select. Value – Level of sound volume to select. Page 125 of 128 Fight Zone Technical Design Document Roll Overs Hit Box The hit box is the portion of the screen that interacts with mouse for detecting the different actions and image states. Parameters Name Description Default Value HitBoxPosX X position of the top left corner of Undefined the hit box on the screen in pixels relative to (0, 0). HitBoxPosY Y position of the top left corner of Undefined the hit box on the screen in pixels relative to (0, 0). HitBoxWidth NormalImgScrnWidth Width of the hit box in pixels relative to the skin width. HitBoxHeight NormalImgScrnHeight Height of the hit box in pixels relative to the skin height. Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Same as buttons. States The images representing each state can also be specified uniquely. This can be done by inserting the state name directly in front of (no white space) any of the default image parameters. This will then override that parameter for this state’s image. States Name Description Normal Roll over is not being interacted with. MouseOver Mouse is over the hit box. Tag Names The following tag names can be used with the roll over object parameters. Roll Overs Name Description Additional Parameters RollOver Swaps images when the None mouse goes over the hit box. Page 126 of 128 Fight Zone Technical Design Document Text Displays Hit Box The hit box is the portion of the screen that determines where the text should fit in for wrapping. Parameters Name Description Default Value HitBoxPosX X position of the top left corner of Undefined the hit box on the screen in pixels relative to (0, 0). HitBoxPosY Y position of the top left corner of Undefined the hit box on the screen in pixels relative to (0, 0). HitBoxWidth NormalImgScrnWidth Width of the hit box in pixels relative to the skin width. HitBoxHeight NormalImgScrnHeight Height of the hit box in pixels relative to the skin height. Image The images representing the object on screen must be given a source rectangle within an image file (jpeg, targa, or windows bitmap) and a destination rectangle on the screen. Parameters Same as buttons. States The images representing each state can also be specified uniquely. This can be done by inserting the state name directly in front of (no white space) any of the default image parameters. This will then override that parameter for this state’s image. States Name Description Normal Text display is in an active state. Disabled Text display is in an inactive state. Text The text settings determine how to display the text. Parameters Name Description TextPosX Default text X position in pixels on the screen relative to HitBoxPosX. TextPosY Default text Y position in pixels on the screen Default Value 0 0 Page 127 of 128 Fight Zone Technical Design Document TextSize TextColor DisabledTextColor NormalTextColor SelectedNormalTextColor relative to HitBoxPosY. Default text size in pixels on the screen. Default text color in ARGB format. This is easiest to specify as a hexadecimal value, which will require a prefix of 0x before the hexadecimal number. Disabled text color in ARGB format. Normal text color in ARGB format. Normal selected text color in ARGB format. HitBoxHeight Undefined TextColor UnselectedTextColor SelectedTextColor Tag Names The following tag names can be used with the text display object parameters. Text Displays Name Description Additional Parameters ErrorMessageDisplay Displays the current None error message. MaxPlayersDisplay Display the maximum None number of players allowed in the game. NumBotsDisplay Display the number of None bots to be in the game. Page 128 of 128