《c语言课程设计黄金矿工(提高篇)》由会员分享,可在线阅读,更多相关《c语言课程设计黄金矿工(提高篇)(10页珍藏版)》请在技术文库上搜索。
1、C C 语言课程设计语言课程设计-黄金矿工黄金矿工 一、实验内容一、实验内容 玩家通过键盘的按键控制矿工抓取金块,将钩子碰触到的金块抓取过来。 要求如下: 1. 游戏的初始界面如下图(一) ,单机键盘上的空格键进入游戏,进入后界面如图 (二) ,金块的总数是 20,大小位置是随机的。 2. 在没有抓取状态下,钩子左右摆动,此时矿工的是静止的。当钩子摆动到一定角 度,玩家可以单击键盘上的上下左右键中的下方向键控制矿工伸出长钩,抓取金 子,此时矿工是向下摇动转轴。获取到金子往回拉后,矿工是不断转动转轴,知 道金子拉动到钩子初始处,矿工恢复静止,钩子继续左右摇摆,直到玩家再次单 击向下方向键。 3.。
2、 伸出的钩子如果碰触到金子,则钩子和金子一起往回拉,回收的速度根据抓取到 的金子的大小变化而变化,金子越大,回拉的速度越慢,反之亦然。如果钩子没 有碰触到金子,而是碰触到左右和下的边界,则钩子保持原来的速度往回收。 4. 抓取到的金子拉回到转轴处消失,此时金子数目减少一个。如果玩家将所有金子 抓取完,游戏返回到如图(一)的初始界面。 图(一) 图(二) 二、实验指南二、实验指南 实验一实验一 开始实验开始实验 【实验任务】 步骤一、打开 FunCode,创建一个的 C 语言项目; 步骤二、导入 Goldman 模板。 【实验思路】 按实验指导完成。 【实验指导】 1、 打开 FunCode,点。
3、击“项目”菜单,选择“创建 C 语言工程” 注意:工程名名称要求字母开头,只能包含字母和数字,且名字中间不能有空格名字中间不能有空格。 2、 点击菜单“项目”中的“导入地图模块” ,如图一。跳出一个对话框,选中 “Goldman”模板,点击“导入到工程”按钮,如图二。 图 一 图 二 3、导入成功后的,界面如下图所示: 实验二实验二 单击空格键,开始游戏单击空格键,开始游戏 【实验内容】 步骤、启动游戏显示“空格开始” ,单击空格键进入游戏初始界面。 【实验思路】 系统会自动响应 dOnKeyDown 函数来响应键盘按下消息,这部分代码实现在 main.cpp 里。 我们要做的就是通过在 ma。
4、in.cpp 的 dOnKeyDown 函数里实现我们的代码。当用户单击键盘 上的空格键之后,设置 GameBegin 即“空格开始”精灵不可见。 【实验指导】 1、 首先游戏会有不同的游戏状态,我们设置全局变量 g_iGameState,分别用游戏状 0 表示游戏结束等待开始状态;游戏状态 1 表示按下空格键开始,初始化游戏; 游戏状态 2 表示游戏进行中; 2、 有了以上游戏状态的定义,我们就可以将游戏的主流程写出来;由于游戏是一直 进行的,所以一下要写在 while 循环当中: switch( g_iGameState ) / 初始化游戏,清空上一局相关数据 case 1: GameIn。
5、it(); g_iGameState=2; / 初始化之后,将游戏状态设置为进行中 break; / 游戏进行中,处理各种游戏逻辑 case 2: / 金子数量大于 0 的时候,继续游戏 if( g_iGoldCount 0 ) GameRun( fTimeDelta ); else / 游戏结束。调用游戏结数函数并把游戏状态修改为结束状态 g_iGameState=0; GameEnd(); break; / 游戏结束/等待按空格键开始 case 0: default: break; ; 这是游戏的总体框架,那么我们就来完成这个游戏; 3、 我们已经知道,系统会自动检测键盘的按下消息,即 m。
6、ain.cpp 里面的dOnKeyDown 函数。系统会捕获按下什么键,是否同时按下 Alt 键或 Shift 键或 Ctrl 键,通过 dOnKeyDown 的参数传递进来,供编程者使用。 4、 键盘的键值我们通过枚举类型给出,其中空格对应的键值为KEY_SPACE,所以当 ikey 参数的值为 KEY_SPACE 且游戏的状态为 0,即 g_iGameState 的值为 0,说明用户 单击了空格键,之后将 g_iGameState 的值改为 1,说明游戏开始,并且把“游戏开始” 精灵隐藏掉。 5、 如果是空格键按下,则说明现在游戏开始,说明游戏状态进入 1,我们在 GameInit 中调用。
7、 dSetSpriteVisible 函数将“空格开始”隐藏;这里我们就不在 添加代码。 至此,实验二完成,单机空格键, “空格开始”消失,游戏进入初始化状态。 实验三实验三 钩子左右摇摆钩子左右摇摆 【实验内容】 步骤、钩子在等待抓取状态下左右摇摆 【实验思路】 钩子的摆动实际是动画精灵以某个点为中心位置,在某个角度范围来回旋转。在 FunCode 中,游戏不断刷新屏幕,每次时间为几微秒,每次刷新相应改变精灵的角度, 就能达到旋转的效果。 游戏每刷新一次屏幕,while 循环执行一次,并且通过参数 fTimeDelta 把刷新屏幕的 时间传递进去。因此,在该函数中,通过精灵的旋转速度、旋转时。
8、间就可以获得每个 时刻,精灵的旋转角度。最后,利用 FunCode 提供的 API 接口 dSetSpriteRotation 函 数,设置精灵每个时刻对应的角度,从而获得精灵旋转的动画效果。 具体到钩子左右摆动,要考虑的因素有四个:摆动方向(从左往右、从右往左) 、摆动 速度、摆动时间、摆动的角度范围。 定义两个变量 g_iHookRotToLeft 表示钩子当前是往左摆动还是往右摆动( 1 右-左, 0 左-右 ),g_fHookRotation 表示钩子当前转动的朝向。判断当 g_iHookRotToLeft 不为 0 的时候(钩子往左摆),将 g_fHookRotation 加上上面计。
9、算的本次旋转的度数。 如果 g_fHookRotation 大于 180 度,则将其改为 180 度,并且将 g_iHookRotToLeft 设 置为 0(往右摆)。往左到头后,开始往右摆。往右摆与往左摆相反,但是算法是一致的 定义变量 g_iHookRotToLeft 表示钩子当前是往左摆动还是往右摆动( 1 右-左, 0 左 -右 )。定义变量 g_fHookRotation 表示钩子当前角度。当前角度=摆动速度摆动时 间。 规定钩子摆动弧度,从左往右或从右往左正好都是摆动到水平位置,因此钩子摆动角 度的范围正好是0, 180。从右往左摆时,摆动大于 180 度时,设置当前角度为 180。
10、 度,钩子变为从左往右摆。从左往右摆时,摆动小于 0 度时,设置当前就得为 0 度, 钩子变为从右向左摆。 【实验指导】 1、 根据实验思路,为了实现钩子左右摇摆,我们需要定义获得金子的状态、钩子的角 度、是否再往左方向摆动、以及钩子的坐标点等全局变量,并且在初始化函数 GameInit 中进行初始化 2、 在 Main.cpp 文件中,定义 GameRun 函数,要实现钩子左右摇摆,则判断当 g_iHookRotToLeft 不为 0 的时候(钩子往左摆),将 g_fHookRotation 加上上面计 算的本次旋转的度数。如果 g_fHookRotation 大于 180 度,则将其改为 。
11、180 度,并 且将 g_iHookRotToLeft 设置为 0(往右摆)。往左到头后,开始往右摆。往右摆与 往左摆相反,但是算法是一致的。思路如下: 1)如果当前为等待抓取状态,那么钩子以一定的角速度左右摇摆,如果钩子左摆的 角度大于了 180 度,就给角度变量赋值为 180 度,并改变是否往左摇摆的变量为 否,这样钩子就可以往右摇摆了; 2)如果往右摇摆的角度小于了 0 度,那么就给角度变量赋值为 0 度,并且改变是否 往左摇摆的变量,这样钩子就可以不停的左右摇摆。 到此实验三完成,游戏最开始钩子左右摇摆动作的实现了。 实验四实验四 显示金子显示金子 【实验内容】 步骤一、初始化金子实例。
12、 步骤二、随机显示金子 步骤三、保存初始化的每一个金子 【实验思路】 以我们在实验一中添加的一个金子精灵作为模板,定义好金子精灵数量,调用 dCloneSprite 函数,使用一个 for 循环来复制金子。这里可以在 for 循环里面嵌入 if 判断来实现复制不同大小的金子精灵,最后在地图上随机显示金子精灵。 【实验指导】 1、 在 Main.cpp 中添加要赋值金子的个数和金子分布的世界边界的坐标等全局变量; 并在 GameInit 函数中添加代码,初始化全局变量。 2、 接着在使用 if 语句,以限定金子最终在地图上的显示范围不能超过世界边界,数 字部分只是一个参考值,自己也可以定义在一个。
13、合理的范围内。 / 以下变量只需要初始化一次 static intiInitedHookPos=0; if( 0 = iInitedHookPos ) iInitedHookPos=1; / 钩子初始位置值初始化 g_fHookStartPosX=dGetSpritePositionX( “GoldHook“ ); g_fHookStartPosY=dGetSpritePositionY( “GoldHook“ ); / 金子可以出现的边界范围初始化 g_iGoldBornMinX=dGetWorldLeft() + 5; g_iGoldBornMaxX=dGetWorldRight() - 。
14、5; g_iGoldBornMinY=dGetWorldTop() + 20; g_iGoldBornMaxY=dGetWorldBottom() - 5; 3、在 if 后面,我们需要用一个 for 循环来创建所有的金子。我们规定金子的大小为 三种,用 iSize 来记录,分别是 iSize=4,iSize=6,iSize=8。数量的比例是 10 个,6 个,4 个(这个是在金子总数为 20 的前提下,如果总数不是 20,根据比例 创建) 。我们可以再 for 循环里面通过 if 判断循环变量 iLoop 的大小范围为创建 不同大小的金子。设置金子大小的函数分别为SetSpriteWidth。
15、(设置宽度) dSetSpriteHeight(设置高度),最后使用 FunCode 提供的随机函数随机生成每个金 子的(x,y)坐标放入地图: 其中(float)iSize 是类型转换,因为 iSize 是 int 型,而 SetSpriteWidth 函数的 参数是 float 型,如果直接传进去可能会丢失数据,所以需要先将 int 型转换为 float 型。 4、 最后添加下面代码,恢复挖金者的动作。 / 播放挖金者的动作(恢复初始守候动作) dAnimateSpritePlayAnimation( “GoldMan“, “GolderManAnimation2“, 0 ); 至此,实验。
16、四显示金子的部分就完成了。 实验五实验五 抓取金子抓取金子 【实验内容】 步骤一、从缆绳器那里画根线到钩子上 步骤二、检测钩子和金子的碰撞 步骤三、实现金子绑定在钩子上并往回拖 步骤四、回拖之后使金子消失,金子数目减一 【实验思路】 从缆绳器画线到钩子上: 在地图上创建精灵的链接点,然后获取他们的坐标位置,调用 FunCode 的 dDrawLine函 数即可。 钩子与金子的碰撞: 系统检测到两者的碰撞之后会调用 dOnSpriteColSprite 函数,所以我们只要在此函数中 实现碰撞之后钩子抓取金子的代码就可以了。这里需要注意的是钩子抓取金子之后的速度 处理,抓的金子越大,钩子回收的速度。
17、就会越慢。 【实验指导】 1、打开 funcode,单击地图上的矿工精灵图像,在显示框的上面五个选择左数第二个“编 辑次精灵的链接点”,按如图所示依次单击这位置显示 0,保存即可。 2、 同上,点击地图上的钩子精灵,选择“编辑此精灵的链接点” ,依次单击这三个位 置显示 0,1,2,最后保存即可。 3、首先在 Main.cpp 中添加全局的字符数组变量,用它来存放抓到的金子的名字,并定义 空钩子在抓取金子的时候移向钩子的速度变量,定义完成之后在 GameInit 中初始化; 4、 精灵的碰撞方式为:当 A 移动中碰上 B 时,如果 A 是可以产生碰撞的,B 是可以接 受碰撞的,则这 2 个物体。
18、会产生碰撞,精灵碰撞的 API 将被调用。否则无碰撞发生 通过调用库函数 dSetSpriteCollisionSend 设置钩子可以发送碰撞,通过 dSetSpriteCollisionReceive 函数设置金子可以接收碰撞,这样,当在地图上钩 子和金子相碰时,系统就能检测到。 5、 首先实现从缆绳器画线到钩子。首先在 Main.cpp 进行声明: voidDrawHookLine(); 然后,添加函数的定义。画线的原理是先获取缆绳器的坐标和钩子的坐标,然后 调用 DrawLine 函数即可。 函数定义如下 voidDrawHookLine() / 首先,从矿工精灵上获取一个缆绳链接点作为。
19、绳子的起始点(该链接点在 编/ 辑器里编辑好) floatfStartX =dGetSpriteLinkPointPosX( “GoldMan“, 1 ); floatfStartY =dGetSpriteLinkPointPosY( “GoldMan“, 1 ); / 绳子终点在钩子精灵上获取(该链接点在编辑器里编辑好) floatfEndX=dGetSpriteLinkPointPosX( “GoldHook“, 1 ); floatfEndY=dGetSpriteLinkPointPosY( “GoldHook“, 1 ); / 在这两点之间划线.线的颜色红绿蓝值都为 50,即灰色 dD。
20、rawLine( fStartX, fStartY, fEndX, fEndY, 2.f, 0, 50, 50, 50, 255 ); dDrawLine 函数参数参见文档前面部分的介绍或者是 CommonAPI.h 中关于 dDrawLine 的介绍。 6、main.cpp 文件里面的主函数中的 while 循环每次调用 GameMainLoop 函数时能保证调用 到DrawHookLine 函数,保证了钩子与缆绳器之间的线是一直连着的。 在while 循环的最后面添加如下代码: / 画钩子的缆绳线。不管游戏是什么状态,这根缆绳线都要画出来 DrawHookLine(); 7、 接下来要实现。
21、单击键盘上的下方向键伸出钩子。如实验二所说,系统检测到键盘按 下,会响应 main.cpp 里面的dOnKeyDown 函数,向下方向键的宏定义是 KEY_DOWN, 因此我们只要判断dOnKeyDown 获取的键值 ikey 等于它,并且游戏是正在进行的 (g_iGameState 等于 2),钩子没有抓到金子(g_iGetGoldState 等于 0)即可。之后 利用系统提供的函数给钩子一个向前的速度,在播放挖金者手臂往下压的动作即可。 在main.cpp里面 dOnKeyDown 函数 if 后面添加如下代码: / 当前处于游戏进行中,按下向下的方向键,钩子伸出抓取金子 else if(。
22、 KEY_DOWN = iKey / 以当前朝向给钩子一个向前的速度 dSetSpriteLinearVelocityPolar(“GoldHook“,g_fEmptyHookSpeed, g_fHookRotation ); / 播放挖金者的动作(一个胳膊往下压的动作) dAnimateSpritePlayAnimation( “GoldMan“, “GolderManAnimation1“, 0 ); 8、 实现钩子抓金子的精灵与精灵碰撞事件。 / 首先判断钩子是否伸出,已经游戏是否真在进行,否则推出函数: if( 2 != g_iGameState | 1 != g_iGetGoldSt。
23、ate ) return; /判断是否是钩子与金子进行碰撞(即这两个名字字符串里必须一个是金子名,一 /个是钩子名) if( stricmp(“GoldHook“,szSrcName)!=0; / 找到哪个是金子的名字 const char*szGoldName =NULL; if( strstr( szSrcName, “GoldBlock“ ) ) szGoldName = szSrcName; else if( strstr( szTarName, “GoldBlock“ ) ) szGoldName = szTarName; else return; 9、 得到金子实例之后,使用 Fu。
24、nCode 给的绑定函数 SpriteMountToSpriteLinkPoint()将 金子绑定在钩子上随钩子移动: / 将金子挂接到钩子的 2 号挂接点上 dSpriteMountToSpriteLinkPoint( szGoldName, “GoldHook“, 2 ); / 设置抓取状态为:钩子往回收,抓取到东西。记录金子名字 g_iGetGoldState=3; strcpy( g_szCurGetGold, szGoldName ); / 根据金子大小,计算钩子的往回收的速度,越大的越慢。 / 算法:之前设置的金子大小为 4,6,8,用 10 减去该大小再除以 10,得到 3 个小。
25、 / 数:0.6,0.4,0.2.该小数乘以空钩子的速度即得到挂接不同金子后的实际速度 floatfWidth=dGetSpriteWidth( szGoldName ); floatfSpeed=(10.f - fWidth) / 10.f) * g_fEmptyHookSpeed; / 钩子往初始位置移动 dSpriteMoveTo( “GoldHook“, g_fHookStartPosX, g_fHookStartPosY, fSpeed, 1); / 播放挖金者的动作(胳膊来回动的动作) dAnimateSpritePlayAnimation( “GoldMan“, “GolderM。
26、anAnimation3“, 0 ); 10、 金子抓取之后回收到缆绳器之后,系统判断钩子的是否往回运动,是的话判断钩 子是否回到终点,若是则调用 dSpriteDismount 函数取消金子与钩子的绑定,同时调 用 dDeleteSprite 函数删除该金子精灵,再将金子精灵的总数减一。在 GameRun 函数 后面添加如下代码: / 如果当前为钩子往回归位,则判断是否已经运动到终点。到了终点,则又开始 摇/ 摆、等待 else if( 2 = g_iGetGoldState | 3 = g_iGetGoldState ) / 判断是否移动到终点(判断的依据是 XY 方向的移动速度为 0,即。
27、金子是否 / 已经停止移动) floatfSpeedX =dGetSpriteLinearVelocityX( “GoldHook“ ); floatfSpeedY =dGetSpriteLinearVelocityY( “GoldHook“ ); / 当前速度不为 0,还在运动中 / 浮点数是否为 0,不能直接判断 = != 0 if( fSpeedX 0.00001f | fSpeedX 0.00001f | fSpeedY -0.00001f ) return; / 速度为 0,钩子回到初始点,开始下一轮的抓取 / 当前抓取到金子,将抓取到的金子释放并删除之。然后将金子数量减一 if( 。
28、3 = g_iGetGoldState ) g_iGoldCount-; dSpriteDismount( g_szCurGetGold ); dDeleteSprite( g_szCurGetGold ); / 恢复等待状态与播放等待动作 g_iGetGoldState =0; dAnimateSpritePlayAnimation( “GoldMan“, “GolderManAnimation2“, 0 ); 至此,抓取金子的实验完成。 11、 要令游戏更加完整,在抓取完全部金子之后设置游戏回到初始界面,即显示“空 格开始”界面。只需要在 Main.cpp 中定义 GameEnd 函数中将。
29、“空格开始”显示即 可。 至此,抓金子试验完成了。 实验六实验六 钩子碰到边界处理钩子碰到边界处理 【实验内容】 步骤、处理钩子碰到世界边界的动作 【实验思路】 通过 dSetSpriteWorldLimit 函数设置钩子碰到世界边界是需要进一步处理,因而当系统检 测到钩子与世界边界碰触后会响应 dOnSpriteColWorldLimit 函数,从而我们获取参数进行 操作。 【实验指导】 1、 在 Main.cpp 中对函数 OnSpriteColWorldLimit 进行定义,第一个参数是钩子的名 称,第二个参数是碰撞到的边界代号,通过 main.cpp 中的OnSpriteColWorldLimit 的 iColSide 参数传入,当其为 0 时是指左边的世界边界,1 为右边边界,2 为上边边 界,3 为下边边界。 2、首先判断钩子是否碰到边界,即传进来的字符串参数 szName 的值为钩子的名称 “GoldHook” ,是的话设置钩子的抓取状态为 2,即未取到东西,然后钩子按原路 径返回,调用 dSpriteMoveTo 函数,最后播放挖金者胳膊来回动。 至此,本实验结束。 。