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

天行健 君子當自強而不息

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>
            亚洲高清免费在线| 亚洲欧美999| 久久在线免费| 久久精品国产清自在天天线| 国产日韩在线亚洲字幕中文| 久久激情五月激情| 久久久.com| 亚洲国产欧美日韩另类综合| 最新国产成人av网站网址麻豆| 欧美精品日韩综合在线| 亚洲欧美国产高清| 欧美一区二区性| 亚洲经典一区| 亚洲一区二区3| 精久久久久久| 日韩一级黄色av| 国产三区精品| 亚洲国产三级网| 国产精品久久久久永久免费观看| 久久久久99| 欧美激情亚洲精品| 欧美在线视频观看| 欧美成人免费网站| 欧美在线日韩精品| 欧美99在线视频观看| 亚洲欧美日韩国产综合在线| 久久精品国产99精品国产亚洲性色 | 欧美午夜视频在线| 久久在线免费观看| 欧美日韩在线视频首页| 久久久久国产一区二区三区| 欧美日本不卡视频| 久久久爽爽爽美女图片| 欧美日韩精品国产| 猫咪成人在线观看| 国产农村妇女毛片精品久久麻豆| 欧美激情 亚洲a∨综合| 国产乱码精品一区二区三区av | 亚洲自拍偷拍色片视频| 久久久噜噜噜久噜久久| 亚洲一区观看| 欧美经典一区二区| 美女日韩欧美| 国产性色一区二区| 久久成人精品| 在线播放中文一区| 中日韩美女免费视频网址在线观看 | 亚洲日本电影在线| 在线电影院国产精品| 先锋影音一区二区三区| 亚洲综合丁香| 欧美日韩一区二区在线| 亚洲国产成人av在线| 国产亚洲第一区| 亚洲欧美日韩成人| 午夜精品久久| 国产精品激情av在线播放| 亚洲精品视频一区| 99视频精品全部免费在线| 久久久亚洲成人| 免费看精品久久片| 在线精品福利| 免费成人美女女| 欧美成人xxx| 在线国产日韩| 另类av导航| 亚洲二区视频在线| 亚洲精品中文字| 欧美日韩成人综合天天影院| 亚洲精品欧洲精品| 亚洲一区二区精品在线观看| 欧美日韩三区| 亚洲永久字幕| 欧美主播一区二区三区| 国产三级欧美三级| 久久久久九九视频| 亚洲国产精品va在线观看黑人| 最近看过的日韩成人| 欧美精品日韩| 亚洲网站在线观看| 欧美一区二区视频在线观看2020 | 欧美~级网站不卡| 亚洲日本欧美在线| 亚洲在线一区二区| 国产一区二区看久久| 久久久久久网| 亚洲国产成人午夜在线一区 | 国产乱码精品一区二区三区不卡 | av成人免费在线观看| 午夜一区在线| 在线精品一区二区| 欧美日韩aaaaa| 亚洲在线网站| 欧美激情在线有限公司| 亚洲午夜精品久久久久久app| 国产精品久久久久久久7电影| 欧美伊人久久大香线蕉综合69| 美女久久一区| 午夜精品久久久久久久白皮肤| 黑丝一区二区| 欧美日韩精品久久久| 欧美一级理论性理论a| 亚洲国产精品一区二区久| 亚洲一区免费看| 亚洲国产精品精华液2区45| 国产精品美女久久久免费| 久久综合九色九九| 亚洲在线一区| 亚洲精品美女在线| 男女精品视频| 久久久999精品视频| 亚洲午夜影视影院在线观看| 在线免费观看日本欧美| 国产乱码精品一区二区三区忘忧草| 欧美大香线蕉线伊人久久国产精品| 亚洲欧美自拍偷拍| 亚洲免费高清| 亚洲国产专区| 暖暖成人免费视频| 久久―日本道色综合久久| 亚洲欧美另类在线观看| 欧美亚洲一级| 亚洲国产毛片完整版| 欧美视频日韩| 一本色道久久88综合日韩精品| 久久久成人网| 在线亚洲+欧美+日本专区| 亚洲欧洲日本国产| 国产久一道中文一区| 欧美精品手机在线| 久久蜜桃资源一区二区老牛 | 久久久久欧美精品| 亚洲私人影院| 亚洲精品中文字| 国产在线观看一区| 国产一区二区精品久久91| 欧美日韩一区二区国产| 久久综合伊人77777麻豆| 亚洲女同同性videoxma| 久久免费观看视频| 久久蜜臀精品av| 午夜久久久久久| 一区二区日韩| 亚洲欧洲在线看| 国产日本欧美一区二区三区| 国产精品久久久久久久久久尿| 欧美久久电影| 欧美成ee人免费视频| 久久手机免费观看| 欧美专区第一页| 午夜性色一区二区三区免费视频| 亚洲人成网站777色婷婷| 久久国产精品免费一区| 一区二区三区三区在线| 国产模特精品视频久久久久| 国产精品乱人伦一区二区| 欧美三级特黄| 欧美视频中文在线看| 美女在线一区二区| 欧美日韩一区二区免费视频| 欧美福利电影网| 欧美区日韩区| 欧美日韩视频专区在线播放| 国产精品露脸自拍| 国产精品一区二区久久久久| 国产精品成人一区| 国产精品婷婷| 国产精品久久久久久久久久免费| 国产日产亚洲精品| 国色天香一区二区| 在线观看三级视频欧美| 亚洲电影免费在线观看| 在线观看亚洲专区| 亚洲精品乱码久久久久久按摩观| 亚洲乱码视频| 久久久人成影片一区二区三区 | 国产日韩欧美精品| 国内揄拍国内精品久久| 亚洲国产精品视频| 在线成人激情| 亚洲午夜视频在线| 欧美在线视频观看免费网站| 久久久综合激的五月天| 欧美国产日韩精品免费观看| 这里只有精品丝袜| 欧美一区二区三区四区夜夜大片| 欧美在线观看网站| 欧美成人一二三| 国产精品三级视频| 亚洲国产成人精品女人久久久| 亚洲精品国产视频| 欧美伊久线香蕉线新在线| 亚洲欧洲日本mm| 午夜精品久久久| 欧美国产极速在线| 国产日韩欧美综合一区| 亚洲一卡久久| 欧美国产综合一区二区| 亚洲一区国产视频| 欧美成人一区二免费视频软件|