meteordefense.cpp
来自「《24小时教会你游戏编程》上的源码」· C++ 代码 · 共 331 行
CPP
331 行
//-----------------------------------------------------------------
// Meteor Defense Application
// C++ Source - MeteorDefense.cpp
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include "MeteorDefense.h"
//-----------------------------------------------------------------
// Game Engine Functions
//-----------------------------------------------------------------
BOOL GameInitialize(HINSTANCE hInstance)
{
// Create the game engine
_pGame = new GameEngine(hInstance, TEXT("Meteor Defense"),
TEXT("Meteor Defense"), IDI_METEORDEFENSE, IDI_METEORDEFENSE_SM, 600, 450);
if (_pGame == NULL)
return FALSE;
// Set the frame rate
_pGame->SetFrameRate(30);
// Store the instance handle
_hInstance = hInstance;
return TRUE;
}
void GameStart(HWND hWindow)
{
// Seed the random number generator
srand(GetTickCount());
// Create the offscreen device context and bitmap
_hOffscreenDC = CreateCompatibleDC(GetDC(hWindow));
_hOffscreenBitmap = CreateCompatibleBitmap(GetDC(hWindow),
_pGame->GetWidth(), _pGame->GetHeight());
SelectObject(_hOffscreenDC, _hOffscreenBitmap);
// Create and load the bitmaps
HDC hDC = GetDC(hWindow);
_pGroundBitmap = new Bitmap(hDC, IDB_GROUND, _hInstance);
_pTargetBitmap = new Bitmap(hDC, IDB_TARGET, _hInstance);
_pCityBitmap = new Bitmap(hDC, IDB_CITY, _hInstance);
_pMeteorBitmap = new Bitmap(hDC, IDB_METEOR, _hInstance);
_pMissileBitmap = new Bitmap(hDC, IDB_MISSILE, _hInstance);
_pExplosionBitmap = new Bitmap(hDC, IDB_EXPLOSION, _hInstance);
_pGameOverBitmap = new Bitmap(hDC, IDB_GAMEOVER, _hInstance);
// Create the starry background
_pBackground = new StarryBackground(600, 450);
// Play the background music
_pGame->PlayMIDISong(TEXT("Music.mid"));
// Start the game
NewGame();
}
void GameEnd()
{
// Close the MIDI player for the background music
_pGame->CloseMIDIPlayer();
// Cleanup the offscreen device context and bitmap
DeleteObject(_hOffscreenBitmap);
DeleteDC(_hOffscreenDC);
// Cleanup the bitmaps
delete _pGroundBitmap;
delete _pTargetBitmap;
delete _pCityBitmap;
delete _pMeteorBitmap;
delete _pMissileBitmap;
delete _pExplosionBitmap;
delete _pGameOverBitmap;
// Cleanup the background
delete _pBackground;
// Cleanup the sprites
_pGame->CleanupSprites();
// Cleanup the game engine
delete _pGame;
}
void GameActivate(HWND hWindow)
{
// Resume the background music
_pGame->PlayMIDISong(TEXT(""), FALSE);
}
void GameDeactivate(HWND hWindow)
{
// Pause the background music
_pGame->PauseMIDISong();
}
void GamePaint(HDC hDC)
{
// Draw the background
_pBackground->Draw(hDC);
// Draw the ground bitmap
_pGroundBitmap->Draw(hDC, 0, 398, TRUE);
// Draw the sprites
_pGame->DrawSprites(hDC);
// Draw the score
TCHAR szText[64];
RECT rect = { 275, 0, 325, 50 };
wsprintf(szText, "%d", _iScore);
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, RGB(255, 255, 255));
DrawText(hDC, szText, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
// Draw the game over message, if necessary
if (_bGameOver)
_pGameOverBitmap->Draw(hDC, 170, 150, TRUE);
}
void GameCycle()
{
if (!_bGameOver)
{
// Randomly add meteors
if ((rand() % _iDifficulty) == 0)
AddMeteor();
// Update the background
_pBackground->Update();
// Update the sprites
_pGame->UpdateSprites();
// Obtain a device context for repainting the game
HWND hWindow = _pGame->GetWindow();
HDC hDC = GetDC(hWindow);
// Paint the game to the offscreen device context
GamePaint(_hOffscreenDC);
// Blit the offscreen bitmap to the game screen
BitBlt(hDC, 0, 0, _pGame->GetWidth(), _pGame->GetHeight(),
_hOffscreenDC, 0, 0, SRCCOPY);
// Cleanup
ReleaseDC(hWindow, hDC);
}
}
void HandleKeys()
{
}
void MouseButtonDown(int x, int y, BOOL bLeft)
{
if (!_bGameOver && bLeft)
{
// Create a new missile sprite and set its position
RECT rcBounds = { 0, 0, 600, 450 };
int iXPos = (x < 300) ? 144 : 449;
Sprite* pSprite = new Sprite(_pMissileBitmap, rcBounds, BA_DIE);
pSprite->SetPosition(iXPos, 365);
// Calculate the velocity so that it is aimed at the target
int iXVel, iYVel = -6;
y = min(y, 300);
iXVel = (iYVel * ((iXPos + 8) - x)) / (365 - y);
pSprite->SetVelocity(iXVel, iYVel);
// Add the missile sprite
_pGame->AddSprite(pSprite);
// Play the fire sound
PlaySound((LPCSTR)IDW_FIRE, _hInstance, SND_ASYNC |
SND_RESOURCE | SND_NOSTOP);
// Update the score
_iScore = max(--_iScore, 0);
}
else if (_bGameOver && !bLeft)
// Start a new game
NewGame();
}
void MouseButtonUp(int x, int y, BOOL bLeft)
{
}
void MouseMove(int x, int y)
{
// Track the mouse with the target sprite
_pTargetSprite->SetPosition(x - (_pTargetSprite->GetWidth() / 2),
y - (_pTargetSprite->GetHeight() / 2));
}
void HandleJoystick(JOYSTATE jsJoystickState)
{
}
BOOL SpriteCollision(Sprite* pSpriteHitter, Sprite* pSpriteHittee)
{
// See if a missile and a meteor have collided
if ((pSpriteHitter->GetBitmap() == _pMissileBitmap &&
pSpriteHittee->GetBitmap() == _pMeteorBitmap) ||
(pSpriteHitter->GetBitmap() == _pMeteorBitmap &&
pSpriteHittee->GetBitmap() == _pMissileBitmap))
{
// Kill both sprites
pSpriteHitter->Kill();
pSpriteHittee->Kill();
// Update the score
_iScore += 6;
_iDifficulty = max(50 - (_iScore / 10), 5);
}
// See if a meteor has collided with a city
if (pSpriteHitter->GetBitmap() == _pMeteorBitmap &&
pSpriteHittee->GetBitmap() == _pCityBitmap)
{
// Play the big explosion sound
PlaySound((LPCSTR)IDW_BIGEXPLODE, _hInstance, SND_ASYNC |
SND_RESOURCE);
// Kill both sprites
pSpriteHitter->Kill();
pSpriteHittee->Kill();
// See if the game is over
if (--_iNumCities == 0)
_bGameOver = TRUE;
}
return FALSE;
}
void SpriteDying(Sprite* pSprite)
{
// See if a meteor sprite is dying
if (pSprite->GetBitmap() == _pMeteorBitmap)
{
// Play the explosion sound
PlaySound((LPCSTR)IDW_EXPLODE, _hInstance, SND_ASYNC |
SND_RESOURCE | SND_NOSTOP);
// Create an explosion sprite at the meteor's position
RECT rcBounds = { 0, 0, 600, 450 };
RECT rcPos = pSprite->GetPosition();
Sprite* pSprite = new Sprite(_pExplosionBitmap, rcBounds);
pSprite->SetNumFrames(12, TRUE);
pSprite->SetPosition(rcPos.left, rcPos.top);
_pGame->AddSprite(pSprite);
}
}
//-----------------------------------------------------------------
// Functions
//-----------------------------------------------------------------
void NewGame()
{
// Clear the sprites
_pGame->CleanupSprites();
// Create the target sprite
RECT rcBounds = { 0, 0, 600, 450 };
_pTargetSprite = new Sprite(_pTargetBitmap, rcBounds, BA_STOP);
_pTargetSprite->SetZOrder(10);
_pGame->AddSprite(_pTargetSprite);
// Create the city sprites
Sprite* pSprite = new Sprite(_pCityBitmap, rcBounds);
pSprite->SetPosition(2, 370);
_pGame->AddSprite(pSprite);
pSprite = new Sprite(_pCityBitmap, rcBounds);
pSprite->SetPosition(186, 370);
_pGame->AddSprite(pSprite);
pSprite = new Sprite(_pCityBitmap, rcBounds);
pSprite->SetPosition(302, 370);
_pGame->AddSprite(pSprite);
pSprite = new Sprite(_pCityBitmap, rcBounds);
pSprite->SetPosition(490, 370);
_pGame->AddSprite(pSprite);
// Initialize the game variables
_iScore = 0;
_iNumCities = 4;
_iDifficulty = 50;
_bGameOver = FALSE;
// Play the background music
_pGame->PlayMIDISong();
}
void AddMeteor()
{
// Create a new meteor sprite and set its position
RECT rcBounds = { 0, 0, 600, 390 };
int iXPos = rand() % 600;
Sprite* pSprite = new Sprite(_pMeteorBitmap, rcBounds, BA_DIE);
pSprite->SetNumFrames(14);
pSprite->SetPosition(iXPos, 0);
// Calculate the velocity so that it is aimed at one of the cities
int iXVel, iYVel = (rand() % 4) + 3;
switch(rand() % 4)
{
case 0:
iXVel = (iYVel * (56 - (iXPos + 50))) / 400;
break;
case 1:
iXVel = (iYVel * (240 - (iXPos + 50))) / 400;
break;
case 2:
iXVel = (iYVel * (360 - (iXPos + 50))) / 400;
break;
case 3:
iXVel = (iYVel * (546 - (iXPos + 50))) / 400;
break;
}
pSprite->SetVelocity(iXVel, iYVel);
// Add the meteor sprite
_pGame->AddSprite(pSprite);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?