这里的3个文件input,power,random,都比较小,一起说。
分别是输入,电源,随机数。
上来是一个数组,存的是char*,也就是所有输入的名字
char *KeyNames[] =
{
"?",
"Left Mouse Button", "Right Mouse Button", "?", "Middle Mouse Button",
"?", "?", "?", "Backspace", "Tab", "?", "?", "?", "Enter", "?", "?",
"Shift", "Ctrl", "Alt", "Pause", "Caps Lock", "?", "?", "?", "?", "?", "?",
"Escape", "?", "?", "?", "?",
"Space", "Page Up", "Page Down", "End", "Home",
"Left Arrow", "Up Arrow", "Right Arrow", "Down Arrow",
"?", "?", "?", "?", "Insert", "Delete", "?",
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"?", "?", "?", "?", "?", "?", "?",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
"Left Win", "Right Win", "Application", "?", "?",
"NumPad 0", "NumPad 1", "NumPad 2", "NumPad 3", "NumPad 4",
"NumPad 5", "NumPad 6", "NumPad 7", "NumPad 8", "NumPad 9",
"Multiply", "Add", "?", "Subtract", "Decimal", "Divide",
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"Num Lock", "Scroll Lock",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"Semicolon", "Equals", "Comma", "Minus", "Period", "Slash", "Grave",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"?", "?", "?", "?", "?", "?",
"Left bracket", "Backslash", "Right bracket", "Apostrophe",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
"?", "?", "?"
};
----------------------------------------------------------------------------------------------------------------------------------------
bool CALL HGE_Impl::Input_GetEvent(hgeInputEvent *event)
{
CInputEventList *eptr;
if(queue)
{
eptr=queue;
memcpy(event, &eptr->event, sizeof(hgeInputEvent));
queue=eptr->next;
delete eptr;
return true;
}
return false;
}
第一个函数,接受一个叫做hgeInputEvent的东西
这个结构体是这样的:
/*
** HGE Input Event structure
*/
struct hgeInputEvent
{
int type; // event type
int key; // key code
int flags; // event flags
int chr; // character code
int wheel; // wheel shift
float x; // mouse cursor x-coordinate
float y; // mouse cursor y-coordinate
};
里面记录了事件类型,键值,坐标等等。
这里的GetEvent是把事件从事件列表里提取出来,然后把拿出来的在队列里删除。
void CALL HGE_Impl::Input_GetMousePos(float *x, float *y)
{
*x=Xpos; *y=Ypos;
}
void CALL HGE_Impl::Input_SetMousePos(float x, float y)
{
POINT pt;
pt.x=(long)x; pt.y=(long)y;
ClientToScreen(hwnd, &pt);
SetCursorPos(pt.x,pt.y);
}
获取鼠标指针位置和设定鼠标指针位置。
int CALL HGE_Impl::Input_GetMouseWheel()
{
return Zpos;
}
bool CALL HGE_Impl::Input_IsMouseOver()
{
return bMouseOver;
}
bool CALL HGE_Impl::Input_GetKeyState(int key)
{
return ((GetKeyState(key) & 0x8000) != 0);
}
bool CALL HGE_Impl::Input_KeyDown(int key)
{
return (keyz[key] & 1) != 0;
}
bool CALL HGE_Impl::Input_KeyUp(int key)
{
return (keyz[key] & 2) != 0;
}
char* CALL HGE_Impl::Input_GetKeyName(int key)
{
return KeyNames[key];
}
int CALL HGE_Impl::Input_GetKey()
{
return VKey;
}
int CALL HGE_Impl::Input_GetChar()
{
return Char;
}
后面这些都是返回各种各样的状态,基本都是直接返回全局的值,知道每个值的具体意义就可以。
所有的参数key都是键的编号,Vkey是值,Char是表示字符
后面的实现部分更重要一些。
void HGE_Impl::_InputInit()
{
POINT pt;
GetCursorPos(&pt);
ScreenToClient(hwnd, &pt);
Xpos = (float)pt.x;
Ypos = (float)pt.y;
memset(&keyz, 0, sizeof(keyz));
}
初始化,现实初始化鼠标位置(当前指针位置),然后是按键状态(0为默认状态 1为按下,2为弹起)
void HGE_Impl::_UpdateMouse()
{
POINT pt;
RECT rc;
GetCursorPos(&pt);
GetClientRect(hwnd, &rc);
MapWindowPoints(hwnd, NULL, (LPPOINT)&rc, 2);
if(bCaptured || (PtInRect(&rc, pt) && WindowFromPoint(pt)==hwnd))
bMouseOver=true;
else
bMouseOver=false;
}
更新鼠标状态(位置),并且判断鼠标现在是否还在游戏程序的窗口中
void HGE_Impl::_BuildEvent(int type, int key, int scan, int flags, int x, int y)
{
CInputEventList *last, *eptr=new CInputEventList;
unsigned char kbstate[256];
POINT pt;
eptr->event.type=type;
eptr->event.chr=0;
pt.x=x; pt.y=y;
GetKeyboardState(kbstate);//获取键盘状态
if(type==INPUT_KEYDOWN)
{
if((flags & HGEINP_REPEAT) == 0) keyz[key] |= 1;
ToAscii(key, scan, kbstate, (unsigned short *)&eptr->event.chr, 0);//把虚拟键码和键盘状态翻译成字符或字符串,由事件节点eptr的成员event接受翻译结果
}
if(type==INPUT_KEYUP)
{
keyz[key] |= 2;
ToAscii(key, scan, kbstate, (unsigned short *)&eptr->event.chr, 0);
}
if(type==INPUT_MOUSEWHEEL)
{
eptr->event.key=0; eptr->event.wheel=key;
ScreenToClient(hwnd,&pt);//屏幕坐标转用户坐标
}
else { eptr->event.key=key; eptr->event.wheel=0; }
if(type==INPUT_MBUTTONDOWN)
{
keyz[key] |= 1;
SetCapture(hwnd);//给窗口设置鼠标捕获,无论鼠标在哪,都由这个窗口响应
bCaptured=true;
}
if(type==INPUT_MBUTTONUP)
{
keyz[key] |= 2;
ReleaseCapture();//取消鼠标捕获
Input_SetMousePos(Xpos, Ypos);
pt.x=(int)Xpos; pt.y=(int)Ypos;
bCaptured=false;
}
//复合按的时候
if(kbstate[VK_SHIFT] & 0x80) flags|=HGEINP_SHIFT;
if(kbstate[VK_CONTROL] & 0x80) flags|=HGEINP_CTRL;
if(kbstate[VK_MENU] & 0x80) flags|=HGEINP_ALT;
if(kbstate[VK_CAPITAL] & 0x1) flags|=HGEINP_CAPSLOCK;
if(kbstate[VK_SCROLL] & 0x1) flags|=HGEINP_SCROLLLOCK;
if(kbstate[VK_NUMLOCK] & 0x1) flags|=HGEINP_NUMLOCK;
eptr->event.flags=flags;
if(pt.x==-1) { eptr->event.x=Xpos;eptr->event.y=Ypos; }
else
{
if(pt.x<0) pt.x=0;
if(pt.y<0) pt.y=0;
if(pt.x>=nScreenWidth) pt.x=nScreenWidth-1;
if(pt.y>=nScreenHeight) pt.y=nScreenHeight-1;
eptr->event.x=(float)pt.x;
eptr->event.y=(float)pt.y;
}
eptr->next=0;
//加入队列
if(!queue) queue=eptr;
else
{
last=queue;
while(last->next) last=last->next;
last->next=eptr;
}
//设定键值(键盘事件),位置(鼠标事件),滚轮位置(滚轮)
if(eptr->event.type==INPUT_KEYDOWN || eptr->event.type==INPUT_MBUTTONDOWN)
{
VKey=eptr->event.key;Char=eptr->event.chr;
}
else if(eptr->event.type==INPUT_MOUSEMOVE)
{
Xpos=eptr->event.x;Ypos=eptr->event.y;
}
else if(eptr->event.type==INPUT_MOUSEWHEEL)
{
Zpos+=eptr->event.wheel;
}
}
通过类型,值,坐标等建立一个事件,加入输入事件队列
这里有一点点可以优化的地方 ,就是中间那个判断类型type,这里用的if else,在3个条件以上时使用switch case会好一点
它的效率是不低于ifelse的,不过编译器优化的很好,两者效率实际上差不了多少,测试的时候跑了10w组没发现特别大的差别
总之写的时候可以考虑情况较多用switchcase。
void HGE_Impl::_ClearQueue()
{
CInputEventList *nexteptr, *eptr=queue;
memset(&keyz, 0, sizeof(keyz));
while(eptr)
{
nexteptr=eptr->next;
delete eptr;
eptr=nexteptr;
}
queue=0; VKey=0; Char=0; Zpos=0;
}
清空队列~
--------------------------------------------------------------------------------------------分割
下面是电源状态
/*
** Haaf's Game Engine 1.8
** Copyright (C) 2003-2007, Relish Games
** hge.relishgames.com
**
** Core functions implementation: power status
*/
#include "hge_impl.h"
void HGE_Impl::_InitPowerStatus()
{
hKrnl32 = LoadLibrary("kernel32.dll");
if(hKrnl32 != NULL)
lpfnGetSystemPowerStatus = (GetSystemPowerStatusFunc)GetProcAddress(hKrnl32, "GetSystemPowerStatus");
_UpdatePowerStatus();
}
void HGE_Impl::_UpdatePowerStatus()
{
SYSTEM_POWER_STATUS ps;
if(lpfnGetSystemPowerStatus != NULL && lpfnGetSystemPowerStatus(&ps))
{
if(ps.ACLineStatus == 1)
{
nPowerStatus = HGEPWR_AC;
}
else if(ps.BatteryFlag < 128)
{
nPowerStatus = ps.BatteryLifePercent;
}
else
{
nPowerStatus = HGEPWR_UNSUPPORTED;
}
}
else
{
nPowerStatus = HGEPWR_UNSUPPORTED;
}
}
void HGE_Impl::_DonePowerStatus()
{
if(hKrnl32 != NULL) FreeLibrary(hKrnl32);
}
调用动态库获取系统电源信息,然后判断电源是否正常,HGE对电源定义只有两种,连通和无
--------------------------------------------再分割下
random
/*
** Haaf's Game Engine 1.8
** Copyright (C) 2003-2007, Relish Games
** hge.relishgames.com
**
** Core functions implementation: random number generation
*/
#include "hge_impl.h"
unsigned int g_seed=0;
void CALL HGE_Impl::Random_Seed(int seed)
{
if(!seed) g_seed=timeGetTime();
else g_seed=seed;
}
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 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);
}
就3个函数,一个设置时间种子,另外两个一个生成整数,一个生成浮点数