Putting Together a Full Game(16)

Putting Together a Full Game(16)

 

Processing Scripts

Script processing controls the entire game's content. The content includes adding
characters to the maps, displaying dialogue, and other functions not hard-coded
into the game engine.

The sample uses the script and derived script class.
Whereas that script class is stored in the files script.h and script.cpp, The Tower
stores the derived version of the script class that is used in the files game_script.h
and game_script.cpp. Skipping the script class, examine the derived script class, called cGameScript:

#define  SCRIPT_ELSE     1
#define  SCRIPT_ENDIF    2
#define  SCRIPT_GOTO     8

class  cApp;

class  cGameScript :  public  cScript
{
private :
    
bool             m_flags[256];
    
long             m_vars[256];

    cTextWindow     m_text_window;

    
long             m_num_route_points;
    sRoutePoint*    m_route;

    cApp*           m_app;

    
//////////////////////////////////////////////////////////////////////// //

public :
    cGameScript()
    {
        m_app = NULL;

        m_route = NULL;
        m_num_route_points = 0;

        ZeroMemory(m_flags, 
sizeof (m_flags));
        ZeroMemory(m_vars, 
sizeof (m_vars));
    }
    
    ~cGameScript()
    {
        delete[] m_route; 
        m_route = NULL;
    }

    
virtual   void  release()
    {
        delete[] m_route;
        m_route = NULL;

        m_num_route_points = 0;
    }

    
void  attach_app(cApp* app);
    
void  reset_data();

    
bool  save( const   char * filename);
    
bool  load( const   char * filename);

private :
    
virtual   const  sScriptInfo* process( const  sScriptInfo* script);

    
//////////////////////////////////////////////////////////////////////// //

private :
    
const  sScriptInfo* script_end( const  sScriptInfo* script)
    {
        
return  NULL;     // force end of processing
    }

    
const  sScriptInfo* script_else( const  sScriptInfo* script)
    {
        
return  script->next;
    }
    
    
const  sScriptInfo* script_endif( const  sScriptInfo* script)
    {
        
return  script->next;
    }

    
const  sScriptInfo* script_set_flag( const  sScriptInfo* script)
    {
        m_flags[script->entries[0].long_value] = script->entries[1].bool_value;

        
return  script->next;
    }

    
const  sScriptInfo* script_set_var( const  sScriptInfo* script)
    {
        m_vars[script->entries[0].long_value] = script->entries[1].long_value;

        
return  script->next;
    }

    
const  sScriptInfo* script_label( const  sScriptInfo* script)
    {
        
return  script->next;
    }
    
    
//////////////////////////////////////////////////////////////////

    
const  sScriptInfo* script_if_flag_then( const  sScriptInfo* script);
    
const  sScriptInfo* script_if_var_then( const  sScriptInfo* script);

    
const  sScriptInfo* script_goto( const  sScriptInfo* script);
    
const  sScriptInfo* script_message( const  sScriptInfo* script);

    
const  sScriptInfo* script_if_then( const  sScriptInfo* script,  bool  skip);

    
const  sScriptInfo* script_add_char( const  sScriptInfo* script);
    
const  sScriptInfo* script_remove_char( const  sScriptInfo* script);
    
const  sScriptInfo* script_move_char( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_char_direction( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_char_type( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_char_ai( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_char_target( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_no_target( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_char_bound( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_char_distance( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_char_script( const  sScriptInfo* script);

    
const  sScriptInfo* script_char_message( const  sScriptInfo* script);

    
const  sScriptInfo* script_char_update_enable( const  sScriptInfo* script);
    
const  sScriptInfo* script_create_route( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_route_point( const  sScriptInfo* script);
    
const  sScriptInfo* script_assign_route( const  sScriptInfo* script);

    
const  sScriptInfo* script_alter_hp_mp( const  sScriptInfo* script);
    
const  sScriptInfo* script_char_ailment( const  sScriptInfo* script);
    
const  sScriptInfo* script_alter_spell( const  sScriptInfo* script);
    
const  sScriptInfo* script_teleport( const  sScriptInfo* script);

    
const  sScriptInfo* script_short_message( const  sScriptInfo* script);
    
const  sScriptInfo* script_set_char_action( const  sScriptInfo* script);
    
const  sScriptInfo* script_if_level_at_least( const  sScriptInfo* script);
    
const  sScriptInfo* script_barter( const  sScriptInfo* script);

    
const  sScriptInfo* script_if_more_item( const  sScriptInfo* script);
    
const  sScriptInfo* script_add_item( const  sScriptInfo* script);
    
const  sScriptInfo* script_remove_item( const  sScriptInfo* script);

    
const  sScriptInfo* script_add_barrier( const  sScriptInfo* script);
    
const  sScriptInfo* script_enable_barrier( const  sScriptInfo* script);
    
const  sScriptInfo* script_remove_barrier( const  sScriptInfo* script);

    
const  sScriptInfo* script_add_trigger( const  sScriptInfo* script);
    
const  sScriptInfo* script_enable_trigger( const  sScriptInfo* script);
    
const  sScriptInfo* script_remove_trigger( const  sScriptInfo* script);

    
const  sScriptInfo* script_play_sound( const  sScriptInfo* script);
    
const  sScriptInfo* script_play_music( const  sScriptInfo* script);
    
const  sScriptInfo* script_stop_music( const  sScriptInfo* script);
    
    
const  sScriptInfo* script_win_game( const  sScriptInfo* script);
    
const  sScriptInfo* script_comment_or_separator( const  sScriptInfo* script);
    
const  sScriptInfo* script_wait( const  sScriptInfo* script);
    
const  sScriptInfo* script_if_random_then( const  sScriptInfo* script);
    
const  sScriptInfo* script_render( const  sScriptInfo* script);
};

The scripts use an array of flags and variables (m_flags and m_vars), both arrays being
256 elements in size. Several script actions use these flags and variables to store and
perform condition-checks to control the flow of script processing. Also, a pointer to
the application class instance is stored (to call the application’s functions), and a
text window object is created to display the character’s dialogue and other text.

Next in the cGameScript function, you define a sRoutePoint object that is used by the
scripts to construct and assign a route to a character.

From here on in, the majority of functions to follow are the script action processing
functions. These functions are called when an action from the script is being
processed—for example, the script_set_flag function is called when the SetFlag
action is being processed from a script.

Whew! That’s a lot of functions—and as I said, they directly relate to the script actions.
Thankfully, the script action processing functions are brief and easy to process.

With all the if...then-related functions in the action template, it’s easier to develop a
single function that deals with the conditional processing. This function (script_if_then)
takes a pointer to the next script function after the if...then action and a flag that
determines the conditional state. If Skip is set to TRUE, all proceeding script actions are
skipped until an Else or End script action is found, whereas if Skip is set to FALSE, the condition
was met, and all script actions are processed until an Else or End script action is
found. Note that the Else script action toggles the Skip flag (from TRUE to FALSE, and vice
versa), allowing for true if...then...else processing.

The cGameScript declaration finishes with two more private functions—the first,
release, is called to free the script’s internal data whenever a script completes processing.
The second function, Process, contains a large switch statement that sends
off the script actions to be processed by their respective functions.

The cGameClass finishes with the public function prototypes—you have the constructor,
the destructor, the attach_app function that records the application class instance
pointer, a function to reset all flags and variables, and a duo of functions to save
and load the flags and variables to a file.

void  cGameScript::attach_app(cApp* app)
{
    m_app = app;

    m_text_window.create(app->m_font);
}

void  cGameScript::reset_data()
{
    ZeroMemory(m_flags, 
sizeof (m_flags));
    ZeroMemory(m_vars, 
sizeof (m_vars));
}

///////////////////////////////////////////////////////////////////////////////// //

bool  cGameScript::save( const   char * filename)
{
    FILE* fp = fopen(filename, "wb");

    
if (fp == NULL)
        
return   false ;

    fwrite(&m_flags, 1, 
sizeof (m_flags), fp);
    fwrite(&m_vars,  1, 
sizeof (m_vars), fp);

    fclose(fp);

    
return   true ;
}

bool  cGameScript::load( const   char * filename)
{
    FILE* fp = fopen(filename, "rb");

    
if (fp == NULL)
        
return   false ;

    fread(&m_flags, 1, 
sizeof (m_flags), fp);
    fread(&m_vars,  1, 
sizeof (m_vars), fp);

    fclose(fp);

    
return   true ;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::process( const  sScriptInfo* script)
{
    
switch (script->action_index)
    {
    
case  0:      return  script_end(script);
    
case  1:      return  script_else(script);
    
case  2:      return  script_endif(script);
    
case  3:      return  script_if_flag_then(script);
    
case  4:      return  script_if_var_then(script);
    
case  5:      return  script_set_flag(script);
    
case  6:      return  script_set_var(script);
    
case  7:      return  script_label(script);
    
case  8:      return  script_goto(script);
    
case  9:      return  script_message(script);

    
case  10:     return  script_add_char(script);
    
case  11:     return  script_remove_char(script);
    
case  12:     return  script_move_char(script);
    
case  13:     return  script_set_char_direction(script);
    
case  14:     return  script_set_char_type(script);
    
case  15:     return  script_set_char_ai(script);
    
case  16:     return  script_set_char_target(script);
    
case  17:     return  script_set_no_target(script);        
    
case  18:     return  script_set_char_bound(script);
    
case  19:     return  script_set_char_distance(script);
    
case  20:     return  script_set_char_script(script);
    
case  21:     return  script_char_message(script);
    
case  22:     return  script_char_update_enable(script);
    
case  23:     return  script_create_route(script);
    
case  24:     return  script_set_route_point(script);
    
case  25:     return  script_assign_route(script);
    
case  26:     return  script_alter_hp_mp(script);
    
case  27:     return  script_char_ailment(script);
    
case  28:     return  script_alter_spell(script);
    
case  29:     return  script_teleport(script);
    
case  30:     return  script_short_message(script);
    
case  31:     return  script_set_char_action(script);
    
case  32:     return  script_if_level_at_least(script);
    
    
case  33:     return  script_barter(script);

    
case  34:     return  script_if_more_item(script);
    
case  35:     return  script_add_item(script);
    
case  36:     return  script_remove_item(script);

    
case  37:     return  script_add_barrier(script);
    
case  38:     return  script_enable_barrier(script);
    
case  39:     return  script_remove_barrier(script);

    
case  40:     return  script_add_trigger(script);
    
case  41:     return  script_enable_trigger(script);
    
case  42:     return  script_remove_trigger(script);

    
case  43:     return  script_play_sound(script);
    
case  44:     return  script_play_music(script);
    
case  45:     return  script_stop_music(script);

    
case  46:     return  script_win_game(script);

    
case  47:     return  script_comment_or_separator(script);
    
case  48:     return  script_comment_or_separator(script);

    
case  49:     return  script_wait(script);
    
case  50:     return  script_if_random_then(script);
    
case  51:     return  script_render(script);
    }

    
return  NULL;  // Error executing
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_if_flag_then( const  sScriptInfo* script)
{
    
bool  skip;

    
if (m_flags[script->entries[0].long_value] == ( bool )script->entries[1].bool_value)
        skip = 
false ;
    
else  
        skip = 
true ;

    
return  script_if_then(script->next, skip);
}

const  sScriptInfo* cGameScript::script_if_var_then( const  sScriptInfo* script)
{
    
bool  skip;
    
    
if (m_vars[script->entries[0].long_value] == script->entries[1].long_value)
        skip = 
false ;
    
else
        skip = 
true ;

    
return  script_if_then(script->next, skip);
}

const  sScriptInfo* cGameScript::script_goto( const  sScriptInfo* script)
{
    
// search entire script for lable
     for ( const  sScriptInfo* script_ptr = get_root_script_info(); script_ptr != NULL; script_ptr = script_ptr->next)
    {
        
if (script_ptr->entries[0].long_value == script->entries[0].long_value)
            
return  script_ptr->next;
    }

    
return  NULL;     // end of script, return completion.
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_message( const  sScriptInfo* script)
{
    m_text_window.set_text(script->entries[0].text, COLOR_LIGHT_YELLOW);
    m_text_window.move(4, 4, 624, 0, -1, -1, COLOR_DARK_BLUE, COLOR_ARGENTINE);

    m_app->m_keyboard.m_locks[KEY_SPACE] = 
true ;
    m_app->m_keyboard.set_key_state(KEY_SPACE, 
false );
    m_app->m_mouse.m_locks[MOUSE_LBUTTON] = 
true ;
    m_app->m_mouse.set_button_state(MOUSE_LBUTTON, 
false );

    
// render the scene while waiting for key press or button press.
     for (;;)
    {
        m_app->m_keyboard.acquire();
        m_app->m_keyboard.read();

        
if (m_app->m_keyboard.get_key_state(KEY_SPACE))
            
break ;

        m_app->m_mouse.acquire();
        m_app->m_mouse.read();

        
if (m_app->m_mouse.get_button_state(MOUSE_LBUTTON))
            
break ;

        clear_display_zbuffer(1.0f);

        begin_display_scene();        

        m_app->render_frame(0);
        m_text_window.render(NULL, 0);

        end_display_scene();        

        present_display();
    }

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_if_then( const  sScriptInfo* script,  bool  skip)
{
    
// At this point, Skipping states if the script actions need to be skipped due to a 
    // conditional if..then statement. Actions are further processed if skipped = false, 
    // looking for an else to flip the skip mode, or an endif to end the conditional block.
     while (script != NULL)
    {
        
// if else, flip skip mode.
         if (script->action_index == SCRIPT_ELSE)
            skip = !skip;

        
// break on end if
         if (script->action_index == SCRIPT_ENDIF)
            
return  script->next;

        
if (skip)
            script = script->next;
        
else
        {
            
// return to normal processing if goto encountered
             if (script->action_index == SCRIPT_GOTO)
                
return  process(script);

            script = process(script);
        }
    }

    
return  NULL;     // end of script reached
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_add_char( const  sScriptInfo* script)
{
    sEntry* entries = script->entries;

    m_app->m_game_chars.add_char(entries[0].long_value, entries[1].long_value, entries[2].selection, CHAR_STAND,
                                 entries[3].float_value, entries[4].float_value, entries[5].float_value,
                                 entries[6].float_value);

    m_app->m_game_chars.update(0);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_remove_char( const  sScriptInfo* script)
{
    m_app->m_game_chars.remove(script->entries[0].long_value);
    m_app->m_game_chars.update(0);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_move_char( const  sScriptInfo* script)
{
    sEntry* entries = script->entries;

    m_app->m_game_chars.move_char(entries[0].long_value,
        entries[1].float_value, entries[2].float_value, entries[3].float_value);

    m_app->m_game_chars.update(0);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_char_direction( const  sScriptInfo* script)
{
    sCharacter* character = m_app->m_game_chars.get_char(script->entries[0].long_value);

    
if (character != NULL)
        character->direction = script->entries[1].float_value;

    m_app->m_game_chars.update(0);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_char_type( const  sScriptInfo* script)
{
    m_app->m_game_chars.set_char_type(script->entries[0].long_value, script->entries[1].selection);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_char_ai( const  sScriptInfo* script)
{
    m_app->m_game_chars.set_char_ai(script->entries[0].long_value, script->entries[1].selection);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_char_target( const  sScriptInfo* script)
{
    m_app->m_game_chars.set_char_target(script->entries[0].long_value, script->entries[1].selection);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_no_target( const  sScriptInfo* script)
{
    m_app->m_game_chars.set_char_target(script->entries[0].long_value, -1);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_char_bound( const  sScriptInfo* script)
{
    sEntry* entries = script->entries;

    m_app->m_game_chars.set_char_bound(entries[0].long_value,
        entries[1].float_value, entries[2].float_value, entries[3].float_value,
        entries[4].float_value, entries[5].float_value, entries[6].float_value);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_char_distance( const  sScriptInfo* script)
{
    m_app->m_game_chars.set_char_distance(script->entries[0].long_value, script->entries[1].float_value);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_char_script( const  sScriptInfo* script)
{
    m_app->m_game_chars.set_char_script(script->entries[0].long_value, script->entries[1].text);

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_char_message( const  sScriptInfo* script)
{
    
// get the transformation matrices

    D3DXMATRIX mat_world, mat_view, mat_proj;

    D3DXMatrixIdentity(&mat_world);
    get_display_view_matrix(&mat_view);
    get_display_proj_matrix(&mat_proj);

    
// get the viewport
    D3DVIEWPORT9 viewport;
    get_display_viewport(&viewport);

    
// get the character's height

    sCharacter* character = m_app->m_game_chars.get_char(script->entries[1].long_value);

    
float  max_y;
    character->
object .get_bounds(NULL, NULL, NULL, NULL, &max_y, NULL, NULL);

    
// project the 3D coordinates in 2D coordinates

    D3DXVECTOR3 pos_screen;
    D3DXVECTOR3 pos_3d(character->pos_x, character->pos_y + max_y, character->pos_z);

    D3DXVec3Project(&pos_screen, &pos_3d, &viewport, &mat_proj, &mat_view, &mat_world);

    
// create the text and position the text window
    m_text_window.set_text(script->entries[0].text, COLOR_WHITE);
    m_text_window.move(4, 4, 624, 0, pos_screen.x, pos_screen.y, COLOR_DARK_BLUE, COLOR_ARGENTINE);

    
// lock the keyboard and mouse
    m_app->m_keyboard.m_locks[KEY_SPACE] =  true ;
    m_app->m_keyboard.set_key_state(KEY_SPACE, 
false );
    m_app->m_mouse.m_locks[MOUSE_LBUTTON] = 
true ;
    m_app->m_mouse.set_button_state(MOUSE_LBUTTON, 
false );

    
// render the scene while waiting for key press / button press
     for (;;)
    {
        
// break when space pressed

        m_app->m_keyboard.acquire();
        m_app->m_keyboard.read();

        
if (m_app->m_keyboard.get_key_state(KEY_SPACE))
            
break ;

        
// break when left mouse button pressed

        m_app->m_mouse.acquire();
        m_app->m_mouse.read();

        
if (m_app->m_mouse.get_button_state(MOUSE_LBUTTON))
            
break ;

        
// render the scene and window text

        clear_display_zbuffer(1.0f);
        begin_display_scene();
        
        m_app->render_frame(0);
        m_text_window.render(NULL, COLOR_WHITE);

        end_display_scene();
        present_display();
    }

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_char_update_enable( const  sScriptInfo* script)
{
    m_app->m_game_chars.set_update_enable(script->entries[1].long_value, script->entries[0].bool_value);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_create_route( const  sScriptInfo* script)
{
    delete[]  m_route;
    m_route = NULL;
    m_num_route_points = 0;

    m_num_route_points = script->entries[0].long_value;
    m_route = 
new  sRoutePoint[m_num_route_points];

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_route_point( const  sScriptInfo* script)
{
    
long  point_index = script->entries[0].long_value;

    m_route[point_index].pos_x = script->entries[1].float_value;
    m_route[point_index].pos_y = script->entries[2].float_value;
    m_route[point_index].pos_z = script->entries[3].float_value;

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_assign_route( const  sScriptInfo* script)
{
    m_app->m_game_chars.set_char_route(script->entries[0].long_value, m_num_route_points, m_route);

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_alter_hp_mp( const  sScriptInfo* script)
{
    sCharacter* character = m_app->m_game_chars.get_char(script->entries[3].long_value);

    
if (character != NULL)
    {
        
if (script->entries[0].selection == 0)    // add
        {
            
if (script->entries[2].selection == 0)    // health
                character->health_points += script->entries[1].long_value;
            
else
                character->mana_points += script->entries[1].long_value;
        }
        
else      // remove
        {
            
if (script->entries[2].selection == 0)    // health
                character->health_points -= script->entries[1].long_value;
            
else
                character->mana_points -= script->entries[1].long_value;
        }

        
// bounds check values

        
if (character->health_points > character->char_def.health_points)
            character->health_points = character->char_def.health_points;

        
if (character->health_points < 0)
            character->health_points = 0;

        
if (character->mana_points > character->char_def.mana_points)
            character->mana_points = character->char_def.mana_points;

        
if (character->mana_points < 0)
            character->mana_points = 0;
    }

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_char_ailment( const  sScriptInfo* script)
{
    sCharacter* character = m_app->m_game_chars.get_char(script->entries[2].long_value);

    
if (character != NULL)
    {
        
if (script->entries[0].selection == 0)    // cure ailments
            character->ailments &= ~script->entries[1].long_value;
        
else                                      // cause ailments
            character->ailments |= script->entries[1].long_value;
    }

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_alter_spell( const  sScriptInfo* script)
{
    sCharacter* character = m_app->m_game_chars.get_char(script->entries[0].long_value);

    
if (character != NULL)
    {
        
long  spell_index = script->entries[2].long_value;
        
long  bit_flag    = 1 << (spell_index & 31);

        
if (script->entries[1].selection == 0)    // learn a spell
            character->char_def.magic_spell[spell_index / 32] |= bit_flag;
        
else                                      // forget a spell
            character->char_def.magic_spell[spell_index / 32] &= ~bit_flag;
    }

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_teleport( const  sScriptInfo* script)
{
    sCharacter* character = m_app->m_game_chars.get_char(script->entries[0].long_value);

    
if (character != NULL)
    {
        sEntry* entries = script->entries;

        m_app->teleport_player(entries[1].long_value,
            entries[2].float_value, entries[3].float_value, entries[4].float_value);

        
return  NULL;     // stop processing after teleport
    }

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_short_message( const  sScriptInfo* script)
{
    sEntry* entries = script->entries;
    sCharacter* character = m_app->m_game_chars.get_char(entries[0].long_value);

    
if (character != NULL)    
        m_app->m_game_chars.set_char_msg(character, entries[1].text, entries[2].long_value, COLOR_WHITE);
    
    
return  script->next;
}

const  sScriptInfo* cGameScript::script_set_char_action( const  sScriptInfo* script)
{
    sEntry* entries = script->entries;
    sCharacter* character = m_app->m_game_chars.get_char(entries[0].long_value);

    
if (character != NULL)
        m_app->m_game_chars.set_char_action(character, entries[1].long_value, entries[2].long_value);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_if_level_at_least( const  sScriptInfo* script)
{
    
bool  skip;

    sCharacter* character = m_app->m_game_chars.get_char(script->entries[0].long_value);

    
// see if level matches values
     if (character != NULL && character->char_def.level >= script->entries[1].long_value)
        skip = 
false ;
    
else
        skip = 
true ;

    
return  script_if_then(script->next, skip);
}

const  sScriptInfo* cGameScript::script_barter( const  sScriptInfo* script)
{
    m_app->setup_barter(script->entries[0].text);

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_if_more_item( const  sScriptInfo* script)
{
    sCharacter* character = m_app->m_game_chars.get_char(script->entries[2].long_value);

    
long  item_index = script->entries[1].long_value;
    
long  quantity   = script->entries[0].long_value;

    
bool  skip;

    
// see if item in inventory and check count
     if (character != NULL && character->char_ics->get_item(item_index)->quantity >= quantity)
        skip = 
false ;
    
else
        skip = 
true ;

    
return  script_if_then(script->next, skip);
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_add_item( const  sScriptInfo* script)
{
    sCharacter* character = m_app->m_game_chars.get_char(script->entries[2].long_value);

    
// only handle add item if character has an ics
     if (character && character->char_ics)
    {
        
long  item_index = script->entries[1].long_value;
        sCharItem* char_item;

        
// find matching item and add to it's quantity
         for (char_item = character->char_ics->get_root_item(); char_item != NULL; char_item = char_item->next)
        {
            
if (char_item->item_index == item_index)
            {
                char_item->quantity += script->entries[0].long_value;
                
break ;
            }
        }

        
// add to inventory if nothing found
         if (char_item == NULL)
            character->char_ics->add(item_index, script->entries[0].long_value, NULL);
    }

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_remove_item( const  sScriptInfo* script)
{
    sCharacter* character = m_app->m_game_chars.get_char(script->entries[2].long_value);
    cCharIcs*   char_ics  = character->char_ics;

    
if (character && char_ics)
    {
        
// find item that we are looking for first
         for (sCharItem* char_item = char_ics->get_root_item(); char_item != NULL; char_item = char_item->next)
        {
            
// if item matched, remove quantity.
             if (char_item->item_index == script->entries[1].long_value)
            {
                char_item->quantity -= script->entries[0].long_value;

                
if (char_item->quantity <= 0)
                    char_ics->remove(char_item);

                
break ;
            }
        }
    }

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_add_barrier( const  sScriptInfo* script)
{
    sEntry* entries = script->entries;

    m_app->m_barrier.add_triangle(entries[0].long_value, 
true ,
                                  0.0f, 0.0f, 0.0f,
                                  0.0f, 0.0f, 0.0f,
                                  entries[1].float_value, entries[2].float_value,
                                  entries[3].float_value, entries[4].float_value,
                                  entries[5].float_value, entries[6].float_value,
                                  entries[7].float_value, 
                                  entries[8].float_value);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_enable_barrier( const  sScriptInfo* script)
{
    sEntry* entries = script->entries;

    
if (entries[0].selection == 0)
        m_app->m_barrier.enable(entries[1].long_value);
    
else
        m_app->m_barrier.disable(entries[1].long_value);

    
return  script->next;
}       

const  sScriptInfo* cGameScript::script_remove_barrier( const  sScriptInfo* script)
{
    m_app->m_barrier.remove(script->entries[0].long_value);

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_add_trigger( const  sScriptInfo* script)
{
    sEntry* entries = script->entries;

    m_app->m_trigger.add_triangle(entries[0].long_value, 
true ,
                                  entries[1].float_value, entries[2].float_value,
                                  entries[3].float_value, entries[4].float_value,
                                  entries[5].float_value, entries[6].float_value,
                                  entries[7].float_value, 
                                  entries[8].float_value);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_enable_trigger( const  sScriptInfo* script)
{
    sEntry* entries = script->entries;

    
if (entries[0].selection == 0)
        m_app->m_trigger.enable(entries[1].long_value);
    
else
        m_app->m_trigger.disable(entries[1].long_value);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_remove_trigger( const  sScriptInfo* script)
{
    m_app->m_trigger.remove(script->entries[0].long_value);

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_play_sound( const  sScriptInfo* script)
{
    m_app->play_sound(script->entries[0].long_value);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_play_music( const  sScriptInfo* script)
{
    m_app->play_music(script->entries[0].long_value);

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_stop_music( const  sScriptInfo* script)
{
    m_app->stop_music();

    
return  script->next;
}

///////////////////////////////////////////////////////////////////////////////// //

const  sScriptInfo* cGameScript::script_win_game( const  sScriptInfo* script)
{
    m_app->win_game();

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_comment_or_separator( const  sScriptInfo* script)
{
    
return  script->next;
}

const  sScriptInfo* cGameScript::script_wait( const  sScriptInfo* script)
{
    DWORD timer = timeGetTime() + script->entries[0].long_value;

    
// wait for some milliseconds
     while (timeGetTime() < timer)
        ;

    
return  script->next;
}

const  sScriptInfo* cGameScript::script_if_random_then( const  sScriptInfo* script)
{
    
bool  skip;

    
if ((rand() % script->entries[0].long_value) >= script->entries[1].long_value)
        skip = 
false ;
    
else
        skip = 
true ;

    
return  script_if_then(script->next, skip);
}

const  sScriptInfo* cGameScript::script_render( const  sScriptInfo* script)
{
    clear_display_zbuffer(1.0f);

    begin_display_scene();
    m_app->render_frame(0);
    end_display_scene();

    present_display();

    
return  script->next;
}
 

Assembling the Pieces

You are now more than familiar with the individual pieces of the puzzle. With the
sample game, you'll get a true hands-on experience
putting those pieces together! You learned about how the components are defined,
developed, and coded. With a call to the cApp::init function, followed by repeated
calls to cApp::frame, the game comes alive! The scripts execute, characters interact,
spells and attacks go flying. Each component pulls its weight, and they all work
together to form the whole.

When exploring the game project, I suggest starting with the WinMain.h and
WinMain.cpp files; those files contain the application class that forms the application
framework. As detailed in this chapter, you can follow the flow of the program,
from initialization to shutdown.

download warrior_load.part01.rar

download warrior_load.part02.rar

download warrior_load.part03.rar

你可能感兴趣的:(Putting Together a Full Game(16))