标签:新手入门 c++ cocos2d-x3.0 塔防实例游戏
/* 说明:
**1.本次游戏实例是《cocos2d-x游戏开发之旅》上的最后一个游戏,这里用3.0重写并做下笔记
**2.我也问过木头本人啦,他说:随便写,第一别完全照搬代码;第二可以说明是学习笔记---好人
**3.这里用cocos2d-x 3.0版本重写,很多地方不同,但是从重写过程中也很好的学习了cocos2d-x
*/
***每一步对应的所有代码以及用到的资源都会打包在最后给出
***为避免代码过多,每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用Git?)
***可以根据设计思路(好吧,那名字太高大上。实际就是这一步要干啥)先自己实现---cocos2d-x本来就是如此,相同的功能有许多不同实现方法;先自己折腾是蛮不错的。
***为了方便移植到手机上,对于每一步都进行编译android测试;因为很多时候代码在win32下可以,编译就会出错,给出的代码会是测试过后的。
本次笔记内容:
1、设计思路&问题注意
2、效果图
3、跟随设计思路看代码
4、下节知识预览
一:设计思路&问题注意
一步步来
(1)为了响应MainScene中的编辑按钮,需要一个PosEditorScene,然而这个Scene里面需要做的事比较多;所以这里把Scene单独抽离出来,然后在里面添加各种Layer
(2)先来一个万能的GetBackLayer;为什么是万能的呢?这个层的作用很简单,里面有一按钮,Back; 通过这个按钮,你可以在任何地方回到MainScene。你Start之后进行关卡选择,发现自己要重编辑怪物路线,你就Back,游戏中你不想玩了Back,编辑场景中,编辑好了想要测试?Back。到这,你就可以测试一下了
(3)来一个PosEditorLayer,这个层我们来编辑怪物路线和炮台位置,那么通过屏幕触摸,可以添加一个Pos,就需要我们给这个Layer触摸事件,到这,你也可以在触摸事件中测试一下
(4)既然触摸是添加一个点,那么我们就需要PosBase,继承自Node,然后重写draw 函数,屏幕触摸之后,添加这个点,这个点draw出来。然而这里需要注意的就是我们分Tower和 Monster两种点;木头的做法是抽离一个PosBase基类,然后分别继承。这样的话是方便以后扩充,如果又有一种点,那么同样可以继承;我这里看两种点的功能差不多,就偷了懒,干脆只用PosBase,然后用一个枚举类来区分当前点是Tower 还是Monster
(5)需要注意的是枚举类是必要的,在编辑层中你也需要改变不同的Type 来进行编辑
(6)这里的GetBackLayer中的按钮用了Extension库,有一点点问题需要处理--比较简单
(7)那么这里的点重写draw函数的话,不知道为什么,会被背景挡住,N多方法都试过;最后机智的想到,把背景图片设置透明度;还果然就看到了;不过问过木头大哥啦,他测试的解决方法是:draw函数最先被画,那么PosBase就不要添加到有背景的层,可以单独抽离一个层,就可以啦;
(8)编辑器的内容比较多,这一步先到这里
二:最后效果图
点击屏幕任意位置,出现一个Tower,同时PosEditorLayer 中有一个枚举成员,初始化为Tower,也可以弄成Monster 测试
三:跟随设计思路看代码
首先是PosEditorScene.h
class PosEditorScene{ public: static Scene* createScene(); };/**/
是的,就这么简单,我们这里只要获取一个Scene即可,其他的Layer在createScene里面
.cpp
Scene* PosEditorScene::createScene(){ Scene* scene = Scene::create(); //auto posEditorLayer = PosEditorLayer::create(); //scene->addChild(posEditorLayer); auto getBackLayer = GetBackLayer::create(); scene->addChild(getBackLayer); return scene; }然后看看GetBackLayer.h
#include "cocos2d.h" #include "cocos-ext.h" USING_NS_CC; USING_NS_CC_EXT; class GetBackLayer : public Layer{ public: CREATE_FUNC(GetBackLayer); virtual bool init(); private: void getBack(Ref* pSender, Control::EventType event); };/**/
CREATE_FUNC实际是一个宏定义的create函数,后面在Scene中的添加Layer的时候create,然后会调用Layer的 init 函数,这里我们只需要virtual bool init 函数的实现
.cppbool GetBackLayer::init(){ auto visibleSize = Director::getInstance()->getVisibleSize(); auto btnTitle = Label::create("Back","Arial",30); auto norSprite = Scale9Sprite::create("Button/public_ui_blue_btn.png"); auto highLightSprite = Scale9Sprite::create("Button/public_ui_green_btn.png"); auto outPutBtn = ControlButton::create(btnTitle,norSprite); outPutBtn->setBackgroundSpriteForState(highLightSprite,Control::State::HIGH_LIGHTED); outPutBtn->setPosition( ccp(visibleSize.width-norSprite->getContentSize().width/2, visibleSize.height - norSprite->getContentSize().height)); outPutBtn->addTargetWithActionForControlEvents( this, cccontrol_selector(GetBackLayer::getBack), Control::EventType::TOUCH_UP_INSIDE); this->addChild(outPutBtn,20); return true; } void GetBackLayer::getBack(Ref* pSender,Control::EventType event){ CCLOG("Back to MainScene"); auto scene = MainScene::createScene(); Director::getInstance()->replaceScene(scene); }
这里由于用到了Extension,会遇到些问题:解决方法之前提到过:
也就三步三个添加:之前也有过 图文解释
到这里,就可以测试一下Back按钮的使用,那么GetBackLayer可以添加到很多Scene中那么现在来看看PosEditorLayer.h
class PosEditorLayer : public Layer{ public: PosEditorLayer(); ~PosEditorLayer(); CREATE_FUNC(PosEditorLayer); virtual bool init(); private: //**2**当前关卡级别 int _curLevel; //------------成员&函数分割线---------------------- //**2**预加载内容 void preLoad(); };.cpp
PosEditorLayer::PosEditorLayer(){ _curLevel = 1; } PosEditorLayer::~PosEditorLayer(){ } bool PosEditorLayer::init(){ //**2**---------------触摸事件---------------------------- auto listener = EventListenerTouchOneByOne::create(); listener->setSwallowTouches(true); listener->onTouchBegan = [](Touch* touch, Event* event){ return true; }; listener->onTouchMoved = [](Touch* touch, Event* event){ }; listener->onTouchEnded = [=](Touch* touch, Event* event){ auto touchPos = touch->getLocationInView(); auto pos = Director::getInstance()->convertToUI(touchPos); CCLOG("Touch pos.X is %f, Touch pos.Y is %f",pos.x, pos.y); }; _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this); //------------------------------------------------------------ //**2** preLoad(); return true; } void PosEditorLayer::preLoad(){ //**2**add map auto visibleSize = Director::getInstance()->getVisibleSize(); auto sBg = __String::createWithFormat("game/level_%d.jpg",_curLevel); auto mapBg = Sprite::create(sBg->getCString()); mapBg->setPosition(ccp(visibleSize.width/2,visibleSize.height/2)); mapBg->setOpacity(150); this->addChild(mapBg); }然后把这个层添加到PosEditorScene中,为了不挡住getBackLayer,你可以在GetBackLayer之前 加入scene里面
然后F5测试,输出中可以看到你触摸屏幕的位置
触摸屏幕是为了添加点,那么来看看PosBase
enum EnumPosType{ enTowerPos, enMonsterPos }; class PosBase : public Node{ public: PosBase(); ~PosBase(); //**2** static PosBase* create(Point pos, EnumPosType posType, bool isDebug); //**2** bool init(cocos2d::Point pos, EnumPosType posType, bool isDebug); //**2** virtual void draw(cocos2d::Renderer *renderer, const kmMat4& transform, bool transformUpdated); protected: CC_SYNTHESIZE(Point,_pos,Pos); //**2** bool _isDebug; EnumPosType _posType; };/**/这里是根据 位置,点类型,是否调试;三个变量来创建一个PosBase的;依据_isDebug来判断是否调试,是的话,就将点画出来 ,这里的CC_SYNTHESIZE 也是一个宏,就是添加私有成员,等价于:
private:
Point _pos;
public:
void setPos(Point pos) { _pos = pos ; };
Point getPos() { return _pos; };
.cpp
#define Tower_Radius 32 #define Monster_Radius 10 PosBase::PosBase(){ _pos = CCPointMake(0,0); _isDebug = false; _posType = enTowerPos; } PosBase::~PosBase(){ } PosBase* PosBase::create(Point pos, EnumPosType posType, bool isDebug){ PosBase* tPos = new PosBase(); if(tPos && tPos->init(pos, posType,isDebug)){ tPos->autorelease(); }else{ CC_SAFE_DELETE(tPos); } return tPos; } bool PosBase::init(Point pos, EnumPosType posType, bool isDebug){ //**2** _SYNTHESIZE(Point,_pos,Pos); 的方法 setPos(pos); _posType = posType; _isDebug = isDebug; return true; } void PosBase::draw(Renderer *renderer, const kmMat4& transform, bool transformUpdated){ if(_isDebug){ glLineWidth(5); //根据posMode 设置判断的半径 float radius; if(_posType == enTowerPos){ radius = Tower_Radius; } else{ radius = Monster_Radius; } //draw TowerPos if(_posType == enTowerPos){ Point srcPos = Point(_pos.x-radius, _pos.y+radius); Point destPos = Point(_pos.x+radius, _pos.y-radius); ccDrawRect(srcPos,destPos); } else{ //draw MonsterPos ccDrawCircle(_pos, radius, 360, 20, false); } glLineWidth(1); } }然后测试:在PosEditorLayer中添加成员函数 editorPos
void PosEditorLayer::editPos(Point pos){ //**2**test auto posBase = PosBase::create(pos, _posType, true); this->addChild(posBase); }
然后在触摸事件中添加函数,就能任意点击屏幕添加点;
四:下节知识点预览
既然要编辑,只能添加点不然删除算什么?要在代码中改变PosType算什么?难道只能编辑一级的关卡吗?这些点不保存?
下面解决
------------------------------------------------资源&代码
------------------------------------------------
个人愚昧观点,欢迎指正与讨论
cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第二步---编辑器(1)--触摸添加点
标签:新手入门 c++ cocos2d-x3.0 塔防实例游戏
原文地址:http://blog.csdn.net/zyy173533832/article/details/38775293