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

天行健 君子當自強而不息

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>
            99综合电影在线视频| 亚洲国产成人精品女人久久久| 欧美激情亚洲激情| 免费视频最近日韩| 99av国产精品欲麻豆| 一区二区欧美日韩| 国产精品你懂的在线欣赏| 久久精品99久久香蕉国产色戒| 久久久国际精品| 亚洲人成网站在线播| 夜夜狂射影院欧美极品| 国产亚洲精品aa午夜观看| 免费91麻豆精品国产自产在线观看| 欧美freesex8一10精品| 亚洲欧美韩国| 麻豆国产精品777777在线 | 久久精品人人爽| 一区二区亚洲精品| 一区二区免费在线观看| 一区二区三区在线免费播放| 亚洲日韩成人| 国产综合婷婷| 一区二区三区欧美日韩| 国产一区清纯| 一本久久综合| 亚洲成人资源网| 在线视频一区二区| 亚洲人成久久| 性欧美1819性猛交| 一区二区电影免费在线观看| 亚洲天天影视| 夜夜爽www精品| 久久蜜桃资源一区二区老牛| 亚洲欧美综合国产精品一区| 欧美成人午夜激情视频| 久久久久久久久一区二区| 欧美色大人视频| 欧美国产综合视频| 狠狠入ady亚洲精品经典电影| 亚洲精品欧美专区| 亚洲高清av| 久久www免费人成看片高清| 亚洲午夜精品在线| 美国十次了思思久久精品导航| 欧美在线|欧美| 欧美午夜免费| 亚洲精品久久视频| 日韩系列在线| 欧美福利视频在线| 美女精品一区| 在线播放日韩专区| 久久久久久亚洲精品中文字幕| 午夜欧美精品久久久久久久| 欧美揉bbbbb揉bbbbb| 亚洲国产mv| 亚洲片区在线| 欧美大片在线看免费观看| 欧美电影免费观看| 亚洲高清一区二| 男男成人高潮片免费网站| 免费观看成人鲁鲁鲁鲁鲁视频| 黄色在线一区| 久久人人九九| 亚洲电影激情视频网站| 亚洲精品视频在线| 欧美极品在线视频| 亚洲精品乱码久久久久久久久| 亚洲毛片网站| 欧美视频二区| 亚洲自拍偷拍视频| 久久久精品日韩| 在线观看不卡| 欧美人妖另类| 亚洲五月六月| 久久久久久久成人| 亚洲电影激情视频网站| 欧美国产亚洲另类动漫| 亚洲乱码精品一二三四区日韩在线| 一区二区三区精品国产| 国产精品久久久一本精品| 亚洲综合成人在线| 麻豆精品视频在线观看视频| 亚洲欧洲三级电影| 欧美日韩国产影院| 亚洲欧美在线磁力| 欧美.com| 亚洲欧美亚洲| 亚洲电影免费观看高清| 欧美精品三级| 欧美一区二区| 亚洲日本成人女熟在线观看| 午夜在线视频观看日韩17c| 海角社区69精品视频| 欧美激情区在线播放| 亚洲一区在线看| 欧美激情小视频| 欧美一级在线视频| 亚洲高清一区二区三区| 国产精品美女诱惑| 久久亚洲一区二区| 亚洲一区在线免费观看| 欧美国产精品日韩| 欧美一区二区私人影院日本| 91久久在线视频| 国产一区二区三区精品欧美日韩一区二区三区 | aa级大片欧美三级| 国产一区二区福利| 欧美激情国产日韩精品一区18| 亚洲在线一区二区| 亚洲日本无吗高清不卡| 久久亚洲私人国产精品va媚药 | 亚洲电影在线播放| 国产精品三上| 欧美日韩国产另类不卡| 久久久久久夜| 欧美一级视频精品观看| 艳妇臀荡乳欲伦亚洲一区| 欧美α欧美αv大片| 久久国产一区二区| 亚洲天堂av在线免费观看| 亚洲高清在线| 精品动漫3d一区二区三区| 国产精品一区毛片| 欧美午夜免费| 欧美日韩在线不卡| 欧美激情精品久久久六区热门| 久久午夜av| 久久久精品999| 欧美一区二区三区免费视| 亚洲伊人伊色伊影伊综合网| 亚洲免费av电影| 亚洲精品美女在线观看播放| 亚洲第一免费播放区| 欧美r片在线| 欧美1级日本1级| 免费日韩成人| 噜噜噜久久亚洲精品国产品小说| 久久av免费一区| 久久国产加勒比精品无码| 欧美在线视频网站| 欧美在线看片| 狼狼综合久久久久综合网| 久久躁日日躁aaaaxxxx| 久久久久久一区二区三区| 久久久久成人精品| 久久这里只有| 欧美高清视频一区二区三区在线观看 | 国产三级欧美三级日产三级99| 国产精品mv在线观看| 国产精品日韩欧美| 国产一区二区三区四区五区美女 | 亚洲日本在线观看| 一本到12不卡视频在线dvd| 中日韩男男gay无套| 宅男噜噜噜66一区二区| 欧美一级欧美一级在线播放| 亚洲欧美色婷婷| 欧美中文在线观看国产| 另类av一区二区| 亚洲第一精品影视| 夜夜嗨网站十八久久| 亚洲欧美日韩第一区| 久久久久国产一区二区三区四区 | 欧美日韩日韩| 国产亚洲激情| 亚洲精选久久| 午夜精品视频在线| 欧美成人中文字幕| 一区二区三区国产盗摄| 欧美中文字幕| 欧美激情第三页| 国产欧美丝祙| 亚洲人成网在线播放| 先锋影院在线亚洲| 欧美成熟视频| 亚洲自啪免费| 欧美黄色一区| 国产日韩欧美在线看| 亚洲精品美女91| 久久国产高清| 日韩午夜激情| 免费看成人av| 国产午夜一区二区三区| 日韩亚洲综合在线| 久久久在线视频| 一区二区三区四区国产精品| 久久婷婷人人澡人人喊人人爽| 欧美丝袜一区二区三区| 亚洲高清免费视频| 久久本道综合色狠狠五月| 亚洲国产精品t66y| 久久久精品免费视频| 国产精品欧美经典| 99精品久久久| 亚洲大胆人体视频| 久久大香伊蕉在人线观看热2| 国产精品久久久久久久app| 亚洲人成人一区二区三区| 久久婷婷麻豆| 欧美中文字幕|