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

天行健 君子當自強而不息

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>
            亚洲少妇一区| 欧美大片一区二区三区| 亚洲看片免费| 欧美激情第8页| 99热免费精品在线观看| 亚洲人成小说网站色在线| 久久亚洲高清| 亚洲精品中文字幕在线| 99国产精品久久久久久久成人热| 欧美日韩视频| 欧美一级欧美一级在线播放| 午夜免费在线观看精品视频| 永久免费精品影视网站| 欧美成人免费全部观看天天性色| 欧美激情中文字幕乱码免费| 亚洲欧美日韩爽爽影院| 欧美在线三区| 在线中文字幕一区| 性做久久久久久久免费看| 亚洲高清影视| 一本一本久久| 狠狠狠色丁香婷婷综合激情| 亚洲黄色视屏| 国产欧美一区二区三区国产幕精品| 久久综合图片| 国产精品vvv| 欧美/亚洲一区| 国产精品久久久久久久久果冻传媒| 久久久久久亚洲精品杨幂换脸| 欧美国产一区二区| 欧美中文字幕在线| 欧美精选午夜久久久乱码6080| 久久精品亚洲| 欧美三级电影大全| 免费不卡在线观看| 国产精品对白刺激久久久| 欧美华人在线视频| 国产日韩欧美一区二区三区在线观看| 亚洲国产一区在线观看| 国产欧美日韩三区| 最新日韩在线| 精品成人一区二区| 中国成人亚色综合网站| 在线观看日韩av电影| 亚洲综合丁香| 亚洲激情校园春色| 欧美一区二区三区免费视频| 一区二区三区久久久| 久久蜜桃av一区精品变态类天堂| 亚洲一区二区四区| 欧美成人亚洲成人日韩成人| 久久久久综合网| 国产欧美欧美| 亚洲一区二区高清| 一区二区三区日韩欧美| 奶水喷射视频一区| 久久亚洲精品中文字幕冲田杏梨| 国产精品婷婷午夜在线观看| 99精品99| 亚洲视频大全| 欧美精品播放| 亚洲欧洲在线一区| 亚洲欧洲日韩女同| 免费成人黄色av| 美女视频黄a大片欧美| 国精品一区二区三区| 欧美一区二区三区精品| 久久av二区| 国产日产欧产精品推荐色 | 91久久一区二区| 91久久精品视频| 免费成人美女女| 亚洲国产日日夜夜| 一本大道久久a久久精品综合| 欧美韩日视频| 亚洲看片一区| 性欧美1819性猛交| 国产日韩欧美自拍| 久久九九久精品国产免费直播| 久久免费视频在线| 精品成人一区二区| 欧美+日本+国产+在线a∨观看| 亚洲国产日韩欧美一区二区三区| 亚洲精品韩国| 欧美男人的天堂| 一区二区三区欧美视频| 午夜精品亚洲一区二区三区嫩草| 国产精品天天摸av网| 欧美在线不卡| 欧美激情第五页| 亚洲午夜久久久| 国产午夜精品美女毛片视频| 久久久久免费观看| 亚洲欧洲三级电影| 性高湖久久久久久久久| 黄色国产精品| 欧美女同在线视频| 亚洲欧美日韩国产中文 | 亚洲品质自拍| 国产精品久久久久久影院8一贰佰| 午夜日韩激情| 亚洲国产精品综合| 欧美在线亚洲一区| 亚洲精品视频一区二区三区| 欧美午夜精品久久久久久人妖| 久久国产精彩视频| 亚洲美女电影在线| 久久综合九色| 亚洲一区中文| 亚洲国产另类 国产精品国产免费| 欧美日韩一本到| 久久久久高清| 中文精品一区二区三区| 免费视频最近日韩| 亚洲一级在线观看| 亚洲激情午夜| 国内精品久久久久久| 欧美日韩综合视频| 女同一区二区| 久久精品夜色噜噜亚洲a∨| 99热免费精品在线观看| 美日韩精品视频免费看| 午夜欧美大片免费观看| 99精品久久久| 1769国产精品| 国内精品写真在线观看| 国产精品久久毛片a| 欧美人成在线视频| 免费av成人在线| 久久精品国产77777蜜臀| 亚洲综合精品自拍| 亚洲美女尤物影院| 亚洲欧洲一级| 亚洲激情视频网| 欧美成人自拍| 免费在线成人av| 久久网站免费| 久久青草欧美一区二区三区| 欧美一区二区视频免费观看| 亚洲一区二区三区777| 99国产精品自拍| 99国产精品久久久| 在线视频欧美日韩| 日韩亚洲综合在线| 亚洲精品无人区| 亚洲精品婷婷| 99在线精品观看| 一本在线高清不卡dvd| 99re6这里只有精品视频在线观看| 在线观看日韩专区| 亚洲电影在线看| 亚洲欧洲日本mm| 99精品视频免费全部在线| 99一区二区| 亚洲午夜激情免费视频| 99综合视频| 亚洲深夜影院| 久久高清一区| 另类激情亚洲| 欧美黄色精品| 亚洲精品乱码久久久久久黑人| 亚洲免费电影在线| 99精品热6080yy久久 | 久久久久久久久岛国免费| 噜噜噜久久亚洲精品国产品小说| 麻豆精品视频| 亚洲精品黄网在线观看| 一区二区三区不卡视频在线观看| 亚洲深夜福利网站| 欧美一区二区免费观在线| 欧美/亚洲一区| 国产精品成人一区二区| 国产一区欧美| 一本色道久久99精品综合| 亚洲欧美激情四射在线日| 久久久久久噜噜噜久久久精品| 欧美成人中文| 亚洲一区精彩视频| 久久人人超碰| 欧美日一区二区三区在线观看国产免| 国产精品视频你懂的| 激情欧美日韩| 中文亚洲免费| 免费观看30秒视频久久| 99re6热只有精品免费观看| 午夜精品久久久99热福利| 麻豆国产精品va在线观看不卡| 欧美日韩一区在线视频| 激情五月婷婷综合| 亚洲一区二区日本| 欧美成人一区二区| 国产精品99久久99久久久二8| 久久精品国产免费观看| 欧美日韩专区在线| 亚洲第一精品福利| 欧美一区亚洲| 日韩视频第一页| 免费观看成人网| 国产亚洲一区在线| 亚洲欧美日韩一区|