📄 gameengine.cpp
字号:
// GameEngine.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "GameEngine.h"
#include <assert.h>
// Construction & destruction function
GameEngine::GameEngine(int iWidth, int iHeight)
{
m_iWidth = iWidth;
m_iHeight = iHeight;
m_iFrameDelay = 20;
m_bSleep = TRUE;
m_iCurrentKey = 0;
m_iBufferKey = 0;
m_uCount = 0;
m_bHaveBoss = FALSE;
m_bGameOver = FALSE;
m_iLife = 3;
m_iScore = 0;
}
GameEngine::~GameEngine(void)
{
delete m_pFighter;
delete m_pSmallFighter;
}
void GameEngine::KeyDown(WPARAM KeyCode)
{
switch(KeyCode)
{
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
if (KeyCode == m_iCurrentKey || KeyCode==m_iBufferKey)
return; // 重复的键盘消息,忽略
//if(m_iBufferKey && m_iCurrentKey)
// return; // 同时按3个方向键,非法输入,忽略
m_iBufferKey = m_iCurrentKey;
m_iCurrentKey = KeyCode;
if( m_iBufferKey==VK_LEFT && m_iCurrentKey==VK_UP
|| m_iBufferKey==VK_UP && m_iCurrentKey==VK_LEFT )
m_pFighter->Action( Fighter::GO_LEFT_UP );
else if( m_iBufferKey==VK_LEFT && m_iCurrentKey==VK_DOWN
|| m_iBufferKey==VK_DOWN && m_iCurrentKey==VK_LEFT )
m_pFighter->Action( Fighter::GO_LEFT_DOWN );
else if( m_iBufferKey==VK_RIGHT && m_iCurrentKey==VK_UP
|| m_iBufferKey==VK_UP && m_iCurrentKey==VK_RIGHT )
m_pFighter->Action( Fighter::GO_RIGHT_UP );
else if( m_iBufferKey==VK_RIGHT && m_iCurrentKey==VK_DOWN
|| m_iBufferKey==VK_DOWN && m_iCurrentKey==VK_RIGHT )
m_pFighter->Action( Fighter::GO_RIGHT_DOWN );
else
m_pFighter->Action( (Fighter::ACTION) (Fighter::GO_LEFT + KeyCode - VK_LEFT) );
break;
case VK_SPACE:
m_pFighter->Action(Fighter::START_FIRING);
break;
//case VK_TAB:
// m_pFighter->Action(Fighter::CHANGE_WEAPON);
// break;
}
}
void GameEngine::KeyUp(WPARAM KeyCode)
{
if(KeyCode == m_iCurrentKey)
{
m_iCurrentKey = 0;
if(m_iBufferKey != 0)
{
m_iCurrentKey = m_iBufferKey;
m_iBufferKey = 0;
m_pFighter->Action(( Fighter::ACTION )( m_iCurrentKey - VK_LEFT ));
}
else
{
m_pFighter->Action( Fighter::STOP_MOVING );
}
}
else if(KeyCode == m_iBufferKey)
m_iBufferKey = 0;
else if(KeyCode == VK_SPACE)
m_pFighter->Action(Fighter::STOP_FIRING);
}
void GameEngine::Draw(HDC hdc)
{
list<Bullet*>::iterator iterFighterBullets;
list<EnemyFigher*>::iterator iterEnemyFighters;
list<Bullet*>::iterator iterEnemyBullets;
list<Sprite*>::iterator iterAnimation;
m_pFighter->Draw(hdc);
// 画战机子弹
if (!m_listFighterBullets.empty())
{
for (iterFighterBullets = m_listFighterBullets.begin();
iterFighterBullets != m_listFighterBullets.end();
iterFighterBullets++)
{
(*iterFighterBullets)->Draw(hdc);
}
}
// 画敌机
if (!m_listEnemy.empty())
{
for (iterEnemyFighters = m_listEnemy.begin();
iterEnemyFighters != m_listEnemy.end();
iterEnemyFighters++)
{
(*iterEnemyFighters)->Draw(hdc);
}
}
// 画敌人子弹
if (!m_listEnemyBullets.empty())
{
for (iterEnemyBullets = m_listEnemyBullets.begin();
iterEnemyBullets != m_listEnemyBullets.end();
iterEnemyBullets++)
{
(*iterEnemyBullets)->Draw(hdc);
}
}
// 画爆炸动画
if (!m_listAnimation.empty())
{
for (iterAnimation = m_listAnimation.begin();
iterAnimation != m_listAnimation.end();
iterAnimation++)
{
(*iterAnimation)->Draw(hdc);
}
}
// 画剩余战机小图标
for (int i = 0; i < m_iLife - 1; ++i)
{
m_pSmallFighter->Draw(hdc, 20 * (i + 1), 20,
m_pSmallFighter->GetWidth(), m_pSmallFighter->GetHeight(), 0, 0);
}
// 显示得分
char score[10];
sprintf(score, "%d", m_iScore);
TextOut(hdc, 200, 20, score, strlen(score));
}
void GameEngine::Update()
{
list<Bullet*>::iterator iterFighterBullets;
list<EnemyFigher*>::iterator iterEnemyFighters;
list<Bullet*>::iterator iterEnemyBullets;
list<Sprite*>::iterator iterAnimation;
m_pFighter->Update();
if (m_pFighter->IsDead() || m_pFighter->GetLife() <= 0)
{
// 如果战机挂了。。。
if (--m_iLife> 0)
{
POINT ptPosition;
ptPosition.x = (m_iWidth - 50) / 2;
ptPosition.y = m_iHeight - 50;
m_pFighter->SetPosition(ptPosition); // 把战机移到原地,像是新的
m_pFighter->SetLife(100); // 把生命值设成100
}
else
{
m_pFighter->Kill();
m_bGameOver = TRUE;
}
m_listAnimation.push_back(AddExplodeAnimation(m_pFighter));
m_pSound->Play(1);
}
// 战机开火
if (m_pFighter->IsFiring() && m_uCount % 5 == 0)
{
m_listFighterBullets.push_back(m_pFighter->AddSprite());
m_pFireSound->Play(1);
}
CheckFighterHitting();
CheckFighterHitted();
CheckFighterCollistion();
// 更新战机子弹, 本来是写在一个循环里的, 会出问题,分开了
if (!m_listFighterBullets.empty())
{
for (iterFighterBullets = m_listFighterBullets.begin();
iterFighterBullets != m_listFighterBullets.end();
iterFighterBullets++)
{
// 如果死了,就清除
if ((*iterFighterBullets)->IsDead())
{
delete (*iterFighterBullets);
iterFighterBullets = m_listFighterBullets.erase(iterFighterBullets);
}
}
}
if (!m_listFighterBullets.empty())
{
for (iterFighterBullets = m_listFighterBullets.begin();
iterFighterBullets != m_listFighterBullets.end();
iterFighterBullets++)
{
(*iterFighterBullets)->Update();
}
}
// 更新敌机
if (!m_listEnemy.empty())
{
for (iterEnemyFighters = m_listEnemy.begin();
iterEnemyFighters != m_listEnemy.end();
iterEnemyFighters++)
{
if ((*iterEnemyFighters)->IsDead() ||
(*iterEnemyFighters)->GetLife() <= 0)
{
// 敌BOSS挂了,出爆炸音效,显示爆炸动画,小兵没有这个待遇
if ((*iterEnemyFighters)->IsBoss())
{
m_listAnimation.push_back(AddExplodeAnimation(*iterEnemyFighters));
m_pSound->Play(1);
m_bHaveBoss = FALSE;
}
// 被干掉的才加分,飞出边界自己死掉的不算
if ((*iterEnemyFighters)->GetLife() <= 0)
m_iScore += (*iterEnemyFighters)->GetValue();
delete (*iterEnemyFighters);
iterEnemyFighters = m_listEnemy.erase(iterEnemyFighters);
}
}
}
if (!m_listEnemy.empty())
{
for (iterEnemyFighters = m_listEnemy.begin();
iterEnemyFighters != m_listEnemy.end();
iterEnemyFighters++)
{
if ((*iterEnemyFighters)->IsBoss())
{
m_bHaveBoss = TRUE;
(*iterEnemyFighters)->Update();
if (m_uCount % 10 == 0)
m_listEnemyBullets.push_back((*iterEnemyFighters)->AddSprite(m_pFighter));
}
else
{
(*iterEnemyFighters)->Update();
if ((*iterEnemyFighters)->IsFiring())
{
// 小兵只能开一枪, 惨
m_listEnemyBullets.push_back((*iterEnemyFighters)->AddSprite(m_pFighter));
(*iterEnemyFighters)->StopFire();
}
}
}
}
// 更新敌机子弹
if (!m_listEnemyBullets.empty())
{
for (iterEnemyBullets = m_listEnemyBullets.begin();
iterEnemyBullets != m_listEnemyBullets.end();
iterEnemyBullets++)
{
// 如果死了,就清除
if ((*iterEnemyBullets)->IsDead())
{
delete (*iterEnemyBullets);
iterEnemyBullets = m_listEnemyBullets.erase(iterEnemyBullets);
}
}
}
if (!m_listEnemyBullets.empty())
{
for (iterEnemyBullets = m_listEnemyBullets.begin();
iterEnemyBullets != m_listEnemyBullets.end();
iterEnemyBullets++)
{
(*iterEnemyBullets)->Update();
}
}
// 更新动画
if (!m_listAnimation.empty())
{
for (iterAnimation = m_listAnimation.begin();
iterAnimation != m_listAnimation.end();
iterAnimation++)
{
// 如果死了,就清除
if ((*iterAnimation)->IsDead())
{
delete (*iterAnimation);
iterAnimation = m_listAnimation.erase(iterAnimation);
}
}
}
if (!m_listAnimation.empty())
{
for (iterAnimation = m_listAnimation.begin();
iterAnimation != m_listAnimation.end();
iterAnimation++)
{
(*iterAnimation)->Update();
}
}
m_uCount++;
if (m_uCount % 40 ==0)
AddEnemy();
// 如果没有BOSS, 加一个
if ((m_uCount % 500 == 0) && (m_bHaveBoss == FALSE))
AddBoss();
}
BOOL GameEngine::Initialize()
{
// 清空列表
m_listEnemy.clear();
m_listFighterBullets.clear();
m_listEnemyBullets.clear();
m_listAnimation.clear();
// 创建音效对象
m_pSound = new MusicPlay();
m_pFireSound = new MusicPlay();
m_pSound->Load(".\\Sounds\\explode.wav");
m_pFireSound->Load(".\\Sounds\\fire.wav");
// 初始化战斗机
Bitmap *bmp =
new Bitmap(".\\images\\Plane.bmp", TRUE, RGB(255, 0, 255));
POINT ptPosition, ptVelocity;
ptPosition.x = (m_iWidth - 50) / 2;
ptPosition.y = m_iHeight - 50;
ptVelocity.x = 0;
ptVelocity.y = 0;
RECT rcBounds;
rcBounds.left = 0;
rcBounds.right = m_iWidth;
rcBounds.top = 0;
rcBounds.bottom = m_iHeight;
m_pFighter = new Fighter(bmp, ptPosition, ptVelocity,
1, rcBounds, BA_STOP, 8.0f);
m_pFighter->SetNumFrames(3);
m_pFighter->SetFrameDelay(1);
m_pSmallFighter = new Bitmap(".\\images\\SmallPlane.bmp", TRUE, RGB(255, 0, 255));
return TRUE;
}
BOOL CheckCollision(RECT rc1, RECT rc2)
{
// 这个算法可能有点笨,有空再想
// 分别判断矩形的四个角是否在另一个矩形内,如果在判断为相撞
if ((rc1.left > rc2.left && rc1.left < rc2.right) &&
(rc1.top > rc2.top && rc1.top < rc2.bottom))
return TRUE;
if ((rc1.right > rc2.left && rc1.right < rc2.right) &&
(rc1.top > rc2.top && rc1.top < rc2.bottom))
return TRUE;
if ((rc1.left > rc2.left && rc1.left < rc2.right) &&
(rc1.bottom > rc2.top && rc1.bottom < rc2.bottom))
return TRUE;
if ((rc1.right > rc2.left && rc1.right < rc2.right) &&
(rc1.bottom > rc2.top && rc1.bottom < rc2.bottom))
return TRUE;
// 再判断另一个矩形,主要担心一个矩形完全在另一个矩形内
if ((rc2.left > rc1.left && rc2.left < rc1.right) &&
(rc2.top > rc1.top && rc2.top < rc1.bottom))
return TRUE;
if ((rc2.right > rc1.left && rc2.right < rc1.right) &&
(rc2.top > rc1.top && rc2.top < rc1.bottom))
return TRUE;
if ((rc2.left > rc1.left && rc2.left < rc1.right) &&
(rc2.bottom > rc1.top && rc2.bottom < rc1.bottom))
return TRUE;
if ((rc2.right > rc1.left && rc2.right < rc1.right) &&
(rc2.bottom > rc1.top && rc2.bottom < rc1.bottom))
return TRUE;
return FALSE;
}
BOOL GameEngine::SpriteCollision(Sprite* pSpriteHitter, Sprite* pSpriteHittee)
{
RECT rectSpriteHitter, rectSpriteHittee;
pSpriteHitter->CalcCollisionRect();
pSpriteHittee->CalcCollisionRect();
rectSpriteHitter = pSpriteHitter->GetCollision();
rectSpriteHittee = pSpriteHittee->GetCollision();
if (CheckCollision(rectSpriteHitter, rectSpriteHittee))
//if (pSpriteHitter->TestCollision(pSpriteHitter))
return TRUE;
else
return FALSE;
}
// 检查战机子弹是否击中敌机
void GameEngine::CheckFighterHitting()
{
list<Bullet*>::iterator iterFighterBullets;
list<EnemyFigher*>::iterator iterEnemyFighters;
int life;
for (iterFighterBullets = m_listFighterBullets.begin();
iterFighterBullets != m_listFighterBullets.end();
iterFighterBullets++)
{
for (iterEnemyFighters = m_listEnemy.begin();
iterEnemyFighters != m_listEnemy.end();
iterEnemyFighters++)
{
if (SpriteCollision((*iterEnemyFighters),(*iterFighterBullets)))
{
// 敌机生命减去子弹攻击力
life = (*iterEnemyFighters)->GetLife() -
(*iterFighterBullets)->GetAttack();
(*iterEnemyFighters)->SetLife(life);
// 添加子弹爆炸动画,销毁子弹
m_listAnimation.push_back(AddSprite(*iterFighterBullets));
(*iterFighterBullets)->Kill();
}
}
}
}
// 检查敌机子弹是否击中战机
void GameEngine::CheckFighterHitted()
{
list<Bullet*>::iterator iterEnemyBullets;
int life;
for (iterEnemyBullets = m_listEnemyBullets.begin();
iterEnemyBullets != m_listEnemyBullets.end();
iterEnemyBullets++)
{
if (SpriteCollision(m_pFighter, (*iterEnemyBullets)))
{
life = m_pFighter->GetLife() - (*iterEnemyBullets)->GetAttack();
m_pFighter->SetLife(life);
(*iterEnemyBullets)->Kill();
}
}
}
// 检查战机是否与敌机相撞
void GameEngine::CheckFighterCollistion()
{
list<EnemyFigher*>::iterator iterEnemyFighters;
int life = 0;
for (iterEnemyFighters = m_listEnemy.begin();
iterEnemyFighters != m_listEnemy.end();
iterEnemyFighters++)
{
if (SpriteCollision(m_pFighter, (*iterEnemyFighters)))
{
// 如果被BOSS撞就挂了,如果被小兵撞,挂一半
if ((*iterEnemyFighters)->IsBoss())
life = 0;
else
{
life = m_pFighter->GetLife() - 50;
(*iterEnemyFighters)->Kill();
}
m_pFighter->SetLife(life);
}
}
}
Sprite* GameEngine::AddSprite(Bullet* pBullet)
{
Bitmap *pBmp =
new Bitmap(".\\images\\explode1.bmp", TRUE, RGB(255, 0, 255));
RECT rcBounds = {0, 0, 480, 640};
RECT rcPos = pBullet->GetPosition();
Sprite *pNew = NULL;
pNew = new Sprite(pBmp, rcBounds, BA_DIE);
pNew->SetPosition(rcPos);
pNew->SetVelocity(0, 0);
pNew->SetNumFrames(8);
pNew->SetFrameDelay(1);
pNew->SetSpriteAction(SA_SHOW);
return pNew;
}
Sprite* GameEngine::AddExplodeAnimation(Sprite* pSprite)
{
Bitmap *pBmp =
new Bitmap(".\\images\\explode.bmp", TRUE, RGB(255, 0, 255));
RECT rcBounds = {0, 0, 480, 640};
RECT rcPos = pSprite->GetPosition();
POINT ptPos;
ptPos.x = rcPos.left;
ptPos.y = rcPos.top;
Sprite *pNew = NULL;
pNew = new Sprite(pBmp, rcBounds, BA_STOP);
pNew->SetPosition(ptPos);
pNew->SetVelocity(0, 0);
pNew->SetNumFrames(8);
pNew->SetFrameDelay(1);
pNew->SetSpriteAction(SA_SHOW);
return pNew;
}
void GameEngine::AddBoss(void)
{
// 创建敌BOSS
Bitmap *bmpEnemy =
new Bitmap(".\\images\\3.bmp", TRUE, RGB(255, 0, 255));
POINT ptPosition, ptVelocity;
RECT rcBounds;
ptPosition.x = (m_iWidth - bmpEnemy->GetWidth()) / 2;
ptPosition.y = 50;
ptVelocity.x = 4;
ptVelocity.y = 3;
rcBounds.left = 50;
rcBounds.right = m_iWidth - 50;
rcBounds.top = 50;
rcBounds.bottom = 250;
EnemyFigher *pEnemyFighter = new EnemyFigher(
bmpEnemy, ptPosition, ptVelocity, 1, rcBounds, BA_BOUNCE, 0.0f);
pEnemyFighter->SetLife(100);
pEnemyFighter->SetValue(500);
pEnemyFighter->SetBoss();
m_listEnemy.push_back(pEnemyFighter);
}
void GameEngine::AddEnemy(void)
{
// 创建敌机
Bitmap *bmpEnemy =
new Bitmap(".\\images\\4.bmp", TRUE, RGB(255, 255, 255));
POINT ptPosition, ptVelocity;
RECT rcBounds;
ptPosition.x = rand() % (m_iWidth - bmpEnemy->GetWidth());
ptPosition.y = 0;
ptVelocity.x = rand() % 3;
ptVelocity.y = 5 + rand() % 5;
rcBounds.left = 0;
rcBounds.right = m_iWidth;
rcBounds.top = 0;
rcBounds.bottom = m_iHeight;
EnemyFigher *pEnemyFighter = new EnemyFigher(
bmpEnemy, ptPosition, ptVelocity, 1, rcBounds, BA_DIE, 0.0f);
pEnemyFighter->SetLife(10);
pEnemyFighter->SetValue(50);
pEnemyFighter->StartFire();
m_listEnemy.push_back(pEnemyFighter);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -