38

Mypos Games – An Auspicious Adventure – Technical Design Document

Mypos Games Presents: An Auspicious Adventure

Technical Design Document

© 2002 Jonathan Stern, Tech. Dir., Mypos Games

GAM200

Summer 2002

Team 3

1 System Information 5

1.1 Target Platform 5

1.2 Minimum System Requirements 5

2 Coding Standards 5

2.1 Comments 5

2.2 File Structure 5

2.3 Header File Structure 6

2.4 CPP Module Structure 6

2.5 Global Constants 6

2.6 Variables and Parameters 7

2.7 Additional notes for pointers 7

2.8 Pointers vs. References 7

2.9 Global Variables 8

2.10 Functions and Methods 8

2.11 Classes 8

2.12 Structs 8

2.13 Functions 9

2.14 Whitespace, Indenting, and Braces 9

2.15 Breaking Statements up onto Multiple Lines 10

2.16 Whitespace 11

2.17 Preprocessor Use 12

3 Windows Application Setup and Main Message Loop 12

3.1 Generating Enemy A.I. 13

3.2 Obtaining User Input 13

3.3 Updating the Display 13

4 Display 13

4.1 Display Modes 13

4.2 Initializing the Display: The Display Class 14

4.3 Initializing DirectDraw 15

4.4 Initializing the Primary Surface 15

4.5 Initializing the Display at Startup 15

4.6 Changing the Display Mode in Mid-Game 15

4.7 The DisplaySurface Class 16

4.8 Rendering Bitmap Files to DirectDraw Surfaces 16

4.9 Checking for Surface Loss 17

4.10 Rendering to the Back Buffer and the Primary Surface 18

4.11 Updating the Game Display 19

4.12 Parallax Layers 19

4.13 Rendering the Sprites 20

4.14 DirectDraw Cleanup 20

5 Title Screen and Menus 20

5.1 Menus 21

5.2 Character Select 22

6 Game Mechanics 22

6.1 Game World Perspective 22

6.2 Coordinate System 22

6.3 Scrolling 23

6.4 The Camera 23

6.5 Movement Boundaries and the Yon Wall 23

6.6 Game Timer 24

6.7 Pausing the Game 24

7 Sprites, Animations, and Actions 25

7.1 Animation Sets 25

7.2 Animation Frames 25

7.3 Actions 26

7.4 Sprites 27

7.5 Sentient Object Class 29

7.6 Player Class 29

7.7 Enemy Class 33

7.8 Acquirable Items 35

7.9 Projectiles 36

8 Sentient Object Movement and Attacks 37

8.1 Walking 37

8.2 Dashing 37

8.3 Jumping 37

8.4 Combo System 37

8.5 Dashing Attacks 37

8.6 Jumping and Jumping Attacks 38

8.7 Damage, Knockback, and Knockdown 38

9 Collision Detection 38

9.1 Attack Collision 38

9.2 Picking Up Items 40

10 Maps and Tiles 40

10.1 Maps 40

10.2 Tiles 40

10.3 Map Class 40

10.4 Objects on the Map 41

10.5 Map File Format 41

10.6 Map Zones 41

10.7 Items on the Map 42

11 Heads-Up-Display 42

11.1 The HUD Class 42

12 User Input 43

12.1 Keyboard Input and The Input Class 43

12.2 Processing Player Input 44

12.3 Unmappable Keyboard Keys 47

12.4 Keyboard Input in Menus 47

12.5 Mouse Input 47

12.6 Input Cleanup 47

13 Artificial Intelligence 47

13.1 The Enemy AIAttack Struct 48

13.2 Generating Enemy AI Actions 48

14 Sound 48

14.1 The Sound System class 48

14.2 The SoundBuffer class 49

15 Asset Memory Management and File Formats 50

15.1 File Formats 50

15.2 Data Script Files 50

15.3 Memory Management 50

15.4 Initializing Play 50

15.5 Memory Allocation 51

15.6 Parsing the Script Files 51

15.7 Bitmap Script File 52

15.8 Sound Script File 52

15.9 Animset Script File 52

15.10 Player Script File 53

15.11 Enemy Script File 53

15.12 Projectile Script File 53

15.13 Item Script File 53

15.14 Memory Cleanup 54

16 Loading and Saving User Data 54

16.1 User Game Progress 54

16.2 User Configuration Data 54

17 Message Logging 54

17.1 The Log Class 54

18 Miscellaneous Data Structures 55

18.1 String Class 55

18.2 Linked List Class 55

19 Memory Map 57

1  System Information

1.1  Target Platform

IBM compatibles running Windows 9x, Windows 2000, or Windows XP.

1.2  Minimum System Requirements

·  Windows 95/98/ME/XP/2000

·  64 megs of system RAM

·  Pentium II 300 MHz or better

·  30 MB free disk space

·  DirectX 7

·  4MB video card

·  Keyboard

2  Coding Standards

In order to maintain consistency and readability among files in the project, certain standards shall be adopted.

2.1  Comments

Use C++-style comments (preceded by ‘//’) whenever possible. C-style comments (/* … */) can be used to comment out blocks of code, but they should be applied minimally as they do not generally nest.

2.2  File Structure

Names of files in the project should follow the same nomenclature applied to function names (see below). At the top of each source code file in the project (both .h and .cpp), the following header must be included:

//======

// Filename -

// Purpose -

// Creator -

// Date Started -

// Last Updated -

//======

2.3  Header File Structure

The following structure will be adopted for header files. <Module Name> corresponds to the name of the file (sans the ‘.h’ extension) and should be in all caps in the preprocessor definition. Note that the order of the separate sections should be followed as a general guideline but can be altered as necessary. Additional sections can be added as needed.

#ifndef <Module Name>_H

#define <Module Name>_H

//=== Includes ======

//=== Enumerated Set Definitions ======

//=== Constants ======

//=== Macros ======

//=== Global Variables ======

//=== Global Function Declarations ======

//=== Class Function Definitions ======

//=== Class, Struct and Union Declarations ======

#endif // <Module Name>_H

2.4  CPP Module Structure

CPP modules should make use of the following structure. Again, the order of the separate sections should be followed as a general guideline but can be altered as necessary.

//=== Includes ======

//=== Enumerated Set Definitions ======

//=== Constants ======

//=== Macros ======

//=== Global Variables ======

//=== Global Function Definitions ======

//=== Class Function Definitions ======

2.5  Global Constants

Use all upper case letters. Concatenate “words” with an underscore. Prefixes are not necessary.

Example: const DWORD SCREEN_WIDTH = 640;

2.6  Variables and Parameters

Start with a lower case letter. Concatenate “words” with an upper case letter. In addition, the following prefixes should be used, in compliance with Hungarian Notation (from Programming Windows, Petzold):

c char or WCHAR or TCHAR

by BYTE (unsigned char)

n short

i int

x, y, z int used as x-, y-, or z-coordinates

cx, cy int used as x or y length; c stands for "count"

b or f bool (int); f stands for "flag"

w WORD (unsigned short)

l LONG (long)

dw DWORD (unsigned long)

s string

sz string terminated by 0 character

h handle

p pointer

Simple integers and floating point numbers will not require a prefix. When defining variables, align the types, the names, and the initial values (aligned on the equal sign) of the variables each in separate columns. For example:

int iMyInt = 6;

bool bMyBool = false;

DWORD dwMyDword = 0xA000;

2.7  Additional notes for pointers

With the p prefix for pointers, additional prefixes are not necessary (e.g., you do not need to use pdwMyDword for a pointer to a DWORD), unless it is a pointer to a pointer, in which case pp should be used instead. Additionally, if the pointer points to a byte, pb can be used instead of pby if so desired.

When defining a pointer variable, use a space both before and after the asterisk. If the variable is a pointer to a pointer, the two asterisks need not be separated (e.g. MyStruct ** ppMyStructInstance).

2.8  Pointers vs. References

Use pointers instead of references for sake of clarity, unless you have good reason or they are necessary in class methods parameters. Above all, try to remain consistent.

2.9  Global Variables

Prefix all globals with g_ (‘g’ followed by an underscore). After the underscore, apply the same rules for regular variables.

Example: DWORD * g_pdwMyDword;

2.10  Functions and Methods

Start with an upper case letter. Concatenate “words” with an upper case letter.

Example: void MyFunc( void );

2.11  Classes

Classes will be preceded by the following comment heading:

//======

// Class - CClassName

// Purpose –

// Creator -

//======

Class names will be prefixed by a capital ‘C’, after which the same rules for functions and methods are applied. Use an m_ (‘m’ followed by an underscore) prefix for all member variables.

Example: class CSprite {…};

2.12  Structs

Structs will be preceded by the following comment heading:

//======

// Struct - StructName

// Purpose –

// Creator -

//======

Struct names follow the same fules for functions and methods. When using ‘typedef struct,’ use the following format:

typedef struct tMyStruct

{

int memberVariable;

} MyStruct, * PMYSTRUCT;

In C++ this format is not necessary since the compiler tags struct definitions anyway. Unlike classes, member variables of structs do not need the m_ prefix.

2.13  Functions

The prototype for each function should have a short one-line (or possibly longer) comment above it. If desired, prototypes for several related functions can be grouped together under one comment.

// Descriptive comment

void MyFunc( char * input1, int input2 );

The definition of a function will be proceeded by a function header as demonstrated below. On the first line should be the return type followed by the name. Then there are two options for the parameter list: if there are few parameters, put them all on the same line; if there are many, put the opening parenthesis on the next line, then give each parameter its own line, indented as if a block of code. Then close the parentheses on the next line, followed by the body of the function. Try to keep the number of returns in the code to a minimum.

//======

// Function - Name of function

// Purpose -

// Creator -

// Inputs - pInput1: array of items

// dwInput2: number of items in array

// etc.

// Return -

//======

void MyFunc

(

char * pInput1,

DWORD dwInput2

)

{

.

.

.

}

2.14  Whitespace, Indenting, and Braces

Indents should all be four spaces and use the actual space character rather than tabs. For if statements and for and while loops, the opening brace should go on its own line immediately following the initial statement, aligned with that statement; the body of the loop or if statement should be indented. Enumeration and structure definitions should follow a similar format, although if an enumerated set is short enough, it can go all on one line. With classes, indent once for the ‘public:’ and ‘private:’ section headings, and again for the member variables or method prototypes. If an if statement or loop has only one line in its body, that line need not be in braces, but it should be indented and on the next line. In addition, try to avoid leaving extraneous whitespace at the end of lines.

Examples:

if ( condition )

{

.

.

}

while ( condition )

{

.

.

}

enum State { ALIVE, DEAD };

enum Color

{

RED,

GREEN,

BLUE,

YELLOW,

NUM_COLORS

};

class CMyClass

{

public:

CMyClass();

int MyMethod( int nParam );

private:

LONG lMemberVariable;

};

With switch statements, use the following format:

switch (msg)

{

case SOME_CASE:

DoSomething();

break;

case SOME_OTHER_CASE:

{

// Using local variables

int nMyVar;

DoSomethingElse(nMyVar);

break;

}

default:

break;

}

2.15  Breaking Statements up onto Multiple Lines

The following comes from the code standards established for CS120 in the Fall of 2001.

When a statement extends beyond the end of the line, break it at an appropriate place and fit it onto two or more lines in a way that maintains the current indentation level. In an "if" construct with multiple conditions, align the conditional expressions if they require more than one line:

if ( ( numberOfFiles < totalNumberOfFiles ) &

( status == true ) )

{

}

If a function call requires more than one line, group the arguments and, where possible, align them vertically with the first formal argument in the list; otherwise, indent the first argument on each succeeding line one level from the beginning of the function name:

bool bRet = Function( servers, NULL,

numberOfServers, done );

For functions with many formal arguments or arguments that require explanation, put each argument on a separate line (useful when using a very unfamiliar and complicated function), followed by a comment:

bool bRet = Function( servers,

NULL,

numberOfServers,

done );

2.16  Whitespace

The following comes from the code standards established for CS120 in the Fall of 2001.

There should be no space between a unary operator and its operand:

--count;

++numberOfFilesOpen;

Leave at least one space between a binary operator and each of its operands; use extra spaces to align operands if this improves readability:

x = y;

min = -max;

letter = *pDrive;

x += y;

( pItem->GetID() == id ) & ( status == true ) )

Function calls should not have a space between the statement and the associated parenthesized expression. Thus,

if ( status == true )

{

DoThing( status );

}

Formal arguments in a function call should be preceded by a single space and followed immediately by a comma, except for the final argument which is followed by a space:

bool bRet = MyFunction( servers, NULL );

2.17  Preprocessor Use

Use typedefs and global constants instead of preprocessor #defines whenever possible. Names of preprocessor-#defined macros should follow the same nomenclature as for global constants (all caps, underscores to separate “words”).

When using preprocessor #ifs to set aside a block of code, align the preprocessor statements as if they were normal code, and indent the code inside. For example:

void ProcessMap( const char * szMapName )

{

char * pMap;

if ( NULL != szMapName )

{

bool bSuccess = false;

# if defined( PALM_OS )

bSuccess = ReadMapFromDatabase( &pMap, szMapName,

&g_hMapHandle );

# elif defined( MAC_OS )

bSuccess = ReadMapFromResource( &pMap, szMapName,

&g_hResourceID );

# else // Using Windows

bSuccess = ReadMapFromFile( &pMap, szMapName );

# endif

DoStuffWithMap( pMap );

}