cocos2d-x游戏摇杆开发

时间:2023-02-07 21:32:00

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

cocos2d-x游戏摇杆开发
//没什么人物素材,瞎找的

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