cocos2d-x游戏摇杆开发

1.最近想做一个横屏格斗类游戏,但当然第一步必不可少的就是开发一个摇杆来控制游戏人物的移动,本来打算在网上找个简单看看,没想到都好几个文件,很麻烦,而且版本太旧了,索性自己动手算了。看看效果图

这里写图片描述
//没什么人物素材,瞎找的

2.其实总结一下,开发个摇杆原理并不复杂,大概思路就是这样:随便继承自node,sprite,layer都行,两个sprite,一张是摇杆背景,一个是可以移动的部分,然后注册个触摸监听,根据坐标换算成方向传回来。使用的时候就是scheduleupdate中每一帧取出方向,然后对游戏对象sprite进行相应位置改变,同样道理,稍微改一下就能增加各种技能了,不多说废话,直接看代码算了。

3.使用时。

bool GameScene::init():
...
    bg = Sprite::create("green.png");
    bg>setPosition(visibleSize.width/2,visibleSize.height/2);
    this->addChild(bg);

    jr = JoyRocker::create(Vec2(100,100));
    this->addChild(jr);

    jr->startRocker();


    this->scheduleUpdate();
...

void GameScene::update(float ft)
{


    switch( jr->getDirection() )
    {
    case 1:
            bg->setPosition(Vec2(bg->getPosition().x+2,bg->getPosition().y));       

        break;
    case 2:


            bg->setPosition(Vec2(bg->getPosition().x, bg->getPosition().y+2));      

        break;
    case 3:

            bg->setPosition(Vec2(bg->getPosition().x-2,bg->getPosition().y));       

        break;
    case 4:

            bg->setPosition(Vec2(bg->getPosition().x,bg->getPosition().y-2));       

        break;
    case 5:
            bg->setPosition(Vec2(bg->getPosition().x-1,bg->getPosition().y+1));
        ;break;
    case 6:
            bg->setPosition(Vec2(bg->getPosition().x+1,bg->getPosition().y+1));
        ;break;
    case 7:
            bg->setPosition(Vec2(bg->getPosition().x-1,bg->getPosition().y-1));
        ;break;
    case 8:
            bg->setPosition(Vec2(bg->getPosition().x+1,bg->getPosition().y-1));
        ;break;
    default:

        break;
    }
}

4.主要就两个文件,很容易看懂。

JoyRocker.h

#ifndef __JOY_ROCKER_H__
#define __JOY_ROCKER_H__

#include "cocos2d.h"

USING_NS_CC;

#define PI 3.1415926

//用于标识摇杆方向
typedef enum{
    rocker_stay = 0,
    rocker_right,
    rocker_up,
    rocker_left,
    rocker_down,
    rocker_leftUp,
    rocker_rightUp,
    rocker_leftDown,
    rocker_rightDown,
}rockerDirecton;

// 标志 摇杆背景与中心
typedef enum
{
    rockerBackGround = 2,
    rockerCenter,
};

class JoyRocker : public Layer
{
public:

    //创建摇杆
    static JoyRocker* create(Vec2 pos);

    // 使用摇杆
    void startRocker(void);
    // 停止使用摇杆
    void stopRocker(void);


    // 获取 摇杆 方向
    int getDirection(void);
    // 获取 人物 朝向
    bool getIsLeft(void);


    //触屏事件  
    virtual bool TouchBegan(Touch* touch, Event* event);  
    virtual void TouchMoved(Touch* touch, Event* event);  
    virtual void TouchEnded(Touch* touch, Event* event);  

    CREATE_FUNC(JoyRocker);

private:

    bool initRocker(Vec2 pos);
    //获取当前摇杆与用户触屏点的角度
    float getRad(Vec2 pos1,Vec2 pos2);
    // 根据角度,返回点坐标
    Vec2 getAnglePosition(float r,float angle);

    // 摇杆 是否可以移动(是否超过摇杆背景)
    bool isCanMove;
    //摇杆 中心的坐标
    Vec2 rockerCenterPos;
    //摇杆背景的半径
    float rockerBGR;
    //摇杆 的半径
    float rockerCenterR;
    //判断控制杆方向,用来判断精灵上、下、左、右、左上、右上、左下、右下 运动
    int rocketDirection;
    // 判断人物是否朝向左面
    bool isLeft;

    EventListenerTouchOneByOne* listener; 
};

#endif

JoyRocker.cpp


#include "JoyRocker.h"

JoyRocker* JoyRocker::create(Vec2 pos)
{
    JoyRocker* layer = JoyRocker::create();
    if ( layer )
    {
        layer->initRocker(pos);
        return layer;
    }
    CC_SAFE_DELETE(layer);
    return NULL;
}

bool JoyRocker::initRocker(Vec2 pos)
{
    // 摇杆背景 图片
    Sprite* spRockerBG = Sprite::create("spi_joystickBG.png");
    spRockerBG->setPosition(pos);
    spRockerBG->setTag(rockerBackGround);
    spRockerBG->setVisible(false);
    this->addChild(spRockerBG,0);

    // 摇杆中心 图片
    Sprite* spRockerCenter = Sprite::create("spi_joystickCenter.png");
    spRockerCenter->setPosition(pos);
    spRockerCenter->setTag(rockerCenter);
    spRockerCenter->setVisible(false);
    this->addChild(spRockerCenter,1);

    // 设置 摇杆中心 位置
    rockerCenterPos = pos;
    // 获取 摇杆背景 半径
    rockerBGR = spRockerBG->getContentSize().width*0.5;
    //表示摇杆方向不变
    rocketDirection = 0;


    // 事件监听部分
    listener = EventListenerTouchOneByOne::create();
    // 吞掉这个触摸
    listener->setSwallowTouches(true);

    listener->onTouchBegan = CC_CALLBACK_2(JoyRocker::TouchBegan,this);
    listener->onTouchMoved = CC_CALLBACK_2(JoyRocker::TouchMoved,this);
    listener->onTouchEnded = CC_CALLBACK_2(JoyRocker::TouchEnded,this);

    return true;
}

void JoyRocker::startRocker( void )
{
    Sprite *rocker = (Sprite*)this->getChildByTag(rockerCenter);
    rocker->setVisible(true);

    Sprite *rockerBG = (Sprite*)this->getChildByTag(rockerBackGround);
    rockerBG->setVisible(true);

    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); 
}


//停止摇杆(隐藏摇杆,取消摇杆的触屏监听)
void JoyRocker::stopRocker(void)
{
    Sprite *rocker = (Sprite *)this->getChildByTag(rockerCenter);
    rocker->setVisible(false);

    Sprite * rockerBG = (Sprite *)this->getChildByTag(rockerBackGround);
    rockerBG->setVisible(false);

    _eventDispatcher->removeEventListener(listener);
}

float JoyRocker::getRad(Vec2 pos1,Vec2 pos2)
{
    float px1 = pos1.x;
    float py1 = pos1.y;
    float px2 = pos2.x;
    float py2 = pos2.y;

    //得到两点x的距离
    float x = px2 - px1;
    //得到两点y的距离
    float y = py1 - py2;
    //算出斜边长度
    float xie = sqrt(pow(x,2) + pow(y,2));
    //得到这个角度的余弦值(通过三角函数中的点里:角度余弦值=斜边/斜边)
    float cosAngle = x / xie;
    //通过反余弦定理获取到期角度的弧度
    float rad = acos(cosAngle);
    //注意:当触屏的位置Y坐标<摇杆的Y坐标,我们要去反值-0~-180
    if (py2 < py1)
    {
        rad = -rad;
    }
    return rad;
}

// 根据角度,返回点坐标
Vec2 JoyRocker::getAnglePosition(float r,float angle)
{
    return Vec2(r*cos(angle),r*sin(angle));
}


bool JoyRocker::TouchBegan(Touch* touch, Event* event)
{
    Sprite* sp = (Sprite*)this->getChildByTag(rockerCenter);  

    //得到触屏点坐标  
    Vec2 point = touch->getLocation();  

    //判断是否点击到sp这个精灵:boundingBox()精灵大小之内的所有坐标  
    if(sp->boundingBox().containsPoint(point))  
    {  
        // 可以移动了
        isCanMove = true;  
    }

    return true;
}

// 获取移动方向
int JoyRocker::getDirection(void)
{
    return rocketDirection;
}

// 获取正面朝向,true为向右,false向左
bool JoyRocker::getIsLeft(void)
{
    return isLeft;
}

void JoyRocker::TouchMoved(Touch* touch, Event* event)
{
    // 如果不能移动,直接返回
    if(!isCanMove)  
    {  
        return;  
    }  

    Sprite* sp = (Sprite*)getChildByTag(rockerCenter);  
    Vec2 point = touch->getLocation();  

    //得到摇杆与触屏点所形成的角度
    float angle = getRad(rockerCenterPos,point);

    //判断两个圆的圆心距是否大于摇杆背景的半径
    if (sqrt(pow((rockerCenterPos.x - point.x),2) + pow((rockerCenterPos.y - point.y),2)) >= rockerBGR)
    {
        //保证内部小圆运动的长度限制
        sp->setPosition(ccpAdd(getAnglePosition(rockerBGR,angle),Vec2(rockerCenterPos.x,rockerCenterPos.y)));
    }
    else
    {
        //当没有超过,让摇杆跟随用户触屏点移动即可
        sp->setPosition(point);
    }

    //判断方向

    // 右方
    if( angle>=-PI/8 && angle<PI/8 )    {
        rocketDirection = rocker_right;
        isLeft = false;
    }
    // 右上方
    else if( angle>=PI/8 && angle<3*PI/8 )  {
        rocketDirection = rocker_rightUp;
        isLeft = false;
    }
    // 上方
    else if( angle>=3*PI/8 && angle<5*PI/8 )    {
        rocketDirection = rocker_up;
    }
    // 左上方
    else if( angle>=5*PI/8 && angle<7*PI/8 )    {
        rocketDirection = rocker_leftUp;
        isLeft = true;
    }
    // 左方
    else if( (angle>=7*PI/8&&angle<=PI) || (angle>=-PI&&angle<-7*PI/8) )    {
        rocketDirection = rocker_left;
        isLeft = true;
    }
    // 左下方
    else if( angle>=-7*PI/8 && angle<-5*PI/8 )  {
        rocketDirection = rocker_leftDown;
        isLeft = true;
    }
    // 下方
    else if( angle>=-5*PI/8 && angle<-3*PI/8 )  {
        rocketDirection = rocker_down;
    }
    // 右下方
    else if( angle>=-3*PI/8 && angle<-PI/8 )    {
        rocketDirection = rocker_rightDown;
        isLeft = false;
    }

}

void JoyRocker::TouchEnded(Touch* touch, Event* event)
{
    if(!isCanMove)  
    {  
        return;  
    }  

    // 获取 摇杆背景 与 摇杆中心
    Sprite* rocker = (Sprite*)getChildByTag(rockerCenter);  
    Sprite* rockerBG = (Sprite*)getChildByTag(rockerBackGround);  

    // 让 摇杆中心 停止之前所有动作,然后开始 执行归位
    rocker->stopAllActions();  
    rocker->runAction(MoveTo::create(0.08, rockerBG->getPosition()));  

    // 设置 方向为 stay,并且 在下次触摸开始前 不可移动
    rocketDirection=rocker_stay;
    isCanMove = false;  
}

5大概就这么多,可以直接用,完整游戏还在开发中,以后再写吧.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>