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

天行健 君子當自強而不息

Controlling Players and Characters(36)

Notice that I keep talking about removing characters from the list. What about all
the hard work you’ve put into your PCs—how are you ever going to store their
achievements for later loading? With the following set of saving and loading functions,
of course!

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

bool cCharController::save_char(long id, const char* filename)
{
    sCharacter* character = get_char(id);
    
if(character == NULL)
        
return false;

    FILE* fp = fopen(filename, "wb");
    
if(fp == NULL)
        
return false;

    
// output character data
    fwrite(&character->char_def,      1, sizeof(character->char_def),      fp);
    fwrite(&character->health_points, 1, 
sizeof(character->health_points), fp);
    fwrite(&character->mana_points,   1, 
sizeof(character->mana_points),   fp);
    fwrite(&character->ailments,      1, 
sizeof(character->ailments),      fp);
    fwrite(&character->pos_x,         1, 
sizeof(character->pos_x),         fp);
    fwrite(&character->pos_y,         1, 
sizeof(character->pos_y),         fp);
    fwrite(&character->pos_z,         1, 
sizeof(character->pos_z),         fp);
    fwrite(&character->direction,     1, 
sizeof(character->direction),     fp);

    fclose(fp);

    
// save inventory
    if(character->char_ics)
    {
        
char ics_file[MAX_PATH];
        sprintf(ics_file, "ICS%s", filename);
        character->char_ics->save(ics_file);
    }

    
return true;
}

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

bool cCharController::load_char(long id, const char* filename)
{
    sCharacter* character = get_char(id);
    
if(character == NULL)
        
return false;

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

    
// read in character data
    fread(&character->char_def,      1, sizeof(character->char_def),      fp);
    fread(&character->health_points, 1, 
sizeof(character->health_points), fp);
    fread(&character->mana_points,   1, 
sizeof(character->mana_points),   fp);
    fread(&character->ailments,      1, 
sizeof(character->ailments),      fp);
    fread(&character->pos_x,         1, 
sizeof(character->pos_x),         fp);
    fread(&character->pos_y,         1, 
sizeof(character->pos_y),         fp);
    fread(&character->pos_z,         1, 
sizeof(character->pos_z),         fp);
    fread(&character->direction,     1, 
sizeof(character->direction),     fp);

    fclose(fp);

    
// load inventory
    if(character->char_ics)
    {
        
char ics_file[MAX_PATH];
        sprintf(ics_file, "ICS%s", filename);
        character->char_ics->load(ics_file);
    }

    
return true;
}

Both of the two preceding functions take the character’s identification number to
save or load, as well as the filename to use.

That about rounds up the functions used to prepare, add, and remove the characters
from the game. Now it’s time to get them all moving around performing their actions.
Previously you saw the functions used to update the individual character types; now
comes the single function you’ll call to update all characters at once:

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

void cCharController::update(long elapsed)
{    
    
if(m_root_char == NULL)
        
return;

    
static long effect_counter = 0;
    effect_counter += elapsed;

    
float x_move, y_move, z_move;
    sCharacter* next_char;

    
// loop through all characters
    for(sCharacter* char_ptr = m_root_char; char_ptr != NULL; char_ptr = next_char)
    {
        next_char = char_ptr->next;     
// remember next character

        // only update if enabled, not asleep or paralyzed.
        if(! char_ptr->update_enable)
            
continue;

        
// update action timer if in use
        if(char_ptr->action_timer != 0)
        {
            char_ptr->action_timer -= elapsed;

            
if(char_ptr->action_timer < 0)
                char_ptr->action_timer = 0;
        }

        
if(char_ptr->msg_timer > 0)
            char_ptr->msg_timer -= elapsed;

        
// reset charge counter if attacking, spell, or item.
        if(char_ptr->action == CHAR_ATTACK || char_ptr->action == CHAR_SPELL || char_ptr->action == CHAR_ITEM)
            char_ptr->charge = 0.0f;

        
// kill character if no health left
        if(char_ptr->health_points <= 0 && char_ptr->action != CHAR_DIE)
            set_char_action(char_ptr, CHAR_DIE, 0);

        
bool to_process = true;     // mark that processing can continue later on
        bool dead_char  = false;    // mark character as still alive

        // do not allow on update if asleep or paralyzed
        if((char_ptr->ailments & AILMENT_SLEEP) || (char_ptr->ailments & AILMENT_PARALYZE))
            to_process = 
false;

        
// process actions
        if(char_ptr->action_timer == 0)
        {
            
switch(char_ptr->action)
            {
            
case CHAR_ATTACK:
                
if(to_process)
                    attack(char_ptr, char_ptr->victim);

                
break;

            
case CHAR_SPELL:
                
if(to_process)
                    m_spell_controller->add(char_ptr);

                
break;

            
case CHAR_ITEM:
                
if(to_process)
                    use_item(char_ptr, char_ptr, char_ptr->item_index, char_ptr->char_item);

                
break;

            
case CHAR_DIE:
                death(char_ptr->attacker, char_ptr);
                dead_char  = 
true;
                to_process = 
false;
                
break;
            }
        }

        
// clear movement
        x_move = y_move = z_move = 0.0f;

        
// only continue if allowed (in case character died)
        if(to_process)
        {
            
// only allow updates if lock/timer not in use
            if(char_ptr->action_timer == 0 && !char_ptr->is_lock)
            {                    
                char_ptr->action = CHAR_IDLE;   
// reset action

                
if(char_ptr->type == CHAR_PC)
                    pc_update(char_ptr, elapsed, &x_move, &y_move, &z_move);
                
else
                    npc_monster_update(char_ptr, elapsed, &x_move, &y_move, &z_move);

                
// check for validity of movement (clear if invalid)
                if(!check_move(char_ptr, &x_move, &y_move, &z_move))
                {
                    x_move = y_move = z_move = 0.0f;
                    char_ptr->action = CHAR_IDLE;
                }
            }

            process_update(char_ptr, x_move, y_move, z_move);

            char_ptr->charge += (elapsed/1000.0f * get_charge_rate(char_ptr));

            
if(char_ptr->charge > 100.0f)
                char_ptr->charge = 100.0f;
        }

        
// process timed ailments (only in live characters)
        if(!dead_char && char_ptr->ailments)
        {
            
// sleeping characters have 4% to wake up
            if((char_ptr->ailments & AILMENT_SLEEP) && rand()%100 < 4)
                char_ptr->ailments &= ~AILMENT_SLEEP;

            
// paralyzed character have 2% chance to recover
            if((char_ptr->ailments & AILMENT_PARALYZE) && rand()%100 < 2)
                char_ptr->ailments &= ~AILMENT_PARALYZE;

            
// poison removes 2 hp every 4 seconds
            if((char_ptr->ailments & AILMENT_POISON) && effect_counter >= 4000)
            {
                char_ptr->health_points -= 2;
                set_char_msg(char_ptr, "Poison -2 HP", 500, D3DCOLOR_RGBA(0, 255, 64, 255));
            }
        }
    }

    
// reset effect counter (after 4 seconds)
    if(effect_counter >= 4000)
        effect_counter = 0;
}

The Update function is called once every frame. Taking a single argument (the time
elapsed since the last update), the Update function calls upon each character’s
respective update function, validates each character’s movements and actions, and
wraps up by processing the actions. Then a call to Render is in order to display all
characters visible within the specified frustum.
///////////////////////////////////////////////////////////////////////////////////////////////////

void cCharController::render(long elapsed, 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;
    }

    DWORD time = 0;

    
// get time to update animations (30fps) if elapsed value passed == -1
    if(elapsed == -1)
        time = timeGetTime() / 30;

    
// variables for printing messages
    bool got_matrices = false;
    D3DXMATRIX mat_world, mat_view, mat_proj;
    D3DVIEWPORT9 viewport;

    
// loop through each character and draw
    for(sCharacter* char_ptr = m_root_char; char_ptr != NULL; char_ptr = char_ptr->next)
    {
        
// update animation based on elapsed time passed
        if(elapsed != -1)
        {
            char_ptr->last_anim_time += elapsed/30;
            time = char_ptr->last_anim_time;
        }

        
float max_y, radius;
        cObject& 
object = char_ptr->object;
        
object.get_bounds(NULL, NULL, NULL, NULL, &max_y, NULL, &radius);

        
// draw character if in viewing frustum
        if(! m_frustum->is_sphere_in(object.get_x_pos(), object.get_y_pos(), object.get_z_pos(), radius))
            
continue;

        
object.update_anim(time, true);
        
object.render();
        
        
if(char_ptr->char_def.weapon != -1)
            char_ptr->weapon_object.render();

        
// draw message if needed
        if(char_ptr->msg_timer > 0)
        {
            
// get the matrices and viewport if not done already
            if(!got_matrices)
            {
                got_matrices = 
true;

                
// get the world, projection, and view transformations.
                D3DXMatrixIdentity(&mat_world);
                get_display_view_matrix(&mat_view);
                get_display_proj_matrix(&mat_proj);
                get_display_viewport(&viewport);
            }

            D3DXVECTOR3 pos;
            D3DXVECTOR3 src_pos(char_ptr->pos_x, char_ptr->pos_y + (max_y * 0.5f), char_ptr->pos_z);

            
// project a 3D vector from object space into screen space
            D3DXVec3Project(&pos, &src_pos, &viewport, &mat_proj, &mat_view, &mat_world);

            draw_font(m_font, char_ptr->msg, pos.x, pos.y, 0, 0, char_ptr->msg_color, DT_LEFT);
        }
    }
}

With render, you have a few optional arguments. You use the first one to control
the animation timing of the characters. In a task-switchable environment such as
Windows, merely using the time elapsed from the last processed frame is unacceptable;
you must instead specify a fixed amount of time passed and ensure that your
game engine sticks to updates at that rate.

As for the viewing frustum pointer, the application can provide its own pre-created
object, or pass NULL (and an optional Z-distance) to create its own frustum.

 

posted on 2007-12-04 18:55 lovedday 閱讀(299) 評論(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>
            欧美巨乳在线| 亚洲一二三四区| 欧美/亚洲一区| 亚洲狠狠婷婷| 亚洲国内高清视频| 欧美日韩高清在线观看| 亚洲一区综合| 久久国产成人| 亚洲精选91| 夜夜爽夜夜爽精品视频| 国产日韩欧美黄色| 欧美大片免费久久精品三p| 欧美成人在线影院| 亚洲免费影视| 久久国产精品免费一区| 亚洲精品一线二线三线无人区| 国产精品久久久久久久免费软件| 欧美精品99| 亚洲一区日韩| 久久这里有精品15一区二区三区| 欧美破处大片在线视频| 亚洲天堂免费观看| 欧美一区二区三区另类| 亚洲激情偷拍| 亚洲一区二区三区精品在线观看| 欧美电影专区| 欧美一区激情| 欧美精品亚洲二区| 久久免费99精品久久久久久| 欧美成人国产一区二区| 久久成人久久爱| 欧美精品免费在线| 久久不射电影网| 欧美精品自拍偷拍动漫精品| 久久av老司机精品网站导航| 欧美精品一区二区三区四区 | 夜夜爽www精品| 国产精品影院在线观看| 亚洲黄色在线| 国产午夜精品久久久久久久| 亚洲欧洲另类| 136国产福利精品导航网址| 亚洲伊人一本大道中文字幕| 亚洲伦理网站| 美日韩精品免费| 久久人人97超碰国产公开结果| 欧美在线黄色| 亚洲欧美变态国产另类| 欧美精品国产一区| 欧美成人午夜77777| 韩日午夜在线资源一区二区| 亚洲午夜国产成人av电影男同| 欧美性生交xxxxx久久久| 欧美激情精品久久久久久变态| 久久在线免费观看| 性色一区二区| 国产精品久久影院| 日韩一级不卡| 亚洲视屏一区| 欧美无乱码久久久免费午夜一区| 午夜亚洲性色福利视频| 欧美经典一区二区| 亚洲欧洲另类| 亚洲一级一区| 国产精品美女主播在线观看纯欲| 久久国产精品99久久久久久老狼| 性做久久久久久久免费看| 午夜视频久久久久久| 国产精品久久久久免费a∨| 亚洲视频导航| 欧美一级片一区| 国产午夜精品久久| 欧美一区二区| 久久综合网络一区二区| 亚洲电影欧美电影有声小说| 久久综合国产精品| 最新日韩中文字幕| 亚洲一区二区视频在线| 国产精品www| 性欧美长视频| 亚洲大胆女人| 亚洲午夜精品在线| 国产精品无人区| 久久久www| 欧美亚韩一区| 欧美一级网站| 欧美激情网友自拍| 亚洲一区二区三区在线| 国产伦精品免费视频| 久久精品成人| 亚洲精品一级| 性久久久久久| 最近看过的日韩成人| 欧美系列电影免费观看| 欧美影院在线| 亚洲精品综合精品自拍| 午夜精品久久久久久久蜜桃app| 欧美在线观看一区二区| 欧美韩日一区| 欧美亚洲视频| 亚洲精品久久久久久一区二区| 亚洲欧美网站| 欧美成人在线免费视频| 亚洲专区一二三| 韩国av一区二区三区在线观看| 亚洲麻豆视频| 久久综合国产精品| 亚洲一区999| 在线日本高清免费不卡| 国产精品国产三级国产aⅴ入口| 你懂的成人av| 亚洲一二三区在线| 亚洲黄页一区| 国产视频不卡| 国产精品黄视频| 免费观看成人| 午夜精品免费在线| aa级大片欧美三级| 欧美国产视频在线| 久久夜色撩人精品| 午夜精品久久久久久久久久久久久 | 亚洲国产欧美一区二区三区久久 | 亚洲一区二区三区高清| 久久在线播放| 午夜久久久久| aa级大片欧美三级| 亚洲欧洲在线免费| 国产在线精品自拍| 国产女精品视频网站免费| 欧美涩涩视频| 欧美日韩亚洲免费| 欧美日韩高清不卡| 欧美喷水视频| 欧美精品日韩精品| 欧美激情1区2区| 奶水喷射视频一区| 美女诱惑黄网站一区| 欧美制服丝袜第一页| 亚洲图片自拍偷拍| 国产精品99久久久久久人| 亚洲另类一区二区| 亚洲精品美女在线观看播放| 亚洲国产精品国自产拍av秋霞| 久久综合福利| 久久一本综合频道| 久久综合伊人77777| 欧美一级淫片aaaaaaa视频| 午夜亚洲精品| 久久成人一区| 久久只有精品| 欧美激情一区二区三区蜜桃视频| 亚洲日本黄色| 91久久久久久| 亚洲欧洲日本国产| 亚洲理伦在线| 夜夜嗨一区二区| 亚洲女ⅴideoshd黑人| 欧美一区在线视频| 久久久久欧美| 欧美激情第五页| 欧美性猛交视频| 国产一区视频在线观看免费| 在线不卡中文字幕| 亚洲免费av电影| 亚洲影视在线播放| 久久久精品一区| 国产精品亚洲美女av网站| 国产精品一区二区久激情瑜伽| 蜜桃av一区二区三区| 欧美精品在线一区| 国产精品一区二区你懂的| 国产视频亚洲| 亚洲九九九在线观看| 亚洲一区在线免费观看| 久久综合狠狠综合久久综青草 | 欧美日韩免费区域视频在线观看| 久久精品视频网| 99精品久久| 性色av一区二区怡红| 猛男gaygay欧美视频| 亚洲第一天堂无码专区| 日韩一级免费| 久久色在线观看| 国产精品久久毛片a| 亚洲电影av| 久久岛国电影| 99riav1国产精品视频| 久久精视频免费在线久久完整在线看| 夜夜狂射影院欧美极品| 久久精品最新地址| 欧美午夜无遮挡| 在线日韩av片| 久久国产欧美精品| 日韩一区二区高清| 久久久亚洲国产美女国产盗摄| 亚洲一区二区三区激情| 欧美高清日韩| 在线国产精品播放| 久久精品首页| 亚洲综合成人在线|