zoukankan      html  css  js  c++  java
  • cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第二步---编辑器(1)--触摸加入点

    /* 说明:

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

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

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

    */

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

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

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

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

    本次笔记内容:

    1、设计思路&问题注意

    2、效果图

    3、尾随设计思路看代码

    4、下节知识预览

    一:设计思路&问题注意

    一步步来

    (1)为了响应MainScene中的编辑button,须要一个PosEditorScene,然而这个Scene里面须要做的事比較多;所以这里把Scene单独抽离出来,然后在里面加入各种Layer

    (2)先来一个万能的GetBackLayer;为什么是万能的呢?这个层的作用非常easy,里面有一button,Back; 通过这个button,你能够在不论什么地方回到MainScene。你Start之后进行关卡选择,发现自己要重编辑怪物路线,你就Back,游戏中你不想玩了Back,编辑场景中,编辑好了想要測试?Back。到这,你就能够測试一下了

    (3)来一个PosEditorLayer,这个层我们来编辑怪物路线和炮台位置,那么通过屏幕触摸,能够加入一个Pos,就须要我们给这个Layer触摸事件,到这,你也能够在触摸事件中測试一下

    (4)既然触摸是加入一个点,那么我们就须要PosBase,继承自Node,然后重写draw 函数,屏幕触摸之后,加入这个点,这个点draw出来。然而这里须要注意的就是我们分TowerMonster两种点;木头的做法是抽离一个PosBase基类,然后分别继承。这种话是方便以后扩充,假设又有一种点,那么相同能够继承;我这里看两种点的功能差点儿相同,就偷了懒,干脆仅仅用PosBase,然后用一个枚举类来区分当前点是Tower 还是Monster

    (5)须要注意的是枚举类是必要的,在编辑层中你也须要改变不同的Type 来进行编辑

    (6)这里的GetBackLayer中的button用了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 函数的实现

    .cpp

    bool 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,会遇到些问题:解决方法之前提到过:

    也就三步三个加入:之前也有过  图文解释

    到这里,就能够測试一下Backbutton的使用,那么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中加入成员_posType,而且在构造函数中赋值 enTowerPos 表示默认当前是编辑炮台坐标

    成员函数  editorPos

    void PosEditorLayer::editPos(Point pos){
    	//**2**test
    	auto posBase = PosBase::create(pos, _posType, true);
    	this->addChild(posBase);
    }

    然后在触摸事件中加入函数,就能随意点击屏幕加入点;


    四:下节知识点预览

    既然要编辑,仅仅能加入点不然删除算什么?要在代码中改变PosType算什么?难道仅仅能编辑一级的关卡吗?这些点不保存?

    以下解决

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

    资源&代码
    ------------------------------------------------
    个人愚昧观点,欢迎指正与讨论





  • 相关阅读:
    iOS中几种定时器
    开发基于Handoff的App(Swift)
    [react ] TextArea 光标定位到最后
    图片上传 配合客户端做出效果展示
    ["1", "2", "3"].map(parseInt)
    react 微信公众号 cnpm start 启动页面报path错误解决
    在家办公这点事
    【转】关于请求时 options 相关问题
    cnpm i 遇到报错
    react + antd Menu 点击菜单,收起其他展开的所有菜单
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3945660.html
Copyright © 2011-2022 走看看