您的位置:首页 > 其它

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

2016-11-14 14:45 330 查看

<考古笔记>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

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类中,以良好的函数命名以及注释来划分。



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。

[b]Texture[/b]

struct CTextureList
{
HTEXTURE            tex;
int                 width;
int                 height;
CTextureList*       next;
};


[b]Target[/b]

struct CRenderTargetList
{
int                 width;
int                 height;
IDirect3DTexture8*  pTex;
IDirect3DSurface8*  pDepth;
CRenderTargetList*  next;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: