• <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>

            天行健 君子當自強而不息

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

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            久久久人妻精品无码一区 | 日韩久久久久中文字幕人妻| 国产午夜精品理论片久久影视| 国产欧美一区二区久久| 激情综合色综合久久综合| 久久久精品视频免费观看| 久久婷婷五月综合国产尤物app| 久久成人国产精品| 国产成人精品久久亚洲高清不卡 | 久久精品国产福利国产琪琪| 亚洲AV成人无码久久精品老人| 伊人久久大香线蕉影院95| 久久精品国产色蜜蜜麻豆| 国产L精品国产亚洲区久久| 久久久精品国产免大香伊| 久久最新精品国产| 人妻精品久久久久中文字幕一冢本| 国产成人精品久久亚洲高清不卡 | 亚洲精品乱码久久久久久按摩| 伊人久久免费视频| 精品久久久久久久无码| 久久亚洲国产精品成人AV秋霞| 久久93精品国产91久久综合| 久久国产精品-久久精品| 亚洲va久久久噜噜噜久久狠狠 | 91精品国产高清久久久久久91| 无码国产69精品久久久久网站| 久久久久亚洲AV成人网| 999久久久国产精品| 日本福利片国产午夜久久| 久久天天躁狠狠躁夜夜96流白浆| 热99RE久久精品这里都是精品免费 | 久久国产三级无码一区二区| 国产精品久久久久久影院| 亚洲国产精品无码久久SM| 伊人色综合久久天天人守人婷| 99久久婷婷国产综合精品草原 | 久久精品毛片免费观看| 久久丫精品国产亚洲av不卡| 久久精品人人做人人爽电影蜜月 | 免费国产99久久久香蕉|