您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x遥感控制角色移动简单实现之JoyStick

2013-08-07 00:00 597 查看
cocos2d-x手游开发过程中有时会遇到使用遥感控制角色移动,例如《忘仙》。

本例使用cocos2d-x和CocoStudio工具开发,

1.JoyStick.h

#ifndef _JOYSTICK_H_
#define _JOYSTICK_H_

#include "cocos2d.h"
#include "UIButton.h"

USING_NS_CC;
USING_NS_CC_EXT;

class JoyStick : public UIButton
{
public:
JoyStick()	{};
~JoyStick()	{};

virtual void		onTouchMoved(cocos2d::CCPoint &touchPoint);
virtual void		onTouchEnded(cocos2d::CCPoint &touchPoint);
void				setOriginalPos(cocos2d::CCPoint pos){m_originalPos.x = pos.x, m_originalPos.y = pos.y;}
static UIWidget*	create();

static JoyStick*	Inistance()	{return (JoyStick*)create();}
protected:
virtual bool		init();
static JoyStick*	s_pInst;
private:
CCPoint	m_originalPos;
};

#endif


2.JoyStick.cpp

#define Moving_Radius 150.0f
#define Name_Joystick "joystick"

JoyStick* JoyStick::s_pInst = NULL;
//将弧度角度的方向转化为8方向,上、下、左、右、左上、左下、右上、右下
kmVec2 adjustTo8Directions(kmVec2 dir)
{
kmVec2 arr[8] = {0.0f,1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f,-1.0f, 0.0f,-1.0f, -1.0f,-1.0f, -1.0f,0.0f, -1.0f,1.0f};
float maxDot = -2;
int maxDotIndx = 0;
for (int i = 0; i < 8; i++)
{
maxDot = kmVec2Dot(&arr[i], &dir) > maxDot ? (maxDotIndx = i, kmVec2Dot(&arr[i], &dir)) : maxDot;
}

return arr[maxDotIndx];
}

//初始化函数
UIWidget* JoyStick::create()
{
if (s_pInst)
return s_pInst;
s_pInst = new JoyStick();
if (s_pInst && s_pInst->init())
{
return s_pInst;
}
CC_SAFE_DELETE(s_pInst);
return NULL;
}

//添加轮盘纹理
bool JoyStick::init()
{
bool ret = UIButton::init();
setPosition(ccp(150,150));
setOriginalPos(m_pRender->getPosition());
setAnchorPoint(ccp(0.5, 0.5));
setTextures("assets\\CocoUI\\assets\\common\\btn1_dis.png",
"assets\\CocoUI\\assets\\common\\btn1_down.png",
"assets\\CocoUI\\assets\\common\\btn1_up.png");
setTouchEnable(true);
setName(Name_Joystick);

return ret;
}

//主要实现方法,onTouchMoved中不断控制移动方向
void JoyStick::onTouchMoved(cocos2d::CCPoint &touchPoint)
{
cocos2d::CCPoint nsp = m_pRender->getParent()->convertToNodeSpace(touchPoint);

kmVec2 dir = {abs(touchPoint.x - m_originalPos.x), abs(touchPoint.y - m_originalPos.y)};
kmVec2Normalize(&dir, &dir);
kmVec2 edge = {dir.x * Moving_Radius, dir.y * Moving_Radius};
setPosition(ccp(clampf(nsp.x, m_originalPos.x - edge.x, m_originalPos.x + edge.x),
clampf(nsp.y, m_originalPos.y - edge.y, m_originalPos.y + edge.y)));   //轮盘控制在一个圆圈以内;
float a = ccpSub(nsp, m_originalPos).getAngle();    //这是最终得到的弧度角度

//向其他模块发送消息,角色要向某一方向移动,监听了次消息的对象就是让角色去移动
CCNotificationCenter::sharedNotificationCenter()->postNotification(geHeroEvent,GameEvent::create(mapEvent_JoystickDirChanged,(void*)&a,this));

UIButton::onTouchMoved(touchPoint);
}
//当玩家松开轮盘时停止移动
void JoyStick::onTouchEnded(cocos2d::CCPoint &touchPoint)
{
setPosition(m_originalPos);
UIButton::onTouchEnded(touchPoint);

//向其他模块发送消息,角色要停止移动,监听了此消息的对象就是让角色停止移动
CCNotificationCenter::sharedNotificationCenter()->postNotification(geHeroEvent,GameEvent::create(mapEvent_JoystickGoBack,NULL,this));
}


3.监听了轮盘事件的对象就可以处理上述两个事件了,例如移动事件

case mapEvent_JoystickDirChanged:
{
pEntity->prepareMove(pEntity->getPosition(),*(float*)event->data);
pEntity->refreshDisplay();
SafeReleaseGameEvent(event);
return true;
}
void MobileObject::prepareMove( const CCPoint& curPos,const CCPoint& targetPos  )
{
m_bIsArrive = false;

m_bJoystick = false;
m_tCurPos = curPos;
m_tTargetPos = targetPos;
m_fAngle = ccpSub(m_tTargetPos,m_tCurPos).getAngle();
m_fDeltaX = cosf(m_fAngle);
m_fDeltaY = sinf(m_fAngle);
m_nMobileState = eMobileState_move;
}
//在step方法里面移动
bool MobileObject::step( float dt )
{
m_tDiff.x = m_fDeltaX*m_nSpeed*dt;
m_tDiff.y = m_fDeltaY*m_nSpeed*dt;
if ( !m_bJoystick && m_tCurPos.getDistanceSq(m_tTargetPos) < m_tDiff.getLengthSq() )
{
m_tCurPos = m_tTargetPos;
m_nMobileState = eMobileState_Arrive;
m_bIsArrive = true;
}
else
{
m_tCurPos.x += m_tDiff.x;
m_tCurPos.y += m_tDiff.y;
}
afterStep();
return m_bIsArrive;
}


// step最后会调用该函数,用于更新对象的坐标信息或者与服务器进行同步
void CRole::afterStep()
{
setPosition(m_tCurPos);
//其他操作
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: