Cocos3.4 横版游戏制作-《KillBear》-添加摇杆并控制Hero

Cocos3.4 横版游戏制作-《KillBear》-添加摇杆并控制Hero,第1张

概述转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。 资源为网上寻找的,仅研究学习用,若是侵犯版权请通知本人整改。 上一篇:Cocos3.4 横版游戏制作-《KillBear》-加入Hero 在这一篇中, 上半部分我们将在控制层OperateLayer中加入一个摇杆,并通过摇杆控制Hero 下半部分我们控制Hero防止其跑出地图和跑上墙 开发环境 win64 : vs2010 Coco

转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。
资源为网上寻找的,仅研究学习用,若是侵犯版权请通知本人整改。

上一篇:Cocos3.4 横版游戏制作-《KillBear》-加入Hero
在这一篇中,
上半部分我们将在控制层OperateLayer中加入一个摇杆,并通过摇杆控制Hero
下半部分我们控制Hero防止其跑出地图和跑上墙

开发环境 win64 : vs2010 Cocos2d-x v3.4Final TexturePackerGUI MapEdit 代码构建A 管理Operate

我们先做一个Joystick

摇杆Joystick .h
class 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段,

某个范围A内,随意移动 超出最大范围B-接触点移出了摇杆背景时,将其设定在最大边沿B处 在这两个范围A-B之间,会沿着A的边沿放置

最大的好处:我可以通过摇杆移动距离控制角色 (走),(跑)切换
相当的讨厌必须按2下才能让角色执行跑动,自己写简单点行不行啊?

控制层OperateLayer .h
#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是全局单类

代码构建B

首先引入一个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

角色Role Hero

更新我们的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,就可以让其移动了
其他代码我们后期再用

控制Operate Joystick

去掉里面的ontouchesEnded,updateJoystick中关于global->hero的//
实现Joystick控制Global中的hero

效果B


额,主角的状态切换了,但是还是不能动?什么情况

找到原因了…..GameLayer中没有更新主角坐标啊

Game GameLayer .h
voID 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所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1038843.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存