Cocos2d-x《赵云要格斗》--虚拟摇杆控制精灵上下左右运动

  本文将要实现一个横版格斗类游戏,并实现摇杆控制英雄上下左右运动。这里实现了能通过虚拟摇杆控制精灵的运动,而且能够改变精灵运动时的脸部朝向。之前看了好多人写虚拟摇杆,但是就是没写控制精灵的运动和脸朝向的。所以自己就想要写个文章好好讲下它的实现思路。好了,下面我们开始吧。

  最终效果:

  

  cocos2d-x版本:2.2.5

  工程环境:windows7+VS2010

  打开方式:将工程放在cocos2d-x安装目录下的project文件夹下用VS打开

  目录:

  一、修改背景图片和窗口大小

  二、添加虚拟摇杆

  三、添加精灵并用摇杆控制精灵的运动

  四、思路总结

  一、修改背景图片和窗口大小

  新建一个工程,工程名为HelloCpp.为了让效果更加好些,首先修改下窗口的大小,在main.cpp中改

  eglView->setFrameSize(480,320);为

  eglView->setFrameSize(640,480);

  然后在我们要显示的层上HelloWorldScene.cpp的init()函数添加:

  //得到窗口的大小

  CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

  CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

  //修改背景图片

  CCSprite* pSprite = CCSprite::create("background_1.jpg");

  pSprite->setPosition(ccp(visibleSize.width/2 + origin.x,

  visibleSize.height/2 + origin.y));

  this->addChild(pSprite, 0);//这里的0表示放在最底层

  效果如下:

  

  二、添加虚拟摇杆

  首先,先将摇杆素材放入到项目的Resources文件夹下,注意,最好把要用到的素材都放在这里,项目工程默认的素材是从此文件夹下查找。

  

  

  这是摇杆的背景图片,图片不容易找啊。没有美工,只能随便网上找了点

  

  

  这是摇杆里面的按钮图片,它是可以移动的

  好了,接下来我们要开始加入摇杆的进入背景中了,我的思路是把摇杆封装成一个类,然后照看继承CCLayer,就可以响应触摸事件了,看看代码,新建一个HRocker.h头文件。这里要注意要把.cpp和.h都放到项目的class文件夹下,要不会提示找不到文件。代码如下:

  #ifndef __HROCKER_H__

  #define __HROCKER_H__

  #include "cocos2d.h"

  using namespace cocos2d;

  //用于标识摇杆与摇杆的背景

  typedef enum{

  tag_rocker,

  tag_rockerBG,

  }tagForHRocker;

  //用于标识摇杆方向

  typedef enum{

  rocker_stay,

  rocker_right,

  rocker_up,

  rocker_left,

  rocker_down,

  }tagDirecton;

  class HRocker:public CCLayer

  {

  public:

  HRocker(void);

  ~HRocker(void);

  //创建摇杆(摇杆的操作题图片资源名,摇杆背景图片资源名,起始坐标)

  static HRocker* createHRocker(const char *rockerImageName,const char *rockerBGImageName,CCPoint position);

  //启动摇杆(显示摇杆、监听摇杆触屏事件)

  void startRocker(bool _isStopOther);

  //停止摇杆(隐藏摇杆,取消摇杆的触屏监听)

  void stopRocker();

  //判断控制杆方向,用来判断精灵上、下、左、右运动

  int rocketDirection;

  //当前人物行走方向,用来判断精灵的朝向,精灵脸朝右还是朝左

  bool rocketRun;

  CREATE_FUNC(HRocker);

  private:

  //自定义初始化函数

  void rockerInit(const char* rockerImageName,const char* rockerBGImageName,CCPoint position);

  //是否可操作摇杆

  bool isCanMove;

  //获取当前摇杆与用户触屏点的角度

  float getRad(CCPoint pos1,CCPoint pos2);

  //摇杆背景的坐标

  CCPoint rockerBGPosition;

  //摇杆背景的半径

  float rockerBGR;

  //触屏事件

  virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);

  virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);

  virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);

  };

  #endif

  再建其相应的实现HRocker.cpp,这里要注意要把.cpp和.h都放到项目的class文件夹下,要不会提示找不到文件。代码如下:

  #include "HRocker.h"

  const double PI=3.1415;

  HRocker::HRocker(void)

  {

  rocketRun=false;

  }

  HRocker::~HRocker(void)

  {

  }

  //创建摇杆(摇杆的操作题图片资源名,摇杆背景图片资源名,起始坐标)

  HRocker* HRocker::createHRocker(const char *rockerImageName,const char *rockerBGImageName,CCPoint position)

  {

  HRocker *layer = HRocker::create();

  if (layer)

  {

  layer->rockerInit(rockerImageName,rockerBGImageName,position);

  return layer;

  }

  CC_SAFE_DELETE(layer);

  return NULL;

  }

  //自定义初始化函数

  void HRocker::rockerInit(const char* rockerImageName,const char* rockerBGImageName,CCPoint position)

  {

  CCSprite *spRockerBG = CCSprite::create(rockerBGImageName);

  spRockerBG->setPosition(position);

  spRockerBG->setVisible(false);

  addChild(spRockerBG,0,tag_rockerBG);

  CCSprite *spRocker = CCSprite::create(rockerImageName);

  spRocker->setPosition(position);

  spRocker->setVisible(false);

  addChild(spRocker,1,tag_rocker);

  rockerBGPosition = position;

  rockerBGR = spRockerBG->getContentSize().width*0.5;//

  rocketDirection=-1;//表示摇杆方向不变

  }

  //启动摇杆(显示摇杆、监听摇杆触屏事件)

  void HRocker::startRocker(bool _isStopOther)

  {

  CCSprite *rocker = (CCSprite*)this->getChildByTag(tag_rocker);

  rocker->setVisible(true);

  CCSprite *rockerBG = (CCSprite *)this->getChildByTag(tag_rockerBG);

  rockerBG->setVisible(true);

  CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,-1,_isStopOther);

  }

  //停止摇杆(隐藏摇杆,取消摇杆的触屏监听)

  void HRocker::stopRocker()

  {

  CCSprite *rocker = (CCSprite *)this->getChildByTag(tag_rocker);

  rocker->setVisible(false);

  CCSprite * rockerBG = (CCSprite *)this->getChildByTag(tag_rockerBG);

  rockerBG->setVisible(false);

  CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);

  }

  //获取当前摇杆与用户触屏点的角度

  float HRocker::getRad(CCPoint pos1,CCPoint 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;

  }

  CCPoint getAngelePosition(float r,float angle){

  return ccp(r*cos(angle),r*sin(angle));

  }

  //抬起事件

  bool HRocker::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)

  {

  CCPoint point = pTouch->getLocation();

  CCSprite *rocker = (CCSprite *)this->getChildByTag(tag_rocker);

  if (rocker->boundingBox().containsPoint(point))

  isCanMove = true;

  return true;

  }

  //移动事件

  void HRocker::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)

  {

  if (!isCanMove)

  {

  return;

  }

  CCPoint point = pTouch->getLocation();

  CCSprite *rocker = (CCSprite *)this->getChildByTag(tag_rocker);

  //得到摇杆与触屏点所形成的角度

  float angle = getRad(rockerBGPosition,point);

  //判断两个圆的圆心距是否大于摇杆背景的半径

  if (sqrt(pow((rockerBGPosition.x - point.x),2) + pow((rockerBGPosition.y - point.y),2)) >= rockerBGR)

  {

  //保证内部小圆运动的长度限制

  rocker->setPosition(ccpAdd(getAngelePosition(rockerBGR,angle),ccp(rockerBGPosition.x,rockerBGPosition.y)));

  }

  else

  rocker->setPosition(point);

  //判断方向

  if(angle>=-PI/4&&angle

猜你喜欢

转载自blog.csdn.net/weixin_44239023/article/details/89412049