青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

Controlling Players and Characters(24)

 

The cSpellController Class

Because the spell controller is needed only for tracking the spell meshes and
animation, the class definition is relatively small:

typedef class cSpellController
{
private:
    cCharController*    m_char_controller;

    cFrustum*           m_frustum;

    sSpell              m_spells[NUM_SPELL_DEF];
    sSpellTracker*      m_spell_tracker;

    
long                m_num_mesh_anim;    
    sMeshAnim*          m_mesh_anim;

    
char                m_texture_path[MAX_PATH];

Now check the private data of the spell controller before examining the public
functions. The spell controller uses a frustum object. The frustum
object (m_frustum) can be supplied from outside code or calculated from within
the spell-rendering function.

Next comes the MSL, which is contained in the array m_spells. Notice that the
macro NUM_SPELL_DEF defines the size of the MSL array, which means that you
can easily adjust the size for later enhancements.

Following the MSL is the linked list pointer m_spell_tracker, which tracks the spells
that have been cast and are being displayed. Next comes
m_num_mesh_anim (which stores
the number of meshes used) and
m_mesh_anim (a list of meshes).

Because this example uses 3-D meshes to represent the spells, you need to load textures,
and in order for the spell controller to find those textures, you must store a
directory path that indicates the location of the bitmaps to be used as textures.

Something you haven’t seen up to now is the m_char_controller pointer, which points to the
character controller class object in use. This class pointer triggers the spell effects.

cSpellController contains two private functions: SetAnimData and SpellSound. The
set_animData function sets up the mesh to use as well as the movement of the mesh.
play_spell_sound is called whenever a spell mesh is used; it’s your job to override this function
to play the appropriate sound as specified in the function’s argument list.

With private data and functions covered, you can move on to the class’s public functions
(the Constructor, Destructor, init, shutdown, free, get_spell, add, update, and render):

public:
    cSpellController()
    {
        m_char_controller   = NULL;

        m_frustum           = NULL;
        m_spell_tracker     = NULL;

        m_mesh_anim         = NULL;
        m_num_mesh_anim     = 0;

        m_texture_path[0]   = '\0';

        ZeroMemory(m_spells, 
sizeof(m_spells));
    }

    ~cSpellController()
    {
        shutdown();
    }

    
void free()
    {
        delete m_spell_tracker;
        m_spell_tracker = NULL;
    }

    sSpell* get_spell(
long spell_index)
    {
        
return &m_spells[spell_index];
    }

    sSpell* get_spell_list()
    {
        
return m_spells;
    }

    
void attach(cCharController* char_controller)
    {
        m_char_controller = char_controller;
    }

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

    
bool init(PCSTR msl_file, long num_mesh_anim, PCSTR* mesh_anim_name, PCSTR texture_path);
    
void shutdown();
    
bool add(sCharacter* caster);
    
void update(long elapsed);
    
void render(cFrustum* frustum, float z_dist);

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

private:
    
void set_anim_data(sSpellTracker* tracker, long cur_anim);
    
virtual void play_spell_sound(long index) { }

}

 

cSpellController::cSpellController and cSpellController::~sSpellController

Typical in C++ classes, the constructor and destructor clear the class data and free
all used resources, respectively. The destructor relies on a separate function (the
Shutdown function) to clear the data.


cSpellController::init and cSpellController::shutdown

Before using the spell controller class, you must initialize it. When you finish with
the class, you call Shutdown to free up the resources.

bool cSpellController::init(PCSTR msl_file, long num_mesh_anim, PCSTR* mesh_anim_name, PCSTR texture_path)
{
    free();

    
if(msl_file == NULL || mesh_anim_name == NULL)
        
return false;

    
// load the spells

    FILE* fp;
    
if((fp = fopen(msl_file, "rb")) == NULL)
        
return false;

    fread(m_spells, 1, 
sizeof(m_spells), fp);
    fclose(fp);

    
if(texture_path)
        strcpy(m_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_anim_name[i]);
    }

    
return true;
}

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

void cSpellController::shutdown()
{
    free();

    
// release spell meshes
    for(long i = 0; i < m_num_mesh_anim; i++)
    {
        m_mesh_anim[i].mesh.free();
        m_mesh_anim[i].anim.free();
        m_mesh_anim[i].count = 0;
    }

    delete[] m_mesh_anim;
    m_mesh_anim = NULL;

    m_num_mesh_anim = 0;
}

cSpellController::free

When you’re done with a spell controller class instance but want to reuse it without
having to shut it down, a call to cSpellController::Free is in order. Free releases the
spell tracking list as well as the mesh list.

cSpellController::get_spell

Outside code might need access to the MSL, and GetSpell fills that need. Providing
the MSL reference number returns a pointer into the array of the loaded MSL.

cSpellController::add

Now the real fun begins! Add is the function you use the most because it initiates a spell.

bool cSpellController::add(sCharacter* caster)
{
    
// add a spell to spell tracker list

    
long spell_index = caster->spell_index;

    
// make sure character is allowed to cast spell
    if(!(caster->char_def.magic_spell[spell_index/32] & (1 << (spell_index & 31))))
        
return false;

    
// make sure caster has enough mana to cast
    if(caster->mana_points < m_spells[spell_index].cost)
        
return false;
  
    
// allocate a new spell stracker and link into head of list

    sSpellTracker* spell_tracker = 
new sSpellTracker;

    
if(m_spell_tracker)
        m_spell_tracker->prev = spell_tracker;

    spell_tracker->next = m_spell_tracker;

    m_spell_tracker = spell_tracker;

    
// set structure data
    spell_tracker->spell_index = spell_index;
    spell_tracker->caster      = caster;
    spell_tracker->affect_type = caster->target_type;
    spell_tracker->source_x    = caster->pos_x;
    spell_tracker->source_y    = caster->pos_y;
    spell_tracker->source_z    = caster->pos_z;
    spell_tracker->target_x    = caster->target_x;
    spell_tracker->target_y    = caster->target_y;
    spell_tracker->target_z    = caster->target_z;

    
// setup the mesh/animation movement data
    set_anim_data(spell_tracker, 0);

    
return true;
}

cSpellController::set_anim_data

The private function set_anim_data initializes the three meshes in use by a spell. If one
of the meshes is not used (as specified by the POSITION_NONE value in mesh_pos), the
next mesh in the three is used. After all three meshes are used up, the spell’s
effects are triggered.

oid cSpellController::set_anim_data(sSpellTracker* tracker, long cur_anim)
{
    sSpell& spell = m_spells[tracker->spell_index];

    
long mesh_index;
    tracker->cur_anim = cur_anim;

    
// process spell effect if no more animations left while storing the current animation number.
    if(tracker->cur_anim >= 3)
    {
        
if(m_char_controller)
            m_char_controller->spell(tracker->caster, tracker, m_spells);

        
// remove any mesh and animation if any, or just decrease reference count.
        for(int i = 0; i < 3; i++)
        {
            
if(spell.mesh_pos[i] != POSITION_NONE)
            {
                mesh_index = spell.mesh_index[i];

                
if(--m_mesh_anim[mesh_index].count == 0)
                {
                    m_mesh_anim[mesh_index].mesh.free();
                    m_mesh_anim[mesh_index].anim.free();
                }
            }
        }

        
// remove spell tracker from list

        
if(tracker->prev)
            tracker->prev->next = tracker->next;
        
else
            m_spell_tracker = tracker->next;

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

        tracker->prev = tracker->next = NULL;
        delete tracker;

        
return;
    }

    
// setup local data
    float source_x = tracker->source_x;
    
float source_y = tracker->source_y;
    
float source_z = tracker->source_z;
    
float target_x = tracker->target_x;
    
float target_y = tracker->target_y;
    
float target_z = tracker->target_z;

    
// goto next animation if no mesh to use
    if(spell.mesh_pos[cur_anim] == POSITION_NONE)
        
return set_anim_data(tracker, cur_anim+1);

    mesh_index = spell.mesh_index[cur_anim];
    sMeshAnim& mesh_anim = m_mesh_anim[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);
        mesh_anim.anim.set_loop(spell.mesh_loop[cur_anim], "Anim");
    }

    cObject& spell_obj = tracker->
object;
    spell_obj.create(&mesh_anim.mesh);
    mesh_anim.count++;

    
float x_angle = 0.0f, y_angle = 0.0f;
    
float x_diff, y_diff, z_diff, dist;
    
float scale = 1.0f;

    
// setup mesh movements
    switch(spell.mesh_pos[cur_anim])
    {
    
case POSITION_CASTER:
        tracker->x_pos = source_x;
        tracker->y_pos = source_y;
        tracker->z_pos = source_z;
        tracker->holding_time = spell.mesh_speed[cur_anim];

        
if(tracker->caster)
            y_angle = tracker->caster->direction;

        
break;

    
case POSITION_TOTARGET:
        
// store position and speed information
        tracker->x_pos = source_x;
        tracker->y_pos = source_y;
        tracker->z_pos = source_z;
        tracker->speed = spell.mesh_speed[cur_anim];

        
// calculate mevement
        x_diff = fabs(target_x - source_x);
        y_diff = fabs(target_y - source_y);
        z_diff = fabs(target_z - source_z);

        dist = sqrt(x_diff * x_diff + y_diff * y_diff + z_diff * z_diff);

        tracker->dist_to_target = dist;

        
if(! float_equal(dist, 0.0f))
        {
            tracker->x_add = (target_x - source_x) / dist;
            tracker->y_add = (target_y - source_y) / dist;
            tracker->z_add = (target_z - source_z) / dist;

            
// calculate angles
            x_angle = -atan(tracker->y_add);
            y_angle = atan2(tracker->x_add, tracker->z_add);
        }

        
break;

    
case POSITION_TARGET:
        tracker->x_pos = target_x;
        tracker->y_pos = target_y;
        tracker->z_pos = target_z;
        tracker->holding_time = spell.mesh_speed[cur_anim];

        
// calculate distance from source to target
        x_diff = fabs(target_x - source_x);
        z_diff = fabs(target_z - source_z);
        dist   = sqrt(x_diff * x_diff + z_diff * z_diff);

        tracker->x_add = (target_x - source_x) / dist;
        tracker->z_add = (target_z - source_z) / dist;

        y_angle = atan2(tracker->x_add, tracker->z_add);
        
break;

    
case POSITION_TOCASTER:
        
// store position and speed information
        tracker->x_pos = target_x;
        tracker->y_pos = target_y;
        tracker->z_pos = target_z;
        tracker->speed = spell.mesh_speed[cur_anim];

        
// calculate movement
        x_diff = fabs(source_x - target_x);
        y_diff = fabs(source_y - target_y);
        z_diff = fabs(source_z - target_z);

        dist = sqrt(x_diff * x_diff + y_diff * y_diff + z_diff * z_diff);

        tracker->dist_to_target = dist;

        
if(! float_equal(dist, 0.0f))
        {
            tracker->x_add = (source_x - target_x) / dist;
            tracker->y_add = (source_y - target_y) / dist;
            tracker->z_add = (source_z - target_z) / dist;

            
// calculate angles
            x_angle = -atan(tracker->y_add);
            y_angle = atan2(tracker->x_add, tracker->z_add);
        }

        
break;

    
case POSITION_SCALE:
        
// store position and speed information
        tracker->x_pos = source_x;
        tracker->y_pos = source_y;
        tracker->z_pos = source_z;
        tracker->holding_time = spell.mesh_speed[cur_anim];

        
// get distance from source to target and size of mesh

        x_diff = fabs(target_x - source_x);
        y_diff = fabs(target_y - source_y);
        z_diff = fabs(target_z - source_z);

        dist = sqrt(x_diff * x_diff + y_diff * y_diff + z_diff * z_diff);

        
float length;
        spell_obj.get_bounds(NULL, NULL, NULL, NULL, NULL, &length, NULL);

        scale = dist / length;

        tracker->x_add = (target_x - source_x) / dist;
        tracker->y_add = (target_y - source_y) / dist;
        tracker->z_add = (target_z - source_z) / dist;

        x_angle = -atan(tracker->y_add);
        y_angle = atan2(tracker->x_add, tracker->z_add);

        
break;
    }

    spell_obj.rotate(x_angle, y_angle, 0.0f);
    spell_obj.scale(1.0f, 1.0f, scale);
    spell_obj.set_anim_set(&mesh_anim.anim, "Anim", timeGetTime()/30);

    
if(spell.mesh_sound[cur_anim] != -1)
        play_spell_sound(spell.mesh_sound[cur_anim]);
}

cSpellController::update

Spells need to move, have their timing updated, and have their mesh initiated at
the various steps. Update is responsible for all those functions. To use Update, just pass
the amount of time (in milliseconds) that has elapsed from the last call to Update
(or the amount of time you want the controller to update the spells).

void cSpellController::update(long elapsed)
{
    
// update all spells based on elapsed time

    sSpellTracker* next_tracker;

    
// scan through all spells in use
    for(sSpellTracker* tracker = m_spell_tracker; tracker != NULL; tracker = next_tracker)
    {
        
// remember next spell in list
        next_tracker = tracker->next;

        
long spell_index = tracker->spell_index;
        
long cur_anim    = tracker->cur_anim;

        
bool goto_next_anim = false;

        
// update/move/countdown spell object
        switch(m_spells[spell_index].mesh_pos[cur_anim])
        {
        
case POSITION_NONE:
            goto_next_anim = 
true;
            
break;

        
case POSITION_CASTER:
        
case POSITION_TARGET:
        
case POSITION_SCALE:
            tracker->holding_time -= elapsed;

            
if(tracker->holding_time <= 0)
                goto_next_anim = 
true;

            
break;

        
case POSITION_TOTARGET:
        
case POSITION_TOCASTER:
            
float speed = elapsed/1000.0f * tracker->speed;
            tracker->dist_to_target -= speed;

            
if(tracker->dist_to_target > 0.0f)
            {
                tracker->x_pos += (tracker->x_add * speed);
                tracker->y_pos += (tracker->y_add * speed);
                tracker->z_pos += (tracker->z_add * speed);
            }
            
else
                goto_next_anim = 
true;

            
break;
        }

        
// update next animation if any
        if(goto_next_anim)
            set_anim_data(tracker, cur_anim+1);
    }
}
 

cSpellController::render

The last of the functions, Render, is used to render all spell meshes that are in effect.
Providing the Render function with an optional frustum and viewing distance helps
alter the way the meshes are rendered.

void cSpellController::render(cFrustum* frustum, float z_dist)
{
    m_frustum = frustum;

    
// construct the viewing frustum (if none passed)
    if(m_frustum == NULL)
    {
        cFrustum view_frustum;
        view_frustum.create(z_dist);
        m_frustum = &view_frustum;
    }

    
// get time to update animations (30 fps)
    DWORD time = timeGetTime() / 30;

    
// loop through each spell and draw
    for(sSpellTracker* tracker = m_spell_tracker; tracker != NULL; tracker = tracker->next)
    {
        
float radius;
        tracker->
object.get_bounds(NULL, NULL, NULL, NULL, NULL, NULL, &radius);

        
// draw spell if in viewing frustum
        if(m_frustum->is_sphere_in(tracker->x_pos, tracker->y_pos, tracker->z_pos, radius))
        {
            tracker->
object.move(tracker->x_pos, tracker->y_pos, tracker->z_pos);
            tracker->
object.update_anim(time, TRUE);
            tracker->
object.render();
        }
    }
}

posted on 2007-12-03 19:46 lovedday 閱讀(281) 評論(0)  編輯 收藏 引用

公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美在线视频日韩| 午夜欧美电影在线观看| 亚洲精品免费看| 亚洲人成网站精品片在线观看| 国产一区二区久久久| 国内精品视频666| 有码中文亚洲精品| 亚洲国产婷婷| 中日韩在线视频| 性久久久久久久久| 久久亚洲私人国产精品va媚药| 久久九九免费| 亚洲第一毛片| 欧美激情一区二区三区在线| 亚洲精品免费网站| 亚洲资源在线观看| 老司机免费视频一区二区三区| 欧美激情小视频| 国产精品亚洲аv天堂网| 激情综合中文娱乐网| 亚洲美女尤物影院| 性色av一区二区三区在线观看| 久久久久国色av免费看影院 | 最近看过的日韩成人| 日韩视频免费在线| 久久不射电影网| 欧美日韩精品系列| 国产日韩精品视频一区| 91久久精品美女高潮| 香蕉精品999视频一区二区| 奶水喷射视频一区| 亚洲免费在线看| 欧美日韩国产黄| 亚洲第一精品在线| 性色av一区二区三区| 亚洲美女黄网| 鲁大师成人一区二区三区| 国产精品一区久久| 一区二区三区四区五区精品视频| 久久亚洲综合| 亚洲女爱视频在线| 欧美日韩一区二区免费在线观看 | 欧美v日韩v国产v| 国产精品久久久久久妇女6080| 精品动漫av| 欧美在线视频网站| 一区二区三区四区在线| 欧美电影免费观看| 亚洲福利精品| 麻豆久久婷婷| 欧美一级黄色网| 国产精品自拍三区| 亚洲视频一区二区免费在线观看| 亚洲成人在线网| 麻豆9191精品国产| 亚洲国产一区二区三区高清| 鲁大师影院一区二区三区| 欧美亚洲日本国产| 国产香蕉97碰碰久久人人| 亚洲欧美综合v| 亚洲伊人网站| 国产亚洲成精品久久| 欧美一区二区国产| 亚洲欧美在线播放| 国产欧美精品久久| 久久精品日产第一区二区三区| 亚洲欧美日韩国产另类专区| 国产视频久久| 美女在线一区二区| 牛牛精品成人免费视频| 日韩西西人体444www| 亚洲精品一区二区三区樱花| 欧美日韩一区二区视频在线| 亚洲一区区二区| 午夜视频在线观看一区二区| 狠狠色2019综合网| 欧美高清视频一二三区| 欧美激情片在线观看| 一区二区三区国产盗摄| 亚洲私人影院在线观看| 国产婷婷精品| 欧美成人免费网| 欧美日韩国产a| 午夜免费在线观看精品视频| 欧美一区2区视频在线观看| 在线观看视频亚洲| 日韩视频中文字幕| 国产欧美精品日韩精品| 欧美a级大片| 国产精品a久久久久久| 久久久久久久一区二区三区| 欧美大片在线看| 午夜欧美电影在线观看| 久久婷婷国产综合尤物精品| 亚洲精品孕妇| 香蕉乱码成人久久天堂爱免费 | 亚洲黄色免费| 国产精品va在线播放我和闺蜜| 久久国产精品毛片| 久久久伊人欧美| 亚洲一区二区免费在线| 裸体歌舞表演一区二区| 一区二区三区免费观看| 亚洲欧美日韩第一区| 亚洲精品久久久久久下一站 | 亚洲二区在线| 亚洲一品av免费观看| 亚洲国产一二三| 欧美一区2区三区4区公司二百 | 一区二区三区在线观看欧美| 亚洲青涩在线| 精品不卡一区| 亚洲午夜在线视频| 亚洲美女av黄| 久久精品亚洲乱码伦伦中文 | 欧美国产日本高清在线| 国产乱人伦精品一区二区| 欧美国产综合一区二区| 国产色综合天天综合网| 这里只有精品视频在线| 亚洲精品一区二区三| 久久久久久网址| 欧美一级专区| 国产精品xxxxx| 日韩视频精品在线观看| 亚洲人成人一区二区在线观看| 久久成人免费网| 欧美一区二区三区视频在线观看| 欧美区日韩区| 最新国产成人在线观看| 亚洲激情第一区| 久热综合在线亚洲精品| 看欧美日韩国产| 精久久久久久| 久久综合一区二区| 免费永久网站黄欧美| 影音先锋久久资源网| 久久精品在线| 免费的成人av| 亚洲高清在线| 欧美高清你懂得| 亚洲国产欧美一区二区三区丁香婷| 亚洲成在人线av| 免播放器亚洲| 亚洲欧洲精品一区二区| 99精品国产一区二区青青牛奶| 欧美精品久久久久久久免费观看| 91久久中文字幕| 亚洲午夜一区二区| 国产伦理一区| 久久精品中文字幕一区二区三区| 久久嫩草精品久久久精品| 在线不卡视频| 欧美激情五月| 亚洲一级黄色片| 久久久久久久精| 亚洲人成网在线播放| 欧美日韩在线三区| 一区二区三欧美| 欧美日韩精品免费观看| 老鸭窝亚洲一区二区三区| 激情一区二区三区| 免费欧美日韩| 在线午夜精品自拍| 久久国产主播精品| 亚洲黄色免费| 欧美无砖砖区免费| 午夜精品久久久久久久99樱桃| 久久综合九色99| 99精品热视频| 国产深夜精品| 欧美日韩1080p| 久久爱www.| 一本久久知道综合久久| 久久精品亚洲热| 亚洲精品日韩在线| 国产区精品视频| 欧美黄色精品| 欧美有码在线视频| 亚洲美女性视频| 免费成人在线视频网站| 亚洲专区在线视频| 最新亚洲视频| 国产视频精品va久久久久久| 欧美久久久久中文字幕| 久久久www免费人成黑人精品| 亚洲蜜桃精久久久久久久| 老司机久久99久久精品播放免费| 99这里只有久久精品视频| 激情视频亚洲| 国产精自产拍久久久久久蜜| 欧美区亚洲区| 欧美成人高清视频| 久久久久久久久久久久久女国产乱 | 亚洲国产精品久久久久| 国产精品一区二区三区四区五区| 欧美www视频| 久久精品国产77777蜜臀| 一级成人国产| 亚洲国产欧美一区二区三区丁香婷|