转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。
资源为网上寻找的,仅研究学习用,若是侵犯版权请通知本人整改。
上一篇:Cocos3.4 横版游戏制作-《KillBear》-加入Hero
在这一篇中,
上半部分我们将在控制层OperateLayer中加入一个摇杆,并通过摇杆控制Hero
下半部分我们控制Hero防止其跑出地图和跑上墙
我们先做一个Joystick
摇杆Joystick .hclass Joystick : public Sprite{public: Joystick(); ~Joystick(); virtual bool init(); virtual voID ontouchesBegan(const std::vector<cocos2d::touch*>& touches,cocos2d::Event *unused_event); virtual voID ontouchesMoved(const std::vector<cocos2d::touch*>& touches,cocos2d::Event *unused_event); virtual voID ontouchesEnded(const std::vector<cocos2d::touch*>& touches,cocos2d::Event *unused_event); voID setJoystick(Vec2 point); CREATE_FUNC(Joystick);private: voID showJoystick(); voID hIDeJoystick(); voID updateJoystick(touch* touch); int m_pJoystickr; int m_pJoystickR; Sprite *m_pJoystick; Sprite *m_pJoystickBg; Vec2 start;};.cpp
bool Joystick::init(){ bool ret = false; do { CC_BREAK_IF( !Sprite::init() ); m_pJoystickBg = Sprite::create("JoystickBg.png");//背景 m_pJoystick = Sprite::create("Joystick.png");//摇杆 this->addChild(m_pJoystickBg,0); this->addChild(m_pJoystick,1); this->hIDeJoystick(); //this->showJoystick(); m_pJoystickR= m_pJoystickBg->getContentSize().wIDth/2; m_pJoystickr= m_pJoystick->getContentSize().wIDth/2; //新的API注册这么写 auto Listener = EventListenertouchAllAtOnce::create(); Listener->ontouchesBegan = CC_CALLBACK_2(Joystick::ontouchesBegan,this); Listener->ontouchesMoved = CC_CALLBACK_2(Joystick::ontouchesMoved,this); Listener->ontouchesEnded = CC_CALLBACK_2(Joystick::ontouchesEnded,this); _eventdispatcher->addEventListenerWithSceneGraPHPriority(Listener,this); ret = true; } while(0); return ret;}voID Joystick::showJoystick(){ //显示摇杆 m_pJoystick->setVisible(true); m_pJoystickBg->setVisible(true);}voID Joystick::hIDeJoystick(){ //隐藏摇杆 //m_pJoystick->setposition(m_pJoystickBg->getposition()); m_pJoystick->setVisible(false); //m_pJoystickBg->setVisible(false); m_pJoystickBg->setVisible(true);}voID Joystick::ontouchesBegan(const vector<touch*>& touches,Event *unused_event){ //按下事件处理 std::vector<touch*>::const_iterator touchIter = touches.begin(); touch* touch = (touch*)(*touchIter); if(m_pJoystick->getBoundingBox().containsPoint(touch->getLocation())) { this->showJoystick(); updateJoystick(touch); cclOG("***************"); cclOG("update touch:%f %f",touch->getLocation().x,touch->getLocation().y); return; }}voID Joystick::ontouchesMoved(const vector<touch*>& touches,Event *unused_event){ //移动时处理 std::vector<touch*>::const_iterator touchIter = touches.begin(); touch* touch = (touch*)(*touchIter); if(m_pJoystick->isVisible()) { updateJoystick(touch); return; }}voID Joystick::ontouchesEnded(const vector<touch*>& touches,Event *unused_event){ //离开是处理 //m_pJoystick->runAction(Moveto::create(0.08f,start)); //m_pJoystick->setposition(start); //global->hero->onStop(); this->hIDeJoystick();}voID Joystick::setJoystick(Vec2 point){ //将这个摇杆的放在某个坐标上 start =point; m_pJoystickBg->setposition(start); m_pJoystick->setposition(m_pJoystickBg->getposition());}voID Joystick::updateJoystick(touch* touch){ //更新摇杆状态 //我用向量来判断 Vec2 hit = touch->getLocation(); float distance = start.getdistance(hit); Vec2 direction = (hit - start).getnormalized(); //为了防止摇杆移出摇杆背景 if(distance < m_pJoystickr/2) { m_pJoystick->setposition(start + (direction * distance)); }else if(distance >m_pJoystickr) { m_pJoystick->setposition(start + (direction * m_pJoystickr)); }else { m_pJoystick->setposition(start + (direction * m_pJoystickr/2)); } //global->hero->onMove(direction,distance);}
这个JoyStick的写法我用了向量,不用笛卡尔坐标(xOy),我认为这样写更好理解它.
而且这个摇杆分为2段,
最大的好处:我可以通过摇杆移动距离控制角色 (走),(跑)切换
相当的讨厌必须按2下才能让角色执行跑动,自己写简单点行不行啊?
#include "Joystick.h".cpp
init中
auto m_pjoystick = Joystick::create(); m_pjoystick->setJoystick(Vec2(50,50)); this->addChild(m_pjoystick);效果A
大功告成:
接下来我提一个问题:Joystick和我们的Hero在不同层,如何让这个摇杆控制我们的Hero呢?
实现的方法有很多.
这里通过创建另一个Global,并将Joystick和Hero”注册”上去,通过Joystick控制Global中的Hero,也就是直接控制Hero实现
Global是全局单类
首先引入一个Single.h
Other 唯一实例Single这是一个优秀的单例实例(这是从别人的代码中找到的)
.h#ifndef _SINGLetoN_H#define _SINGLetoN_Husing namespace std;template <class T>class Singleton{public: //获取类的唯一实例 static inline T* instance(); //释放类的唯一实例 voID release();protected: Singleton(voID){} ~Singleton(voID){} static T* _instance;};template <class T>inline T* Singleton<T>::instance(){ if(NulL == _instance){ _instance = new T; } return _instance;}template <class T>voID Singleton<T>::release(){ if (!_instance) return; delete _instance; _instance = 0;}//cpp文件中需要先声明静态变量#define DECLARE_SINGLetoN_MEMBER(_Ty) \ template <> _Ty* Singleton<_Ty>::_instance = NulL;#endif//_SINGLetoN_H全局类Global
我把后面需要用的都放进去了,头文件好说.
- .h
#ifndef _GLOBAL_H_#define _GLOBAL_H_#include "cocos2d.h"USING_NS_CC; #include "Singleton.h"#include "GameLayer.h"#include "OperateLayer.h"#include "StateLayer.h"//需引入以下类,否则在这些类中访问单例对象会报错class GameLayer;class OperateLayer;class StateLayer;class Hero;class Enemy;//全局单例class Global :public Singleton<Global>{public: Global(voID); ~Global(voID); //GameScene *gameScene; GameLayer *gameLayer; //游戏层 OperateLayer *operateLayer; // *** 作层 StateLayer * stateLayer; //状态层 Hero *hero; //英雄 __Array *enemIEs; //敌人 TMXTiledMap *tileMap; //地图 Point tilePosFromLocation(Vec2 MovePoint,TMXTiledMap *map = NulL);//将point转换成地图GID的point bool tileAllowMove(Vec2 MovePoint);};#define global Global::instance()#endif.cpp
#include "Global.h"DECLARE_SINGLetoN_MEMBER(Global);Global::Global(voID){}Global::~Global(voID){ CC_SAFE_DELETE(gameLayer); CC_SAFE_DELETE(operateLayer); CC_SAFE_DELETE(stateLayer); CC_SAFE_DELETE(hero); CC_SAFE_DELETE(enemIEs); //CC_SAFE_DELETE(tileMap); gameLayer = NulL; operateLayer= NulL; stateLayer= NulL; hero= NulL; enemIEs= NulL; tileMap= NulL; }Point Global::tilePosFromLocation(Point MovePoint,TMXTiledMap *map) { Point point = MovePoint - map->getposition(); Point pointGID = Vec2::ZERO; pointGID.x = (int) (point.x / map->getTileSize().wIDth); pointGID.y = (int) ((map->getMapSize().height * map->getTileSize().height - point.y) / map->getTileSize().height); return pointGID; }bool Global::tileAllowMove(Point MovePoint){ TMXLayer *floor = global->tileMap->getLayer("Floor"); Point tileGID = tilePosFromLocation(MovePoint,global->tileMap); auto allowpoint =floor->getTileGIDAt(tileGID); if(0 == allowpoint) { return false; } return true;}
在需要用到的地方注册他比如GameLayer中:
.h#include "Global.h"
根据Global.h中所定义的,在对应cpp中需要添加诸如
- .cpp
GameLayer::GameLayer(){ global->gameLayer=this;}
OperateLayer::OperateLayer(){ global->operateLayer=this;}
StateLayer::StateLayer(){ global->stateLayer = this;}
………需要添加的地方………太多了 还是看代码吧.
不过后来如果有新的头文件我就扔上一个.
目前需要添加的头文件
MapLayer
GameLayer
StateLayer
OpreateLayer
Hero
JoyStick
更新我们的Hero,添加下面代码
- .h
voID onMove(Vec2 direction,float distance); voID onStop(); voID onAttack(int number); voID updateSelf();.cpp
voID Hero::onMove(Vec2 direction,float distance)//移动调用{ this->setFlippedX(direction.x < 0 ? true : false); this->runWalkAction(); Vec2 veLocity = direction * (distance < 33 ? 1 : 3); this->setVeLocity(veLocity);}voID Hero::onStop()//站立{ this->runIDleAction(); this->setVeLocity(Vec2::ZERO);}voID Hero::onAttack(int number)//执行攻击{ this->runNomalAttackA();}voID Hero::updateSelf()//刷新自己{ if(this->getCurrActionState() == ACTION_STATE_WALK) { Vec2 currentP= this->getposition(); //当前坐标 Vec2 expectP = currentP + this->getVeLocity(); //期望坐标 Vec2 actualP = expectP; //实际坐标 this->setposition(actualP); this->setLocalZOrder( Director::getInstance()->getVisibleSize().height - this->getpositionY()); }}
之后我们在Joystick中调用Hero的onMove,就可以让其移动了
其他代码我们后期再用
去掉里面的ontouchesEnded,updateJoystick中关于global->hero的//
实现Joystick控制Global中的hero
额,主角的状态切换了,但是还是不能动?什么情况
找到原因了…..GameLayer中没有更新主角坐标啊
Game GameLayer .hvoID update(float dt); voID updateHero(float dt);.cpp
init中启动默认定时器update
this->scheduleUpdate();
然后是实现方法
voID GameLayer::update(float dt){ this->updateHero(dt);}
而updateHero
voID GameLayer::updateHero(float dt){ m_pHero->updateSelf();//自更新状态}效果C 结语
至此,我们终于实现了标题的效果:添加摇杆并控制Hero
不过还是有一堆BUG,比如主角能跑到天上,主角移出了地图
地图不会动等.
将在下一篇中消除这些BUG
以上是内存溢出为你收集整理的Cocos3.4 横版游戏制作-《KillBear》-添加摇杆并控制Hero全部内容,希望文章能够帮你解决Cocos3.4 横版游戏制作-《KillBear》-添加摇杆并控制Hero所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)