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

天行健 君子當(dāng)自強(qiáng)而不息

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 閱讀(285) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導(dǎo)航

統(tǒng)計

常用鏈接

隨筆分類(178)

3D游戲編程相關(guān)鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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在线精品观看| 亚洲免费观看在线观看| 欧美激情一区二区三区在线视频观看| 亚洲欧美韩国| 久久久蜜桃一区二区人| 美女诱惑一区| 亚洲国产视频一区| 欧美大尺度在线观看| 亚洲欧洲精品一区二区三区波多野1战4| 欧美黄色免费网站| 一本大道久久a久久综合婷婷| 亚洲精品视频免费在线观看| 国产欧美日韩不卡免费| 伊人成人在线视频| 亚洲欧美福利一区二区| 久久久久久久欧美精品| 亚洲人成亚洲人成在线观看| 中文亚洲视频在线| 久久这里只有| 国产一区二区三区免费观看| 亚洲免费成人| 欧美黄色免费| 亚洲精品激情| 久久精品99无色码中文字幕| 亚洲精品一区二区在线| 久久九九热免费视频| 国产精品免费一区二区三区在线观看 | 久久夜色精品国产亚洲aⅴ| 亚洲毛片av| 欧美另类女人| 正在播放欧美一区| 99re66热这里只有精品3直播| 欧美成人亚洲成人日韩成人| 国产亚洲一区二区在线观看| 欧美自拍偷拍午夜视频| 亚洲欧美一区二区三区在线| 国产亚洲精品aa午夜观看| 欧美一区二区三区婷婷月色| 欧美在线亚洲一区| 亚洲麻豆av| 在线视频欧美精品| 国产一区免费视频| 欧美成人激情视频| 国产精品ⅴa在线观看h| 亚洲伊人网站| 久久免费国产| 亚洲欧美日韩国产综合在线 | 亚洲一区二区欧美| 亚洲一二三区精品| 久久精品首页| 亚洲精品一区二区三区蜜桃久| 亚洲欧洲日产国产网站| 国产精品女同互慰在线看| 久久午夜影视| 国产欧美日韩一区二区三区在线观看 | 欧美在线播放| 欧美插天视频在线播放| 欧美一级电影久久| 欧美日韩调教| 最新国产乱人伦偷精品免费网站 | 亚洲欧美日韩国产中文| 免费日韩av| 欧美高清影院| 黄色资源网久久资源365| 亚洲午夜极品| 亚洲免费小视频| 欧美色道久久88综合亚洲精品| 欧美大片免费观看| 在线观看亚洲精品视频| 理论片一区二区在线| 老妇喷水一区二区三区| 国内精品美女在线观看| 亚洲精品综合| 久久精品国产欧美亚洲人人爽| 在线视频中文亚洲| 在线观看日韩av| 久久精品国产综合精品| 国产农村妇女精品| 中文欧美在线视频| 久热这里只精品99re8久| 亚洲缚视频在线观看| 欧美freesex交免费视频| 欧美国产精品专区| 亚洲精品影视| 国产精品对白刺激久久久| 亚洲视频999| 日韩一区二区免费高清| 日韩视频一区二区三区在线播放免费观看 | 亚洲视频免费观看| 精品1区2区3区4区| 欧美涩涩网站| 欧美理论在线播放| 老牛国产精品一区的观看方式| 欧美韩日精品| 久久手机免费观看| 玖玖玖国产精品| 欧美日韩在线影院| 一区二区视频免费在线观看 | 亚洲午夜女主播在线直播| 国内精品一区二区| 国产精品免费看片| 欧美视频一区在线| 国产精品国产三级国产专播精品人 | 国产精品久久夜| 欧美三级午夜理伦三级中文幕 | 欧美在线一区二区| 一本大道久久a久久精品综合| 久久一区精品| 久久偷窥视频| 免费观看一级特黄欧美大片| 久久精品成人| 久久精品欧美| 欧美jizz19性欧美| 亚洲国产成人porn| 亚洲国产精品一区在线观看不卡| 亚洲国产精品日韩| 欧美一区二区三区婷婷月色| 欧美成人在线免费观看| 国产精品一区二区久久久久| 91久久久亚洲精品| 久久久久一区二区三区| 亚洲欧美乱综合| 亚洲一区二区三区四区中文 | 麻豆久久婷婷| 亚洲二区在线视频| 午夜日韩在线| 免费看黄裸体一级大秀欧美| 欧美精品免费视频| 国内一区二区在线视频观看| 国内自拍一区| 最新国产精品拍自在线播放| 亚洲最新中文字幕| 欧美一区二区在线观看| 欧美大片在线观看一区二区| 欧美国产日韩亚洲一区| 欧美日韩免费在线观看| 国产欧美日韩另类一区| 一区二区三区视频在线播放| 你懂的网址国产 欧美| 亚洲一区视频在线| 国产精品h在线观看| 99国产精品一区| 亚洲国产老妈| 久久精品国产91精品亚洲| 欧美三级乱人伦电影| 亚洲午夜伦理| 亚洲最快最全在线视频| 欧美日韩国产精品一区| 一区二区三区久久网| 日韩视频免费看| 国产精品久久7| 久久精品国产亚洲a| 欧美一区二区精美| 美国成人毛片| 欧美日韩精品在线观看| 亚洲一区二区欧美日韩| 亚洲欧美国产一区二区三区| 国产嫩草一区二区三区在线观看 | 欧美一区二区啪啪| 国产亚洲一区二区三区在线观看| 久久精品视频在线| 久久亚洲一区二区| 中文无字幕一区二区三区| 亚洲深夜福利视频| 在线不卡视频| 在线亚洲高清视频| 一区久久精品| 在线亚洲+欧美+日本专区| 国产丝袜美腿一区二区三区| 亚洲第一视频网站| 国产亚洲精品aa| 亚洲免费黄色| 亚洲免费成人av| 久久久噜噜噜久久久| 欧美日韩亚洲三区| 久久精品亚洲一区二区三区浴池| 欧美成人午夜影院| 欧美国产一区二区| 国产永久精品大片wwwapp| 一级日韩一区在线观看| 伊人夜夜躁av伊人久久| 欧美亚洲免费电影| 亚洲欧美国产毛片在线| 欧美日韩的一区二区| 欧美高清视频免费观看| 国产在线高清精品| 欧美在线综合| 久久久久久9999| 韩国久久久久| 久久天天躁狠狠躁夜夜av| 另类成人小视频在线| 在线观看成人一级片| 男女av一区三区二区色多| 亚洲国产黄色片| 亚洲欧美日韩一区在线| 国产精品美女午夜av| 久久午夜视频|