cocos2d-x游戏摇杆开发

来源:互联网 发布:程序员 博客 编辑:程序博客网 时间:2024/05/16 00:51

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大概就这么多,可以直接用,完整游戏还在开发中,以后再写吧.

0 0