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

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

            游戲中時(shí)間的封裝

            時(shí)鐘類GE_TIMER可用來取得游戲已進(jìn)行的時(shí)間,計(jì)算出兩個(gè)時(shí)間點(diǎn)之間的時(shí)間片大小,從而可在某一時(shí)間點(diǎn)處,自動(dòng)更新某些游戲狀態(tài)。此外,還可用來獲取程序的幀頻FSP(Frame Per Second)大小,檢驗(yàn)3D渲染的速度,即游戲速度。

            Windows API函數(shù)timeGetTime用來取得游戲開始后的時(shí)間,返回的時(shí)間值單位為ms(毫秒)。

            The timeGetTime function retrieves the system time, in milliseconds. The system time is the time elapsed since Windows was started.

            DWORD timeGetTime(VOID);

            Parameters

            This function does not take parameters.

            Return Values

            Returns the system time, in milliseconds.

            但是這個(gè)函數(shù)的精度只有10ms左右,如果需要采用更為精確的時(shí)間,可使用小于1ms時(shí)間精度的Windows API函數(shù)QueryPerformanceCounter和QueryPerformanceFrequency,這兩個(gè)函數(shù)直接使用了Windows 內(nèi)核的精度非常高的定時(shí)器。不同的硬件和操作系統(tǒng),定時(shí)器的頻率稍有不同。

            The QueryPerformanceFrequency function retrieves the frequency of the high-resolution performance counter,
            if one exists. The frequency cannot change while the system is running.

            Syntax

            BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

            Parameters

            lpFrequency
            [out] Pointer to a variable that receives the current performance-counter frequency, in counts per second.
            If the installed hardware does not support a high-resolution performance counter, this parameter can be zero.

            Return Value

            If the installed hardware supports a high-resolution performance counter, the return value is nonzero.

            If the function fails, the return value is zero. To get extended error information, call GetLastError. For example,
            if the installed hardware does not support a high-resolution performance counter, the function fails. 

            The QueryPerformanceCounter function retrieves the current value of the high-resolution performance counter. 

            Syntax

            BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);

            Parameters

            lpPerformanceCount
            [out] Pointer to a variable that receives the current performance-counter value, in counts.

            Return Value

            If the function succeeds, the return value is nonzero.

            If the function fails, the return value is zero. To get extended error information, call GetLastError. 

            Remarks

            On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on
            different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL).
            To specify processor affinity for a thread, use the SetThreadAffinityMask function.

            這兩個(gè)函數(shù)都使用了結(jié)構(gòu)體LARGE_INTEGER,我們來看看它的結(jié)構(gòu):

            The LARGE_INTEGER structure is used to represent a 64-bit signed integer value.

            Note  Your C compiler may support 64-bit integers natively. For example, Microsoft® Visual C++® supports the __int64 sized integer type.
            For more information, see the documentation included with your C compiler.

            typedef union _LARGE_INTEGER
            {
                 struct {    DWORD LowPart;    LONG HighPart;  }; 
                 struct {    DWORD LowPart;    LONG HighPart;  } u;
                 LONGLONG QuadPart;
            } LARGE_INTEGER, *PLARGE_INTEGER;

            Members

            LowPart 
            Low-order 32 bits.

            HighPart 
            High-order 32 bits.


            LowPart 
            Low-order 32 bits. 
            HighPart 
            High-order 32 bits.

            QuadPart 
            Signed 64-bit integer.

            Remarks

            The LARGE_INTEGER structure is actually a union. If your compiler has built-in support for 64-bit integers,
            use the QuadPart member to store the 64-bit integer. Otherwise, use the LowPart and HighPart members to store the 64-bit integer.

            看的出來,它實(shí)際上是1個(gè)聯(lián)合體。

            提示:要正確編譯運(yùn)行,需要鏈接winmm.lib。
            由于本人水平有限,可能存在錯(cuò)誤,敬請(qǐng)指出。

            源碼下載

            好了,現(xiàn)在看看GE_COMMON.h的定義,主要用來包含公用的頭文件和宏定義:

            /*************************************************************************************
             [Include File]

             PURPOSE: 
                Include common header files and common macro.
            ************************************************************************************
            */

            #ifndef GAME_ENGINE_COMMON_H
            #define GAME_ENGINE_COMMON_H

            #define DIRECTINPUT_VERSION 0x0800  // let compile shut up

            #include 
            <windows.h>
            #include 
            <tchar.h>
            #include 
            <string.h>
            #include 
            <stdio.h>

            #include 
            <d3d9.h>
            #include 
            <d3dx9.h>
            #include 
            <dinput.h>
            #include 
            <dsound.h>

            // defines for small numbers
            #define EPSILON_E3  (float)(1E-3)
            #define EPSILON_E4  (float)(1E-4)
            #define EPSILON_E5  (float)(1E-5)
            #define EPSILON_E6  (float)(1E-6)

            #define Safe_Release(object) if((object) != NULL) { (object)->Release(); (object)=NULL; }

            #define FCMP(a, b) (fabs((a) - (b)) < EPSILON_E3 ? 1 : 0)

            #endif

            由于浮點(diǎn)數(shù)不能直接比較大小,所以定義了1個(gè)宏來比較浮點(diǎn)數(shù)的大小。

            #define FCMP(a, b) (fabs((a) -& nbsp;(b)) < EPSILON_E3 ? 1& nbsp;: 0)

            再來看看GE_TIMER.h的定義:

            /*************************************************************************************
             [Include File]

             PURPOSE: 
                Encapsulate system time for game.
            ************************************************************************************
            */

            #ifndef GAME_ENGINE_TIMER_H
            #define GAME_ENGINE_TIMER_H

            class GE_TIMER
            {
            private:
                
            bool _use_large_time;               // flag that indicate whether use large time

                __int64 _one_second_ticks;          
            // ticks count in one second
                __int64 _tick_counts_start;         // tick counts at start count time

                unsigned 
            long _time_start;          // start time for timeGetTime()

                
            int _frame_count;                   // frame count number
                float _fps;                         // frame per second
                float _time1, _time2, _time_slice;  // time flag and time slice

            public:
                GE_TIMER();
                
            ~GE_TIMER();
                
            void Init_Game_Time();
                
            float Get_Game_Play_Time();
                
            void Update_FPS();

                
            float Get_FPS() { return _fps; }
            };

            #endif

            并非所有系統(tǒng)都支持內(nèi)核的定時(shí)器讀取,因此要定義一個(gè)
            _use_large_time來標(biāo)志是否使用這個(gè)高精度的定時(shí)器,否則將使用timeGetTime函數(shù)進(jìn)行時(shí)間計(jì)算。

            我們來看看構(gòu)造函數(shù)和析構(gòu)函數(shù)的定義:

            //------------------------------------------------------------------------------------
            // Constructor, initialize game time.
            //------------------------------------------------------------------------------------
            GE_TIMER::GE_TIMER()
            {
                Init_Game_Time();
            }

            //------------------------------------------------------------------------------------
            // Destructor, do nothing.
            //------------------------------------------------------------------------------------
            GE_TIMER::~GE_TIMER()

            }

            看的出來,構(gòu)造函數(shù)只是調(diào)用了Init_Game_Time來初始化游戲時(shí)間,而析構(gòu)函數(shù)什么都不做。

            再來看看
            Init_Game_Time的定義:

            //------------------------------------------------------------------------------------
            // Initialize game time.
            //------------------------------------------------------------------------------------
            void GE_TIMER::Init_Game_Time()
            {
                _frame_count 
            = 0;
                _fps 
            = 0;
                _time1 
            = _time2 = _time_slice = 0;

                
            if(QueryPerformanceFrequency((LARGE_INTEGER*&_one_second_ticks))
                {
                    _use_large_time 
            = true;
                    QueryPerformanceCounter((LARGE_INTEGER
            *&_tick_counts_start);
                }
                
            else
                {
                    _use_large_time 
            = false;
                    _time_start 
            = timeGetTime();
                }
            }

            我們使用Get_Game_Play_Time來取得當(dāng)前的游戲時(shí)間,來看看它的定義:

            //------------------------------------------------------------------------------------
            // Get time has escaped since game start.
            //------------------------------------------------------------------------------------
            float GE_TIMER::Get_Game_Play_Time()
            {
                __int64 current_tick_counts;

                
            if(_use_large_time)
                {
                    QueryPerformanceCounter((LARGE_INTEGER
            *&current_tick_counts);
                    
            return ((float) (current_tick_counts - _tick_counts_start) / _one_second_ticks) * 1000
                }

                
            return (float)(timeGetTime() - _time_start);
            }

            分兩種情況進(jìn)行處理,如果使用高精度時(shí)鐘,將計(jì)算開始和結(jié)束時(shí)鐘計(jì)數(shù)之差,除以時(shí)鐘頻率,再乘以1000,即獲得時(shí)間片大小,單位為 ms。
            否則直接利用timeGetTime函數(shù)計(jì)算時(shí)間片大小。

            更新幀頻通過Update_FPS函數(shù)來進(jìn)行,每5幀更新一次。

            //------------------------------------------------------------------------------------
            // Update FPS.
            //------------------------------------------------------------------------------------
            void GE_TIMER::Update_FPS()
            {
                
            // increment frame count by one
                _frame_count++;

                
            if(_frame_count % 5 == 1)
                    _time1 
            = Get_Game_Play_Time() / 1000;
                
            else if(_frame_count % 5 == 0)
                {
                    _time2 
            = Get_Game_Play_Time() / 1000;
                    _time_slice 
            = (float) fabs(_time1 - _time2);    // calculate time escaped
                }

                
            // update fps
                if(! FCMP(_time_slice, 0.0))
                    _fps 
            = 5 / _time_slice;
            }

            完整的GE_TIMER.cpp實(shí)現(xiàn)如下所示:

            /*************************************************************************************
             [Implement File]

             PURPOSE: 
                Encapsulate system time for game.
            ************************************************************************************
            */

            #include 
            "GE_COMMON.h"
            #include 
            "GE_TIMER.h"

            //------------------------------------------------------------------------------------
            // Constructor, initialize game time.
            //------------------------------------------------------------------------------------
            GE_TIMER::GE_TIMER()
            {
                Init_Game_Time();
            }

            //------------------------------------------------------------------------------------
            // Destructor, do nothing.
            //------------------------------------------------------------------------------------
            GE_TIMER::~GE_TIMER()

            }

            //------------------------------------------------------------------------------------
            // Initialize game time.
            //------------------------------------------------------------------------------------
            void GE_TIMER::Init_Game_Time()
            {
                _frame_count 
            = 0;
                _fps 
            = 0;
                _time1 
            = _time2 = _time_slice = 0;

                
            if(QueryPerformanceFrequency((LARGE_INTEGER*&_one_second_ticks))
                {
                    _use_large_time 
            = true;
                    QueryPerformanceCounter((LARGE_INTEGER
            *&_tick_counts_start);
                }
                
            else
                {
                    _use_large_time 
            = false;
                    _time_start 
            = timeGetTime();
                }
            }

            //------------------------------------------------------------------------------------
            // Get time has escaped since game start.
            //------------------------------------------------------------------------------------
            float GE_TIMER::Get_Game_Play_Time()
            {
                __int64 current_tick_counts;

                
            if(_use_large_time)
                {
                    QueryPerformanceCounter((LARGE_INTEGER
            *&current_tick_counts);
                    
            return ((float) (current_tick_counts - _tick_counts_start) / _one_second_ticks) * 1000
                }

                
            return (float)(timeGetTime() - _time_start);
            }

            //------------------------------------------------------------------------------------
            // Update FPS.
            //------------------------------------------------------------------------------------
            void GE_TIMER::Update_FPS()
            {
                
            // increment frame count by one
                _frame_count++;

                
            if(_frame_count % 5 == 1)
                    _time1 
            = Get_Game_Play_Time() / 1000;
                
            else if(_frame_count % 5 == 0)
                {
                    _time2 
            = Get_Game_Play_Time() / 1000;
                    _time_slice 
            = (float) fabs(_time1 - _time2);    // calculate time escaped
                }

                
            // update fps
                if(! FCMP(_time_slice, 0.0))
                    _fps 
            = 5 / _time_slice;
            }

            posted on 2007-05-07 21:33 lovedday 閱讀(921) 評(píng)論(0)  編輯 收藏 引用 所屬分類: ■ DirectX 9 Program

            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(178)

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

            搜索

            最新評(píng)論

            97久久国产亚洲精品超碰热 | 四虎久久影院| 久久久久综合国产欧美一区二区| 亚洲伊人久久成综合人影院| 久久久久无码精品国产不卡| 亚洲国产高清精品线久久| 亚洲人成电影网站久久| 亚洲国产成人久久精品影视| 中文字幕日本人妻久久久免费| 久久99精品久久久久久噜噜| 精品国际久久久久999波多野| 久久免费视频1| 久久久一本精品99久久精品88| 99久久国产综合精品成人影院| 久久精品卫校国产小美女| 狠狠色丁香婷婷久久综合| 精品国产一区二区三区久久蜜臀| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 中文无码久久精品| 国产—久久香蕉国产线看观看| 久久97精品久久久久久久不卡| 日日躁夜夜躁狠狠久久AV| 久久无码AV一区二区三区| 久久久久夜夜夜精品国产| 青青草国产成人久久91网| 久久人人添人人爽添人人片牛牛| 日本久久久精品中文字幕| 亚洲国产另类久久久精品黑人 | 久久99精品久久久久久9蜜桃| 久久超碰97人人做人人爱| 久久这里有精品| 亚洲国产成人久久一区久久| 国产精久久一区二区三区| 久久综合久久综合九色| 国产精品久久久久久久久免费| 亚洲AV无码一区东京热久久 | 亚洲狠狠久久综合一区77777 | 久久天天躁夜夜躁狠狠躁2022| 久久久久99精品成人片牛牛影视| 久久精品女人天堂AV麻| 香蕉久久夜色精品国产小说|