📄 chapter7.txt
字号:
break;
case VK_NUMPAD3:
lastInput=KEY_THROW;
break;
case VK_F5:
bShowFrameCount = !bShowFrameCount;
if( bShowFrameCount )
{
dwFrameCount = 0;
dwFrameTime = timeGetTime();
}
break;
case VK_F6:
{
static i;
//
// find our current mode in the mode list
//
if(bFullscreen)
{
for (i=0; i<NumModes; i++)
{
if (ModeList[i].bpp == (int)GameBPP &&
ModeList[i].w == GameSize.cx &&
ModeList[i].h == GameSize.cy)
{
break;
}
}
}else
{
for (i=0; i<NumModes; i++)
{
if (ModeList[i].w == GameSize.cx &&
ModeList[i].h == GameSize.cy)
{
break;
}
}
}
//
// now step to the next mode, wrapping to the first one.
//
if (++i >= NumModes)
{
i = 0;
}
Msg("ModeList %d %d",i,NumModes);
GameMode.cx = ModeList[i].w;
GameMode.cy = ModeList[i].h;
GameBPP = ModeList[i].bpp;
bStretch = FALSE;
InitGame();
}
break;
case VK_F7:
GameBPP = GameBPP == 8 ? 16 : 8;
InitGame();
break;
case VK_F8:
if (bFullscreen)
{
bStretch = !bStretch;
InitGame();
}
else
{
RECT rc;
GetClientRect(hWnd, &rc);
bStretch = (rc.right != GameSize.cx) ||
(rc.bottom != GameSize.cy);
if (bStretch = !bStretch)
SetRect(&rc, 0, 0, GameMode.cx*2, GameMode.cy*2);
else
SetRect(&rc, 0, 0, GameMode.cx, GameMode.cy);
AdjustWindowRectEx(&rc,
GetWindowStyle(hWnd),
GetMenu(hWnd) != NULL,
GetWindowExStyle(hWnd));
SetWindowPos(hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
}
break;
case VK_F9: DevIndex ++;
bUseEmulation = FALSE;
if (DevIndex >= MaxDevIndex)
DevIndex = 0;
ExitGame();
DDDisable(TRUE); // destroy DirectDraw object
InitGame();
break;
case VK_F4:
// treat F4 like ALT+ENTER (fullscreen)
PostMessage(hWnd, WM_SYSKEYUP, VK_RETURN, 0);
break;
case VK_F3:
bPaused = !bPaused;
break;
case VK_ESCAPE:
case VK_F12:
PostMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
}
break;
case WM_PAINT:
hdc = BeginPaint( hWnd, &ps );
if (bPaused)
{
char *sz = "Game is paused, this is not a bug.";
TextOut(ps.hdc, 0, 0, sz, lstrlen(sz));
}
EndPaint( hWnd, &ps );
return 1;
case WM_DESTROY:
hWndMain = NULL;
lastInput=0;
DestroyGame(); // end of game
DDDisable(TRUE); // destroy DirectDraw object
PostQuitMessage( 0 );
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
} /* MainWndProc */
第三节 游戏初始化
游戏初始化包括三部分:
1.Windows的初始化。
2.游戏工具的初始化。
3.游戏的初始化。
在这三部分中Windows的初始化,也就是对窗口的注册、定义和初始化。我们在Win- dows编程基础中已经谈过,这里就不再详述了。
游戏工具的初始化,是指对游戏程序中用到的工具进行初始化。对于一个游戏而言我们需要针对游戏的需要使用一些对图形或声音管理绘制或播放的以及其他功能的系统,这些系统就是我们所说的游戏工具(有时人们也称之为游戏引擎)。这些工具有时是由一些游戏公司提供的,比如MICROSOFT的DirectX5 SDK,有时是自己针对游戏需要编制的或使用上一部作品中用过的系统。在本例程中是指对Directdraw和DirectSound进行初始化,您可以通过阅读DDinit()和 InitSound()以及InitGame()函数的一部分的原代码以及阅读我们提供有关Directdraw和DirectSound的章节来理解。
DDinit()和 InitSound()以及InitGame()函数的代码:
/*
* InitGame
*
* Initializing current game
*/
BOOL InitGame( void )
{
ExitGame();
GameSize = GameMode;
/*
* initialize sound
*/
InitSound( hWndMain );
/*
* init DirectDraw, set mode, ...
* NOTE GameMode might be set to 640x480 if we cant get the asked for mode.
*/
if( !PreInitializeGame() )
{
return FALSE;
}
if (bStretch && bFullscreen)
{
GameSize.cx = GameMode.cx / 2;
GameSize.cy = GameMode.cy / 2;
GameRect.left = GameMode.cx - GameSize.cx;
GameRect.top = GameMode.cy - GameSize.cy;
GameRect.right = GameMode.cx;
GameRect.bottom = GameMode.cy;
if (lpStretchBuffer)
Msg("Stretching using a system-memory stretch buffer");
else
Msg("Stretching using a VRAM->VRAM blt");
}
else
{
GameRect.left = (GameMode.cx - GameSize.cx) / 2;
GameRect.top = (GameMode.cy - GameSize.cy) / 2;
GameRect.right = GameRect.left + GameSize.cx;
GameRect.bottom = GameRect.top + GameSize.cy;
}
/*
* setup our palette
*/
if( GameBPP == 8 )
{
lpPalette = ReadPalFile( NULL ); // create a 332 palette
if( lpPalette == NULL )
{
Msg( "Palette create failed" );
return FALSE;
}
IDirectDrawSurface_SetPalette( lpFrontBuffer, lpPalette );
}
/*
* load all the art and things.
*/
if( !InitializeGame() )
{
return FALSE;
}
/*
* init our code to draw the FPS
*/
makeFontStuff();
/*
* spew some stats
*/
{
DDCAPS ddcaps;
ddcaps.dwSize = sizeof( ddcaps );
IDirectDraw_GetCaps( lpDD, &ddcaps, NULL );
Msg( "Total=%ld, Free VRAM=%ld", ddcaps.dwVidMemTotal, ddcaps.dwVidMemFree );
Msg( "Used = %ld", ddcaps.dwVidMemTotal- ddcaps.dwVidMemFree ); }
return TRUE;
} /* InitGame */
/*
* InitSound
*
* Sets up the DirectSound object and loads all sounds into secondary
* DirectSound buffers. Returns FALSE on error, or TRUE if successful
*/
BOOL InitSound( HWND hwndOwner )
{
int idx;
DSBUFFERDESC dsBD;
IDirectSoundBuffer *lpPrimary;
DSEnable(hwndOwner);
if (lpDS == NULL)
return TRUE;
/*
* Load all sounds -- any that can't load for some reason will have NULL
* pointers instead of valid SOUNDEFFECT data, and we will know not to
* play them later on.
*/
for( idx = 0; idx < NUM_SOUND_EFFECTS; idx++ )
{
if (SoundLoadEffect((EFFECT)idx))
{
DSBCAPS caps;
caps.dwSize = sizeof(caps);
IDirectSoundBuffer_GetCaps(lpSoundEffects[idx], &caps);
if (caps.dwFlags & DSBCAPS_LOCHARDWARE)
Msg( "Sound effect %s in hardware", szSoundEffects[idx]);
else
Msg( "Sound effect %s in software", szSoundEffects[idx]);
}
else
{
Msg( "cant load sound effect %s", szSoundEffects[idx]);
}
}
/*
* get the primary buffer and start it playing
*
* by playing the primary buffer, DirectSound knows to keep the
* mixer active, even though we are not making any noise.
*/
ZeroMemory( &dsBD, sizeof(DSBUFFERDESC) );
dsBD.dwSize = sizeof(dsBD);
dsBD.dwFlags = DSBCAPS_PRIMARYBUFFER;
if (SUCCEEDED(IDirectSound_CreateSoundBuffer(lpDS, &dsBD, &lpPrimary, NULL)))
{
if (!SUCCEEDED(IDirectSoundBuffer_Play(lpPrimary, 0, 0, DSBPLAY_LOOPING)))
{
Msg("Unable to play Primary sound buffer");
}
IDirectSoundBuffer_Release(lpPrimary);
}
else
{
Msg("Unable to create Primary sound buffer");
}
return TRUE;
} /* InitSound */
/*
* DDInit
*/
BOOL DDInit( void )
{
DirectDrawEnumerate(&DDEnumCallback,NULL);
DDEnumCallback((GUID *)DDCREATE_EMULATIONONLY, "Hardware Emulation Layer", "", NULL);
return TRUE;
}
游戏的初始化是指调入游戏中的图象、声音等资源和游戏中的角色、道具的属性、
初始位置、状态等并画出初始画面的图象以及游戏的系统、操作方法的定义、游戏的规则等。比如说在一个RPG游戏之中,在游戏开始时内存中就应装入主角的图象组(比如走时的几幅图,状态对话框中的图)、状态(级别、HP、MP、DP等等)、属性(性别、职业等)等,描述整个游戏世界的图,NPC的各种属性、游戏的规则(各种攻击方式的效果、升级所需的经验值等)等等,总之要装入您所设计的游戏世界的一切。在例程的InitGame()中调用的函数InitializeGame()就完成了这个任务。
InitializeGame()的代码:
/*
* InitializeGame
*/
BOOL InitializeGame ( void )
{
Splash();
hBitmapList = LoadBitmaps();
if( hBitmapList == NULL )
{
return FALSE;
}
InitTiles( &hTileList, hBitmapList, C_TILETOTAL );
InitPlane( &hForeground, &hForePosList, "FORELIST", C_FORE_W, C_FORE_H, C_FORE_DENOM );
TilePlane( hForeground, hTileList, hForePosList );
InitPlane( &hMidground, &hMidPosList, "MIDLIST", C_MID_W, C_MID_H, C_MID_DENOM );
TilePlane( hMidground, hTileList, hMidPosList );
InitPlane( &hBackground, &hBackPosList, "BACKLIST", C_BACK_W, C_BACK_H, C_BACK_DENOM );
TilePlane( hBackground, hTileList, hBackPosList );
InitSurface( &hSurfaceList, "SURFLIST", C_FORE_W, C_FORE_H );
SurfacePlane( hForeground, hSurfaceList );
InitFox( &hFox, hBitmapList );
InitBear( &hBear, hBitmapList );
InitApple( &hApple, hBitmapList );
DDClear(); // clear all the backbuffers.
return TRUE;
} /* InitializeGame */
在现在的大部分游戏中游戏世界中的每个组成部分通常是用结构或类分别定义储存的。比如一个即时战略游戏中,各种建筑物放在一个类中,而每个建筑物的属性就放在该类的一个子类中;各种武器放在一个类中,每种武器放在该类的一个子类中。
class Weapon
{
WEAPON_TYPE Type;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -