Hge游戏引擎(二)Core

<考古笔记>Hge游戏引擎(二)Core

Hge游戏引擎(二)Core_第1张图片


HgeCoreFunctions(Core Layer)


1.Hge.h的概要:

/*
概要(个人修改的内容已移除、修改字样标记)
*/
版本号:HGE_VERSION

为BorlandC编译提供数学函数支持(不需要,已移除)

基本数据类型:DWORD、WORD、BYTE

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

导出dll的设置:EXPORT、CALL

数学常量:M_PI

32位色处理宏: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(0..1)、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类中,以良好的函数命名以及注释来划分。
Hge游戏引擎(二)Core_第2张图片

System_Initiate结束之后使用System_Start来执行消息循环。

在收到结束消息,退出循环后使用System_Shutdown关闭各个子系统,最后再使用Release释放Hge接口。


3.子系统简介

Random

值得一提的是随机数种子定义的是全局变量,这一点我觉得不如封装成Singleton类,种子为静态变量。

/*
Random概要
*/

unsigned int g_seed=0;

// 随机数种子的获取
// 初始化时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=214013*g_seed+2531011;
    return min+(g_seed ^ g_seed>>15)%(max-min+1);
}

// 获取随机的float数
float CALL HGE_Impl::Random_Float(float min, float max)
{
    g_seed=214013*g_seed+2531011;
    //return min+g_seed*(1.0f/4294967295.0f)*(max-min);
    return min+(g_seed>>16)*(1.0f/65535.0f)*(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<0.25)
        alpha=(BYTE)((dtime*4)*0xFF);
    else if(dtime<1.0)
        alpha=0xFF;
    else if(dtime<1.25)
        alpha=(BYTE)((1.0f-(dtime-1.0f)*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[0]) 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;
};


你可能感兴趣的:(Normal)