Use sensors to change gravity in physics engine

1.4k views Asked by At

I'm searching for a way to use sensors in a mobile device (in a Cordova app) to change the behavior of the physics engine. Currently playing around with PhysicsJS, but also found matter.js as a candidate for the physics engine.

In the first step, the gravity of the engine should change so it's not using device y-direction, but the "real" direction depending on how the device is rotated. Later (optionally) also the z-direction could be used to change the world of the physics engine.

Can anybody give me hints and/or an example?

  • what sensor to read (orientation, accelerometer, gyro, gravity, ?). Is there integrated HTML5-support in decent smartphones/browsers or is it better to add a Cordova-plugin?
  • what changes to apply to the physics engine to reflect the new position of the mobile device

Environment: Cordova, Ionic, HTML5, Android >= Kitkat, iOS >= 7

My own findings so far:

I suppose it's deviceorientation event which works best for my requirements. A very raw implementation (which isn't satisfying) is this:

var acceleration = Physics.behavior('constant-acceleration')
    .setAcceleration({x: 0, y: GRAVITY * options.gravityFactor});

world.add([acceleration]);

if (window.DeviceOrientationEvent) {
    var deviceOrientationHandler = function (event) {
        world.one('step', function () {
            acceleration.setAcceleration({
                x: (90 / event.gamma) * GRAVITY,
                y: (90 / event.beta) * GRAVITY
            });
        });
    };
    window.addEventListener('deviceorientation',
        deviceOrientationHandler, false);
}

Seems like a better option would be to calculate the angle of the device regarding x, y and then split the gravity vector into x- and y-parts. Maybe it's even more complicated. This sounds like a lot of math to me. Sure hundreds or thousands have already done this, so could you help me, please?

So the more concrete question remaining now is:

How to transform DeviceOrientationEvent beta and gamma to gravity in 2D physics engine?

2

There are 2 answers

0
hgoebl On

Found a first solution:

if (window.DeviceOrientationEvent) {
    var deviceOrientationHandler = function (event) {

        var pitch = Math.PI * event.beta / 180;
        var roll = Math.PI * event.gamma / 180;

        var acc = {
            x: Math.cos(pitch) * Math.sin(roll) * GRAVITY,
            y: Math.sin(pitch) * GRAVITY
        };

        world.one('step', function () {
            acceleration.setAcceleration(acc);
        });
    };
    window.addEventListener('deviceorientation',
        deviceOrientationHandler, false);
}

It's working quite well on Android, but on iOS when pitching the phone too much, iOS changes orientation to upside-down and then gravity seems to be inverted. Sure there's a solution for this...

2
liabru On

Have you tried the matter.js mobile demo?
http://brm.io/matter-js-mobile/

It shows how to change gravity based on a mobile device's sensors.

The source code is here:
https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js