cocos2d-x之怪物系统
2014-05-02 15:41
330 查看
这次接着上次的分析,上次加了武器系统,这回增加怪物系统
原文出处http://bbs.9ria.com/thread-242991-1-1.html
MonsterSystem.h
MonsterSystem.cpp
MosterSprite.cpp
原文出处http://bbs.9ria.com/thread-242991-1-1.html
MonsterSystem.h
#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
MonsterSystem.cpp
#include "MonsterSystem.h" #include "DefenderGameLayer.h" USING_NS_CC; MonsterSystem::MonsterSystem(){ idleMonsterArry= CCArray::create();// 用来保存空闲的怪物 idleMonsterArry->retain(); this->runMonsterArray=CCArray::create(); // 用来保存正在奔跑中的怪物 this->runMonsterArray->retain(); /********************************************************************** float initBlood;// 初始化气血 float initSpeed;// 初始化速度 float defend;// 怪物的防御力 float hurt;// 怪物的伤害值 char* picName;// 怪物的图片 char* fileName;// 怪物所对应的plist 文件的名字 int type;// 怪物类型 int runCount;// 奔跑动画张数 int actCount;// 攻击动画张数 int detCount;// 死亡动画张数 float maxRun;// 最大移动距离 float minX; // 下面的这四个参数其实 是在怪物身上划定一个受到的攻击范围 这样可以让不规则的 图片 看起来受到攻击的时候更逼真一点 float minY; float maxX; float maxY; ************************************************************************/ this->dutu.initBlood=100; this->dutu.initSpeed=5; this->dutu.defend=1; this->dutu.hurt=10; this->dutu.monsName="dutu"; this->dutu.picName="monster/dutu.png"; this->dutu.fileName="monster/dutu.plist"; this->dutu.type=1; this->dutu.runCount=8; this->dutu.actCount=14; this->dutu.detCount=8; this->dutu.maxRun=800*0.14; this->dutu.attackRangeRec="{{70,45},{30,110}}"; } ////根据类型来产生响应的怪物 MonsterSprite* MonsterSystem::productMonster(int type){ if(type==1){ MonsterSprite* sp=MonsterSprite::createWithMonsterRul(dutu.fileName,CCTextureCache::sharedTextureCache()->textureForKey(dutu.picName),dutu.monsName,dutu.runCount,dutu.actCount,dutu.detCount); sp->setHurt(dutu.hurt); sp->setDefense(dutu.defend); sp->setBlood(dutu.initBlood); sp->setSpeed(dutu.initSpeed); sp->setmaxRemoving(dutu.maxRun); sp->setMonType(dutu.type); sp->setMonState(1); sp->setAttackRange(CCRectFromString(dutu.attackRangeRec)); sp->setMonsterSystemUtils(this); return sp; } return NULL; } // 把奔跑中的怪物添加到 主界面里面 void MonsterSystem::addDefenderGameLayer(MonsterSprite* monsterSprite){ // 获取0-1 之间的数 float ran=CCRANDOM_0_1(); CCSize size=this->defenderGameLayer->getContentSize(); float x=size.width; float temp=size.height*ran+monsterSprite->getContentSize().height/2;//得到随机放置的纵坐标 float y=0;//初始化y值 if (temp>=size.height){//如果超过了界限 y=size.height-monsterSprite->getContentSize().height/2;//则让精灵的正上方与屏幕对齐 }else{ if(ran!=0){ if (size.height*ran<monsterSprite->getContentSize().height/2){ y=temp+10; }else { y=size.height*ran; }
////////这里我加了一个部分,源代码只是考虑了下半部分,而没有考虑上半部分
/////////else if(size.height*ran>size.height-monsterSprite->getContentSize().height/2){ y=temp-10; } }else { y=monsterSprite->getContentSize().height/2; } } monsterSprite->setAnchorPoint(ccp(0,0.5)); monsterSprite->setPosition(ccp(x,y)); if(this->defenderGameLayer){ this->defenderGameLayer->addChild(monsterSprite,2); monsterSprite->runAnimation(); } this->getRunMonsterArray()->addObject(monsterSprite); } // 传入弓箭 检测是否和怪物发生碰撞 bool MonsterSystem::(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; } void MonsterSystem::recoverMonster(MonsterSprite* monsterSprite){ // 把死掉的怪物回收以下 this->getRunMonsterArray()->removeObject(monsterSprite,false); // 从界面上移除掉 this->defenderGameLayer->removeChild(monsterSprite,false); // 还原怪物的 部分属性 if(monsterSprite->getMonType()==1){ monsterSprite->setBlood(dutu.initBlood); monsterSprite->setPosition(CCPointZero); monsterSprite->setMonType(dutu.type); // 停掉所有动画 monsterSprite->stopAllActions(); } this->getIdleMonsterArry()->addObject(monsterSprite); } ;// 用于主线程调用来远远不断的产生怪物 void MonsterSystem::addMonster(int type,int count){ for(int i=0;i<count;i++){ MonsterSprite* runmon=NULL; for(int j=0;j<this->getIdleMonsterArry()->count();j++){ MonsterSprite* temmon=(MonsterSprite*)this->getIdleMonsterArry()->objectAtIndex(j); if (temmon->getMonType()==type){ runmon=temmon; break; } } // 如果从空闲的线程 得到了需要的 怪物类型 就添加到界面上 反之 则需要创建一个 if (runmon){ this->getIdleMonsterArry()->removeObject(runmon,false); this->addDefenderGameLayer(runmon); }else { MonsterSprite* temmon= this->productMonster(type); if (temmon) { this->getIdleMonsterArry()->addObject( this->productMonster(type)); i--;//这里是把新创建的monster加入到空闲数组中,这样就能够重新检索一遍以便调用addDefenderGameLayer() }else { break; } } } } void MonsterSystem::setDefenderGameLayer(DefenderGameLayer* defenderGameLayer){ this->defenderGameLayer=defenderGameLayer; } CCArray* MonsterSystem::getRunMonsterArray(){ return this->runMonsterArray; } CCArray* MonsterSystem::getIdleMonsterArry(){ return this->idleMonsterArry; } MonsterSystem::~MonsterSystem(){ if (idleMonsterArry) { this->idleMonsterArry->autorelease(); } if (runMonsterArray) { this->runMonsterArray->autorelease(); } }MonsterSprite.h
#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::CC b9fb Texture2D* 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
MosterSprite.cpp
#include "MonsterSprite.h" #include "MonsterSystem.h" USING_NS_CC; MonsterSprite::MonsterSprite(void){ runArray=CCArray::create();//奔跑动画序列帧 runArray->retain(); deathArray=CCArray::create();//死亡动画序列帧 deathArray->retain(); attackArray=CCArray::create();//攻击动画序列帧 attackArray->retain(); } MonsterSprite* MonsterSprite::createWithMonsterRul(const char* filename,CCTexture2D* ccTexture2D,const char* pic,int runcount,int attackcount,int deathcout ){ CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(filename,ccTexture2D);//打开缓冲文件 CCSpriteFrame* temp=CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("%s-10.png",pic)->getCString());//怪物需要一张图片作为初始化的画面 MonsterSprite* monst=MonsterSprite::createWithSpriteFrame(temp);//创建一个初始化的怪物精灵 if (monst&&monst->setUpdateView()&&ccTexture2D){ // 初始化 奔跑动画序列帧 for(int i=0;i<runcount;i++){ monst->runArray->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("%s-1%d.png",pic,i)->getCString())); } // 初始化 攻击动画 序列帧 for(int i=0;i<attackcount;i++){ monst->attackArray->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("%s-2%d.png",pic,i)->getCString())); } // 初始化 死亡动画 序列帧 for(int i=0;i<deathcount;i++){ monst->deathArray->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("%s-3%d.png",pic,i)->getCString())); } // 初始化血条 return monst; }else { return NULL; } } MonsterSprite* MonsterSprite::createWithSpriteFrame(CCSpriteFrame *pSpriteFrame){//创建怪物精灵对象 MonsterSprite* monSter=new MonsterSprite(); if (pSpriteFrame&&monSter&&monSter->initWithSpriteFrame(pSpriteFrame))//如果初始化怪物精灵成功,则将MonsterSprite加入内存管理计数器 { monSter->autorelease(); return monSter; } CC_SAFE_DELETE(monSter); return NULL; } bool MonsterSprite::setUpdateView(){ bool isRet=false; do { // 添加血条的背景图片 CCSprite* bloodbackimg=CCSprite::createWithTexture(CCTextureCache::sharedTextureCache()->textureForKey("game/monster_blood_frame.png")); CC_BREAK_IF(!bloodbackimg); //增加血条框精灵 bloodbackimg->setPosition(ccp(this->getContentSize().width/2,this->getContentSize().height+2));//放到距离怪物上方2高度的正上方 this->addChild(bloodbackimg,1);//添加血条框到怪物 // 添加进度条 CCSprite* blood=CCSprite::createWithTexture(CCTextureCache::sharedTextureCache()->textureForKey("game/monster_blood.png")); CC_BREAK_IF(!blood);//增加血条进度框 this->bloodBwlid=CCProgressTimer::create(blood);//将血条绑定为进度条 CC_BREAK_IF(!bloodBwlid); bloodBwlid->setType(kCCProgressTimerTypeBar);// 设置成横向的 //可以看作是按矩形显示效果的进度条类型 bloodBwlid->setMidpoint(ccp(0,0)); // 用来设定进度条横向前进的方向从左向右或是从右向左 bloodBwlid->setBarChangeRate(ccp(1,0)); bloodBwlid->setPosition(ccp(this->getContentSize().width/2,this->getContentSize().height+2)); bloodBwlid->setPercentage(100); this->addChild(bloodBwlid,2); isRet=true; } while (0); return isRet; } // 执行奔跑动画 void MonsterSprite::runAnimation(){ this->setMonState(2); this->stopAllActions(); if(this->runArray->count()>0){ CCAnimation *animation=CCAnimation::createWithSpriteFrames(runArray,0.15f); CCAnimate *animate=CCAnimate::create(animation); CCCallFuncN *onComplete = CCCallFuncN::create(this, callfuncN_selector(MonsterSprite::runAnimationCallBack)); CCSequence* pse=CCSequence::create(animate,onComplete,NULL); // 一直执行奔跑动画 this->runAction(CCRepeatForever::create(pse)); this->schedule(schedule_selector(MonsterSprite::myload),0.15); } } void MonsterSprite::myload(float tie){ if (this->getMonState()==2){ this->moveRun(); } } void MonsterSprite::runAnimationCallBack(CCNode* pSed){ } // 执行死亡动画 void MonsterSprite::deathAnimation(){ this->setMonState(4); this->stopAllActions(); if(this->deathArray->count()>0){ CCAnimation *animation=CCAnimation::createWithSpriteFrames(deathArray,0.15f); CCAnimate *animate=CCAnimate::create(animation); CCCallFuncN *onComplete = CCCallFuncN::create(this, callfuncN_selector(MonsterSprite::deathAnimationCallBack)); CCSequence* pse=CCSequence::create(animate,onComplete,NULL); this->runAction(pse); } } void MonsterSprite::deathAnimationCallBack(CCNode* pSed){ if(this->monsterSystem){ this->monsterSystem->recoverMonster(this); } this->unscheduleAllSelectors(); } // 执行攻击动画 void MonsterSprite::attackAnimation(){ this->setMonState(3); this->stopAllActions(); if(this->attackArray->count()>0){ CCAnimation *animation=CCAnimation::createWithSpriteFrames(attackArray,0.15f); CCAnimate *animate=CCAnimate::create(animation); CCCallFuncN *onComplete = CCCallFuncN::create(this, callfuncN_selector(MonsterSprite::attackAnimationCallBack)); CCSequence* pse=CCSequence::create(animate,onComplete,NULL); this->runAction(CCRepeatForever::create(pse)); } } // 这个是接受攻击 主要改变 该怪物的气血值 和血条的显示 void MonsterSprite::fallBlood(float hurted){ float temp=this->getBlood(); // 按照 一点防御 能抵挡10%的伤害 来计算 this->setBlood(temp-(hurted-this->getDefense()*0.1)); if(this->getBlood()<=0){ this->bloodBwlid->setPercentage(0); this->deathAnimation(); }else { this->bloodBwlid->setPercentage(this->getBlood()); } } void MonsterSprite::attackAnimationCallBack(CCNode* pSed){ CCLOG("donghuazhixing2"); this->unscheduleAllSelectors(); } void MonsterSprite::moveRun(){ int x=this->getPositionX(); if(this->getMonState()==2){ // 当X 的坐标小于 最小的距离是 需要调用 攻击动画 x=x-this->getSpeed(); this->setPositionX(x); if(x<=this->getmaxRemoving()){ this->attackAnimation(); } } } 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()); } void MonsterSprite::setMonsterSystemUtils(MonsterSystem* monsterSystem){ this->monsterSystem=monsterSystem; } MonsterSprite::~MonsterSprite(void){ if (runArray) { runArray->autorelease(); } if (deathArray) { deathArray->autorelease(); } if (attackArray) { attackArray->autorelease(); } }
相关文章推荐
- 跟着BOY学习开发cocos2d-x 游戏 实战篇(4)之 游戏主界面 -----怪物系统---赌徒来袭
- cocos2d-x之怪物系统
- 跟着BOY学习开发cocos2d-x 游戏 实战篇(4)之 游戏主界面 -----怪物系统---赌徒来袭
- 开发cocos2d-x 游戏 实战篇(4)之 怪物系统
- 【Cocos2d-x-基础概念】坐标系统
- 【转载】cocos2d-x教程 Mac系统下搭建Lua的编码环境
- cocos2d-x——坐标系统
- cocos2d-x 获取系统毫秒数
- cocos2d-x粒子系统
- MAC系统安装/卸载cocos2d-x 2.1.4
- cocos2d-x 判断系统语言
- cocos2d-x学习之粒子系统1
- Cocos2d-x 详解坐标系统
- 【iOS-Cocos2d游戏开发之七】在cocos2d中添加/删除系统组件,并解决View设置透明会影响View中的其他组件的问题!【11月28日更新解决添加组件Cocos2d动画停止播放的BUG】
- 【麦可网】Cocos2d-X跨平台游戏开发学习笔记---第十九课:Cocos2D-X粒子系统1-3
- 为Cocos2d-x增加带Button回调的系统级消息框(MessageBox)
- cocos2d-x 系统动画
- Cocos2d-iphone 文本渲染系统
- Cocos2d-x 详解坐标系统
- cocos2d-js 粒子系统使用自定义图片,还原原来的图片宽高