cocos2dx 三轴螺旋仪

概念

陀螺仪的作用简单点说就是可以跟踪位置变化,只要你在某个时刻得到了当前所在位置,然后只要陀螺仪一直在运行,根据数学计算,就可以知道你的行动轨迹

运用

  • 导航:陀螺仪可以帮助用户在导航时获取设备的姿态和方向信息,从而更准确地确定设备的位置。
  • 游戏:陀螺仪可以用于游戏中的角色控制和虚拟现实等应用程序。
  • 增强现实:陀螺仪可以帮助用户在增强现实应用程序中获取设备的姿态和方向信息,从而更好地显示虚拟对象。
  • 健康监测:陀螺仪可以用于监测用户的运动和健康状况,例如步数、距离、卡路里消耗等。

IOS + coco2dx

cocos2dx 三轴螺旋仪_第1张图片

主要使用的是CoreMotion框架。

在文件CCDevice-ios

#if !defined(CC_TARGET_OS_TVOS)
#import<CoreMotion/CoreMotion.h>
#endif

CMMotionManager常用的方法和属性

  • activityState :返回设备当前活动状态,例如行走、跑步等
  • deviceMotion :返回设备当前运动状态,包括加速度、速度等数据
  • orientation : 返回设备当前的方向,包括俯仰角、滚动角等
  • userActivity : 返回用户当前活动类型,例如散步、跑步等。
设置传感器更新间隔

设置加速计间隔

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

安卓 + cocos

主要用的是 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();
}

Cocos2dxAccelerometer

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];
    }
}

cocos2dx-lua的运用例子

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)

你可能感兴趣的:(cocos2dx学习之路,cocos2d,cocoa,游戏引擎)