cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第八部---怪物出场
/* 说明:
**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文件来配置,仅仅只是要手动
二:代码&效果
这里先有一个移动控制器的基类:
- #define CHECK_MOVE_SPEED_LVL1 0.1f //移动间隔
- #define CHECK_MOVE_SPEED_LVL2 0.04f
- #define CHECK_MOVE_SPEED_LVL3 0.03f
- #define SPEED 1
- class ControllerMoveBase : public Node{
- public:
- ControllerMoveBase();
- ~ControllerMoveBase();
- CC_SYNTHESIZE(int,_speed,Speed);
- protected:
- Entity* _entity; //实体
- bool _isMoving; //是否在移动
- bool _isXLeft; //x方向是否在左移
- bool _isYUp; //y方向是否在上移
- int _checkMoveSpeed;//移动间隔
- //依据当前Pos。以及目标点。获取下一个点坐标
- Point getNextPos(Point curPos,Point destPos);
- };
解释一下getNextPos函数,如我们编辑好的地图,两个点。(0,0) (0,500)那么最開始curPos 就是(0。0) 到达目标点之前,目标点一直都是(0,500),一秒之后走到了(0,100);那么此时curPos就是这个。然后继续依照速度计算下一个点
实现:
- ControllerMoveBase::ControllerMoveBase(){
- _isMoving = false;
- _isXLeft = false;
- _isYUp = false;
- _speed = SPEED;
- _checkMoveSpeed = CHECK_MOVE_SPEED_LVL2;
- _entity = NULL;
- }
- ControllerMoveBase::~ControllerMoveBase(){
- CC_SAFE_RELEASE(_entity);
- }
- Point ControllerMoveBase::getNextPos(Point curPos,Point destPos){
- //移动方向
- if(curPos.x > destPos.x){
- _isXLeft = true;
- }
- else{
- _isXLeft = false;
- }
- if(curPos.y < destPos.y){
- _isYUp = true;
- }
- else{
- _isYUp = false;
- }
- //改变坐标
- if(curPos.x < destPos.x && _isXLeft == false){
- curPos.x += _speed;
- if(curPos.x > destPos.x){
- curPos.x = destPos.x;
- }
- }
- else if(curPos.x > destPos.x && _isXLeft){
- curPos.x -= _speed;
- if(curPos.x < destPos.x){
- curPos.x = destPos.x;
- }
- }
- if(curPos.y < destPos.y && _isYUp == true) {
- curPos.y += _speed;
- if(curPos.y > destPos.y) {
- curPos.y = destPos.y;
- }
- }
- else if(curPos.y > destPos.y && _isYUp == false) {
- curPos.y -= _speed;
- if(curPos.y < destPos.y) {
- curPos.y = destPos.y;
- }
- }
- return curPos;
- }
那么来一个简单的移动控制器。也就是要用到怪物身上的。h
- class ControllerSimpleMove : public ControllerMoveBase{
- public:
- ControllerSimpleMove();
- ~ControllerSimpleMove();
- static ControllerSimpleMove* create(Entity* entity);
- bool init(Entity* entity);
- void moveByPoslist(Vector<PosBase*> posList, int speed, int spanTime);
- private:
- Vector<PosBase*> _movePosList; //依据坐标点移动
- PosBase* _curDestPos; //当前的目标点
- float _moveSpan; //移动时间间隔
- float _moveTimeCnt; //移动计时
- //移动update
- void checkMoveUpdate(float delta);
- void nextMovePos();
- };
.cpp
- ControllerSimpleMove::ControllerSimpleMove(){
- _curDestPos = NULL;
- _moveTimeCnt = 0;
- _moveSpan = 0;
- }
- ControllerSimpleMove::~ControllerSimpleMove(){
- CC_SAFE_RELEASE(_curDestPos);
- }
- ControllerSimpleMove* ControllerSimpleMove::create(Entity* entity){
- ControllerSimpleMove* simpleMove = new ControllerSimpleMove();
- if(simpleMove && simpleMove->init(entity)){
- simpleMove->autorelease();
- }
- else{
- CC_SAFE_DELETE(simpleMove);
- }
- return simpleMove;
- }
- bool ControllerSimpleMove::init(Entity* entity){
- CC_SAFE_RETAIN(entity);
- this->_entity = entity;
- this->schedule(schedule_selector(ControllerSimpleMove::checkMoveUpdate));
- return true;
- }
- void ControllerSimpleMove::checkMoveUpdate(float delta){
- if(_isMoving)
- {
- _moveTimeCnt += delta*1000;
- //移动时间到了
- if(_moveTimeCnt >= _moveSpan)
- {
- _moveTimeCnt = 0;
- //**8**移动
- if(_entity != NULL)
- {
- Point entityPos = _entity->getPosition();
- Point curDestPos = _curDestPos->getPos();
- //依据移动速度,来获得下一个点位置
- entityPos = getNextPos(entityPos,curDestPos);
- _entity->setPosition(entityPos);
- //当走到目标点 PosBase List 中的一个点之后,就要更新目标点
- if(entityPos.x == curDestPos.x && entityPos.y == curDestPos.y)
- {
- if(_movePosList.size() > 0){
- nextMovePos();
- }
- }
- }
- }
- }
- }
- void ControllerSimpleMove::nextMovePos(){
- if( _movePosList.size() <= 0){
- return;
- }
- CC_SAFE_RELEASE(_curDestPos);
- _curDestPos = (PosBase*)_movePosList.front();
- CC_SAFE_RETAIN(_curDestPos);
- _movePosList.eraseObject(_curDestPos);
- }
- void ControllerSimpleMove::moveByPoslist(Vector<PosBase*> posList, int speed, int spanTime){
- this->_speed = speed;
- this->_moveSpan = spanTime;
- if(posList.size() <= 0){
- return;
- }
- this->_movePosList.clear();
- this->_movePosList = posList;
- this->_isMoving = true;
- nextMovePos();
- }
总之能够先从public 成员函数moveByPosList開始看,这里才開始让_isMoving true,然后開始移动一步步移动
接触真正的怪物Monster
- enum EnumMonsterPropConfType {
- enMonsterPropConf_ID, // 怪物ID
- enMonsterPropConf_Name, // 怪物名字
- enMonsterPropConf_Level, // 怪物等级
- enMonsterPropConf_Type, // 怪物类型
- enMonsterPropConf_ModelID, // 怪物模型ID
- enMonsterPropConf_Defense, // 防御力
- enMonsterPropConf_Hp, // 血量
- enMonsterPropConf_Speed, // 移动速度
- };
- class Monster : public Entity{
- public:
- Monster();
- ~Monster();
- static Monster* createFromCsvByID(int monsterID);
- bool initFromCsvByID(int monsterID);
- //**8**有一个移动的方法。在怪物管理器中调用让其移动
- void moveByPosList(Vector<PosBase*> posList);
- private:
- CC_SYNTHESIZE(int,_level,Level);
- CC_SYNTHESIZE(float,_showTime,ShowTime);
- ControllerSimpleMove* _moveController;
- };
这里也有一个public成员函数,moveByPosList。这是留给在怪物管理器中,让怪物開始活动的函数
- Monster::Monster(){
- _moveController = NULL;
- }
- Monster::~Monster(){
- CC_SAFE_RELEASE(_moveController);
- }
- Monster* Monster::createFromCsvByID(int monsterID){
- Monster* monster = new Monster();
- if(monster && monster->initFromCsvByID(monsterID)){
- monster->autorelease();
- }
- else{
- CC_SAFE_DELETE(monster);
- }
- return monster;
- }
- bool Monster::initFromCsvByID(int monsterID){
- //**8**获得ID
- const char* chMonsterID = __String::createWithFormat("%d",monsterID)->getCString();
- //**8**绑定精灵
- const char* monsterSprite = __String::createWithFormat("sprite/monster/monster_%d.png",monsterID)->getCString();
- Sprite* sprite = Sprite::create(monsterSprite);
- bindSprite(sprite);
- //**8**绑定移动控制器
- _moveController = ControllerSimpleMove::create(this);
- this->addChild(_moveController);
- //**8**属性
- CsvUtil* csvUtil = CsvUtil::getInstance();
- Size csvSize = csvUtil->getFileRowColNum("csv/Monster.csv");
- int line = csvUtil->findValueInWithLine(chMonsterID,enMonsterPropConf_ID,"csv/Monster.csv");
- setID(monsterID);
- setLevel(csvUtil->getInt(line,enMonsterPropConf_Level,"csv/Monster.csv"));
- setModeID(csvUtil->getInt(line,enMonsterPropConf_ModelID,"csv/Monster.csv"));
- setDefense(csvUtil->getInt(line,enMonsterPropConf_Defense,"csv/Monster.csv"));
- setHP(csvUtil->getInt(line,enMonsterPropConf_Hp,"csv/Monster.csv"));
- setSpeed(csvUtil->getInt(line,enMonsterPropConf_Speed,"csv/Monster.csv"));
- return true;
- }
- void Monster::moveByPosList(Vector<PosBase*> posList){
- if(posList.size() <= 0) return ;
- _moveController->moveByPoslist(posList,2,getSpeed());
那么这里的属性什么的都和英雄差点儿相同。。
。。
仅仅只是这里须要注意一点点问题,csv/monster.csv要略微改动:怪物ID 从上到下改为1~5。而不是1000~1004、或者直接用本次的资源替换。
然后看看怪物管理器。通过plist文件载入怪物信息。update函数管理怪物出现
- class MonsterManager : public Node{
- public:
- MonsterManager();
- ~MonsterManager();
- static MonsterManager* createWithLevel(int curLevel);
- bool initWithLevel(int curLevel);
- private:
- //**8**有多个怪物。每个的出来的时间递增。用showTime累加。一个个登场
- float _showTime;
- //**8**全部的坐标点
- Vector<PosBase*> _monsterPosList;
- //**8**没有出场的怪物,一開始全部怪物都没出来
- Vector<Monster*> _notShowMonsterList;
- //**8**配置文件里的全部怪物
- Vector<Monster*> _monsterList;
- //**8**在init 函数中,创建怪物
- void createMonsters(int curLevel);
- //没有出场怪物数量
- int getNotShowMonsterCnt();
- //怪物的起始点
- PosBase* getMonsterStartPos();
- PosBase* getMonsterEndPos();
- //**8**展示怪物的update函数
- void showMonster(float dt);
- };
-----------------------------实现:
- MonsterManager::MonsterManager(){
- _showTime = 0;
- }
- MonsterManager::~MonsterManager(){
- }
- MonsterManager* MonsterManager::createWithLevel(int curLevel){
- MonsterManager* monsterMgr = new MonsterManager();
- if(monsterMgr && monsterMgr->initWithLevel(curLevel)){
- monsterMgr->autorelease();
- }
- else{
- CC_SAFE_DELETE(monsterMgr);
- }
- return monsterMgr;
- }
- bool MonsterManager::initWithLevel(int curLevel){
- //**8**依据关卡级别创建怪物
- createMonsters(curLevel);
- //**8**开启update,让怪物有顺序出现
- this->schedule(schedule_selector(MonsterManager::showMonster));
- return true;
- }
- void MonsterManager::createMonsters(int curLevel){
- //**8**载入路线坐标
- __String* monsterPosPath = __String::createWithFormat("tollgate/monsterPos_level_%d.plist",curLevel);
- PosLoadUtil::getInstance()->loadPosWithFile(_monsterPosList,enMonsterPos,monsterPosPath->getCString(),
- this,10,false);
- //**8**读取当前关卡的怪物配置
- __String* monsterConfPath = __String::createWithFormat("tollgate/monster_level_%d.plist",curLevel);
- auto monsterConfList = FileUtils::getInstance()->getValueVectorFromFile(monsterConfPath->getCString());
- for(auto ref : monsterConfList){
- auto temp_map = ref.asValueMap();
- int id = temp_map.at("id").asInt();
- float showTime = temp_map.at("showTime").asFloat();
- if( id != 0 && showTime != 0.0f){
- auto monster = Monster::createFromCsvByID(id);
- monster->setShowTime(showTime);
- monster->setVisible(false);
- _monsterList.pushBack(monster);
- _notShowMonsterList.pushBack(monster);
- this->addChild(monster);
- }
- }
- }
- int MonsterManager::getNotShowMonsterCnt(){
- return _notShowMonsterList.size();
- }
- PosBase* MonsterManager::getMonsterStartPos(){
- return _monsterPosList.front();
- }
- PosBase* MonsterManager::getMonsterEndPos(){
- return _monsterPosList.back();
- }
- void MonsterManager::showMonster(float dt){
- int notShowMonsterCnt = _notShowMonsterList.size();
- if(notShowMonsterCnt > 0){
- _showTime += dt;
- }
- PosBase* monsterFirstPos = getMonsterStartPos();
- //**8**把本次出场的怪物保存。然后删除。C++中不能在容器遍历的过程中删除,会出错
- Vector<Monster*> temp_deletList;
- for(auto monster : _notShowMonsterList){
- if(monster != NULL){
- if(_showTime >= monster->getShowTime()){
- temp_deletList.pushBack(monster);
- monster->setPosition(monsterFirstPos->getPos());
- monster->setVisible(true);
- monster->moveByPosList(_monsterPosList);
- }
- }
- }
- for(auto deletMonster : temp_deletList){
- _notShowMonsterList.eraseObject(deletMonster);
- }
- }
这里可到后面的资源中game/中获取怪物的管理配置文件
---------------------------------------------
然后在MapLayer中加入成员。以及在init函数中把怪物管理加入
- //**8**
- _monsterMgr = MonsterManager::createWithLevel(_curLevel);
- this->addChild(_monsterMgr);
那么最后展演示样例如以下,怪物分组出来啦......
三:下次内容
英雄没有尽职。不攻击怪物!!!
四:
----------------------------------
----------------------------------
个人愚昧观点。欢迎指正与讨论
cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第八部---怪物出场的更多相关文章
- cocos2d-x 3.0游戏实例学习笔记 《跑酷》 完结篇--源代码放送
说明:这里是借鉴:晓风残月前辈的博客,他是将泰然网的跑酷教程,用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第0步---知识点总结&效果预览&设计思路
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏.这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写.第一别全然照搬代码:第二能够说 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第二步---编辑器(1)--触摸加入点
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写,第一别全然照搬代码:第二能够说 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第三步---编辑器(2)---更方便很多其它操作更像编辑器
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第一步---開始界面&关卡选择
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第七步---英雄要升级&属性--解析csv配置文件
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第六步---炮台&点击炮台加入英雄&英雄升级
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写,第一别全然照搬代码:第二能够说 ...
- cocos2d-x 3.0游戏实例学习笔记 《跑酷》移植到android手机
说明:这里是借鉴:晓风残月前辈的博客.他是将泰然网的跑酷教程.用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...
- cocos2d-x 3.0游戏实例学习笔记 《跑酷》第一步--- 开始界面
说明:这里是平局:晓风残月前辈的博客.他是将泰然网的跑酷教程.用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...
随机推荐
- Windows通过远程桌面访问Ubuntu
关于Windows通过远程桌面访问Ubuntu 问题及目标 Window环境通过远程桌面访问Ubuntu Ubuntu机器端 1. 安装所需软件包 sudoapt-get install x ...
- 升级版:深入浅出Hadoop实战开发(云存储、MapReduce、HBase实战微博、Hive应用、Storm应用)
Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式文件系 ...
- webdynpro 下拉列表控件
现在界面上添加下拉列表的控件DropDownByKey 在context中创建新的node,和属性DP 返回界面,绑定DP到控件DropDownByKey的SelectedKey 初始方法中代码如下: ...
- ext4 delalloc相关
ext4文件系统delayed allocation相关研究 最近在一个项目上测试录音时,发现有丢数据的现象.通过串口发现打出了很多overrun的log. overrun是驱动层给上层应用的一个通知 ...
- POJ 1781 In Danger Joseph环 位运算解法
Joseph环,这次模固定是2.假设不是固定模2,那么一般时间效率是O(n).可是这次由于固定模2,那么能够利用2的特殊性,把时间效率提高到O(1). 规律能够看下图: watermark/2/tex ...
- PySide——Python图形化界面
PySide——Python图形化界面 PySide——Python图形化界面入门教程(四) PySide——Python图形化界面入门教程(四) ——创建自己的信号槽 ——Creating Your ...
- js检测是否手机浏览的函数
原文:js检测是否手机浏览的函数 查看一个web应用的时候查看源代码无意发现的,记录一下,万能什么时候能用得着呢! function isMobile() { var mobile = navigat ...
- 推荐一款功能强大的js 在线编辑器
http://jszi.cn/public/oherub/11/edit
- 用ATL开发和部署ActiveX网页控件
用ATL开发和部署ActiveX网页控件 摘 要 ActiveX插件技术广泛的运用于B/S系统中,本文通过一个项目实例,详细介绍用ATL开发和部署ActiveX网页控件的过程.学习使用ActiveX让 ...
- Android监听外部存储设备的状态(SD卡、U盘等等)
近期在项目中须要对外部存储设备的状态进行监听,所以整理了此笔记,以便日后查看. 外部存储设备的状态变化时发出的广播 对照不同状态下的广播 1. 插入外部SD卡时: 2. 移除外部SD卡时: 3. 连接 ...