📄 chapter8.txt
字号:
第八章 例程之初始化部分
第一节DDInit():
DDInit()的作用是枚举驱动程序,它的具体运行过程如下:
首先调用DirectDrawEnumerate(),这个函数的作用在第五章 DirectDraw深入篇第三节选择DirectDraw驱动程序中已经谈到了。在本例程中这个函数的参数是&DDEnumCallback和NULL,&DDEnumCallback是指回调函数DDEnumCallback()的地址,NULL是指没有这个指向应用程序数据的指针。
回调函数DDEnumCallback()的作用是将枚举过的的驱动程序的GUDI、描述和名字存入一个结构数组aDDDevs[]中。待以后选择。
第二节定义命令行参数
1.根据命令行参数确定运行方式
首先,使用while( lpCmdLine[0] == '-' || lpCmdLine[0] == '/')检测命令行参数的标识符,然后再使用switch (*lpCmdLine++)对部分参数的含义进行定义:
-e Use emulator(使用软件模拟)
-S No Sound(无声)
-1 No backbuffer(不使用后备缓冲区)
-2 One backbuffer(一个后备缓冲区)
-4 Three backbuffers(三个后备缓冲区)
-s Use stretch(使用拉伸算法,即是在窗口模式下改变窗口的形状时对图形使用拉伸算法使图象比较匀称。)
-x Demo or stress mode(使用重音模式)
2.根据命令行参数确定显示模式
对显示模式的横轴方向的像素数GameMode.cx、纵轴方向的像素数GameMode.cy及颜色数GameMode.BPP调用getint(char**p, int def)取得命令行参数对这些项目的设定。
getint(char**p, int def)函数的运行过程为:
先检测命令行参数第一个字符是否是“”、“\r”、“\t”、“\n”或“x”。如果是就使指针p自加1并继续检测,否则检测该字符是否是小于9大于0的数。如果该字符不是小于9大于0的数则返回默认值,反之则通过
while (IS_NUM(**p)
i = i*10 + *(*p)++ - '0'
将输入的字符的ASCII值转变为数值。然后通过
while (IS_SPACE(**p))
(*p)++;
检测后面的字符是否是“”、“\r”、“\t”、“\n”或“x”,如果是就使指针p自加1并继续检测,直到出现其他字符或字符串结束。
第三节初始化Windows
程序在这一部分调用了initApplication( HINSTANCE hInstance, int nCmdShow )函数来初始化Windows。
initApplication( HINSTANCE hInstance, int nCmdShow )首先定义窗口类为:
style:指明了类风格为向窗口发送一个鼠标双击的消息。
1pfnWndProc:指明了指向窗口函数的指针,该指针指向MainWndProc。
cbClsExtra:指定在窗口类结构后面分配的字节数为0。
cbWndExtra:指定在窗口实例后面分配的字节数为0。
hInstance:注册窗口类的应用程序实例句柄是hInstance。
hIconhIcon:划定利用窗口最小化时显示的图标通过调用LoadIcon( hInstance, MAKEINTATOM(FOX_ICON))获得。
hCursorhCursor:定义应用程序使用的光标通过调用LoadCursor( NULL, IDC_ARROW )获得。
hbrBackground:背景刷子的标识符通过调用GetStockObject(BLACK_BRUSH)获得。
1pszMenuName:菜单的资源名的指针为NULL。
1pszClassName:窗口类的名字为WinFoxClass。
然后用
if( !rc )
{
return FALSE;
}
注册这个窗口类,并在注册失败时结束程序。
接着用hWndMain = CreateWindowEx(……)创建窗口并将窗口的句柄赋给hWndMain 。该窗口被创建为:
窗口的扩展格式为 WS_EX_APPWINDOW
窗口类为 "WinFoxClass"
窗口名为 OUR_APP_NAME
窗口格式为 WS_VISIBLE |WS_SYSMENU |WS_POPUP(创建一个初始态可见的标题条上有系统菜单的重叠窗口或弹出式窗口
窗口左上角的X坐标 0
窗口左上角的Y坐标 0
窗口宽度 GetSystemMetrics(SM_CXSCREEN)(屏幕宽度)
窗口高度 GetSystemMetrics(SM_CYSCREEN)(屏幕高度)
父窗口的句柄 NULL,
窗口菜单的句柄 NULL,
窗口类的应用程序的实例句柄是 hInstance
32位附加信息为 NULL
然后,用
if( !hWndMain )
{
return FALSE;
}
检测窗口创建是否成功,并在创建失败时结束程序。
最后调用UpdateWindow( hWndMain )和SetFocus( hWndMain )显示窗口和将键盘输入限定在hWndMain所指的窗口(即游戏窗口)中。
第四节帮助信息的显示
在这里调用了MessageBoxA(HWND hWnd ,LPCSTR lpText,LPCSTR lpCaption,UINT uType)函数。它的调用方式如下:
if( bHelp )
{
MessageBox(hWndMain,
"F12 - Quit\n"
"NUMPAD 2 - crouch\n"
"NUMPAD 3 - apple\n"
"NUMPAD 4 - right\n"
"NUMPAD 5 - stop\n"
"NUMPAD 6 - left\n"
"NUMPAD 7 - jump\n"
"\n"
"Command line parameters\n"
"\n"
"-e Use emulator\n"
"-S No Sound\n"
"-1 No backbuffer\n"
"-2 One backbuffer\n"
"-4 Three backbuffers\n"
"-s Use stretch\n"
"-x Demo or stress mode\n",
OUR_APP_NAME, MB_OK );
}
它的含义是:如果bHelp为TURE,则在hWndMain所指向的窗口创建一个消息框。这个消息框的内容是“”所包含的部分,标题是OUR_APP_NAME(在foxbear.c中有#define OUR_APP_NAME "Win Fox Application"语句),并且这个消息框显示一个OK按钮。
第五节初始化游戏
这个部分只是调用了InitGame( void )函数,它的调用方式为:
if( !InitGame() )
{
return FALSE;
}
即如果调用失败,则结束程序。
InitGame( void )是整个初始化部分最庞大的部分,它完成了剩下的初始化的工作。在本章的后面几节中我们将分几部分讲解这个函数
第六节内存刷新
由于在窗口过程中会接受被定义为改变显示模式的消息这时需要对游戏进行重新初始化,于是就会对InitGame()函数进行调用(比如在消息VK_F8时就调用了该函数)。这时的调用会是在游戏运行时发生的,这时在游戏运行中较重要的指针都已被使用(指向了一定的内存区域),同时内存已被分配。如果这时不释放内存和将指针指向NULL(即不指向任何一个内存区域),以后的初始化将会出现错误 。故在该函数的运行过程中调用了ExitGame()函数已进行刷新指针的工作。
ExitGame()的运行过程为:
首先,检测lpFrameRate、lpInfo、lpPalette三个指针,若非0,则释放其所指的内存,并令该指针为NULL使其恢复为初始状态(通过利用IUuknown接口提供的函数Release()递减指针的内部引用值,直至引用值为0释放所分配的内存)。
然后,调用函数DestroyGame()继续释放内存。DestroyGame()的运行过程为:首先,检测hBuffer是否为非0,如果非0则调用下列函数:
DestroyTiles( hTileList )——释放句柄hTileList所指的局部内存块。
DestroyPlane( hForeground )——释放句柄hForeground和hForeground->hBM所指向的内存块。
DestroyPlane( hMidground )——释放句柄hMidground和hMidground->hBM所指向的内存块。
DestroyPlane( hBackground )——释放句柄hBackground和hBackground->hBM所指向的内存块。
DestroyBuffer( hBuffer )——释放所有位图所占用的内存及lpClipper、 lpBackBuffer、 lpFrontBuffer所指向过的内存区域。
DestroySound()——释放所有音效所占用的内存及lpDS所指向过的内存区域。
最后令hTileList、 hForeground、hMidground、hBackground和hBuffer指向空。
第七节初始化声音
这个部分主要调用函数IinitSound()进行对DirectSound进行初始化和声音的播放的工作。它的工作过程为:
调用DSEnable(hwndOwner)进行DirectSound的初始化:先用bUseDSound = GetProfileInt("FoxBear", "use_dsound", bWantSound)选择播放设备;再通过
if (!bUseDSound)
{
lpDS = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -