/* 说明:

**1.本次游戏实例是《cocos2d-x游戏开发之旅》上的最后一个游戏,这里用3.0重写并做下笔记

**2.我也问过木头本人啦,他说:随便写。第一别全然照搬代码。第二能够说明是学习笔记---好人

**3.这里用cocos2d-x 3.0版本号重写。非常多地方不同。可是从重写过程中也非常好的学习了cocos2d-x

*/

***每一步相应的全部代码以及用到的资源都会打包在最后给出

***为避免代码过多。每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用Git?)

***为了方便移植到手机上。对于每一步都进行编译android測试。由于非常多时候代码在win32下能够,编译就会出错,给出的代码会是測试过后的。

本次笔记内容:

1,、简单的设计思路

2、代码&效果

3、下次笔记内容

4、本次代码&资源下载

一:简单的设计思路

1、怪物须要移动。若所有放到Monster类里面就太复杂啦,于是乎和前面一样,也抽离出来一个移动控制器,怪物带着一个控制器就能够依照路线行走

2、关于移动控制器,是依据之前编辑好的怪物路线---也就是那些有顺序的点来行走,那么移动控制器得用update来实现自己主动行走

3、英雄临时仅仅有一种,可是怪物有5中,也有其属性

4、每一关的怪物数量。种类也通过plist文件来配置,仅仅只是要手动

二:代码&效果

这里先有一个移动控制器的基类:

  1. #define CHECK_MOVE_SPEED_LVL1 0.1f //移动间隔
  2. #define CHECK_MOVE_SPEED_LVL2 0.04f
  3. #define CHECK_MOVE_SPEED_LVL3 0.03f
  4.  
  5. #define SPEED 1
  6.  
  7. class ControllerMoveBase : public Node{
  8. public:
  9. ControllerMoveBase();
  10. ~ControllerMoveBase();
  11. CC_SYNTHESIZE(int,_speed,Speed);
  12.  
  13. protected:
  14. Entity* _entity; //实体
  15. bool _isMoving; //是否在移动
  16. bool _isXLeft; //x方向是否在左移
  17. bool _isYUp; //y方向是否在上移
  18. int _checkMoveSpeed;//移动间隔
  19.  
  20. //依据当前Pos。以及目标点。获取下一个点坐标
  21. Point getNextPos(Point curPos,Point destPos);
  22. };

解释一下getNextPos函数,如我们编辑好的地图,两个点。(0,0) (0,500)那么最開始curPos 就是(0。0) 到达目标点之前,目标点一直都是(0,500),一秒之后走到了(0,100);那么此时curPos就是这个。然后继续依照速度计算下一个点

实现:

  1. ControllerMoveBase::ControllerMoveBase(){
  2. _isMoving = false;
  3. _isXLeft = false;
  4. _isYUp = false;
  5. _speed = SPEED;
  6. _checkMoveSpeed = CHECK_MOVE_SPEED_LVL2;
  7. _entity = NULL;
  8. }
  9. ControllerMoveBase::~ControllerMoveBase(){
  10. CC_SAFE_RELEASE(_entity);
  11. }
  12.  
  13. Point ControllerMoveBase::getNextPos(Point curPos,Point destPos){
  14. //移动方向
  15. if(curPos.x > destPos.x){
  16. _isXLeft = true;
  17. }
  18. else{
  19. _isXLeft = false;
  20. }
  21.  
  22. if(curPos.y < destPos.y){
  23. _isYUp = true;
  24. }
  25. else{
  26. _isYUp = false;
  27. }
  28.  
  29. //改变坐标
  30. if(curPos.x < destPos.x && _isXLeft == false){
  31. curPos.x += _speed;
  32. if(curPos.x > destPos.x){
  33. curPos.x = destPos.x;
  34. }
  35. }
  36. else if(curPos.x > destPos.x && _isXLeft){
  37. curPos.x -= _speed;
  38. if(curPos.x < destPos.x){
  39. curPos.x = destPos.x;
  40. }
  41. }
  42.  
  43. if(curPos.y < destPos.y && _isYUp == true) {
  44. curPos.y += _speed;
  45. if(curPos.y > destPos.y) {
  46. curPos.y = destPos.y;
  47. }
  48. }
  49. else if(curPos.y > destPos.y && _isYUp == false) {
  50. curPos.y -= _speed;
  51. if(curPos.y < destPos.y) {
  52. curPos.y = destPos.y;
  53. }
  54. }
  55. return curPos;
  56. }

那么来一个简单的移动控制器。也就是要用到怪物身上的。h

  1. class ControllerSimpleMove : public ControllerMoveBase{
  2. public:
  3. ControllerSimpleMove();
  4. ~ControllerSimpleMove();
  5. static ControllerSimpleMove* create(Entity* entity);
  6. bool init(Entity* entity);
  7.  
  8. void moveByPoslist(Vector<PosBase*> posList, int speed, int spanTime);
  9.  
  10. private:
  11. Vector<PosBase*> _movePosList; //依据坐标点移动
  12. PosBase* _curDestPos; //当前的目标点
  13. float _moveSpan; //移动时间间隔
  14. float _moveTimeCnt; //移动计时
  15.  
  16. //移动update
  17. void checkMoveUpdate(float delta);
  18.  
  19. void nextMovePos();
  20.  
  21. };

.cpp

  1. ControllerSimpleMove::ControllerSimpleMove(){
  2. _curDestPos = NULL;
  3. _moveTimeCnt = 0;
  4. _moveSpan = 0;
  5. }
  6. ControllerSimpleMove::~ControllerSimpleMove(){
  7. CC_SAFE_RELEASE(_curDestPos);
  8. }
  9.  
  10. ControllerSimpleMove* ControllerSimpleMove::create(Entity* entity){
  11. ControllerSimpleMove* simpleMove = new ControllerSimpleMove();
  12. if(simpleMove && simpleMove->init(entity)){
  13. simpleMove->autorelease();
  14. }
  15. else{
  16. CC_SAFE_DELETE(simpleMove);
  17. }
  18. return simpleMove;
  19. }
  20.  
  21. bool ControllerSimpleMove::init(Entity* entity){
  22. CC_SAFE_RETAIN(entity);
  23. this->_entity = entity;
  24.  
  25. this->schedule(schedule_selector(ControllerSimpleMove::checkMoveUpdate));
  26.  
  27. return true;
  28. }
  29.  
  30. void ControllerSimpleMove::checkMoveUpdate(float delta){
  31. if(_isMoving)
  32. {
  33. _moveTimeCnt += delta*1000;
  34.  
  35. //移动时间到了
  36. if(_moveTimeCnt >= _moveSpan)
  37. {
  38. _moveTimeCnt = 0;
  39.  
  40. //**8**移动
  41. if(_entity != NULL)
  42. {
  43. Point entityPos = _entity->getPosition();
  44. Point curDestPos = _curDestPos->getPos();
  45. //依据移动速度,来获得下一个点位置
  46. entityPos = getNextPos(entityPos,curDestPos);
  47.  
  48. _entity->setPosition(entityPos);
  49.  
  50. //当走到目标点 PosBase List 中的一个点之后,就要更新目标点
  51. if(entityPos.x == curDestPos.x && entityPos.y == curDestPos.y)
  52. {
  53. if(_movePosList.size() > 0){
  54. nextMovePos();
  55. }
  56. }
  57. }
  58. }
  59. }
  60. }
  61.  
  62. void ControllerSimpleMove::nextMovePos(){
  63. if( _movePosList.size() <= 0){
  64. return;
  65. }
  66. CC_SAFE_RELEASE(_curDestPos);
  67. _curDestPos = (PosBase*)_movePosList.front();
  68. CC_SAFE_RETAIN(_curDestPos);
  69.  
  70. _movePosList.eraseObject(_curDestPos);
  71. }
  72.  
  73. void ControllerSimpleMove::moveByPoslist(Vector<PosBase*> posList, int speed, int spanTime){
  74. this->_speed = speed;
  75. this->_moveSpan = spanTime;
  76.  
  77. if(posList.size() <= 0){
  78. return;
  79. }
  80. this->_movePosList.clear();
  81. this->_movePosList = posList;
  82.  
  83. this->_isMoving = true;
  84.  
  85. nextMovePos();
  86.  
  87. }

总之能够先从public 成员函数moveByPosList開始看,这里才開始让_isMoving true,然后開始移动一步步移动

接触真正的怪物Monster

  1. enum EnumMonsterPropConfType {
  2. enMonsterPropConf_ID, // 怪物ID
  3. enMonsterPropConf_Name, // 怪物名字
  4. enMonsterPropConf_Level, // 怪物等级
  5. enMonsterPropConf_Type, // 怪物类型
  6. enMonsterPropConf_ModelID, // 怪物模型ID
  7. enMonsterPropConf_Defense, // 防御力
  8. enMonsterPropConf_Hp, // 血量
  9. enMonsterPropConf_Speed, // 移动速度
  10. };
  11.  
  12. class Monster : public Entity{
  13. public:
  14. Monster();
  15. ~Monster();
  16.  
  17. static Monster* createFromCsvByID(int monsterID);
  18. bool initFromCsvByID(int monsterID);
  19.  
  20. //**8**有一个移动的方法。在怪物管理器中调用让其移动
  21. void moveByPosList(Vector<PosBase*> posList);
  22.  
  23. private:
  24. CC_SYNTHESIZE(int,_level,Level);
  25. CC_SYNTHESIZE(float,_showTime,ShowTime);
  26.  
  27. ControllerSimpleMove* _moveController;
  28.  
  29. };

这里也有一个public成员函数,moveByPosList。这是留给在怪物管理器中,让怪物開始活动的函数

  1. Monster::Monster(){
  2. _moveController = NULL;
  3. }
  4. Monster::~Monster(){
  5. CC_SAFE_RELEASE(_moveController);
  6. }
  7.  
  8. Monster* Monster::createFromCsvByID(int monsterID){
  9. Monster* monster = new Monster();
  10.  
  11. if(monster && monster->initFromCsvByID(monsterID)){
  12. monster->autorelease();
  13. }
  14. else{
  15. CC_SAFE_DELETE(monster);
  16. }
  17. return monster;
  18. }
  19.  
  20. bool Monster::initFromCsvByID(int monsterID){
  21. //**8**获得ID
  22. const char* chMonsterID = __String::createWithFormat("%d",monsterID)->getCString();
  23.  
  24. //**8**绑定精灵
  25. const char* monsterSprite = __String::createWithFormat("sprite/monster/monster_%d.png",monsterID)->getCString();
  26. Sprite* sprite = Sprite::create(monsterSprite);
  27. bindSprite(sprite);
  28.  
  29. //**8**绑定移动控制器
  30. _moveController = ControllerSimpleMove::create(this);
  31. this->addChild(_moveController);
  32.  
  33. //**8**属性
  34. CsvUtil* csvUtil = CsvUtil::getInstance();
  35. Size csvSize = csvUtil->getFileRowColNum("csv/Monster.csv");
  36.  
  37. int line = csvUtil->findValueInWithLine(chMonsterID,enMonsterPropConf_ID,"csv/Monster.csv");
  38.  
  39. setID(monsterID);
  40. setLevel(csvUtil->getInt(line,enMonsterPropConf_Level,"csv/Monster.csv"));
  41. setModeID(csvUtil->getInt(line,enMonsterPropConf_ModelID,"csv/Monster.csv"));
  42. setDefense(csvUtil->getInt(line,enMonsterPropConf_Defense,"csv/Monster.csv"));
  43. setHP(csvUtil->getInt(line,enMonsterPropConf_Hp,"csv/Monster.csv"));
  44. setSpeed(csvUtil->getInt(line,enMonsterPropConf_Speed,"csv/Monster.csv"));
  45.  
  46. return true;
  47. }
  48.  
  49. void Monster::moveByPosList(Vector<PosBase*> posList){
  50. if(posList.size() <= 0) return ;
  51. _moveController->moveByPoslist(posList,2,getSpeed());

那么这里的属性什么的都和英雄差点儿相同。。

。。

仅仅只是这里须要注意一点点问题,csv/monster.csv要略微改动:怪物ID 从上到下改为1~5。而不是1000~1004、或者直接用本次的资源替换。

然后看看怪物管理器。通过plist文件载入怪物信息。update函数管理怪物出现

  1. class MonsterManager : public Node{
  2. public:
  3. MonsterManager();
  4. ~MonsterManager();
  5. static MonsterManager* createWithLevel(int curLevel);
  6. bool initWithLevel(int curLevel);
  7.  
  8. private:
  9. //**8**有多个怪物。每个的出来的时间递增。用showTime累加。一个个登场
  10. float _showTime;
  11.  
  12. //**8**全部的坐标点
  13. Vector<PosBase*> _monsterPosList;
  14.  
  15. //**8**没有出场的怪物,一開始全部怪物都没出来
  16. Vector<Monster*> _notShowMonsterList;
  17.  
  18. //**8**配置文件里的全部怪物
  19. Vector<Monster*> _monsterList;
  20.  
  21. //**8**在init 函数中,创建怪物
  22. void createMonsters(int curLevel);
  23.  
  24. //没有出场怪物数量
  25. int getNotShowMonsterCnt();
  26.  
  27. //怪物的起始点
  28. PosBase* getMonsterStartPos();
  29. PosBase* getMonsterEndPos();
  30.  
  31. //**8**展示怪物的update函数
  32. void showMonster(float dt);
  33. };

-----------------------------实现:

  1. MonsterManager::MonsterManager(){
  2. _showTime = 0;
  3. }
  4. MonsterManager::~MonsterManager(){
  5. }
  6.  
  7. MonsterManager* MonsterManager::createWithLevel(int curLevel){
  8. MonsterManager* monsterMgr = new MonsterManager();
  9.  
  10. if(monsterMgr && monsterMgr->initWithLevel(curLevel)){
  11. monsterMgr->autorelease();
  12. }
  13. else{
  14. CC_SAFE_DELETE(monsterMgr);
  15. }
  16. return monsterMgr;
  17. }
  18.  
  19. bool MonsterManager::initWithLevel(int curLevel){
  20. //**8**依据关卡级别创建怪物
  21. createMonsters(curLevel);
  22.  
  23. //**8**开启update,让怪物有顺序出现
  24. this->schedule(schedule_selector(MonsterManager::showMonster));
  25. return true;
  26. }
  27.  
  28. void MonsterManager::createMonsters(int curLevel){
  29. //**8**载入路线坐标
  30. __String* monsterPosPath = __String::createWithFormat("tollgate/monsterPos_level_%d.plist",curLevel);
  31. PosLoadUtil::getInstance()->loadPosWithFile(_monsterPosList,enMonsterPos,monsterPosPath->getCString(),
  32. this,10,false);
  33.  
  34. //**8**读取当前关卡的怪物配置
  35. __String* monsterConfPath = __String::createWithFormat("tollgate/monster_level_%d.plist",curLevel);
  36. auto monsterConfList = FileUtils::getInstance()->getValueVectorFromFile(monsterConfPath->getCString());
  37.  
  38. for(auto ref : monsterConfList){
  39. auto temp_map = ref.asValueMap();
  40.  
  41. int id = temp_map.at("id").asInt();
  42. float showTime = temp_map.at("showTime").asFloat();
  43.  
  44. if( id != 0 && showTime != 0.0f){
  45. auto monster = Monster::createFromCsvByID(id);
  46. monster->setShowTime(showTime);
  47. monster->setVisible(false);
  48.  
  49. _monsterList.pushBack(monster);
  50. _notShowMonsterList.pushBack(monster);
  51. this->addChild(monster);
  52. }
  53. }
  54.  
  55. }
  56.  
  57. int MonsterManager::getNotShowMonsterCnt(){
  58. return _notShowMonsterList.size();
  59. }
  60.  
  61. PosBase* MonsterManager::getMonsterStartPos(){
  62. return _monsterPosList.front();
  63. }
  64.  
  65. PosBase* MonsterManager::getMonsterEndPos(){
  66. return _monsterPosList.back();
  67. }
  68.  
  69. void MonsterManager::showMonster(float dt){
  70. int notShowMonsterCnt = _notShowMonsterList.size();
  71.  
  72. if(notShowMonsterCnt > 0){
  73. _showTime += dt;
  74. }
  75.  
  76. PosBase* monsterFirstPos = getMonsterStartPos();
  77.  
  78. //**8**把本次出场的怪物保存。然后删除。C++中不能在容器遍历的过程中删除,会出错
  79. Vector<Monster*> temp_deletList;
  80.  
  81. for(auto monster : _notShowMonsterList){
  82. if(monster != NULL){
  83. if(_showTime >= monster->getShowTime()){
  84. temp_deletList.pushBack(monster);
  85. monster->setPosition(monsterFirstPos->getPos());
  86. monster->setVisible(true);
  87.  
  88. monster->moveByPosList(_monsterPosList);
  89. }
  90. }
  91. }
  92.  
  93. for(auto deletMonster : temp_deletList){
  94. _notShowMonsterList.eraseObject(deletMonster);
  95. }
  96. }

这里可到后面的资源中game/中获取怪物的管理配置文件

---------------------------------------------

然后在MapLayer中加入成员。以及在init函数中把怪物管理加入

  1. //**8**
  2. _monsterMgr = MonsterManager::createWithLevel(_curLevel);
  3. this->addChild(_monsterMgr);

那么最后展演示样例如以下,怪物分组出来啦......

三:下次内容

英雄没有尽职。不攻击怪物!!!

四:

----------------------------------

资源&代码

----------------------------------

个人愚昧观点。欢迎指正与讨论

cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第八部---怪物出场的更多相关文章

  1. cocos2d-x 3.0游戏实例学习笔记 《跑酷》 完结篇--源代码放送

    说明:这里是借鉴:晓风残月前辈的博客,他是将泰然网的跑酷教程,用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...

  2. cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第0步---知识点总结&amp;效果预览&amp;设计思路

    /* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏.这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写.第一别全然照搬代码:第二能够说 ...

  3. cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第二步---编辑器(1)--触摸加入点

    /* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写,第一别全然照搬代码:第二能够说 ...

  4. cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第三步---编辑器(2)---更方便很多其它操作更像编辑器

    /* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说 ...

  5. cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第一步---開始界面&amp;关卡选择

    /* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说 ...

  6. cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第七步---英雄要升级&amp;属性--解析csv配置文件

    /* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说 ...

  7. cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第六步---炮台&amp;点击炮台加入英雄&amp;英雄升级

    /* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写,第一别全然照搬代码:第二能够说 ...

  8. cocos2d-x 3.0游戏实例学习笔记 《跑酷》移植到android手机

    说明:这里是借鉴:晓风残月前辈的博客.他是将泰然网的跑酷教程.用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...

  9. cocos2d-x 3.0游戏实例学习笔记 《跑酷》第一步--- 开始界面

    说明:这里是平局:晓风残月前辈的博客.他是将泰然网的跑酷教程.用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...

随机推荐

  1. Windows通过远程桌面访问Ubuntu

    关于Windows通过远程桌面访问Ubuntu 问题及目标 Window环境通过远程桌面访问Ubuntu Ubuntu机器端   1.  安装所需软件包   sudoapt-get install x ...

  2. 升级版:深入浅出Hadoop实战开发(云存储、MapReduce、HBase实战微博、Hive应用、Storm应用)

          Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式文件系 ...

  3. webdynpro 下拉列表控件

    现在界面上添加下拉列表的控件DropDownByKey 在context中创建新的node,和属性DP 返回界面,绑定DP到控件DropDownByKey的SelectedKey 初始方法中代码如下: ...

  4. ext4 delalloc相关

    ext4文件系统delayed allocation相关研究 最近在一个项目上测试录音时,发现有丢数据的现象.通过串口发现打出了很多overrun的log. overrun是驱动层给上层应用的一个通知 ...

  5. POJ 1781 In Danger Joseph环 位运算解法

    Joseph环,这次模固定是2.假设不是固定模2,那么一般时间效率是O(n).可是这次由于固定模2,那么能够利用2的特殊性,把时间效率提高到O(1). 规律能够看下图: watermark/2/tex ...

  6. PySide——Python图形化界面

    PySide——Python图形化界面 PySide——Python图形化界面入门教程(四) PySide——Python图形化界面入门教程(四) ——创建自己的信号槽 ——Creating Your ...

  7. js检测是否手机浏览的函数

    原文:js检测是否手机浏览的函数 查看一个web应用的时候查看源代码无意发现的,记录一下,万能什么时候能用得着呢! function isMobile() { var mobile = navigat ...

  8. 推荐一款功能强大的js 在线编辑器

    http://jszi.cn/public/oherub/11/edit

  9. 用ATL开发和部署ActiveX网页控件

    用ATL开发和部署ActiveX网页控件 摘 要 ActiveX插件技术广泛的运用于B/S系统中,本文通过一个项目实例,详细介绍用ATL开发和部署ActiveX网页控件的过程.学习使用ActiveX让 ...

  10. Android监听外部存储设备的状态(SD卡、U盘等等)

    近期在项目中须要对外部存储设备的状态进行监听,所以整理了此笔记,以便日后查看. 外部存储设备的状态变化时发出的广播 对照不同状态下的广播 1. 插入外部SD卡时: 2. 移除外部SD卡时: 3. 连接 ...