cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第六步---炮台&点击炮台加入英雄&英雄升级
/* 说明:
**1.本次游戏实例是《cocos2d-x游戏开发之旅》上的最后一个游戏,这里用3.0重写并做下笔记
**2.我也问过木头本人啦,他说:随便写,第一别全然照搬代码;第二能够说明是学习笔记---好人
**3.这里用cocos2d-x 3.0版本号重写,非常多地方不同,可是从重写过程中也非常好的学习了cocos2d-x
*/
***每一步相应的全部代码以及用到的资源都会打包在最后给出
***为避免代码过多,每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用Git?)
***能够依据设计思路(好吧,那名字太高大上。实际就是这一步要干啥)先自己实现---cocos2d-x本来就是如此,同样的功能有很多不同实现方法;先自己折腾是蛮不错的。
***为了方便移植到手机上,对于每一步都进行编译android測试;由于非常多时候代码在win32下能够,编译就会出错,给出的代码会是測试过后的。
本次笔记内容:
1、设计思路
2、代码&測试效果
3、下次内容预览
4、本次源代码&资源
一:设计思路
在前一步中,进入不同级别的游戏关卡之后,载入了之前自己编辑好的炮台的点
这一步中为这些点用真正的炮台来展示
然后点击炮台能加入英雄
1.首先为了后面的扩展,炮台也是应该有属性的,比方等级什么的。那么英雄和怪物相同也是,速度,防御等各种属性。那么能够抽离出一个基类Entity
2.这一步其中是关于炮台和英雄的 关系,那么首先来设计炮台;炮台继承实体,它通过精灵来展示,而且运行了一个动作---看起来高大上
3.那么在英雄管理器中,前面载入的点保存在容器里面啦,我们对容器遍历,对于每一个炮台坐标放一个炮台
4.然后是英雄,这一步中,我们仅仅实现点击炮台产生英雄,英雄的属性和配置文件Csv有关之后说
5.加入英雄之后,我们再次点击英雄,能够有一些操作,升级!删除!
二:代码&效果
首先看看基类:.h
<span style="font-size:14px;">class Entity : public Node{
public:
Entity();
~Entity(); void bindSprite(Sprite* sprite);
Sprite* getSprite(); void hurtMe(int hurtValue); bool isDead(); Rect boundingBox(); protected:
virtual void onDead(); virtual void onBindSprite(); virtual void onHurt(int hurtValue);
private:
Sprite* _sprite;
bool _isDead; CC_SYNTHESIZE(int,_id,ID);
CC_SYNTHESIZE(int,_modeID,ModeID);
CC_SYNTHESIZE(__String*,_Name,Name);
CC_SYNTHESIZE(int,_hp,HP);
CC_SYNTHESIZE(int,_defense,Defense);
CC_SYNTHESIZE(int,_speed,Speed);
CC_SYNTHESIZE(int,_level,Level);
};</span>
.cpp
<span style="font-size:14px;">Entity::Entity(){
_sprite = NULL;
_Name = __String::create("");
_hp = 1;
_defense = 1;
_isDead = false;
_speed = 1;
_level = 1;
}
Entity::~Entity(){
} void Entity::bindSprite(Sprite* sprite){
if(this->_sprite != NULL){
_sprite->removeFromParentAndCleanup(true);
} this->_sprite = sprite;
this->addChild(_sprite); //**6**假设子类绑定时须要其它作用,就重写以下的函数
onBindSprite();
} Sprite* Entity::getSprite(){
return this->_sprite;
} void Entity::hurtMe(int hurtValue){
if(_isDead){
return ;
} if(hurtValue <= getDefense()){
hurtValue = 1;
} int curHP = getHP();
int afterHP = curHP-hurtValue; onHurt(hurtValue); if(afterHP > 0){
setHP(afterHP);
}
else{
_isDead = true;
onDead();
}
} Rect Entity::boundingBox(){
Node::boundingBox();
if(getSprite() == NULL){
return CCRectMake(0,0,0,0);
}
Point pos = getPosition();
Size size = getSprite()->getContentSize(); return CCRectMake(pos.x,pos.y,size.width,size.height);
} bool Entity::isDead(){
return this->_isDead;
} //空函数,留给子类
void Entity::onDead(){
}
void Entity::onBindSprite(){
}
void Entity::onHurt(int hurtValue){
}</span>
能够看到它是有一些的属性,也有受伤、死亡、精灵什么的函数;后面对于不同的实体实现不同的功能
炮台TowerBorder.h
<span style="font-size:14px;">class TowerBorder : public Entity{
public:
TowerBorder();
~TowerBorder(); CREATE_FUNC(TowerBorder);
virtual bool init(); bool isClickMe(Point pos);//检測是否点击了炮台 private:
};</span>
.cpp
<span style="font-size:14px;">TowerBorder::TowerBorder(){
}
TowerBorder::~TowerBorder(){
} bool TowerBorder::init(){
__String* sFilePath = __String::createWithFormat("sprite/hero/border_%d.png",_level);
Sprite* sprite = Sprite::create(sFilePath->getCString()); bindSprite(sprite); ActionInterval* rotateBy = RotateBy::create(25.0f,360,360);
auto repeat = RepeatForever::create(rotateBy); sFilePath = __String::createWithFormat("sprite/hero/magic_border_%d.png",_level);
sprite = Sprite::create(sFilePath->getCString());
sprite->setOpacity(80);
sprite->runAction(repeat); this->addChild(sprite); return true;
} bool TowerBorder::isClickMe(Point pos){
Size size = getSprite()->getContentSize();
Point borderPos = getPosition(); Point srcPos = Point(borderPos.x-size.width,borderPos.y+size.height);
Point detPos = Point(borderPos.x+size.width,borderPos.y-size.height); if(pos.x>=srcPos.x && pos.x<=detPos.x && pos.y<=srcPos.y && pos.y>=detPos.y){
return true;
} return false;
}</span>
然后測试一下:在HeroManager里面加入成员:
<span style="font-size:14px;">Vector<TowerBorder*> m_towerBorderList;
void createTowerBorder();</span>
那么在createTowerPos之后,我们调用createTowerBorder,也就是通过点来加入炮台
<span style="font-size:14px;">void HeroManager::createTowerPos(int curLevel){
/******************省略代码***************/
//**6** 载入全然部的点,那么就用点来加入炮台
createTowerBorder();
} void HeroManager::createTowerBorder(){
PosBase* tPos = NULL;
for(auto ref : m_towerPosList){
tPos = dynamic_cast<PosBase*>(ref); if(tPos != NULL){
TowerBorder* border = TowerBorder::create();
border->setPosition(tPos->getPos());
this->addChild(border); m_towerBorderList.pushBack(border);
}
}
}</span>
把之前为了看到点坐标的 调式模式改为false,背景图片不设计透明度。执行測试例如以下:
接着,实现点击炮台加入英雄,先看看英雄
<span style="font-size:14px;">class Hero : public Entity{
public:
Hero();
~Hero(); static Hero* createFromCsvFileByID(int heroID);
bool initFromCsvFileByID(int heroID); };</span>
这里是依据ID来加入,也就是说有不同种类的英雄。可是本游戏仅仅有一种---这里理解了也能够自己扩展
<span style="font-size:14px;">Hero::Hero(){
}
Hero::~Hero(){
} Hero* Hero::createFromCsvFileByID(int heroID){
Hero* hero = new Hero();
if(hero && hero->initFromCsvFileByID(heroID)){
hero->autorelease();
}
else{
CC_SAFE_DELETE(hero);
}
return hero;
} bool Hero::initFromCsvFileByID(int heroID){
Sprite* sprite = Sprite::create(__String::createWithFormat("sprite/hero/hero_%d.png",heroID)->getCString());
bindSprite(sprite); return true;
}</span>
那么我们理解加入英雄的过程:点击随意炮台,然后加入。可是,我们须要解决点击了那个炮台?
HeroManager里加入函数:
<span style="font-size:14px;">TowerBorder* findClickTowerBorder(Point pos){
TowerBorder* tBorder = NULL;
for(auto ref : m_towerBorderList){
tBorder = dynamic_cast<TowerBorder*>(ref); if(tBorder){
if(tBorder->isClickMe(pos)){
return tBorder;
}
}
}
return NULL;
}</span>
同一时候,一个炮台仅仅有一个英雄,那么TowerBorder里面加入:
<span style="font-size:14px;">Hero* _hero;
TowerBorder::TowerBorder(){
_hero = NULL;
}
TowerBorder::~TowerBorder(){
CC_SAFE_RELEASE(_hero);
} Hero* getHero(){ return _hero;};
void bindHero(Hero* hero){ _hero = hero; };</span>
那么,在管理器的触摸事件的end函数中:
<span style="font-size:14px;">bool HeroManager::initWithLevel(int curLevel){
/*****************省略***************/
listener->onTouchEnded = [=](Touch* touch,Event* event){
/*****************省略**************/
TowerBorder* clickBorder = findClickTowerBorder(pos); if(clickBorder == NULL){
return ;
}
if(clickBorder->getHero() == NULL){
Hero* hero = Hero::createFromCsvFileByID(1);
hero->setPosition(clickBorder->getPosition());
this->addChild(hero);
clickBorder->bindHero(hero);
}
};
/*************省略*************************************/
}</span>
那么測试,点击炮台加入英雄,效果例如以下:
三:下节预览
看看Csv中的英雄属性怎样加到英雄身上---读取Csv&解析Csv文件,给英雄加入很多其它操作,让它升级,不想要了把它从炮台删除
--------------------------------
四:源代码&资源
-----------------------------------
个人愚昧观点,欢迎指正与讨论
cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第六步---炮台&点击炮台加入英雄&英雄升级的更多相关文章
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第一步---開始界面&关卡选择
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说 ...
- cocos2d-x 3.0游戏实例学习笔记 《跑酷》 完结篇--源代码放送
说明:这里是借鉴:晓风残月前辈的博客,他是将泰然网的跑酷教程,用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第三步---编辑器(2)---更方便很多其它操作更像编辑器
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说 ...
- cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第七步---英雄要升级&属性--解析csv配置文件
/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说 ...
- 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游戏实例学习笔记《卡牌塔防》第八部---怪物出场
/* 说明: **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重写,并做相关笔记 ...
随机推荐
- 变化App.config其中值,并保存
using System; using System.Collections.Generic; using System.Configuration; using System.IO; using S ...
- SICP的一些个人看法
网上搜书的时候,看到非常多人将这本书神话. 坦率地说,个人认为这本书过于学术化, 没什么实际project价值.一大堆题目也基本是高中数学竞赛题类似,浪费时间. 软件的核心技术是什么? 1> ...
- Android:What is ART?
背景:Android4.2之前,安卓手机系统的应用程序均在Dalvik Java的虚拟机上执行,这样的执行模式还要依靠一个编译器来实现与应用程序的沟通.应用程序每次执行时,都须要将程序内的代码转变为机 ...
- 【夸QT在十五】ctkPluginFrameWork插件系统Windows编译器
采用ctkPluginFramework作为一个插件系统开发框架确实有很多优点. 有些车站最近收到的一封信,每个人都想用ctkPluginFramework但我不知道如何建立,本教程对谈ctkPlug ...
- arch linux设备(请参考官方文档,桌面安装没有找到一个好工作后)
首先,启动安装系统(一获得通过vmware虚拟机) 1.设置键盘布局 #loadkeys "us" #设置为美国的键盘布局.一般能够默认就可以 2.建立硬盘的分区 我採用的是fdi ...
- 微软中国裁员曝光:在CD结束后!薪酬不变!
聚众抗议的前诺基亚员工(腾讯科技配图) 腾讯科技 郭晓峰 腾讯科技刚刚获取了一份微软设备事业部中国区管理团队4日晚间发给被裁员工的补偿方案邮件. 邮件内容显示,微软承诺在收购诺基亚交易结束(2014年 ...
- UVA 11774 - Doom's Day(规律)
UVA 11774 - Doom's Day 题目链接 题意:给定一个3^n*3^m的矩阵,要求每次按行优先取出,按列优先放回,问几次能回复原状 思路:没想到怎么推理,找规律答案是(n + m) / ...
- C++ - 内置类型的最大值宏定义
内置类型的最大值宏定义 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24311895 C++中, 常常会使用, 某些类型的最大值 ...
- ti8168 eth0 启动
ti8168 原始文件系统进去后没有网络eth0接口,为了有该接口须要配置/etc/network/interfaces 文件 详细配置例如以下(红色要配置) # /etc/network/inter ...
- UVALive 6469 Deranged Exams (排列:力绝对是无辜的高中知识啊)
标题手段 : 给你个n([1,17])表达n无论从数据结构.然后n个对这些术语的定义,让你对这些术语和定义对号入座(相当于进行连线,A术语连A术语的定义).然后一个 k([0,n]).问你至少前k个术 ...