1、大鱼吃小鱼实训指南游戏规则1. 按下空格键游戏开始。2. 通过 WSAD 键控制玩家鱼上下左右移动,但不能游出边境。3. 克隆出多条鱼放在容器当中。4. 克隆出来的容器中的鱼从右向左移动,不同的鱼游动的速度不同。5. 当玩家鱼碰撞到了容器中的鱼,删除容器中的鱼,并增加玩家鱼的得分。6. 当容器中鱼没有被吃到,而是撞到了左边世界边界,则从玩家鱼的分数中减去该鱼的价值,当玩家鱼的分数被减为负值,游戏结束。实验准备打开 FunCode,创建一个新的 C+项目。注意:项目名称必须为英文和数字,且不能有空格。点击“项目”“导入地图模板” ,从对话框中选取名称为 FishEatFish 的模板导入。导入成
2、功后,界面如下:查看模板设置。模板设置中有如下几点,在项目开发时需要用到:精灵的名称,创建精灵对象时,通过精灵名称把对象和精灵图片绑定在一起。点击“启动 VC 工程” ,将 VC 打开:类的设计游戏中能直接看到的精灵:玩家鱼、电脑鱼、玩家得分文本、玩家等级文本。其中,玩家得分和玩家等级只需要显示分数,可以直接使用 CTextSprite 类。玩家鱼、电脑鱼创建相应的类。可以从玩家鱼和电脑鱼抽象出一个鱼类,作为父类。鱼类继承 CSprite 类,通过 CSprite 类的方法操作精灵。创建一个游戏类,各个类之间的通信在游戏世界类中进行。本游戏是大鱼吃小鱼,该类称为鱼游戏类。创建一个精灵工厂类,用
3、来生成各种精灵类的对象。这就是“工厂模式” 。游戏流程主流程游戏分四个状态:未开始、开始、运行和结束。CGameMain 类是控制游戏流程的类,游戏屏幕每刷新一次,调用一次该类的 GameMainLoop 方法。GameMainLoop 根据m_iGameState 的值分别调用该类的 GameInit、GameRun 和 GameEnd 方法。这三个方法对应初始化游戏、游戏运行和游戏结束这三个状态。GameInit 只执行一次。执行后修改游戏状态。屏幕刷新后,进入状态 2,开始执行 GameRun 方法。当玩家积分=0 即玩家鱼不死的时候,GameRun 一直被执行。玩家鱼死亡后,调用 Ga
4、meEnd 执行一次,清除本局游戏数据,恢复游戏未开始状态。游戏初始化完成游戏初始工作,界面上的工作:玩家积分和等级显示为 0,创建玩家鱼并放置在指定位置,并且把玩家鱼对象加入到 FishesWorld 对象中。游戏运行游戏运行中,每刷新一次屏幕,需要根据最新数据,更新玩家得分和等级,移动玩家鱼,删除被吃掉的电脑鱼,当达到相应的时间间隔时,创建新的电脑鱼。游戏结束将游戏中剩余的精灵删除,包括删除精灵本身和集合中对应的对象。重新显示游戏开始的提示图片。生产精灵对象本游戏中的玩家鱼、电脑鱼这两种精灵类的对象都在精灵工厂类中产生。根据参数确定生产何种精灵。右下图是玩家飞机的生产过程,主要是创建对象,
5、复制模板,并设置几个基本属性(碰撞、世界边界、初始位置、初始速度) 。键盘按下事件本游戏中,游戏状态为 0 时,按下空格键,游戏状态转为 1。游戏状态为 2 时,玩家按下了 WSAD 键,分别设置玩家鱼的上下左右速度。键盘弹起事件本游戏中,游戏状态为 2 时,玩家松开 WSAD 键,设置玩家飞机对应方向上的速度为0。精灵与精灵的碰撞本游戏中,玩家鱼设置为发送碰撞,电脑鱼设置为接收碰撞。精灵碰撞时,如果电脑鱼等级比玩家鱼高,则玩家鱼减少积分,反之,玩家鱼增加积分。世界边界碰撞事件本游戏中,游戏状态为 2 时,玩家鱼碰到边界停止继续游动。电脑鱼碰到边界,设置该鱼的生命值 hp 为 0。获得该鱼的价
6、值,从玩家鱼当前的得分中减去该值。实验任务任务一 完成类的定义根据下方表格,完成以下各个类的定义。其中,set 和 get 方法在当前任务中实现,其他方法的实现留到后面完成。鱼类:Fish 继承自 CSprite 类属性private int iHp 鱼的生命值private int iGrade 鱼的等级private int iDir 鱼的方向private float fSpeedX 鱼 X 轴方向移动速度private float fSpeedY 鱼 Y 轴方向移动速度private float fPointX 鱼 X 轴方向上的位置private float fPointY 鱼 Y
7、轴方向上的位置方法public int getHp() 获得鱼的生命值public void setHp(const int Hp) 设置鱼的生命值public int getGrade() 获取鱼的等级public void setGrade(const int grade) 根据参数设置鱼的等级public float getMoveSpeedX() 获得鱼 X 轴方向上速度public void setMoveSpeedX(float speedX) 设置鱼 X 轴方向上速度public float getMoveSpeedY() 获得鱼 Y 轴方向上速度public void setM
8、oveSpeedY(float speedY) 设置鱼 Y 轴方向上速度public void setDirection(float dir) 根据参数设置鱼的方向public float getDirection() 获取鱼的方向public float getPointX() 获得鱼在 X 轴上的位置public void setPointX(const float fPointX) 设置鱼在 X 轴上的位置public float getPointY() 获得鱼在 Y 轴上的位置public void setPointY(const float fPointX) 设置鱼在 Y 轴上的位置
9、public virtual void move(int ikey)=0 鱼的移动方法玩家鱼类:PlayerFish 继承自 Fish 类属性private int iPlayerScore 玩家鱼的积分方法public int getPlayerScore() 得到玩家积分public void setPlayerScore(int score) 设置玩家积分public virtual void move(int ikey) 玩家鱼移动方法public void stopMove(int ikey) 玩家鱼停止移动方法public void eat(Computer *pFish) 玩家鱼
10、吃电脑鱼的方法public int playScoreTransferLvel() 根据玩家鱼积分得到玩家鱼响应的等级电脑鱼类:ComputerFish 继承自 Fish 类属性private int value 电脑鱼的价值方法public int getValue() 获取电脑鱼价值public void setValue(int value) 设置电脑鱼价值public virtual void move() 电脑鱼移动精灵工厂类:SpriteFactory属性private static int sId静态成员变量。缺省值为 0,每复制一个精灵时递增一次,用于作为新生成的精灵名称的后缀
11、。例如:fish1, fish2, fish3方法public static Fish *getFish(int iType) 获取生产出的精灵。iType:1玩家鱼 2电脑鱼鱼的世界类:FishWorld属性private PlayersFish playersFish 玩家鱼private vector computerFishs 电脑鱼集合public static const int MAX_COMPUTERFISH_NUM 最多电脑鱼数量private float refreshRate 电脑鱼刷新时间间隔private float deltaTimeCount 当前累计时间 pri
12、vate CTextSprite *textLevel 游戏等级文本精灵private CTextSprite *textScore 玩家积分文本精灵Private CTextSprite *gameStart 开始精灵Private float fSpeedX 电脑鱼在 X 方向上的速度Private float fSpeedY 电脑鱼在 Y 方向上的速度方法public void setRefreshRate(float refreshRate) 设置电脑鱼刷新时间间隔public float getRefreshRate() 得到电脑鱼刷新时间间隔public float getDelt
13、aTimeCount() 得到当前累计时间public void setDeltaTimeCount(float deltaTimeCount) 设置当前累计时间public CTextSprite *getTextStarGame() 得到开始游戏文本精灵public void setTextStarGame(CTextSprite *textStarGame) 设置开始游戏文本精灵public CTextSprite *getTextLevel() 得到玩家鱼等级文本精灵public void setTextLevel(CTextSprite *textLevel) 设置玩家鱼等级文本精灵
14、public CTextSprite *getTextScore() 得到玩家鱼积分文本精灵public void setTextScore(CTextSprite *textScore) 设置玩家鱼积分文本精灵public PlayersFish *getPlayersFish() 得到玩家鱼public void setPlayersFish(Fish *playersFish) 设置玩家鱼public vector getComputerFishs() 得到电脑鱼集合public void setComputerFishs(vector *computerFishs) 设置电脑鱼集合pu
15、blic ComputerFish *findComputerFishByName(const char *fName)根据名字在电脑鱼集合中查找响应的电脑鱼public Fish *addFish(int key) 添加一条电脑鱼public int getRandomByGrade()根据玩家鱼的当前等级返回一个随机值,用于控制在不同等级下出现鱼的种类以及比例public void setComputerFishSpeadByGrade(ComputerFish *cFish) 设置电脑鱼移动速度根据鱼的等级在 Fish 类中定义一些宏,在程序中尽量使用这些常量,而不是直接用数值。这样,既
16、有利于代码的阅读,又便于修改。任务二 实现 SpriteFactory 类参考“游戏流程”中“生产精灵对象”一节,完成 SpriteFactory 类的方法。对于玩家鱼,初始速度设为 0,初始位置在游戏屏幕下方边界的中间位置,世界边界设置为屏幕大小(可以通过 CSystem 类的 GetScreenBottom 等方法来设置位置) 。设置等级为 0,玩家得分为 0, 。玩家鱼设置为发送碰撞。世界边界碰撞模式为停止。电脑鱼初始速度向左,等级高的鱼速度相对较快所拥有的价值较高,等级低的鱼速度相对较慢所拥有的价值较低。初始位置应该位于屏幕右方,电脑鱼设置为接收碰撞。从相应的电脑鱼模板复制精灵,命名方
17、式:模板名称+sId。任务三 游戏初始化在 CGameMain 类的 GameInit 方法中完成游戏初始化。任务四 键盘按下事件在 CGameMain 类的 OnKeyDown 方法中完成。键盘按下处理两个事件:一个是游戏的开始;一个是玩家鱼的上下左右移动。完成该任务后,运行程序。任务五 键盘弹起事件在 CGameMain 类的 OnKeyDown 方法中完成。完成任务四后按下键盘相应键鱼儿被设置了移动速度,但当松开后就应该取消设置的移动速度。任务六 完成游戏运行在 CGameMain 类的 GameRun 方法中完成游戏运行代码。这三个函数需要自行添加,在定义类时并没有加入。完成 Fish
18、World 中更新文本精灵数据的方法。完成 FishWorld 中更新玩家数据的方法。完成 FishWorld 中更新电脑鱼的方法完成 FishWorld 中删除 HP 为 0 的电脑鱼的方法完成 FishWorld 中添加电脑鱼的方法运行游戏,这时候,可以看见不断有电脑鱼出现,并且当我们按下 W,S,A,D 键时玩家鱼也会随之移动。任务七 精灵与精灵的碰撞在上一个任务中,即使玩家鱼碰到电脑鱼也不会把电脑鱼吃掉,是因为我们没有处理精灵的碰撞事件。在本任务中,我们通过精灵与精灵的碰撞事件来解决上述问题。在 CGameMain 类的OnSpriteColSprite 方法中完成代码。该方法有两个参
19、数,一个是 szSrcName,表示发送碰撞的精灵的名称;一个是 szTarName,表示接受碰撞的精灵的名称。根据这两个精灵的名称,可以判断碰撞的精灵是什么类型(因为创建精灵时,命名有规则) 。任务八 精灵与世界边界的碰撞在创建敌机精灵和子弹精灵对象时,我们设置了它们的世界边界,以及与世界边界碰撞模式。当它们飞出各自的世界边界时,就会发生精灵与世界边界碰撞事件,对于的方法是CGameMain 类中的 OnSpriteColWorldLimit 方法。对于碰到世界边界的电脑鱼,我们需要删除此精灵,并从集合删除相应的节点。本任务的效果主要是优化程序,避免产生过多无用对象,占用电脑资源。任务九 完成游戏结束当玩家鱼的积分0 时,一局游戏结束。对应的方法是 CGameMain 类的 GameEnd 方法。然后重新显示“空格开始”图片,游戏环境又重新回到未开始状态。