Controlling Players and Characters(35)

Controlling Players and Characters(35)

You're coming to the end of the long haul. You’ve finished the private data and
functions, and the public functions are left:

public :
    cCharController()
    {
        ZeroMemory(
this sizeof (* this ));
    }

    ~cCharController()
    {
        shutdown();
    }

    
void  free()
    {
        delete m_root_char;
        m_root_char = NULL;

        m_num_char = 0;
    }

    
void  shutdown()
    {
        free();

        delete[] m_mesh_anim;
        m_mesh_anim = NULL;
        m_num_mesh_anim = 0;

        delete[] m_char_anim;
        m_char_anim = NULL;
        m_num_char_anim = 0;

        m_spell_controller    = NULL;
        m_def_file[0]         = '\0';
        m_weapon_mesh_path[0] = '\0';
        m_texture_path[0]     = '\0';
    }
///////////////////////////////////////////////////////////////////////////////////////////////////

void  cCharController::init(ID3DXFont* font, PCSTR def_file,
                           sItem* mil, sSpell* msl,
                           
long  num_mesh_anim, PCSTR* mesh_names,
                           PCSTR weapon_mesh_path, PCSTR texture_path,
                           
long  num_char_anim, sCharAnimInfo* char_anims)
{
    free();

    
if (mesh_names == NULL || def_file == NULL)
        
return ;

    m_font = font;

    strcpy(m_def_file, def_file);

    m_mil = mil;
    m_msl = msl;

    
// copy over mesh path and texture path (or set default)
    strcpy(m_weapon_mesh_path, weapon_mesh_path ? weapon_mesh_path : ".\\");
    strcpy(m_texture_path, texture_path ? texture_path : ".\\");

    
// get mesh names
     if ((m_num_mesh_anim = num_mesh_anim) != 0)
    {
        m_mesh_anim = 
new  sMeshAnim[num_mesh_anim];

        
for ( long  i = 0; i < m_num_mesh_anim; i++)
            strcpy(m_mesh_anim[i].filename, mesh_names[i]);
    }

    
// get animation data
     if ((m_num_char_anim = num_char_anim) != 0)
    {
        m_char_anim = 
new  sCharAnimInfo[m_num_char_anim];

        
for ( long  i = 0; i < m_num_char_anim; i++)
            memcpy(&m_char_anim[i], &char_anims[i], 
sizeof (sCharAnimInfo));
    }
}

In addition to the typical class constructor and destructor are the init and shutdown pair
of functions. For the controller to operate, it must first be initialized with a call to init.
When you’re done with the character controller class, a call to shutdown is in order.

Somewhat similar in nature to shutdown, the free function completely
removes all characters in the list of active characters. This function is useful for
clearing the list when a character leaves a level and a whole new set of characters
need to be added to the list.

Speaking of adding characters to the list, here comes the function that does it all.

With the add_char function, you need to provide a unique identification number, the MCL
character definition number to use, the character’s type to assign (CHAR_PC, CHAR_NPC,
or CHAR_MONSTER), the artificial intelligence to use, and the character’s coordinates and
Y-axis angle used to point the character in a specific direction.

Following add_char are two functions that remove a character in the list. The remove function
takes a character’s unique identification number as an argument,
and the remove_char function takes a pointer to the character structure.

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

bool  cCharController::add_char( long  id,  long  def,  long  type,  long  ai,
                               
float  pos_x,  float  pos_y,  float  pos_z,
                               
float  direction)
{
    FILE* fp;
    
if ((fp = fopen(m_def_file, "rb")) == NULL)
        
return   false ;

    sCharacter* character = 
new  sCharacter;

    character->def           = def;
    character->id            = id;
    character->type          = type;
    character->ai            = ai;
    character->pos_x         = pos_x;
    character->pos_y         = pos_y;
    character->pos_z         = pos_z;
    character->direction     = direction;
    character->update_enable = 
true ;
    character->charge        = rand()%101;

    sCharDef& char_def = character->char_def;

    fseek(fp, 
sizeof (sCharDef) * def, SEEK_SET);
    fread(&char_def, 1, 
sizeof (sCharDef), fp);
    fclose(fp);

    character->health_points = char_def.health_points;
    character->mana_points   = char_def.mana_points;

    
// load character ics
     if (char_def.item_filename)
    {
        character->char_ics = 
new  cCharIcs;
        character->char_ics->load(char_def.item_filename);
    }

    sMeshAnim& mesh_anim = m_mesh_anim[char_def.mesh_index];

    
// load mesh and animation if needed
     if (mesh_anim.count == 0)
    {
        mesh_anim.mesh.load(mesh_anim.filename, m_texture_path);
        mesh_anim.anim.load(mesh_anim.filename, &mesh_anim.mesh);
        
        
for ( long  i = 0; i < m_num_char_anim; i++)
            mesh_anim.anim.set_loop(m_char_anim[i].is_loop, m_char_anim[i].name);
    }

    character->
object .create(&mesh_anim.mesh);
    mesh_anim.count++;

    
// load and configure weapon (if any)
     if (m_mil && char_def.weapon != -1 && m_mil[char_def.weapon].mesh_filename)
    {
        
char  path[MAX_PATH];
        sprintf(path, "%s%s", m_weapon_mesh_path, m_mil[char_def.weapon].mesh_filename);
        character->weapon_mesh.load(path, m_texture_path);

        character->weapon_object.create(&character->weapon_mesh);
        character->weapon_object.attach_to_object(&character->
object , "WeaponHand");
    }

    
// link into head of list
     if (m_root_char)
        m_root_char->prev = character;

    character->next = m_root_char;
    m_root_char = character;

    
return   true ;
}

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

void  cCharController::remove_char(sCharacter* character)
{
    
if (character == NULL)
        
return ;

    
// decrease mesh count and release if no more

    sMeshAnim& mesh_anim = m_mesh_anim[character->char_def.mesh_index];

    
if (--mesh_anim.count == 0)
    {
        mesh_anim.mesh.free();
        mesh_anim.anim.free();
    }

    
// remove from list
     if (character->prev)
        character->prev->next = character->next;
    
else
        m_root_char = character->next;

    
if (character->next)
        character->next->prev = character->prev;

    character->prev = character->next = NULL;
    delete character;
}

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

void  remove( long  char_id)
{
     
return  remove_char(get_char(char_id));
}

你可能感兴趣的:(Controlling Players and Characters(35))