天天看點

<考古筆記>Hge遊戲引擎(二)Core<考古筆記>Hge遊戲引擎(二)Core

<考古筆記>Hge遊戲引擎(二)Core

&lt;考古筆記&gt;Hge遊戲引擎(二)Core&lt;考古筆記&gt;Hge遊戲引擎(二)Core

HgeCoreFunctions(Core Layer)

1.Hge.h的概要:

/*
概要(個人修改的内容已移除、修改字樣标記)
*/
版本号:HGE_VERSION

為BorlandC編譯提供數學函數支援(不需要,已移除)

基本資料類型:DWORD、WORD、BYTE

句柄類型:HTEXTURE、HTARGET、HEFFECT、HMUSIC、HSTREAM、HCHANNEL

導出dll的設定:EXPORT、CALL

數學常量:M_PI

位色處理宏:ARGB、Set/GetA(R、G、B)

融合方式選項:Color/Alpha/ZWrite

Int設定:螢幕寬高、位深(bpp)、音效相關設定(采樣頻率、fx、music volume)、Fps

String設定:标題名、圖示名、ini/log檔案名

Bool設定:視窗/全屏,開啟/關閉ZBuffer,開啟/關閉TextureFilter、開啟/關閉Sound、是否Suspend(挂起)、顯示/隐藏滑鼠、開啟/關閉Splash(初始的Hge Logo動畫)

Func設定:FrameFunc、RenderFunc、FocusLost/GainFunc、GFXRestoreFunc、ExitFunc

Hwnd狀态:HWND(普通)、HWNDPARENT(父視窗)

電源狀态控制(源碼空定義,已移除)

Fps狀态:是否開啟垂直同步(可移動至Bool設定)

頂點格式:空間坐标(x,y)、depth()、color、紋理坐标(tx, ty)

圖元類型:線段、三角形、四邊形(頂點數組、紋理貼圖句柄、blend方式)

Input事件:事件類型(KeyDown/Up, MButtonDown/Up, MouseMove/Wheel)、Key碼,Flags(Shift, Ctrl, Alt, Capslock, ScrollLock, NumLock, Repeat),鍵盤按鍵(ascii碼)/滑鼠滾輪/滑鼠位置(x, y)

外部接口--純虛類Hge

hgeCreate全局C接口聲明

虛拟鍵值(Virtual Key Cod
           

2.Hge啟動流程

通過全局的C函數hgeCreate(C++因為提供函數重載,生成的接口函數名會帶有@數字/字元(詳見名稱重整技術,hge.def檔案也是用于解決這個問題的))擷取Hge接口,__stdcall作用為讓函數調用方負責清棧,在使用完Hge接口後調用Release來釋放Hge接口(使用了引用計數技術,Release開銷很小)。

hgeCreate實際工作是new一個Hge_Impl類(public繼承于Hge類),并向上轉型為Hge*傳回。

獲得Hge接口後自行設定一系列Bool、Int、Func、String狀态/開關,然後再使用System_Initiate初始化,初始化過程中Hge會擷取系統目前時間、Hge版本、作業系統版本、實體/虛拟記憶體情況,寫入到log檔案中,再注冊視窗類、建立視窗、初始化Timer、Random、Input、Graphics(GFX)、Sound這些子系統,最後根據是否定義DEMO宏來播放Splash動畫。

Hge_Impl下除了System之外,有Resource、Ini、Random、Timer、Sound(Effect, Music, Stream, Channel)、Input、Graphics(GFX)子系統。值得一提的是,子系統的所有成員變量以及方法全部都放在Hge_Impl類中,以良好的函數命名以及注釋來劃分。

&lt;考古筆記&gt;Hge遊戲引擎(二)Core&lt;考古筆記&gt;Hge遊戲引擎(二)Core

System_Initiate結束之後使用System_Start來執行消息循環。

在收到結束消息,退出循環後使用System_Shutdown關閉各個子系統,最後再使用Release釋放Hge接口。

3.子系統簡介

Random

值得一提的是随機數種子定義的是全局變量,這一點我覺得不如封裝成Singleton類,種子為靜态變量。

/*
Random概要
*/

unsigned int g_seed=;

// 随機數種子的擷取
// 初始化時Random_Seed(0);
void CALL HGE_Impl::Random_Seed(int seed)
{
    if(!seed) g_seed=timeGetTime();
    else g_seed=seed;
}

// 擷取随機的int數
int CALL HGE_Impl::Random_Int(int min, int max)
{
    g_seed=*g_seed+;
    return min+(g_seed ^ g_seed>>)%(max-min+);
}

// 擷取随機的float數
float CALL HGE_Impl::Random_Float(float min, float max)
{
    g_seed=*g_seed+;
    //return min+g_seed*(1.0f/4294967295.0f)*(max-min);
    return min+(g_seed>>)*(f/f)*(max-min);
}
           

Demo

實作方式是将FrameFunc先設定為Demo.cpp中定義的DFrame(RenderFunc設為0,因為DFrame将Render的工作也寫在了一起),貼一張Hge Logo圖(資料在Demo.cpp的hgelogo數組中)到螢幕中心并根據時間修改其alpha值。

/*
splash screen animation
*/  
    dtime+=pHGE->Timer_GetDelta();

    if(dtime<.)
        alpha=(BYTE)((dtime*4)*0xFF);
    else if(dtime<)
        alpha=;
    else if(dtime<)
        alpha=(BYTE)((f-(dtime-f)*4)*0xFF);
           

Timer

//  計時器精度由初始化時timeBeginPeriod(1)設定為1ms
    //  其他數值初始化如下
    //  fTime=0.0f;
    //  t0=t0fps=timeGetTime();
    //  dt=cfps=0;
    //  nFPS=0;
    float               fTime; // 目前時間,可由Timer_GetTime擷取
    float               fDeltaTime; // 幀之間的時間間隔,可由Timer_GetDelta擷取
    DWORD               nFixedDelta;
    int                 nFPS;  // Fps值,可由Timer_GetFPS擷取
    DWORD               t0, t0fps, dt;
    int                 cfps;
           

Log、Ini

log檔案寫入是通過va_list可變長參數和vfprintf實作的:

void CALL HGE_Impl::System_Log(const char *szFormat, ...)
{
    FILE *hf = NULL;
    va_list ap;

    if(!szLogFile[]) return;

    hf = fopen(szLogFile, "a");
    if(!hf) return;

    va_start(ap, szFormat);
    vfprintf(hf, szFormat, ap);
    va_end(ap);

    fprintf(hf, "\n");

    fclose(hf);
}
           

Ini檔案用于儲存本次程式運作的設定參數,使得在下一次程式執行時可直接讀取這些參數。

Ini.cpp提供了對int、float、string三種類型參數的寫入/讀取支援,利用的是Get/WritePrivateProfileString函數。

實際上我覺得可以用lua這樣的腳本語言來做配置參數表,自己封裝Lua與C/C++互動的工具類,開源的庫也有LuaBind。

Sound

// 音頻的資料流使用單連結清單
struct CStreamList
{
    HSTREAM             hstream;
    void*               data;
    CStreamList*        next;
};
           

Sound系統封裝了Bass庫,支援了采樣頻率、多聲道等進階效果。

Resource

struct CResourceList
{
    char                filename[_MAX_PATH];
    char                password[64];
    CResourceList*      next;
};
           

Resource系統封裝了Zlib庫,支援解壓打包好的加密/不加密資源包,使用簡單的單連結清單一一讀取需要的資源。

Input

struct CInputEventList
{
    hgeInputEvent       event;
    CInputEventList*    next;
};
           

滑鼠/鍵盤輸入的事件由單連結清單實作的隊列管理。

Graphics

Gfx封裝了DirectX8的API。

Texture
struct CTextureList
{
    HTEXTURE            tex;
    int                 width;
    int                 height;
    CTextureList*       next;
};
           
Target
struct CRenderTargetList
{
    int                 width;
    int                 height;
    IDirect3DTexture8*  pTex;
    IDirect3DSurface8*  pDepth;
    CRenderTargetList*  next;
};
           

繼續閱讀