/* 说明:

**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. IOS7 UITableView一行滑动删除后 被删除行的下一行的点击事件将被忽略解决办法

    - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSI ...

  2. Android学习总结——Content Provider

    原文地址:http://www.cnblogs.com/bravestarrhu/archive/2012/05/02/2479461.html Content Provider内容提供者 : and ...

  3. <ListView>分列显示

    <ListView> <ListView.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Width="{B ...

  4. css设置

    box-size允许您以特定的方式定义匹配某个区域的特定元素. content-box(默认):宽度和高度分别应用到元素的内容框.在宽度和高度之外绘制元素的内边距和边框.border-box:为元素设 ...

  5. Unique Binary Search Trees In JAVA

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  6. Lambda 表达式中的变量范围

    delegate bool D(); delegate bool D2(int i); class Test { D del; D2 del2; public void TestMethod(int ...

  7. Qt 编程训练之七

    Qt进程间通信 TCP / IP 跨平台的 QtNetwork模块提供的类网络编程便携式和容易. 它提供了高层类(例如,QNetworkAccessManager, QFtp)使用特定的应用层协议通信 ...

  8. xaml控件样式大全(太有用了)C#

    地址:链接:http://pan.baidu.com/s/1jGlMyEi 密码:zaeg http://blog.csdn.net/lhx527099095/article/category/943 ...

  9. 为什么我们需要性能测试,需要loadrunner

    什么是功能: 功能按我理解就是软件实现需求,提供服务,那么功能测试就是实现的需求是否与客户给定需求一致,也就是符合预期结果 什么是性能: 功能是实现需求,提供服务,那么性能就可以理解为服务的好坏.比如 ...

  10. flask twisted 结合方案

    from flask import Flask, render_template, g app = Flask(__name__) @app.route("/") def inde ...