⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gameengine.cpp

📁 一个小的类似于雷电的射击游戏
💻 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 + -