from:http://blog.csdn.net/wuyakenihao/article/details/9394375
兄弟们相比等这一章 等的时间比较长了吧!呵呵这几天公司的事情比较忙每天都只有晚上回来写会。所以进度慢了,不过兄弟们放心 我会坚持把这个游戏写完的写成一个可以买的游戏!哈哈 吹下牛了 其实在开发游戏的过程中 一个人真心感觉力量不够 我现在没游戏中没有数值的策划。很多都是我自己临时设置,不过在后期我会一点一点的来加上这些东西。大家不要着急 好的游戏都是经过精雕细琢慢慢打磨出来的。
废话不多说了 我给大家介绍一下本章主要内容 本章主要围绕着怪物系统 怪物系统包含 释放怪物 回收怪物 和弓箭的碰撞 等等
其中关于怪物类 我这里要仔细讲解一下 在一个游戏中我们的怪物 常常是这样的 有攻击动画 有走路动画 有死亡动画 目前我没考虑收到攻击的动画 考虑太多只会增加开始游戏的难度 我们先把最基本的 实现 慢慢来扩展
我的怪物的图片是从66rpg 上下载的 然后用TexturePacker 把众多的动画 所需要的 图片处理成一张图片 减少加载图片的次数 通过这个工具以后会生成一张图片和一个plist 文件。 在我的代码中大家可以看到如何使用
下面贴出怪物类的主要代码
- #ifndef __MONSTER_SPRITE_H__
- #define __MONSTER_SPRITE_H__
- #include "cocos2d.h"
- class MonsterSystem;
- class MonsterSprite:public cocos2d::CCSprite{
- public:
- MonsterSprite(void);
- ~MonsterSprite(void);
- void moveRun();// 移动函数
- CC_SYNTHESIZE(float,hurt,Hurt);//伤害值
- CC_SYNTHESIZE(float,defense,Defense);//防御值
- CC_SYNTHESIZE(float,speed,Speed);//移动速度
- CC_SYNTHESIZE(float,maxRemoving,maxRemoving);// 移动的最大距离
- CC_SYNTHESIZE(float,blood,Blood);// 怪物气血值
- CC_SYNTHESIZE(int,monType,MonType);// 怪物类型
- CC_SYNTHESIZE(int,monState,MonState);// 怪物状态 1 静止状态 2 行动状态 3 攻击状态 4 死亡状态
- CC_SYNTHESIZE(cocos2d::CCRect,attackRange,AttackRange);// 接受攻击的范围
- void runAnimation();// 执行奔跑动画
- void deathAnimation();// 执行死亡动画
- void attackAnimation();// 执行攻击动画
- void fallBlood(float hurt);// 这个是接受攻击 主要改变 该怪物的气血值 和血条的显示
- // 第一个参数的意思是 加载的plist 文件的名字 第二个是 plist 对应的图片纹理 第三个是 图片的通用名字 第四个 走路动画图片张数,第五个是 攻击时候的参数 第六个是 死亡动画的张数
- // 在这里贴别说明一点为了达到动画的通用性 我们规定 plist 中的图片命名格式是这样的 pic-1编号 是跑步图片 pic-2编号是 攻击图片 pic-x编号是死亡图片
- static MonsterSprite* createWithMonsterRul(const char* filename,cocos2d::CCTexture2D* ccTexture2D,const char* pic,int runcount,int attackcount,int deathcout );
- void setMonsterSystemUtils(MonsterSystem* monsterSystem);
- cocos2d::CCRect converNowRect();// 这个方法是把最初设计的攻击范围 转化到当前 界面的坐标系中的矩形
- protected:
- cocos2d::CCArray* runArray;//奔跑动画序列帧
- cocos2d::CCArray* deathArray;//死亡动画序列帧
- cocos2d::CCArray* attackArray;//攻击动画序列帧
- cocos2d::CCProgressTimer* bloodBwlid;// 这个是血条
- virtual void deathAnimationCallBack(cocos2d::CCNode* pSed);// 死亡动画回调函数
- virtual void attackAnimationCallBack(cocos2d::CCNode* pSed);// 攻击动画回调函数
- virtual void runAnimationCallBack(cocos2d::CCNode* pSed);//奔跑动画回调函数
- virtual bool setUpdateView();
- static MonsterSprite* createWithSpriteFrame(cocos2d::CCSpriteFrame *pSpriteFrame);
- MonsterSystem* monsterSystem;
- void myload(float tim);
- };
- #endif
- CC_SYNTHESIZE(cocos2d::CCRect,attackRange,AttackRange);// 接受攻击的范围
大家要特别主要这行代码 我先讲解一下 为什么会出现这样的一个参数 首先是否发生碰撞并不是 和怪物精灵 直接发生碰撞 而是和这个参数对比 。这一点是问什么呢
我给大家上传一张图
为了看的明显我把透明部分给弄成了红的当大家看到这样一张图片的时候如果按照我们最开始的做法让弓箭直接和怪物所在的矩形发生碰撞 你会看到弓箭 还没打到怪物就消失了 这不是我们愿意看到的 为了打到游戏的逼真性我们规定只要当弓箭碰撞到蓝色区域的时候 才能算碰撞。所以就会出现这样的一个参数。哈哈是不是有点麻烦,呵呵好的游戏都是考虑尽量详细的情况。自夸一下别介意啊。不过还需特别注意一点我们的这个矩形在判断是否发生碰撞的时候需要转化成整个屏幕的坐标系
主要代码如下
- CCRect MonsterSprite::converNowRect(){
- // 得到当前的 怪物的所在的矩形
- CCRect monsret=this->boundingBox();
- float x=monsret.getMinX()+this->getAttackRange().getMinX();
- float y=monsret.getMinY()-this->getAttackRange().getMinY();
- return CCRect(x,y,this->getAttackRange().getMaxX(),this->getAttackRange().getMaxY());
- }
怪物类讲解完了我们下面说下我们的怪物系统 包含 怪物系统包含 释放怪物 回收怪物 和弓箭的碰撞
主要代码如下
- #ifndef __MONSTER_SYSTEM_H__
- #define __MONSTER_SYSTEM_H__
- #include "cocos2d.h"
- #include "MonsterSprite.h"
- #include "BulletsSprite.h"
- typedef struct MonsterUtils{
- float initBlood;// 初始化气血
- float initSpeed;// 初始化速度
- float defend;// 怪物的防御力
- float hurt;// 怪物的伤害值
- char* monsName;// 在设置怪物的时候的通用名字
- char* picName;// 怪物的图片
- char* fileName;// 怪物所对应的plist 文件的名字
- int type;// 怪物类型
- int runCount;// 奔跑动画张数
- int actCount;// 攻击动画张数
- int detCount;// 死亡动画张数
- float maxRun;// 最大移动距离
- char* attackRangeRec;//是在怪物身上划定一个受到的攻击范围 这样可以让不规则的 图片 看起来受到攻击的时候更逼真一点 字符串的 格式是这样的{{x,y},{w, h}}
- } Monster;
- class DefenderGameLayer;
- // 此类是生产和销毁系统
- class MonsterSystem{
- public:
- MonsterSystem();
- ~MonsterSystem();
- cocos2d::CCArray* getIdleMonsterArry();// 用来保存空闲的怪物
- cocos2d::CCArray* getRunMonsterArray();// 用来保存正在奔跑中的怪物
- void addMonster(int type,int count);// 用于主线程调用来远远不断的产生怪物
- void setDefenderGameLayer(DefenderGameLayer* defenderGameLayer);
- bool collisionDetection(BulletsSprite* bulletsSprite);// 传入弓箭 检测是否和怪物发生碰撞
- void recoverMonster(MonsterSprite* monsterSprite);// 回收怪物
- private:
- cocos2d::CCArray* idleMonsterArry;// 用来保存空闲的怪物
- cocos2d::CCArray* runMonsterArray;// 用来保存正在奔跑中的怪物
- MonsterSprite* productMonster(int type);//根据类型来产生响应的怪物的数量
- DefenderGameLayer* defenderGameLayer;// 游戏主类
- void addDefenderGameLayer(MonsterSprite* monsterSprite);// 把奔跑中的怪物添加到 主界面里面
- Monster dutu;// 每次添加新的怪物都需要在这里添加一个 并且在构造方法里面初始化
- };
- #endif
- class DefenderGameLayer;
我就是用前置声明 ,然后在对应的CPP 文件里面 引入头文件 我今天看一篇文章所尽量吧引入头文件的操作放在CPP 文件里面。这里要特别注意下 要不报错让你蛋疼的找不到错误。
具体可以看这个文章的说明查看详细
其实在这里一个重要可以优化的地方就是我在这个类里面生命的这个 怪物结构体 这个本应该放到一个配置文件中的 然后通过读取配置文件来创建响应的怪物 这里 为了加快游戏的开发 我先放到这里 等后期我讲解游戏优化的时候 把这一块更改一下。
下面如果上面的代码你都看懂了并且实现了 你运行将会看到如下的界面
哈哈赌徒很多吧 这么赌徒出现是不是要干掉他 这个在碰撞检测里面有具体的实现
主要代码如下
- // 传入弓箭 检测是否和怪物发生碰撞
- bool MonsterSystem::collisionDetection(BulletsSprite* bulletsSprite){
- bool iscon=false;
- if (this->getRunMonsterArray())
- {
- // 下面是检测 弓箭 是否和怪物发生碰撞
- for(int i=0;i<this->getRunMonsterArray()->count();i++){
- MonsterSprite* monsterSprite=(MonsterSprite*)this->getRunMonsterArray()->objectAtIndex(i);
- // 怪物的状态必须不是死亡的状态
- if (monsterSprite->getMonState()!=4)
- {
- // 判断当前的怪物所受攻击的区域时候和弓箭 是否发生碰撞
- iscon=bulletsSprite->boundingBox().intersectsRect(monsterSprite->converNowRect());
- if (iscon)
- {
- // 表示怪物受到攻击 怪物要进行掉血 操作
- monsterSprite->fallBlood(bulletsSprite->getHurt());
- iscon=true;
- break;
- }else{
- continue;
- }
- }
- }
- }
- return iscon;
- }
不过大家注意一下这个版本 是有问题的就是怪物可以源源不断的产生。如果你要是一直运行估计内存会受不了 这是为什么呢 因为我 每一秒让产生两个怪物这已经大于我们干掉一个怪物的速度了。这个问题怎么解决呢 这就是以后章节的内容 及关卡系统 大家对于关卡系统是不是也很感兴趣啊。呵呵这个放到以后的章节里面进行讲述。 到此为止我们的怪物系统就产生了
对于以上还有的问题就是没有设置炮台的血量 没有给其掉血 让其死亡,这个将是下一章所讲述的内容。让武器系统更好的配合怪物系统,让咱们的游戏看起来是一个可以玩的。