C++面向对象课程设计.doc_第1页
C++面向对象课程设计.doc_第2页
C++面向对象课程设计.doc_第3页
C++面向对象课程设计.doc_第4页
C++面向对象课程设计.doc_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

上海锐格软件有限公司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 = new CSprite(kaishi);在GameInit中添加一下代码:m_pBeginSprite-SetSpriteVisible( false );3、 通过类向导创建CMyFish类。首先添加向左、向右、向上、向下4个方向的运动速度属性。添加OnMove方法控制小鱼的游动,bKeyDown表示键盘时按下的,iKey表示相应的是哪个按键。class CMyFish : public CSprite public:CMyFish(const char *szName);virtual CMyFish();public:void OnMove(bool bKeyDown,int iKey);private:floatm_fVelocityLeft;/ 控制的鱼的上下左右游动速度floatm_fVelocityRight;floatm_fVelocityUp;floatm_fVelocityDown; ;4、 在CMyFish类的构造函数中,首先初始4个方向的速度为0,然后设置小鱼缩小到原图的1/4,最后设置和世界边界的碰撞属性为WORLD_LIMIT_STICKY,当碰到世界边界时,小鱼静止不动。而小鱼的世界边界大小,我们设置为比屏幕的大小大2个单位。/ 设置鱼的模型大小为1/4SetSpriteScale( 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的时候,更改鱼的朝向。void CMyFish:OnMove(bool bKeyDown,int iKey)if(bKeyDown)switch(iKey)case KEY_A: / 左m_fVelocityLeft =30.f;break;case KEY_D: / 右m_fVelocityRight =30.f;break;case KEY_W: / 上m_fVelocityUp =15.f;break;case KEY_S: / 下m_fVelocityDown =15.f;break;elseswitch(iKey)case KEY_A: / 左m_fVelocityLeft =0.f;break;case KEY_D: / 右m_fVelocityRight =0.f;break;case KEY_W: / 上m_fVelocityUp =0.f;break;case KEY_S: / 下m_fVelocityDown =0.f;break;float fVelX= m_fVelocityRight - m_fVelocityLeft;float fVelY = m_fVelocityDown - m_fVelocityUp;SetSpriteLinearVelocity( fVelX,fVelY );/ 当速度不为0的时候,更改鱼的朝向if( fVelX 0.0001f )if( fVelX 0.0001f )SetSpriteFlipX( false );elseSetSpriteFlipX( true );6、 在CGameMain类中,首先添加一个小鱼对象的指针m_pMyFish。其次在构造函数中将m_pMyFish赋予NULL的初始值。再次在GameInit方法中初始化m_pMyFish。因为我们用new方法创建了m_pMyFish对象,分配了内存,所以我们在CGameMain类的析构函数中需要调用delete方法将 m_pMyFish使用的内存释放掉。if( NULL = m_pMyFish )/ 创建对象实例m_pMyFish=new CMyFish(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 );/ 等级设置为1m_pHpText-SetTextValue( 0 );/ 分数设置为0实验二 为游戏添加各种小鱼【实验内容】1、 创建普通鱼CNormalFish类;2、 新添的小鱼一共有4种,从鱼类模板中随机生成;3、 间隔1到2秒生成一只小鱼;4、 小鱼以随机速度从右向左移动;5、 小鱼碰到世界边界后消失;【实验思路】我们将在游戏中出现的敌方小鱼看成对象,这些对象具有共同的属性和方法,因此我们创建一个CNormalFish类。并且给这些鱼一定的速度,让他们从产生就开始运动,游过屏幕,然后到达世界边界的另一端就被删除。【实验指导】1、 根据类向导创建CNormalFish类。/ 普通类型的鱼,有等级属性。我们控制的鱼如果等级大于等于此鱼,则可以吃/ 掉其,如果小于,则被吃掉class CNormalFish : public CSpritepublic:CNormalFish( const char *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 );else if( iRandom 35 )CloneSprite( yu_muban3 );else if( iRandom 60 )CloneSprite( yu_muban2 );elseCloneSprite( 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类的实例。首先添加一个变量表示创建鱼的时间间隔和表示小鱼数目的变量。float m_fCreateNormalTime;int m_iCreatedFishCount;6、 然后在GameRun方法中,游戏循环将m_fCreateNormalTime递减,当m_fCreateNormalTime小于0时,创建一只鱼。并在100,300区间随机去个数除以100做为下一次创建小鱼的时间间隔。char szName128;m_fCreateNormalTime -=fDeltaTime;if( m_fCreateNormalTime pPtr=pSprite;pFish-pNext=NULL;pFish-pPrev=NULL;/ 插入链表中if( NULL = m_pFishHeader )m_pFishHeader=pFish;elseFishList*pTemp=m_pFishHeader;while( NULL != pTemp-pNext )pTemp=pTemp-pNext;pFish-pPrev=pTemp;pTemp-pNext=pFish;6、 同时在碰撞时,我们需要根据小鱼的名称获得小鱼的对象,因此添加GetFishFromName方法。CNormalFish* CGameMain:GetFishFromName( const char *szName )FishList*pFish=NULL;for( pFish=m_pFishHeader; NULL != pFish; pFish=pFish-pNext )if( strcmp( szName, pFish-pPtr-GetName() = 0 )return pFish-pPtr;return NULL;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类中添加碰撞处理函数:void OnColControlFish(CMyFish *pControlFish);定义如下:void CNormalFish:OnColControlFish(CMyFish *pControlFish).在上述函数中添加以下代码:if (pControlFish = NULL)return;elseif( 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 ); / 模型变大else if(m_pMyFish -GetHp() = 100 & m_pMyFish -GetLevel() = 2 )m_pMyFish -SetLevel( 3 );m_pMyFish -SetSpriteScale( 0.75f ); / 模型变大else if(m_pMyFish -GetHp() = 20 & m_pMyFish -GetLevel() = 1 )m_pMyFish -SetLevel( 2 );m_pMyFish -SetSpriteScale( 0.5f ); / 模型变大elsepControlFish-SetHp(0);9、 接着我们在CGameMain类中声明函数OnSpriteColSprite处理碰撞。OnSpriteColSprite函数的第一个参数是碰撞的产生方的名称,第二个参数是碰撞接受方的名称。由上面两个步骤,我们知道碰撞产生方是玩家控制的小鱼的名称,接受方是敌方小鱼的名称。而碰撞方是直接被删除。同时更新玩家控制小鱼的HP。if( 2 != GetGameState() | NULL = m_pMyFish)return;else if( 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将碰撞后的小鱼从链表中删除。void CGameMain:DeleteFishFromName( const char *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-pNext;pFish-pPtr-DeleteSprite();delete pFish;return;11、 在GameRun方法中更新玩家小鱼等级和HP的值m_pLevelText-SetTextValue( m_pMyFish-GetLevel() );m_pHpText-SetTextValue( m_pMyFish-GetHp() );12、 在CGameMain类中增加游戏输赢的判断方法IsGameLost和IsGameWin。玩家小鱼的等级达到4级, 并且HP大于1000时玩家赢。当玩家的HP值小于1时,游戏结束。13、 在GameMainLoop中加入游戏输赢判断。游戏结束或赢都回到游戏开始页面。/ 判断输赢if( IsGameWin() | IsGameLost() )SetGameState(0);GameEnd();else / 游戏未结束,继续游戏GameRun( fDeltaTime );14、 添加判断输赢的方法/ 游戏是否赢了-鱼的等级达到4级, 并且HP 10000bool CGameMain:IsGameWin() if (m_pMyFish-GetHp() 10000 & m_pMyFish-GetLevel() = 4)return true;return false;/ 是否输了 - HP小于1bool CGameMain:IsGameLost() if (m_pMyFish-GetHp() SetLevel( 1 );m_pMyFish-SetHp( 10 ); m_pMyFish-SetSpriteScale( 0.25f );16、 当游戏结束时,显示空格开始。m_pBeginSprite-SetSpriteVisible(true);实验四 增加一种小鱼【实验内容】增加一种小鱼,这种小鱼没有等级,只有HP(生命值),玩家控制的鱼,碰到此特殊鱼,不能吃掉该鱼,反而被减HP。 【实验思路】和一般的小鱼一样,创建一个CSpecialFish类,并且将创建出的对象加入到小鱼链表中。改造链表的节点,使链表能够容纳第二中小鱼。【实验指导】1、 为了将此类型的鱼添加到链表中,需要对结构体做以下修改。struct FishListCSprite*pPtr;FishList*pNext; / 指向链表的下一个FishList*pPrev; / 指向链表的上一个;2、 修改链表中增加小鱼的操作AddFish。/ 添加一个精灵到链表中void CGameMain:AddFish( CSprite *pSprite,int iType )if( NULL = pSprite )return;FishList*pFish=new FishList;/pFish-pPtr=pSprite;pFish-pNext=NULL;pFish-pPrev=NULL;/ 插入链表中if( NULL = m_pFishHeader )m_pFishHeader=pFish;elseFishList*pTemp=m_pFishHeader;while( NULL != pTemp-pNext )pTemp=pTemp-pNext;pFish-pPrev=pTemp;pTemp-pNext=pFish;3、 通过类向导创建CSpecialFish类,其继承与CSprite类。添加生命值属性,获得和设置生命值方法。intm_iHp;intGetHp();void SetHp( const int iHp );4、在其构造函数中将其作为模板鱼6的复制,并将其大小改变。CloneSprite( yu_muban6 );SetSpriteScale(0.5f);5、 接着为小鱼设置X轴坐标和一个随机的Y轴坐标。因为小鱼从右向左游,因此X坐标在世界边界的右边一些。而Y轴坐标的区间在世界边界的Top和Bottom值之间。同时因为小鱼向右游,我们需要将鱼的朝向改为朝向X轴的负方向。int iRandom=CSystem:RandomRange(int)CSystem:GetScreenTop(),(int)CSystem:GetScreenBottom();SetSpritePosition(CSystem:GetScreenRight() + 10.f, (float)iRandom );SetSpriteFlipX( true );6、 最后我们为小鱼设置一个随机速度和世界边界的碰撞属性和范围限制。速度在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();7、初始化其HP的值:m_iHp= 15;8、添加处理这种类型的鱼的碰撞功能函数OnColControlFish,其声明如下:void OnColControlFish(CMyFish *pControlFish);函数定义以及处理如下:void CSpecialFish:OnColControlFish(CMyFish *pControlFish)int HP;if (NULL = pControlFish)return ;elsepControlFish-SetHp( pControlFish-GetHp() - GetHp() ); HP = pControlFish-GetHp();if( HP SetHp(0);pControlFish-SetLevel(1);pControlFish-SetSpriteScale(0.25f);else if (HP SetLevel(1);pControlFish-SetSpriteScale(0.25f);else if (HP SetLevel(2);pControlFish-SetSpriteScale(0.5f);else if (HP SetLevel(3);pControlFish-SetSpriteScale(0.75f);9、在GameRun,生成特殊的鱼,并将它添加到链表中去。char szNameSpecial128;在if( m_fCreateNormalTime GetName(), szSrcName ) = 0 )判断里面。/ 找到该鱼的对象实例,调用碰撞处理函数if(strstr( szTarName, putongyu ) != NULL )CNormalFish* pFish=(CNormalFish*)( GetFishFromName( szTarName )-pPtr);if( NULL != pFish )pFish-OnColControlFish( m_pMyFish );else if ( strstr(szTarName, specialyu) != NULL)CSpecialFish* pFish=(CSpecialFish*)(GetFishFromName( szTarName )-pPtr);if( NULL != pFish )pFish-OnColControlFish( m_pMyFish );/ 碰撞之后,不管谁吃谁,都将游戏里的鱼删除掉DeleteFishFromName( szTarName );实验五 *为小鱼增加父类【实验内容】为CNormalFish、CSpecialFish、CMyFish增加父类CGameSprite。【实验思路】由于CNormalFish、CSpecialFish和CMyFish有许多共同属性和方法,因此把他们的共性提取出来,使用这些共性为他们创建一个父类CGameSprite。增加父类是为了方便以后再有这方面的类需要创建的时候,就可以直接继承于CGameSprite这个类【实验指导】1、 通过类向导添加CGameSprite类,其继续于CSprite类。在类定义前,通过类声明,声明CMyFish类。class CMyFish;class CGameSprite : public CSpritepublic:/ 结合该变量的应用,考虑为什么要用静态成员变量?普通成员变量和静态成员变量的生命周期有什么不同?staticintm_iCreatedFishCount;public:CGameSprite( const char *szName ) : CSprite( szName ) CGameSprite() / Get/ 获取精灵生命值intGetLevel()

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论