10 C课程设计贪吃鱼汇总.docx
《10 C课程设计贪吃鱼汇总.docx》由会员分享,可在线阅读,更多相关《10 C课程设计贪吃鱼汇总.docx(21页珍藏版)》请在冰豆网上搜索。
10C课程设计贪吃鱼汇总
FunCode程序设计实验教材系列
C++面向对象课程设计
实验指南
上海锐格软件有限公司
课程设计二贪吃鱼
一、游戏介绍
贪吃鱼是玩家用WSAD键控制鱼上下左右运动,吃掉其中比自己等级小或者相等的鱼。
鱼从右侧游向左侧。
游戏中有两种鱼,其中一种如果被自己等级高,就被吃掉了,另一种鱼如果等级比自己高,只扣除一定的生命值。
吃到越多的鱼,小鱼就会相应的长大。
二、实验目的
综合应用C++语言和面向对象的知识开发一款小游戏。
三、实验内容
在一个深海里,玩家通过键盘WSAD键控制己方小鱼移动,吃到其中比自己等级低或者等级相等的鱼。
要求如下:
1、游戏运行时,初始界面如下图。
2、按下空格键,游戏开始,玩家通过WSAD键控制小鱼移动;小鱼不能游出世界边界。
3、有2种类型的鱼,普通鱼和特殊鱼。
碰到普通鱼时,如果等级比自己高,小鱼就被吃掉了。
碰到特殊鱼,如果等级比自己高,小鱼只是被扣掉一定的生命值。
4、敌方的小鱼都是从右向左一定。
5、玩家小鱼被吃掉后,游戏停止,重新显示初始界面。
游戏初始界面
四、实验指南
实验准备
打开FunCode,创建一个新的C++项目。
注意:
项目名称必须为英文和数字,且不能有空格。
点击“项目”→“导入地图模板”,从对话框中选取名称为eatfish的模板导入。
导入成功后,界面如下:
实验一游戏开始和控制玩家小鱼
【实验内容】
1、按空格键,游戏开始,“空格开始”字样消失。
2、创建CMyFish类,并创建对象实例玩家控制的小鱼。
3、小鱼的初始大小为原大小的1/4。
4、小鱼左右运动的速度为30。
上下运动的速度为15。
5、小鱼碰到世界边界时,静止。
6、游戏开始后,通过键盘WSAD键控制小鱼移动。
7、在游戏中显示游戏的等级和玩家控制的鱼的HP。
【实验思路】
按空格键开始游戏,属于键盘按下事件,我们在dOnKeyDown函数中编写代码。
在游戏中,我们运用面向对象的知识将小鱼看成一个对象,并为这个对象添加一个类叫CMyFish。
类具有属性和方法,要控制小鱼能在各个方向上自由的游动,我们为CMyFish类添加上下左右四个方向的速度,并且我们为小鱼添加OnMove方法控制小鱼的游动状态。
【实验指导】
1、在OnKeyDown中,当按下的按键为空格键并且此时的游戏状态为0,则设置游戏的状态为1。
0表示此时游戏为等待状态,未开始。
1表示游戏进行初始化,初始化后会进入2游戏运行状态。
//按下空格键,游戏开始
if(KEY_SPACE==iKey&&0==GetGameState())
{
SetGameState
(1);
}
2、在游戏初始化函数GameInit中隐藏"按空格开始游戏"这个提示图片。
在CGameMain中添加成员变量:
CSprite*m_pBeginSprite;
在CGameMain的构造函数中进行初始化:
m_pBeginSprite=newCSprite("kaishi");
在GameInit中添加一下代码:
m_pBeginSprite->SetSpriteVisible(false);
3、通过类向导创建CMyFish类。
首先添加向左、向右、向上、向下4个方向的运动速度属性。
添加OnMove方法控制小鱼的游动,bKeyDown表示键盘时按下的,iKey表示相应的是哪个按键。
classCMyFish:
publicCSprite
{
public:
CMyFish(constchar*szName);
virtual~CMyFish();
public:
voidOnMove(boolbKeyDown,intiKey);
private:
floatm_fVelocityLeft;//控制的鱼的上下左右游动速度
floatm_fVelocityRight;
floatm_fVelocityUp;
floatm_fVelocityDown;
};
4、在CMyFish类的构造函数中,首先初始4个方向的速度为0,然后设置小鱼缩小到原图的1/4,最后设置和世界边界的碰撞属性为WORLD_LIMIT_STICKY,当碰到世界边界时,小鱼静止不动。
而小鱼的世界边界大小,我们设置为比屏幕的大小大2个单位。
//设置鱼的模型大小为1/4
SetSpriteScale(0.25f);
//世界边界限制
SetSpriteWorldLimit(WORLD_LIMIT_STICKY,
CSystem:
:
GetScreenLeft()-2.f,CSystem:
:
GetScreenTop()-2.f,
CSystem:
:
GetScreenRight()+2.f,
CSystem:
:
GetScreenBottom()+2.f);
5、编写CMyFish类OnMove方法代码。
首先判断当前按键是按下还是松开的,其次判断是哪个按键的消息,根据这两个判断,为4个方向的速度矢量赋值。
再次算出X后和Y轴上的速度,并设置小鱼的速度。
最后根据X轴方向的速度值设置鱼的朝向。
当速度不为0的时候,更改鱼的朝向。
voidCMyFish:
:
OnMove(boolbKeyDown,intiKey)
{
if(bKeyDown)
{
switch(iKey)
{
caseKEY_A:
//左
m_fVelocityLeft=30.f;
break;
caseKEY_D:
//右
m_fVelocityRight=30.f;
break;
caseKEY_W:
//上
m_fVelocityUp=15.f;
break;
caseKEY_S:
//下
m_fVelocityDown=15.f;
break;
}
}
else
{
switch(iKey)
{
caseKEY_A:
//左
m_fVelocityLeft=0.f;
break;
caseKEY_D:
//右
m_fVelocityRight=0.f;
break;
caseKEY_W:
//上
m_fVelocityUp=0.f;
break;
caseKEY_S:
//下
m_fVelocityDown=0.f;
break;
}
}
floatfVelX=m_fVelocityRight-m_fVelocityLeft;
floatfVelY=m_fVelocityDown-m_fVelocityUp;
SetSpriteLinearVelocity(fVelX,fVelY);
//当速度不为0的时候,更改鱼的朝向
if(fVelX<-0.0001f||fVelX>0.0001f)
{
if(fVelX>0.0001f)
SetSpriteFlipX(false);
else
SetSpriteFlipX(true);
}
}
6、在CGameMain类中,首先添加一个小鱼对象的指针m_pMyFish。
其次在构造函数中将m_pMyFish赋予NULL的初始值。
再次在GameInit方法中初始化m_pMyFish。
因为我们用new方法创建了m_pMyFish对象,分配了内存,所以我们在CGameMain类的析构函数中需要调用delete方法将m_pMyFish使用的内存释放掉。
if(NULL==m_pMyFish)
{
//创建对象实例
m_pMyFish=newCMyFish("kongzhiyu");
}
7、在OnKeyDown和OnkeyUp中响应小鱼OnMove方法,它们的区别只是第一个参数的值不同。
下面是OnKeyDown方法中的调用。
if(2==GetGameState())
{
m_pMyFish->OnMove(true,iKey);
}
8、在CGameMain类的GameInit方法中显示当前等级和分数。
m_pLevelText和m_pHpText需要在CGameMain类中声明,并在其构造函数中定义,其类类型为CTextSprite。
//更新当前等级/HP显示
m_pLevelText->SetTextValue
(1);//等级设置为1
m_pHpText->SetTextValue(0);//分数设置为0
实验二为游戏添加各种小鱼
【实验内容】
1、创建普通鱼CNormalFish类;
2、新添的小鱼一共有4种,从鱼类模板中随机生成;
3、间隔1到2秒生成一只小鱼;
4、小鱼以随机速度从右向左移动;
5、小鱼碰到世界边界后消失;
【实验思路】
我们将在游戏中出现的敌方小鱼看成对象,这些对象具有共同的属性和方法,因此我们创建一个CNormalFish类。
并且给这些鱼一定的速度,让他们从产生就开始运动,游过屏幕,然后到达世界边界的另一端就被删除。
【实验指导】
1、根据类向导创建CNormalFish类。
//普通类型的鱼,有等级属性。
我们控制的鱼如果等级大于等于此鱼,则可以吃//掉其,如果小于,则被吃掉
classCNormalFish:
publicCSprite
{
public:
CNormalFish(constchar*szName);
~CNormalFish(){}
};
2、在CNormalFish类的构造函数中。
首先生成一个1到100的随机数,根据随机数的大小,我们选择不同的小鱼模板。
当随机数小于15时我们选择yu_muban4的小鱼做为模板,当随机数在[15,35]区间时,我们选择yu_muban3做为模板,当随机数在[35,60]区间时,我们选择yu_muban2做为模板,当随机数在[60,100]区间,我们选择yu_muban1做为模板。
intiRandom=CSystem:
:
RandomRange(1,100);
if(iRandom<15)
{
CloneSprite("yu_muban4");
}
elseif(iRandom<35)
{
CloneSprite("yu_muban3");
}
elseif(iRandom<60)
{
CloneSprite("yu_muban2");
}
else
{
CloneSprite("yu_muban1");
}
3、接着为小鱼设置X轴坐标和一个随机的Y轴坐标。
因为小鱼从右向左游,因此X坐标在世界边界的右边一些。
而Y轴坐标的区间在世界边界的Top和Bottom值之间。
同时因为小鱼向右游,我们需要将鱼的朝向改为朝向X轴的负方向。
iRandom=CSystem:
:
RandomRange((int)CSystem:
:
GetScreenTop(),
(int)CSystem:
:
GetScreenBottom());
SetSpritePosition(CSystem:
:
GetScreenRight()+10.f,(float)iRandom);
SetSpriteFlipX(true);
4、最后我们为小鱼设置一个随机速度和世界边界的碰撞属性和范围限制。
速度在[10,25]区间。
当小鱼碰到世界边界时小鱼消失,因此设置为WORLD_LIMIT_KILL,而范围,我们需设置的比屏幕边界大一些,让小鱼完全游出屏幕时才消失。
iRandom=CSystem:
:
RandomRange(10,25);
SetSpriteLinearVelocityX(-(float)iRandom);
SetSpriteWorldLimit(WORLD_LIMIT_NULL,CSystem:
:
GetScreenLeft()-10.f,CSystem:
:
GetScreenTop(),CSystem:
:
GetScreenRight()+20.f,
CSystem:
:
GetScreenBottom());
5、完成了CNormalFish类后,我们需要在CGameMain类中生成小鱼,即生成CNormalFish类的实例。
首先添加一个变量表示创建鱼的时间间隔和表示小鱼数目的变量。
floatm_fCreateNormalTime;
intm_iCreatedFishCount;
6、然后在GameRun方法中,游戏循环将m_fCreateNormalTime递减,当m_fCreateNormalTime小于0时,创建一只鱼。
并在[100,300]区间随机去个数除以100做为下一次创建小鱼的时间间隔。
charszName[128];
m_fCreateNormalTime-=fDeltaTime;
if(m_fCreateNormalTime<=0.f)
{
intiNextTime=CSystem:
:
RandomRange(100,300);
m_fCreateNormalTime=(float)iNextTime/100.f;
sprintf(szName,"putongyu_%d",m_iCreatedFishCount);
m_iCreatedFishCount++;
CNormalFish*fish=newCNormalFish(szName);
}
实验三吃小鱼
【实验内容】
1、玩家控制小鱼与其它小鱼碰撞,当玩家小鱼等级小于敌方小鱼时,玩家小鱼被吃掉,反之敌方小鱼被吃掉;每吃掉一只小鱼,玩家小鱼的分数增加为敌方小鱼的HP值
2、需要根据小鱼的等级确定碰撞的不同结果,因此为小鱼添加等级的属性;
3、同时不同的等级拥有不同的分数,因此为小鱼增加分数的属性;
【实验思路】
首先为CMyFish类增加碰撞属性;然后为CMyFish类增加表示小鱼等级和HP的属性,增加设置等级、HP值和获得等级、HP值的方法;同理为CNormalFish类增加碰撞属性及其小鱼等级、HP的属性和获得等级、HP值的方法。
CMyFish、CNormalFish类小鱼,是在创建时就设置好了其等级和HP值,因此我们可以在构造函数中增加两个参数,直接在创建小鱼时,就初始化好等级和HP值。
在CGameMain类的OnSpriteColSprite碰撞函数中检测碰撞,并更新游戏界面中HP的值。
在OnSpriteColSprite中,我可以知道碰撞双方的名称,但我们还需要根据名称获得具体的小鱼的对象,以便获得小鱼的等级和HP值等属性,因此我们每创建一只小鱼,就把这只小鱼增加到链表中管理起来。
这样我们就增加了一个FishList链表。
【实验指导】
1、首先为MyFish设置碰撞属性。
MyFish产生碰撞,敌方小鱼接受碰撞。
这个在控制面板中已经设置好了,如果想自己设置么可以添加如下代码,将控制面板中碰撞属性取消,在构造函数中设置碰撞属性。
SetSpriteCollisionActive(true,false);
2、其次为敌方小鱼设置碰撞属性。
敌方小鱼接受碰撞,这个属性和1一样,也在界面中设置好了,如果想要自行设置,可以取消界面中的设置,然后在CNormalFish类的构造函数中增加如下代码。
SetSpriteCollisionActive(false,true);
3、为CMyFish和CNormalFish增加等级和HP值的属性,和设置、获得这两个属性的方法,最后改造构造函数。
intm_iHp;
intm_iLevel;
CMyFish:
:
CMyFish(constchar*szName,constintiHp,constintiLevel);
CNormalFish:
:
CNormalFish(constchar*szName);//普通鱼的HP和level随机生成
4、在LessonX.h中定义结构体FishList,并在CGameMain类中添加一个头节点m_pFishHeader。
structFishList
{
CNormalFish*pPtr;
FishList*pNext;//指向链表的下一个
FishList*pPrev;//指向链表的上一个
};
5、在CGameMain类中添加AddFish方法实现将小鱼添加到链表中,参数为生成的敌方小鱼的指针。
voidCGameMain:
:
AddFish(CNormalFish*pSprite)
{
if(NULL==pSprite)
return;
FishList*pFish=newFishList;
pFish->pPtr=pSprite;
pFish->pNext=NULL;
pFish->pPrev=NULL;
//插入链表中
if(NULL==m_pFishHeader)
m_pFishHeader=pFish;
else
{
FishList*pTemp=m_pFishHeader;
while(NULL!
=pTemp->pNext)
pTemp=pTemp->pNext;
pFish->pPrev=pTemp;
pTemp->pNext=pFish;
}
}
6、同时在碰撞时,我们需要根据小鱼的名称获得小鱼的对象,因此添加GetFishFromName方法。
CNormalFish*CGameMain:
:
GetFishFromName(constchar*szName)
{
FishList*pFish=NULL;
for(pFish=m_pFishHeader;NULL!
=pFish;pFish=pFish->pNext)
{
if(strcmp(szName,pFish->pPtr->GetName())==0)
returnpFish->pPtr;
}
returnNULL;
}
7、在CGameMain类的GameRun方法中,将创建的小鱼对象的指针添加到链表中。
8、玩家的小鱼根据HP值分为1-4不同的等级,初始HP的值为10,等级为1。
当HP大于20时且等级为1时,玩家升为2级;当HP值大于100时且等级为2时,玩家升为3级;当HP值大于1000时且等级为3时,玩家升为4级。
每升1级,鱼的大小也变大25%。
在CNormalFish类中添加碰撞处理函数:
voidOnColControlFish(CMyFish*pControlFish);
定义如下:
voidCNormalFish:
:
OnColControlFish(CMyFish*pControlFish)
{
...
}
在上述函数中添加以下代码:
if(pControlFish==NULL)
{
return;
}
else
{
if(m_pMyFish->GetLevel()>=GetLevel())
{
pControlFish->SetHp(pControlFish->GetHp()+GetHp());
if(m_pMyFish->GetHp()>=1000&&m_pMyFish->GetLevel()==3)
{
m_pMyFish->SetLevel(4);
m_pMyFish->SetSpriteScale(1.0f);//模型变大
}
elseif(m_pMyFish->GetHp()>=100&&m_pMyFish->GetLevel()==2)
{
m_pMyFish->SetLevel(3);
m_pMyFish->SetSpriteScale(0.75f);//模型变大
}
elseif(m_pMyFish->GetHp()>=20&&m_pMyFish->GetLevel()==1)
{
m_pMyFish->SetLevel
(2);
m_pMyFish->SetSpriteScale(0.5f);//模型变大
}
}
else
{
pControlFish->SetHp(0);
}
}
9、接着我们在CGameMain类中声明函数OnSpriteColSprite处理碰撞。
OnSpriteColSprite函数的第一个参数是碰撞的产生方的名称,第二个参数是碰撞接受方的名称。
由上面两个步骤,我们知道碰撞产生方是玩家控制的小鱼的名称,接受方是敌方小鱼的名称。
而碰撞方是直接被删除。
同时更新玩家控制小鱼的HP。
if(2!
=GetGameState()||NULL==m_pMyFish)
return;
elseif(strcmp(m_pMyFish->GetName(),szSrcName)==0)
{
if(!
strstr(szTarName,"putongyu"))
return;
CNormalFish*pFish=GetFishFromName(szTarName);
if(NULL!
=pFish)
{
pFish->OnColControlFish(m_pMyFish);
DeleteFishFromName(szTarName);
}
}
10、DeleteFishFromName将碰撞后的小鱼从链表中删除。
voidCGameMain:
:
DeleteFishFromName(constchar*szName)
{
FishList*pFish=NULL;
for(pFish=m_pFishHeader;NULL!
=pFish;pFish=pFish->pNext)
{
if(strcmp(szName,pFish->pPtr->GetName())==0)
{
if(NULL!
=pFish->pNext)
{
pFish->pNext->pPrev=pFish->pPrev;
}
if(NULL!
=pFish->pPrev)
{
pFish->pPrev->pNext=pFish->pNext;
}
if(pFish==m_pFishHeader)
{
m_pFishHeader=m_pFishHeader-