陀螺仪的作用简单点说就是可以跟踪位置变化,只要你在某个时刻得到了当前所在位置,然后只要陀螺仪一直在运行,根据数学计算,就可以知道你的行动轨迹
主要使用的是CoreMotion框架。
在文件CCDevice-ios中
#if !defined(CC_TARGET_OS_TVOS)
#import<CoreMotion/CoreMotion.h>
#endif
设置加速计间隔
void Device::setAccelerometerInterval(float interval)
{
#if !defined(CC_TARGET_OS_TVOS)
[[CCAccelerometerDispatcher sharedAccelerometerDispatcher] setAccelerometerInterval:interval];
#endif
}
设置陀螺仪间隔(cocos没有)
_motionManage.gyroUpdateInterval = 0.2;
设置磁力计间隔(cocos没有)
_motionManage.magnetometerUpdateInterval = 0.2;
setAccelerometerEnabled
在CCLayer类中有实现
void Layer::setAccelerometerEnabled(bool enabled)
{
if (enabled != _accelerometerEnabled)
{
_accelerometerEnabled = enabled;
Device::setAccelerometerEnabled(enabled);
_eventDispatcher->removeEventListener(_accelerationListener);
_accelerationListener = nullptr;
if (enabled)
{
_accelerationListener = EventListenerAcceleration::create(CC_CALLBACK_2(Layer::onAcceleration, this));
_eventDispatcher->addEventListenerWithSceneGraphPriority(_accelerationListener, this);
}
}
}
开启不同设备的加速计,然后进行监听 EventListenerAcceleration
然后调用OC的
- (void) setAccelerometerEnabled: (bool) isEnabled
{
if (isEnabled)
{
[_motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
[self accelerometer:accelerometerData];
}];
}
else
{
[_motionManager stopAccelerometerUpdates];
}
}
加速计事件,然后将数据抛给accelerometer方法
- (void)accelerometer:(CMAccelerometerData *)accelerometerData
{
_acceleration->x = accelerometerData.acceleration.x;
_acceleration->y = accelerometerData.acceleration.y;
_acceleration->z = accelerometerData.acceleration.z;
_acceleration->timestamp = accelerometerData.timestamp;
double tmp = _acceleration->x;
switch ([[UIApplication sharedApplication] statusBarOrientation])
{
case UIInterfaceOrientationLandscapeRight:
_acceleration->x = -_acceleration->y;
_acceleration->y = tmp;
break;
case UIInterfaceOrientationLandscapeLeft:
_acceleration->x = _acceleration->y;
_acceleration->y = -tmp;
break;
case UIInterfaceOrientationPortraitUpsideDown:
_acceleration->x = -_acceleration->y;
_acceleration->y = -tmp;
break;
case UIInterfaceOrientationPortrait:
break;
default:
NSAssert(false, @"unknown orientation");
}
cocos2d::EventAcceleration event(*_acceleration);
auto dispatcher = cocos2d::Director::getInstance()->getEventDispatcher();
dispatcher->dispatchEvent(&event);
}
该函数处理数据,然后抛给cocos的事件EventAcceleration
主要用的是 SensorEventListener
void Device::setAccelerometerEnabled(bool isEnabled)
{
if (isEnabled)
{
JniHelper::callStaticVoidMethod(helperClassName, "enableAccelerometer");
}
else
{
JniHelper::callStaticVoidMethod(helperClassName, "disableAccelerometer");
}
}
调用的是JNI函数
public static void enableAccelerometer() {
Cocos2dxHelper.sAccelerometerEnabled = true;
Cocos2dxHelper.getAccelerometer().enableAccel();
}
private static Cocos2dxAccelerometer getAccelerometer() {
if (null == sCocos2dxAccelerometer)
Cocos2dxHelper.sCocos2dxAccelerometer = new Cocos2dxAccelerometer(sActivity);
return sCocos2dxAccelerometer;
}
Cocos2dxAccelerometer是继承于类SensorEventListener(安卓的传感器监听事件)
监听的地方为
public void onSensorChanged(final SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
final float z = sensorEvent.values[2];
// needed by VR code
this.accelerometerValues[0] = x;
this.accelerometerValues[1] = y;
this.accelerometerValues[2] = z;
/*
* Because the axes are not swapped when the device's screen orientation
* changes. So we should swap it here. In tablets such as Motorola Xoom,
* the default orientation is landscape, so should consider this.
*/
final int orientation = this.mContext.getResources().getConfiguration().orientation;
if ((orientation == Configuration.ORIENTATION_LANDSCAPE) && (this.mNaturalOrientation != Surface.ROTATION_0)) {
final float tmp = x;
x = -y;
y = tmp;
} else if ((orientation == Configuration.ORIENTATION_PORTRAIT) && (this.mNaturalOrientation != Surface.ROTATION_0)) {
final float tmp = x;
x = y;
y = -tmp;
}
// Invert axes for reverse landscape and reverse portrait
int rotation = Cocos2dxHelper.getActivity().getWindowManager().getDefaultDisplay().getRotation();
if (rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270) {
x = -x;
y = -y;
}
Cocos2dxGLSurfaceView.queueAccelerometer(x,y,z,sensorEvent.timestamp);
/*
if(BuildConfig.DEBUG) {
Log.d(TAG, "x = " + sensorEvent.values[0] + " y = " + sensorEvent.values[1] + " z = " + pSensorEvent.values[2]);
}
*/
}
else if (sensorEvent.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
// needed by VR code
this.compassFieldValues[0] = sensorEvent.values[0];
this.compassFieldValues[1] = sensorEvent.values[1];
this.compassFieldValues[2] = sensorEvent.values[2];
}
}
layer:setAccelerometerEnabled(true)
local label = cc.Label:createWithTTF(title(), "fonts/arial.ttf", 32)
layer:addChild(label, 1)
label:setAnchorPoint(cc.p(0.5, 0.5))
label:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 50) )
local ball = cc.Sprite:create("Images/ball.png")
ball:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y))
layer:addChild(ball)
local function accelerometerListener(event,x,y,z,timestamp)
local target = event:getCurrentTarget()
local ballSize = target:getContentSize()
local ptNowX,ptNowY = target:getPosition()
ptNowX = ptNowX + x * 9.81
ptNowY = ptNowY + y * 9.81
local minX = math.floor(VisibleRect:left().x + ballSize.width / 2.0)
local maxX = math.floor(VisibleRect:right().x - ballSize.width / 2.0)
if ptNowX < minX then
ptNowX = minX
elseif ptNowX > maxX then
ptNowX = maxX
end
local minY = math.floor(VisibleRect:bottom().y + ballSize.height / 2.0)
local maxY = math.floor(VisibleRect:top().y - ballSize.height / 2.0)
if ptNowY < minY then
ptNowY = minY
elseif ptNowY > maxY then
ptNowY = maxY
end
target:setPosition(cc.p(ptNowX , ptNowY))
end
local listener = cc.EventListenerAcceleration:create(accelerometerListener)
layer:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, ball)