/* 说明:

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

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

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

*/

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

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

***能够依据设计思路(好吧,那名字太高大上。实际就是这一步要干啥)先自己实现---cocos2d-x本来就是如此,同样的功能有很多不同实现方法;先自己折腾是蛮不错的。

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

本次笔记内容:

1、设计思路

2、思路代码&效果图

3、下次内容预览

4、本次资源&完整代码下载

一:设计思路

1.首先英雄升级体现放置Hero里面upgrade函数。相应升级有不同的效果体现

2.升级操作抽离成一个操作器继承自Node,然后绑定在炮台上,后面点击炮台,出现三个button---升级、关闭、删除英雄

3.英雄的升级不仅仅是体如今外表,它也有属性。属性提升---属性就得从csv文件读取

5.因为这后面思路基本借鉴书上的,就不班门弄斧啦---直接在代码中结束

二:思路代码&效果图

首先给英雄升级函数。这里写得比較死,同一时候仅仅支持4级提升;每一次提升之后就弄一个动作覆盖上去

void Hero::upgrade(){
Sprite* sprite = getSprite();
if(sprite == NULL || _level >= 4) {
return;
} // 添加等级
_level++; // 英雄遮罩
if(_level == 2) {
Sprite* heroTop = Sprite::create("sprite/hero/hero_top_1.png");
Point pos = ccp(sprite->getContentSize().width / 2, sprite->getContentSize().height / 2);
heroTop->setPosition(pos);
sprite->addChild(heroTop);
}
if(_level == 3) {
Sprite* heroTop = Sprite::create("sprite/hero/hero_top_2.png");
heroTop->setOpacity(255);
Point pos = ccp(sprite->getContentSize().width / 2, sprite->getContentSize().height / 2);
heroTop->setPosition(pos);
sprite->addChild(heroTop); ActionInterval* rotateBy = RotateBy::create(25.0f, 360, 360);
ActionInterval* repeat = RepeatForever::create(rotateBy);
heroTop->runAction(repeat);
}
if(_level == 4) {
Point pos = ccp(sprite->getContentSize().width / 2, sprite->getContentSize().height / 2);
Sprite* heroTop = Sprite::create("sprite/hero/hero_top_3.png");
heroTop->setPosition(pos);
sprite->addChild(heroTop); ActionInterval* rotateBy = RotateBy::create(10.0f, 360, 360);
ActionInterval* repeat = RepeatForever::create(rotateBy);
heroTop->runAction(repeat);
} }

那么相应四个主要的不同效果例如以下:

lv1----lv2----lv3------lv4

效果是动态的动作

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

那么看看那操作器 TowerOperator;它须要和Hero以及炮台保存联系,须要这两个成员

class TowerOperator : public Node{
public:
TowerOperator();
~TowerOperator();
static TowerOperator* create(TowerBorder* towerBorder,Hero* hero);
bool init(TowerBorder* towerBorder,Hero* hero); private:
Hero* _hero;
TowerBorder* _towerBorder; void createOprBtns(); //**7**button事件
void closeEvent(Ref* pSender,Control::EventType event);
void upgradeEvent(Ref* pSender,Control::EventType event);
void deleteEvent(Ref* pSender,Control::EventType event);
};

实现

TowerOperator::TowerOperator(){
_hero = NULL;
_towerBorder = NULL;
}
TowerOperator::~TowerOperator(){
CC_SAFE_RELEASE(_hero);
CC_SAFE_RELEASE(_towerBorder);
} TowerOperator* TowerOperator::create(TowerBorder* towerBorder,Hero* hero){
TowerOperator* towerOperator = new TowerOperator();
if(towerOperator && towerOperator->init(towerBorder,hero)){
towerOperator->autorelease();
}
else{
CC_SAFE_DELETE(towerOperator);
}
return towerOperator;
} bool TowerOperator::init(TowerBorder* towerBorder, Hero* hero){
CC_SAFE_RETAIN(towerBorder);
_towerBorder = towerBorder; CC_SAFE_RETAIN(hero);
_hero = hero; createOprBtns();
return true;
} void TowerOperator::createOprBtns(){
LabelTTF* title = LabelTTF::create("Close", "Arial", 25); auto m_pos = this->getPosition(); ControlButton* closeBtn = ControlButton::create(title, Scale9Sprite::create("Button/opr_btn_nor.png"));
closeBtn->setBackgroundSpriteForState(Scale9Sprite::create("Button/opr_btn_light.png"), Control::State::HIGH_LIGHTED);
closeBtn->addTargetWithActionForControlEvents(this,
cccontrol_selector(TowerOperator::closeEvent), Control::EventType::TOUCH_UP_INSIDE);
closeBtn->setPosition(
ccp(m_pos.x+100,m_pos.y));
this->addChild(closeBtn); title = CCLabelTTF::create("Delete", "Arial", 25);
ControlButton* deleteBtn = ControlButton::create(title, Scale9Sprite::create("Button/opr_btn_nor.png"));
deleteBtn->setBackgroundSpriteForState(Scale9Sprite::create("Button/opr_btn_light.png"), Control::State::HIGH_LIGHTED);
deleteBtn->addTargetWithActionForControlEvents(this,
cccontrol_selector(TowerOperator::deleteEvent), Control::EventType::TOUCH_UP_INSIDE);
deleteBtn->setPosition(
ccp(m_pos.x-100,m_pos.y));
this->addChild(deleteBtn); title = CCLabelTTF::create("Upgrade", "Arial", 25);
ControlButton* upgradeBtn = ControlButton::create(title, Scale9Sprite::create("Button/opr_btn_nor.png"));
upgradeBtn->setBackgroundSpriteForState(Scale9Sprite::create("Button/opr_btn_light.png"), Control::State::HIGH_LIGHTED);
upgradeBtn->addTargetWithActionForControlEvents(this,
cccontrol_selector(TowerOperator::upgradeEvent), Control::EventType::TOUCH_UP_INSIDE);
upgradeBtn->setPosition(
ccp(m_pos.x,m_pos.y+100));
this->addChild(upgradeBtn);
} void TowerOperator::closeEvent(Ref* pSender,Control::EventType event){
CCLOG("close!");
this->removeFromParentAndCleanup(true);
}
void TowerOperator::upgradeEvent(Ref* pSender,Control::EventType event){
CCLOG("upgrade!");
_hero->upgrade();
}
void TowerOperator::deleteEvent(Ref* pSender,Control::EventType event){
CCLOG("delete!");
_towerBorder->deleteHero();
this->removeFromParentAndCleanup(true);
}

三个button,这里也要注意的是相对位置的放置问题,也就是son & parent的位置问题

三个button的函数比較简单。那么相应删除操作,是由——_towerBorder去完毕的。其函数为:

void TowerBorder::deleteHero(){
_hero->removeFromParentAndCleanup(true);
CC_SAFE_RELEASE_NULL(_hero);
}

而且。要注意,不要用_hero直接从parent删除,不然导致这个炮台下次无法继续加入

那么我们的操作器得展示出来。回忆往炮台加英雄的时候,是在触摸事件中,次炮台没有英雄的时候就加入,那么假设有。我们就显示操作器就是啦:

void TowerBorder::showOperator(){
auto towerOperator = TowerOperator::create(this,_hero);
CC_SAFE_RETAIN(towerOperator);
towerOperator->setPosition(ccp(0,0));
this->addChild(towerOperator);
}
//这里的setPostion以及操作器里面的setPos也和前面说过的相对位置有关
bool HeroManager::initWithLevel(int curLevel){
/********************省略*****************/
listener->onTouchEnded = [=](Touch* touch,Event* event){
/********************省略*****************/
if(clickBorder->getHero() == NULL){
Hero* hero = Hero::createFromCsvFileByID(1);
hero->setPosition(clickBorder->getPosition());
this->addChild(hero);
clickBorder->bindHero(hero);
}
else{
clickBorder->showOperator();
}
}; _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this); //------------------------------------------------------------ return true;
}

效果例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWllZMTczNTMzODMy/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="600" height="350" alt="">

那么,我们英雄的升级有了外表的体现啦

但是我们的英雄一直没有属性上的配置-----------------这要通过csv 来弄。

首先须要说明的是:

csv是一种简单的文件。你能够用Excel 来弄,外观像表格,最后保存的格式为csv就是的。

可是用记事本打开,就会发现实际上是用逗号分隔开的如图:

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

那么这里的csv须要解析,然后放到我们的cocos2d-x 里面。使用这些属性。

详细的也是木头书上的。我这里只是多说;可是在3.0版本号中,也改动了不少地方。同一时候为了移植到手机上,也做了对应的改动;这里解析csv文件有三个类:

FileLoadUtil---文件载入  、StringUtil---字符串解析 、CsvUtil---由前两个配合完毕终于解析;假设对应了解其详细工作,最好的方式就是一步步调试。那样非常easy理解

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

那么看看那英雄的属性  Hero.h里面:

enum EnumHeroType{
en_HeroType_Normal
};
enum EnumHeroPropConfType{
enHeroPropConf_ID, // 英雄ID
enHeroPropConf_Name, // 英雄名字
enHeroPropConf_Type, // 英雄类型
enHeroPropConf_ModelID, // 英雄模型ID
enHeroPropConf_BaseAtk, // 基础攻击力
enHeroPropConf_AtkSpeed, // 攻击间隔(单位:秒)
enHeroPropConf_AtkRange, // 攻击范围(半径)
enHeroPropConf_UpgradeAtkBase, // 升级攻击加成系数
enHeroPropConf_UpgradeCostBase, // 升级消耗基础值
};
//--------------以下是类的一些成员-
//**7**
CC_SYNTHESIZE(EnumHeroType,_heroType,HeroType); //英雄类型
CC_SYNTHESIZE(int,_baseAtk,BaseAtk); //基础攻击
CC_SYNTHESIZE(int,_curAtk,CurAtk); //当前攻击--eg:升级之后
CC_SYNTHESIZE(int,_atkSpeed,AtkSpeed); //攻击速度(间隔)
CC_SYNTHESIZE(int,_atkRange,AtkRange); //攻击范围(半径)
CC_SYNTHESIZE(int,_upgradeCostBase,UpgradeConstBase);//升级消耗
CC_SYNTHESIZE(float,_upgradeAtkBase,UpgradeAtkBase); //升级攻击加成

同一时候在Init函数中

	//**7**
CsvUtil* csvUtil = CsvUtil::getInstance();
Size csvSize = csvUtil->getFileRowColNum("cvs/Hero.cvs"); const char* chHeroID = __String::createWithFormat("%d",heroID)->getCString(); int line = csvUtil->findValueInWithLine(chHeroID,enHeroPropConf_ID,"cvs/Hero.cvs"); if(line < 0){
return false;
} setID(heroID);
setModeID(csvUtil->getInt(line,enHeroPropConf_ModelID,"cvs/Hero.cvs"));
setBaseAtk(csvUtil->getInt(line,enHeroPropConf_BaseAtk,"cvs/Hero.cvs"));
setCurAtk(getBaseAtk());
setAtkSpeed(csvUtil->getInt(line,enHeroPropConf_AtkSpeed,"cvs/Hero.cvs"));
setAtkRange(csvUtil->getInt(line,enHeroPropConf_AtkRange,"cvs/Hero.cvs"));
setUpgradeAtkBase(csvUtil->getFloat(line,enHeroPropConf_UpgradeAtkBase,"cvs/Hero.cvs"));
setUpgradeConstBase(csvUtil->getInt(line,enHeroPropConf_UpgradeCostBase,"cvs/Hero.cvs"));
//----------------升级---------------------- // 添加英雄攻击力
setBaseAtk(getBaseAtk() * _upgradeAtkBase);
setCurAtk(getBaseAtk());

那么最后。在AppDelegate的构造函数中,

AppDelegate::AppDelegate() {
CC_SAFE_RETAIN(CsvUtil::getInstance());
} AppDelegate::~AppDelegate(){
CC_SAFE_RELEASE(CsvUtil::getInstance());
}

OK。本次完啦

三:下次内容预览

英雄的属性看不出。是由于没有怪兽让它欺负。那么后面就要加入怪物,而且让它依照我们之前编辑的路线行走啦

四:

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

源代码&资源

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  7. cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第八部---怪物出场

    /* 说明: **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. 【转】android camera(三):camera V4L2 FIMC

    关键词:android  camera CMM 模组 camera参数  CAMIF   V4L2  平台信息:内核:linux系统:android 平台:S5PV310(samsung exynos ...

  2. 利用Python完成一个小游戏:随机挑选一个单词,并对其进行乱序,玩家要猜出原始单词

    一 Python的概述以及游戏的内容 Python是一种功能强大且易于使用的编程语言,更接近人类语言,以至于人们都说它是“以思考的速度编程”:Python具备现代编程语言所应具备的一切功能:Pytho ...

  3. textContent、innerText 以及Event事件兼容性问题

    今天在完成前端的简单练习时发现了一些兼容性的问题,百度后得以解决. 这里主要讨论Firefox与Chrome的兼容性问题. textContent与 innerText 在javascript中, 为 ...

  4. 基于angularJS和requireJS的前端架构

    1.概要描述 1.1.angularJS描述:angularJS是可以用来构建WEB应用的,WEB应用中的一种端对端的完整解决方案.通过开发者呈现一个更高层次的抽象来简化应用的开发.最适合的就是用它来 ...

  5. 【HeadFirst 设计模式总结】1.策略模式

    1.书中举了一个鸭子类的设计,有些会飞或者会叫,有些不会飞可能也不会叫,用继承则导致不该有的功能通过继承而继承了下来,使用接口则代码无法做到最大程度的重用.进而引出设计原则1:找出应用中可能需要变化之 ...

  6. 浅谈postMessage多页面监听事件

    最近做了一个Echarts和Highcharts多图多页面连动的效果,就用到postMessage 如下介绍: 最开始在最外围的页面也就是所有页面的父级页面添加postMessage监听事件以便监听下 ...

  7. OS X EI Capitan 安装mysql-5.7.9

    先去下载mysql-5.7.9-osx10.9-x86_64.dmg安装(一直下一步,输入密码即可)mysql-5.7.9-osx10.9-x86_64.pkg好了,启动MySQL服务. Untitl ...

  8. WebApi 文件上传

    1. 注意给form表单加上enctype = "multipart/form-data" 属性,否则会导致Action的参数HttpPostedFileBase 对象接收不到文件 ...

  9. C#操作注册表——读、写、删除、判断等基本操作

    一.引入命名空间: using Microsoft.Win32; 二.创建注册表项:CreateSubKey(name)方法 添加SubKey时候首先要打开一个表项,并设置参数为true,才能成功创建 ...

  10. phonegap安卓环境下使用BarcodeScanner插件扫描二维码教程

    由于一直在使用phoneGap来开发安卓应用,而对于原生Java小白的我最近这几天一直陷入了如何使用phonegap的BarcodeScanner插件这件事情上,可以说查遍了百度和Google,虽然只 ...