main.cpp
来自「VC游戏编程基础」· C++ 代码 · 共 1,966 行 · 第 1/4 页
CPP
1,966 行
DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
hWnd = CreateWindowEx( 0, TEXT("AdvInAbatWndClass"),
TEXT("Maze Test program"),
dwStyle, CW_USEDEFAULT, CW_USEDEFAULT,
dwWindowWidth, dwWindowHeight, NULL, NULL, hInst, NULL );
if( hWnd == NULL )
return E_FAIL;
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// Save the window size/pos for switching modes
GetWindowRect( hWnd, &g_rcWindow );
*phWnd = hWnd;
*phAccel = hAccel;
g_hMainWnd = hWnd;
return S_OK;
}
HFONT GetGameFont()
{
HFONT hFont ;
LOGFONT lf ;
lf.lfHeight = 40;
lf.lfWidth = 20;
lf.lfEscapement = 0 ;
lf.lfOrientation = 0 ;
lf.lfWeight = 0 ;
lf.lfItalic = false ;
lf.lfUnderline = false;
lf.lfStrikeOut = false;
lf.lfCharSet = DEFAULT_CHARSET ;
lf.lfOutPrecision = 0 ;
lf.lfClipPrecision = 0 ;
lf.lfQuality = 0 ;
lf.lfPitchAndFamily = 0 ;
lstrcpy (lf.lfFaceName, "Times New Roman") ;
hFont = CreateFontIndirect (&lf) ;
// hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
return hFont;
}
//-----------------------------------------------------------------------------
// Name: InitDirectDraw()
// Desc: Create the DirectDraw object, and init the surfaces
//-----------------------------------------------------------------------------
HRESULT InitDirectDraw( HWND hWnd )
{
HRESULT hr;
// Initialize all the surfaces we need
if( FAILED( hr = InitDirectDrawMode( hWnd, g_bWindowed ) ) )
return hr;
// Create a static IDirectSound in the CSound class.
// Set coop level to DSSCL_PRIORITY, and set primary buffer
// format to stereo, 22kHz and 16-bit output.
g_pSoundManager = new CSoundManager();
if( FAILED(hr= g_pSoundManager->Initialize( hWnd, DSSCL_PRIORITY, 2, 22050, 16 ) ) )
{
MessageBox( 0, "Error initializing DirectSound. Game will now exit.",
"Game", MB_OK | MB_ICONERROR );
return hr;
}
g_pSoundManager->Create(&g_pPickupSound,"PickUp");
g_pHandleInput = new SHandleInput();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InitDirectDrawMode()
// Desc: Called when the user wants to toggle between full-screen and windowed
// to create all the needed DDraw surfaces and set the coop level
//-----------------------------------------------------------------------------
HRESULT InitDirectDrawMode( HWND hWnd, BOOL bWindowed )
{
HRESULT hr;
LPDIRECTDRAWPALETTE pDDPal = NULL;
// Release all existing surfaces
SAFE_DELETE( g_pMazeSurface);
#ifdef DISPLAY_STATUS
SAFE_DELETE( g_pTextSurface );
#endif
SAFE_DELETE( g_pLifeTextSurface );
SAFE_DELETE( g_pScoreTextSurface );
SAFE_DELETE( g_pLevelTextSurface );
SAFE_DELETE( g_pSpriteSurface );
SAFE_DELETE ( g_pSplashSurface);
SAFE_DELETE( g_pDisplay );
//在满屏模式和窗口模式下,主页面和后台页面的创建方式是不同的
g_pDisplay = new CDisplay();
//窗口模式
if( bWindowed )
{
if( FAILED( hr = g_pDisplay->CreateWindowedDisplay( hWnd, SCREEN_WIDTH,
SCREEN_HEIGHT ) ) )
return hr;
// 在窗口方式中添加系统菜单
DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
dwStyle |= WS_SYSMENU;
SetWindowLong( hWnd, GWL_STYLE, dwStyle );
// Show the menu in windowed mode
#ifdef _WIN64
HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hWnd, GWLP_HINSTANCE );
#else
HINSTANCE hInst = (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE );
#endif
HMENU hMenu = LoadMenu( hInst, MAKEINTRESOURCE( IDR_MENU ) );
SetMenu( hWnd, hMenu );
}
else//满屏显示
{
if( FAILED( hr = g_pDisplay->CreateFullScreenDisplay( hWnd, SCREEN_WIDTH,
SCREEN_HEIGHT, SCREEN_BPP ) ) )
{
MessageBox( hWnd, TEXT("This display card does not support 640x480x8. "),
TEXT("DirectDraw Sample"), MB_ICONERROR | MB_OK );
return hr;
}
// 无效菜单
SetMenu( hWnd, NULL );
// 从窗口方式中删除系统菜单
/*
DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
dwStyle &= ~WS_SYSMENU;
SetWindowLong( hWnd, GWL_STYLE, dwStyle );
*/
}
// 创建一个页面,在上面绘制文本
#ifdef DISPLAY_STATUS
if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, (char*)g_szGameStatus,
RGB(0,0,0), RGB(255, 255, 0) ) ) )
return hr;
#endif
HFONT hFont = GetGameFont();
if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pLifeTextSurface, hFont, (char*)g_szLifeLeft,
RGB(0,0,0), RGB(255, 255, 0) ) ) )
return hr;
if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore,
RGB(0,0,0), RGB(255, 255, 0) ) ) )
return hr;
// Create a surface, and draw a bitmap resource on it. The surface must
// be newly created every time the screen mode is switched since it
// uses the pixel format of the primary surface
// Create a surface, and draw text to it.
if( FAILED( hr = g_pDisplay->CreateSurface( &g_pMazeSurface, SCREEN_WIDTH, SCREEN_HEIGHT) ))
return hr;
if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pSpriteSurface, MAKEINTRESOURCE(IDB_SPRITE),0, 0) ))
return hr;
g_pSpriteSurface->SetColorKey(RGB(0,0,0));
g_Maze.Draw(g_pMazeSurface);
if (g_nGameState == GAMESTATE_SPLASHSCREEN) {
LoadJPEG(true, SPLASHFILENAME, &g_pSplashSurface);
}
if (g_nGameState == GAMESTATE_CHOICE) {
LoadJPEG(true, CHOICEFILENAME, &g_pSplashSurface);
}
if (g_nGameState == GAMESTATE_GAMEOVERGOOD) {
LoadJPEG(true, GAMEOVERGOODFILENAME, &g_pSplashSurface);
}
if (g_nGameState == GAMESTATE_GAMEOVERBAD) {
LoadJPEG(true, GAMEOVERBADFILENAME, &g_pSplashSurface);
}
if (g_nGameState == GAMESTATE_RUNNING){
g_pDisplay->CreateSurfaceFromText( &g_pLevelTextSurface, hFont, g_Maze.GetName(),
RGB(0,0,0), RGB(255, 255, 0) ) ;
}
DeleteObject(hFont);
return S_OK;
}
inline bool IsHit(RECT& rc)
{
return g_Maze.IsHit(rc);
}
void BulletFindPath(CSprite* pSprite)
{
pSprite->SetState(ST_KILL);
}
void FindPath(CSprite* pSprite)
{
int nH = rand()%2;
int nV = rand()%2;
int nNRnd = rand()%3;
if (nNRnd) {
if (abs(g_pPlayerSprite->m_ptLocation.x - pSprite->m_ptLocation.x) >
abs(g_pPlayerSprite->m_ptLocation.y - pSprite->m_ptLocation.y))
{
pSprite->m_Movement.m_dy = 0;
if (g_pPlayerSprite->m_ptLocation.x < pSprite->m_ptLocation.x) {
pSprite->m_Movement.m_dx= -1 * (rand()%2+1);
pSprite->SetState(ST_WALK_LEFT);
} else {
pSprite->m_Movement.m_dx= 1 * (rand()%2+1);
pSprite->SetState(ST_WALK_RIGHT);
}
} else {
pSprite->m_Movement.m_dx = 0;
if (g_pPlayerSprite->m_ptLocation.y < pSprite->m_ptLocation.y) {
pSprite->m_Movement.m_dy= -1 * (rand()%2+1);
pSprite->SetState(ST_WALK_UP);
} else {
pSprite->m_Movement.m_dy= 1 * (rand()%2+1);
pSprite->SetState(ST_WALK_DOWN);
}
}
} else {
if (nV) {
pSprite->m_Movement.m_dx = 0;
if (nH) {
pSprite->m_Movement.m_dy = 1 * (rand()%2+1);
pSprite->SetState(ST_WALK_DOWN);
} else {
pSprite->m_Movement.m_dy = -1 * (rand()%2+1);
pSprite->SetState(ST_WALK_UP);
}
} else {
pSprite->m_Movement.m_dy = 0;
if (nH) {
pSprite->m_Movement.m_dx = 1 * (rand()%2+1);
pSprite->SetState(ST_WALK_RIGHT);
} else {
pSprite->m_Movement.m_dx = -1 * (rand()%2+1);
pSprite->SetState(ST_WALK_LEFT);
}
}
}
if (pSprite->GetType() == TYPE_ENEMY4) {
if (g_BulletSprite.GetState() == ST_DEAD && pSprite->GetState() != ST_KILL
&& pSprite->GetState() != ST_DEAD) {
RECT rc = pSprite->GetRect();
g_BulletSprite.MoveTo(rc.left,rc.top);
g_BulletSprite.SetState(ST_DEFAULT);
switch (pSprite->GetState()) {
case ST_WALK_UP:
g_BulletSprite.m_Movement.m_dx =0;
g_BulletSprite.m_Movement.m_dy = -3;
break;
case ST_WALK_DOWN:
g_BulletSprite.m_Movement.m_dx =0;
g_BulletSprite.m_Movement.m_dy = 3;
break;
case ST_WALK_LEFT:
g_BulletSprite.m_Movement.m_dx =-3;
g_BulletSprite.m_Movement.m_dy = 0;
break;
case ST_WALK_RIGHT:
g_BulletSprite.m_Movement.m_dx =3;
g_BulletSprite.m_Movement.m_dy = 0;
break;
}
}
}
}
void DeadPig(CSprite* pSprite)
{
++g_nPigDead;
--g_nLivesLeft;
#ifdef DISPLAY_STATUS
wsprintf((char*)g_szGameStatus, (char*)GAMESTATUS_TEXT, g_nPigDead, g_nEnemyDead);
SAFE_DELETE( g_pTextSurface );
g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, (char*)g_szGameStatus,
RGB(0,0,0), RGB(255, 255, 0) );
#endif
SAFE_DELETE( g_pLifeTextSurface );
wsprintf((char*)g_szLifeLeft, (char*)LIFE_LEFT_TEXT, g_nLivesLeft-1);
HFONT hFont = GetGameFont();
g_pDisplay->CreateSurfaceFromText( &g_pLifeTextSurface, hFont , (char*)g_szLifeLeft,
RGB(0,0,0), RGB(255, 255, 0) );
DeleteObject(hFont);
g_pPlayerSprite->MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
g_pPlayerSprite->SetState(ST_WALK_UP);
g_pPlayerSprite->m_Movement.m_nInvulnerable=INVULNERABLE_DELAY;
if (g_nLivesLeft == 0) {
g_nLivesLeft = NO_OF_LIFE;
g_nGameState = GAMESTATE_GAMEOVERBAD;
LoadJPEG(true, GAMEOVERBADFILENAME, &g_pSplashSurface);
}
}
void DeadEnemy(CSprite* pSprite)
{
++g_nEnemyDead;
#ifdef DISPLAY_STATUS
wsprintf((char*)g_szGameStatus, (char*)GAMESTATUS_TEXT, g_nPigDead, g_nEnemyDead);
SAFE_DELETE( g_pTextSurface );
g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, (char*)g_szGameStatus,
RGB(0,0,0), RGB(255, 255, 0) );
#endif
g_nScore += pSprite->m_nPoints;
SAFE_DELETE( g_pScoreTextSurface );
wsprintf((char*)g_szScore, (char*)GAMESCORE_TEXT, g_nScore);
HFONT hFont = GetGameFont();
g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore,
RGB(0,0,0), RGB(255, 255, 0) );
DeleteObject(hFont);
if (g_nNoOfEnemies) {
g_nNoOfEnemies--;
pSprite->SetState(ST_WALK_LEFT);
POINT pt = g_Maze.GetRandDeployPoint();
pt.x *= MAZETEXTURE_WIDTH;
pt.y *= MAZETEXTURE_HEIGHT;
pSprite->MoveTo(pt);
(*pSprite->m_Movement.m_pfnFindPath)(pSprite);
pSprite->m_Movement.m_nInvulnerable=INVULNERABLE_DELAY;
}
}
bool KillSpecial(CSprite* pSprite)
{
if (pSprite->GetState() == ST_DOOR) {
InitLevel();
return false;
}
return true;
}
void DeadSpecial(CSprite* pSprite)
{
static long nSpecialState = ST_FOOD1;
g_nScore += pSprite->m_nPoints;
SAFE_DELETE( g_pScoreTextSurface );
wsprintf((char*)g_szScore, (char*)GAMESCORE_TEXT, g_nScore);
HFONT hFont = GetGameFont();
g_pDisplay->CreateSurfaceFromText( &g_pScoreTextSurface, hFont, (char*)g_szScore,
RGB(0,0,0), RGB(255, 255, 0) );
DeleteObject(hFont);
if (g_nNoOfSpecials) {
pSprite->SetState(rand()%6 + ST_FOOD1);
POINT pt = g_Maze.GetRandDeployPoint();
pt.x *= MAZETEXTURE_WIDTH;
pt.y *= MAZETEXTURE_HEIGHT;
pSprite->MoveTo(pt);
nSpecialState = ST_FOOD1;
--g_nNoOfSpecials;
} else {
switch (nSpecialState) {
case ST_FOOD1:
pSprite->SetState(ST_KEY);
POINT pt = g_Maze.GetRandDeployPoint();
pt.x *= MAZETEXTURE_WIDTH;
pt.y *= MAZETEXTURE_HEIGHT;
pSprite->MoveTo(pt);
nSpecialState = ST_KEY;
break;
case ST_KEY:
pSprite->SetState(ST_DOOR);
pt = g_Maze.GetRandDeployPoint();
pt.x *= MAZETEXTURE_WIDTH;
pt.y *= MAZETEXTURE_HEIGHT;
pSprite->MoveTo(pt);
nSpecialState = ST_DOOR;
break;
case ST_DOOR:
InitLevel();
}
}
}
//初始化精灵,它负责创建猪精灵,兔精灵,羊精灵,敌人精灵,特殊精灵和子弹精灵。
void InitSprites()
{
const int nHeight = SPRITE_HEIGHT;
const int nWidth = SPRITE_WIDTH;
POINT pt;
RECT rcBounding;
// ---------------- 猪精灵----------------- //
g_PigSprite.CreateSprite(&g_pSpriteSurface, TYPE_PLAYER, nHeight,nWidth);
pt.x = 5*64; pt.y =7*64 ;
g_PigSprite.AddState(ST_STAND_STILL, pt, 2, 60);
rcBounding.top = 0;
rcBounding.bottom = nHeight-10;
rcBounding.left = 10;
rcBounding.right= nWidth - 20;
pt.x = 6*64; pt.y =4*64;
g_PigSprite.AddState(ST_WALK_UP, pt, 3, 10,&rcBounding);
rcBounding.top = 10;
rcBounding.bottom = nHeight-10;
pt.x = 64*9;pt.y = 4*64;
g_PigSprite.AddState(ST_WALK_DOWN, pt, 3, 10,&rcBounding);
rcBounding.top = 10;
rcBounding.bottom = nHeight - 20;
rcBounding.left = 0;
rcBounding.right=nWidth - 10;
pt.x = 3*64;pt.y = 4*64;
// g_pPlayerSprite->AddState(ST_WALK_LEFT, pt, 2, 20,"WavPigWalk",true);
g_PigSprite.AddState(ST_WALK_LEFT, pt, 3, 10,&rcBounding);
pt.x = 64*0;pt.y = 4*64;
rcBounding.left = 10;
rcBounding.right=nWidth-10;
g_PigSprite.AddState(ST_WALK_RIGHT, pt, 3, 10,&rcBounding);
pt.x = 64 * 8; pt.y = 7 * 64;
g_PigSprite.AddState(ST_KILL, pt, 4, 20);
g_PigSprite.MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
g_PigSprite.m_pfnDead = DeadPig;
g_PigSprite.m_Movement.m_pfnCollision = IsHit;
g_PigPooSprite.CreateSprite(&g_pSpriteSurface, TYPE_POO, nHeight,nWidth);
rcBounding.top = rcBounding.left = 20;
rcBounding.right=rcBounding.bottom = nHeight - 40;
pt.x = 0*64;pt.y = 7*64;
g_PigPooSprite.AddState(ST_DEFAULT, pt, 3, 50,&rcBounding);
pt.x = 11*64;pt.y = 10*64;
g_PigPooSprite.AddState(ST_DEAD, pt, 3, 50,&rcBounding);
g_PigPooSprite.SetState(ST_DEFAULT);
// --------------- 兔精灵 --------------- //
g_RabbitSprite.CreateSprite(&g_pSpriteSurface, TYPE_PLAYER, nHeight,nWidth);
pt.x = 5*64; pt.y =8*64 ;
g_RabbitSprite.AddState(ST_STAND_STILL, pt, 2, 60);
rcBounding.top = 0;
rcBounding.bottom = nHeight-10;
rcBounding.left = 10;
rcBounding.right= nWidth - 20;
pt.x = 6*64; pt.y =5*64;
g_RabbitSprite.AddState(ST_WALK_UP, pt, 3, 10,&rcBounding);
rcBounding.top = 10;
rcBounding.bottom = nHeight-10;
pt.x = 64*9;pt.y = 5*64;
g_RabbitSprite.AddState(ST_WALK_DOWN, pt, 3, 10,&rcBounding);
rcBounding.top = 10;
rcBounding.bottom = nHeight - 20;
rcBounding.left = 0;
rcBounding.right=nWidth - 10;
pt.x = 3*64;pt.y = 5*64;
g_RabbitSprite.AddState(ST_WALK_LEFT, pt, 3, 10,&rcBounding);
pt.x = 64*0;pt.y = 5*64;
rcBounding.left = 10;
rcBounding.right=nWidth-10;
g_RabbitSprite.AddState(ST_WALK_RIGHT, pt, 3, 10,&rcBounding);
pt.x = 64 * 8; pt.y = 8 * 64;
g_RabbitSprite.AddState(ST_KILL, pt, 4, 20);
g_RabbitSprite.MoveTo(1 * MAZETEXTURE_WIDTH, 19 * MAZETEXTURE_HEIGHT);
g_RabbitSprite.m_pfnDead = DeadPig;
g_RabbitSprite.m_Movement.m_pfnCollision = IsHit;
g_RabbitPooSprite.CreateSprite(&g_pSpriteSurface, TYPE_POO, nHeight,nWidth);
rcBounding.top = rcBounding.left = 20;
rcBounding.right=rcBounding.bottom = nHeight - 40;
pt.x = 0*64;pt.y = 8*64;
g_RabbitPooSprite.AddState(ST_DEFAULT, pt, 3, 50,&rcBounding);
pt.x = 11*64;pt.y = 10*64;
g_RabbitPooSprite.AddState(ST_DEAD, pt, 3, 50,&rcBounding);
g_RabbitPooSprite.SetState(ST_DEFAULT);
// --------------- 羊精灵----------------//
g_SheepSprite.CreateSprite(&g_pSpriteSurface, TYPE_PLAYER, nHeight,nWidth);
pt.x = 5*64; pt.y =9*64 ;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?