C++语言课程设计一拍飞虫
一、实验内容
玩家通过控制拍子拍打飞虫获取分数。
要求如下:
1、 单击空格键即可进入游戏。进入游戏后左上角有两个记录游戏数据标示。上面一个是记录游戏剩余时间,下面一个是记录本局的游戏分数。下面也有五个记录游戏数据的标示,从左到右分别是记录各局游戏分数分数最高的前五个。
2、 移动鼠标可以控制拍子的移动,单击鼠标左键可以控制拍子拍打动作。
3、 游戏开始的时候,系统随机生成12个虫子,其中大虫子5个,小虫子7个,每打死一个大虫子获得1分,打死一个小虫子获得2分。游戏的分数会实时的显示在左上角。
4、 附加:姓名随拍子一块运动。
二、实验代码
LessonX.h
/
//
//
//
//
/
#ifndef _LESSON_X_H_
#define _LESSON_X_H_
//
#include <Windows.h>
/
//
// 游戏总管类。负责处理游戏主循环、游戏初始化、结束等工作
class CGameMain
{
private:
int m_iGameState; // 游戏状态,0:结束或者等待开始;1:初始化;2:游戏进行中
CSprite* m_pPaizi; //拍子精灵
CSprite* m_pKaishi; //空格开始精灵
float m_fGameTime ; // 本局游戏剩余时间
CTextSprite* m_pTime; //显示时间文字编辑精灵
CTextSprite* m_pScore; //显示分数文件编辑精灵
float m_fPosX; //拍子精灵的x坐标
float m_fPosY; //拍子精灵的y坐标
int m_iGameScore; // 本局游戏当前积分值
float m_fRotateTime; // 拍子拍下后距离复位还差多少时间
float m_fOldRotation; // 拍子的初始角度
float m_fScreenLeft;// 屏幕的4个边界值:上下左右
float m_fScreenRight;
float m_fScreenTop;
float m_fScreenBottom;
// CSprite* m_pFeichong; //飞虫精灵
CSprite* m_pFeichong[15]; //飞虫精灵
int m_iScore[15]; //拍中对应飞虫精灵的得分
int m_iCount; // 记录游戏中一共创建多少只飞虫
int m_iHighScore[5] ;// 最高的5局分数
CTextSprite* m_pScoreNum[5];//地图下方的5个文字显示精灵数组
CSprite* m_pMyName;
public:
CGameMain(); //构造函数
~CGameMain(); //析构函数
// Get方法
int GetGameState() { return m_iGameState; }
// Set方法
void SetGameState( const int iState ) { m_iGameState = iState; }
// 游戏主循环等
void GameMainLoop( float fDeltaTime );
void GameInit();
void GameRun( float fDeltaTime );
void GameEnd();
void OnKeyDown( const int iKey, const int bAltPress, const int bShiftPress, const int bCtrlPress );
void OnMouseMove( const float fMouseX, const float fMouseY );
void OnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY );
void Flying(const char* szName); //参数为设置飞虫飞行的名字
void OnSpriteColWorldLimit( const char *szName, const int iColSide );
void AddFlyBugs(); // 添加飞虫
CSprite* FindSpriteByName(const char* szName);//找到飞虫的名字
CTextSprite* FindTextSpriteByName(const char* szName);
};
/
//
extern CGameMain g_GameMain;
#endif // _LESSON_X_H_
LessonX.cpp
/
//
//
//
//
/
#include <Stdio.h>
#include "CommonClass.h"
#include "LessonX.h"
//
//
CGameMain g_GameMain;
//==============================================================================
//
// 大体的程序流程为:GameMainLoop函数为主循环函数,在引擎每帧刷新屏幕图像之后,都会被调用一次。
//==============================================================================
//
// 构造函数
CGameMain::CGameMain()
{
m_iGameState =0;
m_fGameTime =0.f;
m_iGameScore =0;
m_fPosX =0.f;
m_fPosY =0.f;
m_pKaishi =new CSprite("kaishi");
m_pPaizi =new CSprite("paizi");
m_pTime =new CTextSprite("Time");
m_pScore =new CTextSprite("Score");
m_fRotateTime =0.f;
m_fOldRotation =0.f;
//屏幕的4个边界值:上下左右
m_fScreenBottom =0.f;
m_fScreenLeft =0.f;
m_fScreenRight =0.f;
m_fScreenTop =0.f;
//m_pFeichong =new CSprite("feichong_0");
m_iCount =0;
for(int i=0;i<5;i++)
{
m_iHighScore[i]=0;
m_pScoreNum[i]=new CTextSprite(CSystem::MakeSpriteName("Score",i));
}
m_pMyName=new CSprite("MyName");
}
//==============================================================================
//
// 析构函数
CGameMain::~CGameMain()
{
}
//==============================================================================
//
// 游戏主循环,此函数将被不停的调用,引擎每刷新一次屏幕,此函数即被调用一次
// 用以处理游戏的开始、进行中、结束等各种状态.
// 函数参数fDeltaTime : 上次调用本函数到此次调用本函数的时间间隔,单位:秒
void CGameMain::GameMainLoop( float fDeltaTime )
{
switch( GetGameState())
{
// 初始化游戏,清空上一局相关数据
case 1:
{
GameInit();
SetGameState(2); // 初始化之后,将游戏状态设置为进行中
}
break;
// 游戏进行中,处理各种游戏逻辑
case 2:
{
// TODO 修改此处游戏循环条件,完成正确游戏逻辑
if(m_fGameTime>0)
{
GameRun( fDeltaTime );
}
else // 游戏结束。调用游戏结算函数,并把游戏状态修改为结束状态
{
SetGameState(0);
GameEnd();
}
}
break;
// 游戏结束/等待按空格键开始
case 0:
default:
break;
};
}
//=============================================================================
//
// 每局开始前进行初始化,清空上一局相关数据
void CGameMain::GameInit()
{
m_fPosX=m_pPaizi->GetSpritePositionX();
m_fPosY=m_pPaizi->GetSpritePositionY();
m_fOldRotation=m_pPaizi->GetSpriteRotation();
/*
//获取世界边界的值
m_fScreenLeft = CSystem::GetScreenLeft();
m_fScreenRight = CSystem::GetScreenRight();
m_fScreenTop = CSystem::GetScreenTop();
m_fScreenBottom = CSystem::GetScreenBottom();
// 设置该精灵的世界边界
m_pFeichong->SetSpriteWorldLimit(WORLD_LIMIT_NULL, m_fScreenLeft-10.f, m_fScreenTop-10.f, m_fScreenRight+10.f, m_fScreenBottom+10.f);
*/
}
//=============================================================================
//
// 每局游戏进行中
void CGameMain::GameRun( float fDeltaTime )
{
m_fGameTime -= fDeltaTime;
m_pTime->SetTextValue((int)m_fGameTime);
//在游戏中判断拍子拍下后,动作时间是否达到了0,是的话恢复拍子的角度
if(m_fRotateTime > 0)
{
m_fRotateTime -= fDeltaTime;
if(m_fRotateTime <= 0)
{
m_pPaizi->SetSpriteRotation(m_fOldRotation);
}
}
}
//=============================================================================
//
// 本局游戏结束
void CGameMain::GameEnd()
{
m_iGameState = 0;
m_pKaishi->SetSpriteVisible(true);
m_fGameTime = 0.f;
//m_pScore->SetTextValue((int)m_fGameTime);
m_pTime->SetTextValue((int)m_fGameTime);
CSystem::ShowCursor(true);
m_pPaizi->SetSpritePosition(m_fPosX,m_fPosY);
//m_pFeichong->DeleteSprite();
for(int i=0; i<m_iCount; i++)
{
m_pFeichong[i]->DeleteSprite();
}
m_iCount = 0;
// 把本局分数与历史最高的5次分数比较
if(m_iGameScore> m_iHighScore[4])
{
m_iHighScore[4] = m_iGameScore;
int temp = 0;
for(int i=4; i>0; i--)
{
if(m_iHighScore[i] > m_iHighScore[i-1])
{
temp = m_iHighScore[i];
m_iHighScore[i] = m_iHighScore[i-1];
m_iHighScore[i-1] = temp;
}
else
{
break;
}
}
}
char szName[256];
for(int i=0; i<5; i++)
{
sprintf(szName, "Score%d", i);
CTextSprite* tmpSprite=FindTextSpriteByName(szName);
tmpSprite->SetTextValue(m_iHighScore[i]);
}
}
//按键监听
void CGameMain::OnKeyDown( const int iKey, const int bAltPress, const int bShiftPress, const int bCtrlPress )
{
if( KEY_SPACE == iKey && 0 == m_iGameState )
{
m_iGameState = 1;
m_iGameScore = 0;
m_fGameTime = 30.f; //游戏总共的时间
// 更新当前游戏积分显示(清零上一局积分显示值)
m_pScore->SetTextValue(m_iGameScore);
// 更新当前游戏剩余时间显示, 由于游戏刚开始,所以直接设置为g_fMaxGameTime
m_pTime->SetTextValue(m_fGameTime);
// 隐藏 "按空格开始游戏" 这个提示图片
m_pKaishi->SetSpriteVisible(false);
// 隐藏鼠标
CSystem::ShowCursor(false);
// 从精灵模板中复制出一只精灵
//m_pFeichong->CloneSprite("feichong_muban1");
//创建飞虫精灵
AddFlyBugs();
// 调用函数,设置飞虫飞行轨迹
//Flying("feichong_0");
}
}
//监听拍子的移动
void CGameMain::OnMouseMove( const float fMouseX, const float fMouseY )
{
if(m_iGameState==1||m_iGameState==2)
{
m_pPaizi->SetSpritePosition(fMouseX, fMouseY);
m_pMyName->SetSpritePosition(fMouseX, fMouseY+10.0f);
}
}
void CGameMain::OnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY )
{
if(m_iGameState==1||m_iGameState==2)
{
m_pPaizi->SetSpriteRotation(m_fOldRotation - 10);
m_fRotateTime = 0.2f;
}
float fPosX, fPosY;
/*
fPosX = m_pFeichong->GetSpritePositionX();
fPosY = m_pFeichong->GetSpritePositionY();
// 飞虫中心点在拍子范围内,说明拍子打中飞虫
if(m_pPaizi->IsPointInSprite(fPosX, fPosY))
{
Flying("feichong_0");
}
*/
for(int i=0; i<m_iCount; i++)
{
fPosX = m_pFeichong[i]->GetSpritePositionX();
fPosY = m_pFeichong[i]->GetSpritePositionY();
// 飞虫中心点在拍子范围内,说明拍子打中飞虫
if(m_pPaizi->IsPointInSprite(fPosX, fPosY))
{
Flying(m_pFeichong[i]->GetName());
m_iGameScore += m_iScore[i];
}
}
m_pScore->SetTextValue(m_iGameScore);//更改游戏分数显示
}
//创建所有的飞虫
void CGameMain::AddFlyBugs()
{
for(int i=0; i<5; i++)
{
m_pFeichong[m_iCount]=new
CSprite(CSystem::MakeSpriteName("feichong_",m_iCount));
m_iScore[m_iCount]=1;
m_iCount++;
}
for(int i=0; i<7; i++)
{
m_pFeichong[m_iCount]=new
CSprite(CSystem::MakeSpriteName("feichong_",m_iCount));
m_iScore[m_iCount]=2;
m_iCount++;
}
for(int i=0; i<m_iCount; i++)//创建精灵实体
{
// 从精灵模板中复制出一只精灵
if(m_iScore[i] == 1)
{
m_pFeichong[i]->CloneSprite("feichong_muban1");
}
else
{
m_pFeichong[i]->CloneSprite("feichong_muban2");
}
// 获取屏幕边界值
m_fScreenLeft = CSystem::GetScreenLeft();
m_fScreenRight = CSystem::GetScreenRight();
m_fScreenTop = CSystem::GetScreenTop();
m_fScreenBottom = CSystem::GetScreenBottom();
// 设置该精灵的世界边界
m_pFeichong[i]->SetSpriteWorldLimit(WORLD_LIMIT_NULL, m_fScreenLeft-10.f, m_fScreenTop-10.f, m_fScreenRight+10.f, m_fScreenBottom+10.f);
Flying(m_pFeichong[i]->GetName());
}
}
//随机生成飞虫的飞行轨迹
void CGameMain::Flying(const char* szName)
{
int iDir = 0;
float fPosX, fPosY, fPosX1, fPosY1;
float fSpeed;
iDir = CSystem::RandomRange(0,3);//随机生成飞虫出现的方向
switch(iDir)
{
case 0: // 左方
fPosX = CSystem::RandomRange(m_fScreenLeft-5.f, m_fScreenLeft);
fPosY=CSystem::RandomRange(m_fScreenTop-5.f,m_fScreenBottom+5.f);
break;
case 1: // 下方
fPosX= CSystem::RandomRange(m_fScreenLeft-5.f, m_fScreenRight+5.f);
fPosY=CSystem::RandomRange(m_fScreenBottom,m_fScreenBottom+5.f);
break;
case 2: // 右方
fPosX = CSystem::RandomRange(m_fScreenRight, m_fScreenRight+5.f);
fPosY=CSystem::RandomRange(m_fScreenTop-5.f,m_fScreenBottom+5.f);
break;
case 3: // 上方m
fPosX= CSystem::RandomRange(m_fScreenLeft-5.f, m_fScreenRight+5.f);
fPosY = CSystem::RandomRange(m_fScreenTop-5.f, m_fScreenTop-5.f);
}
fSpeed = CSystem::RandomRange(10, 40);//随机生成飞虫飞行速度
//飞虫飞行的终点位置
fPosX1 = CSystem::RandomRange(m_fScreenLeft+15.f, m_fScreenRight-15.f);
fPosY1=CSystem::RandomRange(m_fScreenTop+15.f, m_fScreenBottom-15.f);
CSprite* tmpSprite=FindSpriteByName(szName);
tmpSprite->SetSpritePosition(fPosX, fPosY);
tmpSprite->SpriteMoveTo(fPosX1, fPosY1, fSpeed, false);
}
//飞虫与世界边界的碰撞
void CGameMain::OnSpriteColWorldLimit( const char *szName, const int iColSide )
{
/*
if(strcmp(szName, m_pFeichong->GetName())==0)
{
Flying("feichong_0");
}
*/
if(strstr(szName, "feichong")!=NULL)//判断是否是飞虫精灵
{
//遍历飞虫精灵判断是哪个飞虫
for(int i=0; i<m_iCount; i++)
{
if(strcmp(szName, m_pFeichong[i]->GetName())==0)
{
Flying( m_pFeichong[i]->GetName());//重新设置飞虫的飞行动作
}
}
}
}
CSprite* CGameMain::FindSpriteByName(const char* szName)
{
for(int i=0;i<m_iCount;i++)
if(strcmp(szName,m_pFeichong[i]->GetName())==0)
return m_pFeichong[i];
return NULL;
}
CTextSprite* CGameMain::FindTextSpriteByName(const char* szName)
{
for(int i=0;i<5;i++)
if(strcmp(szName,m_pScoreNum[i]->GetName())==0)
return m_pScoreNum[i];
return NULL;
}
Main.cpp
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#include "CommonClass.h"
#include "LessonX.h"
///
//
// 主函数入口
//
//
int PASCAL WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// 初始化游戏引擎
if( !CSystem::InitGameEngine( hInstance, lpCmdLine ) )
return 0;
// To do : 在此使用API更改窗口标题
CSystem::SetWindowTitle("LessonX");
// 引擎主循环,处理屏幕图像刷新等工作
while( CSystem::EngineMainLoop() )
{
// 获取两次调用之间的时间差,传递给游戏逻辑处理
float fTimeDelta = CSystem::GetTimeDelta();
// 执行游戏主循环
g_GameMain.GameMainLoop( fTimeDelta );
};
// 关闭游戏引擎
CSystem::ShutdownGameEngine();
return 0;
}
//==========================================================================
//
// 引擎捕捉鼠标移动消息后,将调用到本函数
void CSystem::OnMouseMove( const float fMouseX, const float fMouseY )
{
// 可以在此添加游戏需要的响应函数
g_GameMain.OnMouseMove(fMouseX,fMouseY);
}
//==========================================================================
//
// 引擎捕捉鼠标点击消息后,将调用到本函数
void CSystem::OnMouseClick( const int iMouseType, const float fMouseX, const float fMouseY )
{
// 可以在此添加游戏需要的响应函数
g_GameMain.OnMouseClick(iMouseType,fMouseX,fMouseY);
}
//==========================================================================
//
// 引擎捕捉鼠标弹起消息后,将调用到本函数
void CSystem::OnMouseUp( const int iMouseType, const float fMouseX, const float fMouseY )
{
// 可以在此添加游戏需要的响应函数
}
//==========================================================================
//
// 引擎捕捉键盘按下消息后,将调用到本函数
// bAltPress bShiftPress bCtrlPress 分别为判断Shift,Alt,Ctrl当前是否也处于按下状态。比如可以判断Ctrl+E组合键
void CSystem::OnKeyDown( const int iKey, const bool bAltPress, const bool bShiftPress, const bool bCtrlPress )
{
// 可以在此添加游戏需要的响应函数
g_GameMain.OnKeyDown(iKey,bAltPress,bShiftPress,bCtrlPress);
}
//==========================================================================
//
// 引擎捕捉键盘弹起消息后,将调用到本函数
void CSystem::OnKeyUp( const int iKey )
{
// 可以在此添加游戏需要的响应函数
}
//===========================================================================
//
// 引擎捕捉到精灵与精灵碰撞之后,调用此函数
void CSystem::OnSpriteColSprite( const char *szSrcName, const char *szTarName )
{
}
//===========================================================================
//
// 引擎捕捉到精灵与世界边界碰撞之后,调用此函数.
// iColSide : 0 左边,1 右边,2 上边,3 下边
void CSystem::OnSpriteColWorldLimit( const char *szName, const int iColSide )
{
g_GameMain.OnSpriteColWorldLimit(szName,iColSide);
}
三、运行截图
