Cocos2d-x游戏开发实战精解
上QQ阅读APP看书,第一时间看更新

4.4 在Cocos2d-x中使用加速度传感器

上一节介绍了在Cocos2d-x中使用键盘和鼠标的方法,也许很多人还是不大适应在手机上接上一堆外设的行为,那么本节就介绍一种一直被手游玩家喜闻乐见的操作方式:重力感应。

这是一种在赛车游戏中被广泛使用的操作方式,具体原理就是通过加速度传感器分别获取来自x、y、z 3个方向的加速度。由于当手机静止时一定会受到重力,因此就可以确定合力所在的方向就是下方。而当手机被移动时,也可以根据手机静止时的状态以及各个方向加速度的变化,从而确认各个方向。

范例4-5展示在Cocos2d-x中利用加速度传感器获取操作信息的方法,完整内容可以参考源文件当前目录下的项目ChapterFour04。当然,由于实现该功能需要所在的平台支持加速度传感器,因此需要在手机上测试,可以直接运行项目目录下的apk文件进行测试。

【范例4-5】在Cocos2d-x中使用加速度传感器。

01 Size visibleSize = Director::getInstance()->getVisibleSize();        //获取场景尺寸
02      Vec2 origin = Director::getInstance()->getVisibleOrigin();      //获取坐标原点
03      screenWidth = visibleSize.width;                        //场景宽度
04      screenHeight = visibleSize.height;                      //场景高度
05      scale = 1.0f;                                           //缩放倍数
06      sprite = Sprite::create("sprite.png");          //创建“羊驼”
07      sprite->setScale(0.3f);
08      sprite->setPosition(screenWidth / 2, screenHeight / 2);
09      this->addChild(sprite);                              //将“羊驼”加入到场景
10      Device::setAccelerometerEnabled(true);          //打开加速度传感器
11      //创建触发器用来对加速度传感器的数据进行处理
12      auto listener = EventListenerAcceleration::create(CC_CALLBACK_2 
        (HelloWorld::onAcceleration, this));
13      _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, 
        this);
14      /***********对onAcceleration方法进行重写**********/
15      void HelloWorld::onAcceleration(Acceleration* acc, Event* event)
16      {
17              auto point = this->sprite->getPosition();
18              if (acc->x < 0 && point.x>0)
19              {
20                      point.x--;
21              }
22              else if (acc->x > 0 && point.x<this->screenWidth)
23              {
24                      point.x++;
25              }
26              if (acc->y < 0 && point.x>0)
27              {
28                      point.y--;
29              }
30              else if (acc->y > 0 && point.y<this->screenHeight)
31              {
32                      point.y++;
33              }
34              if (acc->z<0 && this->scale>0.1)
35              {
36                      this->scale = this->scale*0.9;
37              }
38              else if (acc->z>0 && this->scale < 10)
39              {
40                      this->scale = this->scale*1.1;
41              }
42              this->sprite->setPosition(point);
43              this->sprite->setScale(0.3*this->scale);
44      }

运行之后会发现屏幕中的羊驼图案随着手机方向的改变,不断改变运动方向以及尺寸大小,如图4-8和图4-9所示。在使用加速度传感器时,首先要在init方法中对当前的场景进行一些简单的设置,如范例第01~14行所示。然后还要新建一个onAcceleration方法,处理加速度传感器获取的数据。

图4-8 羊驼被放大

图4-9 移动设备角度和方向羊驼坐标位置和尺寸均改变

在范例的第01~09行,全部都是使用加速度传感器之前要做的一些准备工作,在运行该项目之后已经可以看到,屏幕上的羊驼会随着手机的倾斜方向不断运动,并且会沿着一定的倾斜方向放大或者缩小尺寸,在这个过程中所需要用到的精灵“羊驼”,以及为了保证羊驼不会跑出屏幕尺寸而要限定的屏幕范围,还有羊驼尺寸变化的倍数等,都是在这段代码中被定义的。

接下来第10行就开始了新的内容,首先是打开重力感应的功能,然后在第12行创建了用于对加速度传感器进行响应的触发器listener,让它在被触发时调用onAcceleration方法,接着在第13行将触发器与当前场景绑定,就可以使用了。

在第15~44行就是对onAcceleration方法的实现,原理非常简单。onAcceleration将设备x、y、z方向的3个加速度存放在参数acc中,然后分别判断它在3个方向上应该进行何种运动,将这些变化保存在参数scale和point中,最后在第42、43行实现这些变化。

下面再来介绍一下在Cocos2d-x中加速度传感器的坐标,当手机水平时的坐标示意图如图4-10所示。也就是说,如果图中的手机以z轴为中心作逆时针转动,那么加速度中x方向分量的值将小于零,而如果顺时针转动,x方向的分量将大于零,其他方向也是类似。至于横屏时的坐标也是一样,就是在图中坐标系的基础上将手机以z轴为轴心逆时针旋转了90度。本节提供的范例就是使用的横屏状态下的坐标系,因此读者能够直接体验到。

图4-10 竖屏时的加速度传感器坐标

提示:本节范例所使用的例子,是不可以引用在实际开发中的,因为在Cocos2d-x中的加速度传感器有时会带有一定的延迟,而本例对羊驼坐标的移动是在每次onAcceleration方法被调用时改变一次。所以说如果加速度传感器延迟了,那么羊驼的运动速度实际上就不是想象中的匀速运动了(即使是做加速运动也是不科学的)。正确的方法应当是在onAcceleration仅保存所需要的数据,如加速度的方向等,而在今后要学习的计数器函数中对数据以及场景中的节点进行统一的处理。