C++语言课程设计一迷你高尔夫


    C++语言课程设计一迷你高尔夫 一、实验内容 玩家通过按下键盘上的上下左右方向键控制球的移动,使其最终到达出口则游戏通关。 要求如下: 1、 游戏分成3关,第一关、第二关、第三关界面图如下: 第一关 第二关 第三关 2、 启动游戏进入第一关,胜利后进入第二关,如果第三关通关,则游戏重新回到第一关。 3、 游戏玩法是通关控制键盘上的上下左右方向键控制球的运动,单击方向键,则球获得一个向该方向直线运动的速度。如果球遇到方块,则球停止运动,如果遇到黑洞,则游戏结束,重新开始该游戏,遇到出口则通关。 4、 球静止状态下会有箭头指示球可以运动的方向,运动状态下则箭头消失。如果球运动出世界边界,则游戏结束,重新回到该游戏。 二、实验指南 实验一 开始实验 【实验任务】 步骤一、打开FunCode,创建一个的C++语言项目; 步骤二、导入GolfGame场景。 【实验思路】 按实验指导完成。 【实验指导】 1、 打开FunCode,点击“项目”菜单,选择“创建C++工程” 注意:工程名名称要求字母开头,只能包含字母和数字,且名字中间不能有空格。 2、 点击菜单“项目”中的“导入地图模块”,如图一。跳出一个对话框,选中“GolfGame”模板,点击“导入到工程”按钮,如图二。 图 一 图 二 3、 导入成功后的,界面如下图所示: 地图不仅包括界面设计,还包括该游戏可能要用到的其他精灵。添加到“场景”中的精灵,都已经取好名称,并根据程序要求设置好中心点、链接点等,学生只需要直接编程就可以。 实验二 游戏关卡初始化 【实验内容】 步骤一、关卡地图初始化 步骤二、清除上一关卡数据 步骤三、根据当前关卡,选择关卡数据 【实验思路】 游戏开始的时候首先要清除上一关的游戏数据,即将上一关创建的精灵从地图中删掉。 将游戏地图分成12*12的方格界面,游戏总共分成三关,因此我们需要用三个二维数组m_iLevelData1[GRID_COUNT][GRID_COUNT] m_iLevelData2[GRID_COUNT][GRID_COUNT] m_iLevelData3[GRID_COUNT][GRID_COUNT] (其中GRID_COUNT的值为12) 来存放这三关的数据即可。二维数组中0表示该位置不创建精灵,否则根据不同的值创建不同精灵,RIGID_BLOCK(值为1)表示创建一个方块精灵,BLACK_HOLE(值为2)表示创建一个黑洞精灵,GOLF_EXIT(值为3)表示创建一个出口精灵。每次把代表该关卡的二维数组的数据拷贝到存储当前关卡m_iGridData的二维数组中。 【实验指导】 1、 进入LessonX.h的CGameMain类中,添加以下成员变量的声明: static const float m_fGridStartX ; // 第一块方块的起始坐标 = -(GRID_COUNT * g_fGridSize * 0.5 - g_fGridSize / 2) static const float m_fGridStartY ; static const float m_fGridSize; // 每块的大小,包括球、出口等都是此大小 int m_iRigidBlockCount; // 本关卡创建的阻挡物方块数量 int m_iBlackHoleCount ; // 本关卡创建的黑洞数量 int m_iGolfExitCount; // 本关卡创建的出口的数量 int m_iCurLevel; // 当前关卡 int m_iMoveState ; // 控制球的移动状态:0当前静止,可以移动, 1、2、3、4:代表上下左右4个方向移动中,按键无响应 int m_iGridData[GRID_COUNT][GRID_COUNT]; // 二维数组,存储当 前关卡N*N的矩阵方块信息 static const int m_iLevelData1[GRID_COUNT][GRID_COUNT] ; static const int m_iLevelData2[GRID_COUNT][GRID_COUNT] ; static const int m_iLevelData3[GRID_COUNT][GRID_COUNT] ; vector<CSprite*> m_vRigidBlock; //阻挡物精灵向量数组 vector<CSprite*> m_vBlackHole; //黑洞精灵向量数组 vector<CSprite*> m_vGolfExit; //出口精灵向量数组 int m_iControlStartX; //控制球的初始X坐标,根据关卡数据自行指定 int m_iControlStartY; //球的初始Y坐标 2、 进入LessonX.h中在头文件声明的后面添加下面的宏定义代码: #define GRID_COUNT 12 // N * N 的矩阵方块,一个N的大小 #define MAX_LEVEL 3 // 最大关卡数量。如果要增加关卡,请先修改此值 #define RIGID_BLOCK 1 // 以下3个分别为方块阻挡物、黑洞、出口的值 #define BLACK_HOLE 2 #define GOLF_EXIT 3 3、 进入LessonX.cpp中添加上面的成员变量的初始化: 1) 在构造函数中把m_iGameState的值由0改为1: m_iGameState = 1; 2) 在构造函数中添加下面代码: m_iRigidBlockCount = 0; // 本关卡创建的阻挡物方块数量 m_iBlackHoleCount = 0; // 本关卡创建的黑洞数量 m_iGolfExitCount = 0; m_iCurLevel = 1; m_iControlStartX = 0; //球的初始X坐标 m_iControlStartY = 0; //球的初始Y坐标 3) 对于const类型的成员变量,我们需要在函数外面单独进行初始化,在文件最后面添加如下代码: const float CGameMain::m_fGridStartX =-27.5f; const float CGameMain::m_fGridStartY =-27.5f; const float CGameMain::m_fGridSize =5.f; const int CGameMain::m_iLevelData1[GRID_COUNT][GRID_COUNT] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, 0, 0, 0}, {0, 0, 0, RIGID_BLOCK, 0, 0, 0, 0, RIGID_BLOCK, 0, 0, 0}, {0, 0, 0, RIGID_BLOCK, 0, 0, 0, 0, RIGID_BLOCK, 0, 0, 0}, {0, 0, 0, RIGID_BLOCK, 0, 0, 0, 0, BLACK_HOLE, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, GOLF_EXIT, RIGID_BLOCK, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; const int CGameMain::m_iLevelData2[GRID_COUNT][GRID_COUNT]={ {0, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, 0, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, 0, 0, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, 0, 0, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, 0, 0, 0, 0, RIGID_BLOCK, 0, 0, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, GOLF_EXIT, RIGID_BLOCK, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, 0}, {0, RIGID_BLOCK, 0, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, 0, RIGID_BLOCK, 0} }; const int CGameMain::m_iLevelData3[GRID_COUNT][GRID_COUNT]={ {0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, RIGID_BLOCK, 0, 0}, {0, 0, RIGID_BLOCK, RIGID_BLOCK, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, RIGID_BLOCK}, {RIGID_BLOCK, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, GOLF_EXIT, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, RIGID_BLOCK, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, 0}, {0, 0, 0, RIGID_BLOCK, 0, 0, 0, 0, 0, 0, RIGID_BLOCK, 0}, {0, 0, 0, 0, BLACK_HOLE, RIGID_BLOCK, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; 二维数组中0表示该位置不创建精灵,否则根据不同的值创建不同精灵,RIGID_BLOCK(值为1)表示创建一个方块精灵,BLACK_HOLE(值为2)表示创建一个黑洞精灵,GOLF_EXIT(值为3)表示创建一个出口精灵。 4) 进入GameInit函数里面,将球的运动状态初始化为静止,添加下面代码: m_iMoveState=0; 4、 游戏初始化的时候,首先我们需要将前边添加的精灵全部删除掉,因此需要自定义的创建清除所有精灵函数ClearAllSprite()来实现这个功能。 1) 进入LessonX.h文件的CGameMain类中添加该函数的声明: void ClearAllSprite(); 2) 在LessonX.cpp最后面添加该函数的定义: void CGameMain:: ClearAllSprite() { } 3) 再使用3个循环,分别将上一关卡创建的3种精灵删除掉。在上边定义的函数中添加如下代码: int iLoop = 0; for( iLoop = 0; iLoop < m_vRigidBlock.size(); iLoop++ ) { m_vRigidBlock[iLoop]->DeleteSprite(); } for( iLoop = 0; iLoop < m_vBlackHole.size(); iLoop++ ) { m_vBlackHole[iLoop]->DeleteSprite(); } for( iLoop = 0; iLoop < m_vGolfExit.size(); iLoop++ ) { m_vGolfExit[iLoop]->DeleteSprite(); } 其中m_vRigidBlock、m_vBlackHole、m_vGolfExit是存储三种精灵的向量数组,每一个循环都遍历一遍向量数组并调用数组中每个精灵的DeleteSprite函数即可。 m_vRigidBlock.size()、m_vBlackHole.size()、m_vGolfExit.size()表示每种精灵的总数。 4) 最后在GameInit()中添加调用此函数的代码: ClearAllSprite(); 5、 在GameInit()中,我们也需要对关卡进行选择初始化。因此我们需要自定义一个初始化关卡函数InitLevel ()来实现这个功能。 1) 进入LessonX.h文件的CGameMain类中添加该函数的声明: void InitLevel(); 2) 在LessonX.cpp最后面添加该函数的定义: void CGameMain:: InitLevel() { } 3) 初始化关卡,要根据当前关卡,选择关卡的数据,即将代表关卡的二维数组中的数据拷贝到m_iGridData中,同时设置控制球在每个数组中的起始位置。首先把需要的数据初始化为0,代码如下: // 总数置0,重新创建 m_iRigidBlockCount = 0; m_iBlackHoleCount = 0; m_iGolfExitCount = 0; 4) 选择关卡我们使用了switch-case结构,程序通过判断switch中的参数进入到不同的case中去,每个case就是一种情况的实现。代码如下: // 根据当前关卡,选择关卡数据 switch( m_iCurLevel ) { case 2: { m_iControlStartX = 5; m_iControlStartY = 9; memcpy( m_iGridData, m_iLevelData2, sizeof(int) * GRID_COUNT * GRID_COUNT ); } break; case 3: { m_iControlStartX = 3; m_iControlStartY = 6; memcpy( m_iGridData, m_iLevelData3, sizeof(int) * GRID_COUNT * GRID_COUNT ); } break; // Level1 或者g_iCurLevel错误 case 1: default: { m_iControlStartX = 5; m_iControlStartY = 6; memcpy( m_iGridData, m_iLevelData1, sizeof(int) * GRID_COUNT * GRID_COUNT ); } break; }; memcpy函数作用是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。因为二维数组在内存中的存放方式是连续的,因此我们将源地址拷贝给m_iGridData的起始地址之后,系统后自动根据m_iGridData的下标来找到正确的值。 5) 最后在GameInit()中添加调用此函数的代码: InitLevel(); 至此,本实验结束。 实验三 初始化游戏精灵 【实验内容】 步骤一、创建精灵 步骤二、初始化精灵位置 【实验思路】 遍历二维数组m_iGridData,根据数组值生成对应的精灵实例:值为0的时候不用创建,需要创建的精灵名字前缀为(按照宏定义的1,2,3顺序):RigidBlock, BlackHole, GolfExit。每创建一种精灵,将其总数加1 :m_iRigidBlockCount, m_iBlackHoleCount,m_iGolfExitCount。 【实验指导】 1、 进入LessonX.h,CGameMain类中添加下面成员变量的声明: CSprite* m_pControlBall; //控制球精灵 CSprite* m_pGolfArrow; //指示箭头精灵 在LessonX.cpp中CGameMain类在构造函数里面添加上面成员变量的初始化: m_pControlBall = new CSprite(“ControlBall“); m_pGolfArrow = new CSprite(“GolfArrow“); 2、 创建精灵之后需要将精灵移到特定位置,因此我们需要定义一个自定义的函数MoveSpriteToBlock来实现这个功能。 6) 进入LessonX.h中添加该函数的声明: void MoveSpriteToBlock( CSprite* tmpSprite, const int iIndexX, const int iIndexY ); 7) 在LessonX.cpp最后面添加该函数的定义: void CGameMain::MoveSpriteToBlock( CSprite* tmpSprite, const int iIndexX, const int iIndexY ) { } 8) 传入该函数的是精灵实体以及x,y坐标参数。再通过SetSpritePosition函数设置精灵位置,在该函数里面添加如下代码: float fPosX = m_fGridStartX + iIndexX * m_fGridSize; float fPosY = m_fGridStartY + iIndexY * m_fGridSize; tmpSprite->SetSpritePosition(fPosX, fPosY); 3、 这里定义一个函数CreateAllSprite()来创建控制球、方块精灵、出口精灵和黑洞精灵。然后在函数内部添加代码创建精灵。 原理是通过两个for循环来,判断m_iGridData的值,如果为0,则不创建,如果为RIGID_BLOCK则创建一个方块精灵,为 BLACK_HOLE则创建一个黑洞精灵,为GOLF_EXIT则创建一个出口精灵。由于我们预先在地图中摆放了三个模板精灵,因此只需要使用CloneSprite函数即可创建新的精灵。然后再调用MoveSpriteToBlock函数将精灵移动到指定位置。最后每创建一个实现精灵,将它添加到相应的精灵向量数组中。 1) 进入LessonX.h文件的CGameMain类中添加该函数的声明: void CreateAllSprite(); 2) 在LessonX.cpp最后面添加该函数的定义: void CGameMain:: CreateAllSprite() { } 3) 在定义汗的函数中添加变量声明: int iLoopX = 0, iLoopY = 0; CSprite* tmpSprite; char *szName = NULL; 4) 实现两个for循环: for( iLoopY = 0; iLoopY < GRID_COUNT; iLoopY++ ) { for( int iLoopX = 0; iLoopX < GRID_COUNT; iLoopX++ ) { } } 5) 在里面的循环添加判断代码: 如果是0,则不创建精灵,continue表示跳出本次循环,继续下一个循环。 if( 0 == m_iGridData[iLoopY][iLoopX] ) continue; 如果是方块,则创建方块精灵: if( RIGID_BLOCK == m_iGridData[iLoopY][iLoopX] ) { szName = CSystem::MakeSpriteName(“RigidBlock“,m_iRigidBlockCount ); tmpSprite=new CSprite(szName); tmpSprite->CloneSprite(“RigidBlockTemplate“); MoveSpriteToBlock( tmpSprite, iLoopX, iLoopY ); m_vRigidBlock.push_back(tmpSprite); m_iRigidBlockCount++; } 如果是黑洞,则创建黑洞精灵: else if( BLACK_HOLE == m_iGridData[iLoopY][iLoopX] ) { szName = CSystem::MakeSpriteName( “BlackHole“, m_iBlackHoleCount ); tmpSprite=new CSprite(szName); tmpSprite->CloneSprite(“BlackHoleTemplate“); MoveSpriteToBlock( tmpSprite, iLoopX, iLoopY ); m_vBlackHole.push_back(tmpSprite); m_iBlackHoleCount++; } 如果是出口,则创建出口精灵: else if( GOLF_EXIT == m_iGridData[iLoopY][iLoopX] ) { szName = CSystem::MakeSpriteName( “GolfExit“, m_iGolfExitCount ); tmpSprite=new CSprite(szName); tmpSprite->CloneSprite(“GolfExitTemplate“); MoveSpriteToBlock( tmpSprite, iLoopX, iLoopY ); m_vGolfExit.push_back(tmpSprite); m_iGolfExitCount++; } 6) 将控制球和指示箭头摆放到初始位置,此时球静止,因此指示箭头可见。在上面的两个循环后面添加下面的代码: m_pControlBall->SetSpriteLinearVelocity( 0.f, 0.f); MoveSpriteToBlock(m_pControlBall,m_iControlStartX,m_iControlStartY); MoveSpriteToBlock(m_pGolfArrow, m_iControlStartX, m_iControlStartY ); m_pGolfArrow->SetSpriteVisible(1); 7) 最后在GameInit()中调用此函数: CreateAllSprite(); 至此,本实验结束。 实验四 移动球 【实验内容】 步骤一、响应键盘按键按下消息 步骤二、球精灵坐标转换为二维格子数组索引 步骤三、判断移动方向,使球获取速度 【实验思路】 首先响应系统的按键消息函数,然后获取精灵坐标,并将其转换为二维格子中的坐标,判断其旁边的格子是否是方块,如果不是则给球一个移动的速度。 【实验指导】 1、 进入LessonX.h中,添加我们自定义的键盘消息处理函数OnKeyDown的声明: void OnKeyDown( const int iKey, const int iAltPress, const int iShiftPress, const int iCtrlPress ); 2、 在LessonX.cpp中添加该函数的定义: void CGameMain::OnKeyDown( const int iKey, const int iAltPress, const int iShiftPress, const int iCtrlPress ) { } 3、 首先判断游戏状态,只有在游戏中已经可以移动状态才响应按键,在上面函数中添加下面的代码: if( 2 != m_iGameState || 0 != m_iMoveState ) return; 4、 获取控制球精灵坐标转换到二维格子数组索引,这里我们需要定义两个函数SpritePosXToIndexX和SpritePosXToIndexY分别处理精灵坐标转换为二维格子的X索引和Y索引: 1) 进入LessonX.h中添加上面两个函数的声明: int SpritePosXToIndexX( const float fPosX ); int SpritePosYToIndexY( const float fPosY ); 2) 进入LessonX.cpp中添加SpritePosXToIndexX的定义: int CGameMain:: SpritePosXToIndexX ( const float fPosX ) { } 3) 首先得到左右边界的坐标值。m_fGridStartX是在方块的中心,所以需要减去半个方块的宽度才是左边边界。在SpritePosXToIndexX函数定义中添加下面的代码: const float fLeftSide = m_fGridStartX - m_fGridSize / 2.f; const float fRightSide = fLeftSide + m_fGridSize * GRID_COUNT; 4) 最后需要判断坐标是否出了左右边界,如果没有则返回X索引值。在上面的函数里面添加下面的判断代码: if( fPosX < fLeftSide || fPosX > fRightSide ) return -1; int iIndexX = (int)( (fPosX - fLeftSide) / m_fGridSize ); return iIndexX; 5) 在LessonX.cpp中添加SpritePosYToIndexY函数的定义: int CGameMain::SpritePosYToIndexY( const float fPosY ) { } 6) 首先获取上下边界坐标值。m_fGridStartY是在方块的中心,所以需要减去半个方块的宽度才是上边边界。在上面的函数定义中添加下面的代码: const float fTopSide = m_fGridStartY - m_fGridSize / 2.f; const float fBottomSide = fTopSide + m_fGridSize * GRID_COUNT; 7) 最后判断是否超过了上下边界,没有则返回Y索引值: if( fPosY < fTopSide || fPosY > fBottomSide ) return -1; int iIndexY = (int)( (fPosY - fTopSide) / m_fGridSize ); return iIndexY; 5、 有了上面的两个函数,我们就可以将控制球精灵坐标转换到二维格子数组索引,并判断坐标是否超出边界,在OnKeyDown函数中添加下面的代码: float fPosX = m_pControlBall->GetSpritePositionX(); float fPosY = m_pControlBall->GetSpritePositionY(); int iIndexX = SpritePosXToIndexX( fPosX ); int iIndexY = SpritePosYToIndexY( fPosY ); if( iIndexX < 0 || iIndexX >= GRID_COUNT || iIndexY < 0 || iIndexY >= GRID_COUNT ) return; 6、 根据上下左右方向键,先判断控制球旁边是否是方块,如果是方块则不能移动。不是方块,则给予控制球一个速度。使用iIndexX, iIndexY的时候,注意要判断是否是边缘的索引,如果不判断就进行加1减1,访问数组会造成下标溢出。即如果要判断左边是否是方块阻挡,则索引值为 IndexX - 1 。此时必须先判断iIndexX大于0,才能减一。如果iIndexX为0,代表直接可以移动。 1) 如果是按下向上方向键: if( KEY_UP == iKey ) { if( iIndexY > 0 && RIGID_BLOCK == m_iGridData[iIndexY - 1][iIndexX] ) return; // 给予控制球一个方向速度,并设置移动状态、隐藏指示箭头 m_iMoveState = 1; m_pControlBall->SetSpriteLinearVelocityY(-30.f); m_pGolfArrow->SetSpriteVisible(0); } 2) 如果是按下向下方向键: else if( KEY_DOWN == iKey ) { if( iIndexY < GRID_COUNT - 1 && RIGID_BLOCK == m_iGridData[iIndexY + 1][iIndexX] ) return; // 给予控制球一个方向速度,并设置移动状态、隐藏指示箭头 m_iMoveState = 2; m_pControlBall->SetSpriteLinearVelocityY(30.f); m_pGolfArrow->SetSpriteVisible(0); } 3) 如果是按下向左方向键: else if( KEY_LEFT == iKey ) { if( iIndexX > 0 && RIGID_BLOCK == m_iGridData[iIndexY][iIndexX - 1] ) return; // 给予控制球一个方向速度,并设置移动状态、隐藏指示箭头 m_iMoveState = 3; m_pControlBall->SetSpriteLinearVelocityX(-30.f); m_pGolfArrow->SetSpriteVisible(0); } 4) 如果是按下向右方向键: else if( KEY_RIGHT == iKey ) { if( iIndexX < GRID_COUNT - 1 && RIGID_BLOCK == m_iGridData[iIndexY][iIndexX + 1] ) return; // 给予控制球一个方向速度,并设置移动状态、隐藏指示箭头 m_iMoveState = 4; m_pControlBall->SetSpriteLinearVelocityX(30.f); m_pGolfArrow->SetSpriteVisible(0); } 7、 最后在Main.cpp中的OnKeyDown函数里面添加我们的自定义函数的调用: g_GameMain.OnKeyDown(iKey,bAltPress,bShiftPress,bCtrlPress); 至此,本实验结束。 实验五球运动情况的处理 【实验内容】 步骤一、获得球所在边缘格子信息 步骤二、不同格子分情况处理 【实验思路】 获取球精灵的当前坐标并将其转换为二维格子的坐标,判断在运动中球边缘的情况,如果已经出了边界则不需要再判断,否则如果是方块则球停靠、是黑洞则重新开始关卡、是出口则通关。 【实验指导】 1、 进入LessonX.cpp中的GameRun函数中,移动状态为移动中,时刻监测控制球的移动情况,根据移动方向的下一个方块,进行对应的处理。添加下面的if判断: if( 0 != m_iMoveState ) { } 2、 先将控制球精灵坐标转换到二维格子数组索引,如果控制球已经出了边界,所以不需要再判断。在上面的判断里面添加下面的代码: float fPosX = m_pControlBall->GetSpritePositionX(); float fPosY = m_pControlBall->GetSpritePositionY(); int iIndexX = SpritePosXToIndexX( fPosX ); int iIndexY = SpritePosYToIndexY( fPosY ); // 控制球已经出了边界,所以不需要再判断 if( iIndexX < 0 || iIndexX >= GRID_COUNT || iIndexY < 0 || iIndexY >= GRID_COUNT ) return; 3、 根据当前方向,获得控制球边缘所在的格子信息(球在坐标是在中心点,所以加上球的大小的一半)。总共有4中方向,即上下左右,分别用1、2、3、4来表示,添加下面的代码: float fNextPosX = fPosX; float fNextPosY = fPosY; // if( 1 == m_iMoveState ) { fNextPosY -= m_fGridSize * 0.5f; } else if( 2 == m_iMoveState ) { fNextPosY += m_fGridSize * 0.5f; } else if( 3 == m_iMoveState ) { fNextPosX -= m_fGridSize * 0.5f; } else if( 4 == m_iMoveState ) { fNextPosX += m_fGridSize * 0.5f; } 4、 将上面得到的坐标再转换为二维格子的坐标,并判断是否越出边界,添加下面的代码: int iNextIndexX = SpritePosXToIndexX( fNextPosX ); int iNextIndexY = SpritePosYToIndexY( fNextPosY ); // 该边缘已经出了边界,不需要往下判断 if( iNextIndexX < 0 || iNextIndexX >= GRID_COUNT || iNextIndexY < 0 || iNextIndexY >= GRID_COUNT ) return; 5、 根据球边缘当前所在的格子的信息,进行不同的处理:是方块则球停靠、是黑洞则重新开始关卡、是出口则通关: 1) 是方块: if( RIGID_BLOCK == m_iGridData[iNextIndexY][iNextIndexX] ) { // 清零移动状态 m_iMoveState = 0; // 速度清零,显示指示箭头 m_pControlBall->SetSpriteLinearVelocity(0.f, 0.f); m_pGolfArrow->SetSpriteVisible(1); // 把球和指示箭头设置在本方块的中心 MoveSpriteToBlock( m_pControlBall, iIndexX, iIndexY ); MoveSpriteToBlock( m_pGolfArrow, iIndexX, iIndexY ); } 2) 是黑洞: else if( BLACK_HOLE == m_iGridData[iNextIndexY][iNextIndexX] ) { // 将游戏状态设置为1,重新开始关卡 m_iGameState = 1; } 3) 是出口: else if( GOLF_EXIT == m_iGridData[iNextIndexY][iNextIndexX] ) { // 将游戏状态设置为1,开始新关卡 m_iGameState = 1; // 往下一关卡,如果已经是最大值,则返回第一关 m_iCurLevel++; if( m_iCurLevel > MAX_LEVEL ) m_iCurLevel = 1; } 至此,本实验结束。 实验六球出边界处理 【实验内容】 步骤、控制球出边界,则游戏重新开始 【实验思路】 此部分比较简单,只要通过系统判断球精灵是否越过世界边界,得到数据之后在我们的自定义函数里面处理即可。 【实验指导】 1、 进入LessonX.h中添加我们的自定义处理函数OnSpriteColWorldLimit的声明: void OnSpriteColWorldLimit( const char *szName, const int iColSide ); 2、 进入LessonX.cpp中添加该函数的定义: void CGameMain::OnSpriteColWorldLimit( const char *szName, const int iColSide ) { } 3、 在上面的函数定义中,我们只要知道系统的OnSpriteColWorldLimit函数中返回的szName是否是球精灵的名称,如果是的话则本局游戏结束,重新开始游戏。在上面的定义里面添加下面的代码: // 只处理控制的球 if( stricmp( szName, m_pControlBall->GetName()) != 0 ) return; // 将游戏状态设置为1,重新开始关卡 m_iGameState = 1; 4、 进入Main.cpp文件,在OnSpriteColWorldLimit函数里面添加我们自定义的函数的调用,填入下面一行代码: g_GameMain.OnSpriteColWorldLimit(szName,iColSide); 5、 打开Funcode,点击地图中的球精灵,在右侧的“编辑”->“世界边界限制”中,选择限制模式为NULL,这样系统就会以我们自定义的函数处理球越过边界的事件了。 至此,本实验结束。 本文档由香当网(https://www.xiangdang.net)用户上传

    下载文档到电脑,查找使用更方便

    文档的实际排版效果,会与网站的显示效果略有不同!!

    需要 2 香币 [ 分享文档获得香币 ]

    下载文档

    相关文档

    银行账户管理系统(c++课程设计)

     2015-2016学年第二学期 面向对象程序设计(c++)大作业说明书学院名称: 计算机与信息工程学院 班级名称: 计算机科学与技术(对口)...

    7个月前   
    200    0

    c++课程设计及图书管理系统(窗口界面)

    C++课程设计课程设计系部:计算机应用技术系专业:计算机应用技术班级学号: 姓名: 一、系统功能分析: 图书...

    7个月前   
    171    0

    C++语言程序设计稿件管理数据系统

    XX大学 本科生课程设计(实践)任务书、设计报告 (C++语言程序设计) 题 目 稿件管理数据系统 学生姓名 指导教师 学 院 专业班级 学生学号 计...

    2年前   
    1065    0

    迷你影院的服务流程

       温馨提示:1、电影院的营业时间:10:00—23:00。           2、使用需提前预约,会员优先; (临时使用,影院设备必须提前十五钟开启)。           3、...

    6年前   
    7120    0

    c语言课程设计总结5篇

    c语言课程设计总结5篇c语言课程设计总结(一):  c语言课程设计总结心得  经过一个学期的学习,我对C语言有了必须的了解。C语言是学习计算机科学的基础,作为一名计算机专业学生,掌握C语言更是...

    3个月前   
    145    0

    2021年c语言课程设计小结

     2021年c语言课程设计小结撰写人:___________日 期:___________2021年c语言课程设计小结关键词:图书管理系统关系模型功能模块随着社会的进步与发展,资源高效利用提...

    3个月前   
    79    0

    C语言课程设计通讯录管理系统

     课程设计报告书 课程名称: C语言课程设计 班 级: 学 号: ...

    2年前   
    1867    0

    c语言课程设计贪吃蛇

    XX 大 学 C语言程序设计 课程设计(论文)题目: 贪吃蛇 院(系): 软件学院 专业班级: ...

    3周前   
    43    0

    高尔夫部

    部门职能 高尔夫部 部门名称: 高尔夫部 上级部门: 康乐宫 下级岗位: 陪练员、服务员、拣球员 部门本职: 为客人的高尔夫球活动提供服务。 主要职能: 1. 维持高...

    11年前   
    22475    0

    迷你DVD管理器java

    实 验 报 告课程名称:面向对象信息系统开发实 验:期中大作业班 级:02学生姓名:李康序 号:34学 号:20181060261 ...

    1年前   
    178    0

    高尔夫部领班

    岗位描述 高尔夫部领班 岗位名称: 高尔夫部领班 直接上级: 康乐宫主管 直接下级: 陪练员、拣球员、服务员 本职工作: 主持高尔夫部的日常工作 直接责任: 1....

    6年前   
    25507    0

    移动高尔夫

    移动高尔夫  项目名称:移动高尔夫  又名:珠行万里  项目介绍:  所有队员一字排开,每人手持接力棒(半块puc管),在保证圆珠(高尔夫球等)不掉落的情况下从教练指定的位置运送到达终点。  ...

    6年前   
    159    0

    高尔夫部拣球员

    岗位描述 高尔夫部拣球员 岗位名称: 高尔夫部拣球员 直接上级: 高尔夫部领班 本职工作: 为高尔夫部客人拣球 工作责任: 1. 为高尔夫部客人拣球。 2. 为客人...

    6年前   
    15430    0

    高尔夫主持词

    中国人寿泰安分公司个险二部六周年庆典感恩客户答谢酒会一、会前提醒暖场音乐:“ 钢琴曲 ”等音乐1、尊敬的各位嘉宾、各位亲爱的朋友们!大家上午好,欢迎您来到中国人寿泰安分公司个险二部六周年庆典感...

    9年前   
    136    0

    c++程序实习报告

    c++程序实习报告  针对我们这学期学的c++,假期进行了五天的实习。第一天听老师讲实习内容和提示的时候觉得思路挺明确的一个程序,哪有传说中的那么难。下午和同学讨论的时候觉得很有目的,只要按部...

    9年前   
    112    0

    C语言课程设计学生通讯录管理系统设计

    C语言课程设计学生通讯录管理系统设计一、题目内容的描述学生通讯录管理系统设计设计一个学生通信录,学生通迅录数据信息构成内容可自行设计(如:姓名、家庭地址、邮政编码、电话号码等等),通信录数据类...

    11个月前   
    375    0

    数据结构课程设计运动会分数统计(C语言版)

    数据结构课程设计运动会分数统计(C语言版)目 录第一章 绪 论 1 1.1 运动会分数统计系统的背景 1 1.2 运动会分数统计系统的任务和目标 1第二章 运动会分数统...

    7个月前   
    251    0

    高尔夫部服务员

    岗位描述 高尔夫部服务员 岗位名称: 高尔夫部服务员 直接上级: 高尔夫部领班 本职工作: 为高尔夫部客人提供侍应服务 工作责任: 1. 保管客人的衣物。 2. 按...

    10年前   
    23342    0

    高尔夫部服务员

    岗位描述 高尔夫部服务员 岗位名称: 高尔夫部服务员 直接上级: 高尔夫部领班 本职工作: 为高尔夫部客人提供侍应服务 工作责任: 1. 保管客人的衣物。 2. 按...

    6年前   
    16089    0

    高尔夫赛事企划方案

    高尔夫赛事企划方案一年一度的“XX杯”又将拉开帷幕,在20XX年成功举办的基础上,20XX年的春天里,XX银行XX市分行又将举办20XX第二届XX“XX杯”大客户高尔夫邀请赛,以更好的答谢社会...

    8个月前   
    198    0

    文档贡献者

    文***品

    贡献于2021-07-17

    下载需要 2 香币 [香币充值 ]
    亲,您也可以通过 分享原创文档 来获得香币奖励!
    下载文档

    该用户的其他文档