Reza Ghobadinic

Accelerometer

Accelerometer Event

The accelerometer is fun!

First, we have to activate the accelerometer in the init() method.

Device::setAccelerometerEnabled(true);

As usual, we need to create an event listener but this time for the accelerometer. Although, unlike the previous listeners, this one needs a callback function as an input parameter. Then we add the listener to the event dispatcher.

// EventListenerAcceleration::create(const std::function<void (Acceleration *, Event *)> &callback)

auto listener = EventListenerAcceleration::create(callback);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

I define a lambda for the callback function in the format below and I pass the local variables that I need in the brackets:

function<void(Acceleration*, Event*)> callback = [](Acceleration *acceleration, Event *event){
   // do something
}

Just keep in mind that the accelerometer drains your phone’s battert. So, use it wisely!

Accelerometer Example

In this example I make a ball sprite and move it around with the accelerometer.

I am just listing the init() method here as the rest are the same business as before which by now you know by heart!

AccelScene.cpp

bool AccelScene::init()
{
    // Setup the ball sprite
    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    float x = origin.x + visibleSize.width / 2;
    float y = origin.y + visibleSize.height / 2;
     
    auto ball = Sprite::create("ball.png");
    ball->setVisible(true);
    ball->setPosition(x, y);
    this->addChild(ball);
    
    // Setup the accelerometer event handler
    Device::setAccelerometerEnabled(true);
    
    // The callback lambda
    function<void(Acceleration*, Event*)> callback = [ball, visibleSize, origin](Acceleration *acceleration, Event *event){
        
        // Update the ball position using the accelerometr x and y values
        float x = ball->getPositionX();
        float y = ball->getPositionY();
        x += (acceleration->x * 10);
        y += (acceleration->y * 10);
        
        // Make sure the ball stays in the screen
        if (x < origin.x) x = origin.x;
        if (y < origin.y) y = origin.y;
        if (x >= (origin.x + visibleSize.width))  x = origin.x + visibleSize.width  - 1;
        if (y >= (origin.y + visibleSize.height)) y = origin.y + visibleSize.height - 1;
        
        // Update the ball position
        ball->setPosition(x, y);
        
        cout << acceleration->timestamp << " " << acceleration->x << " " << acceleration->y << " " << acceleration->z << endl;
    };
    
    auto listener = EventListenerAcceleration::create(callback); // Create an accelerometer listener
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    
    return true;
}

After running this code, I realized the starting position of the phone (the angle you hold it) registers as the initial pose somehow! You can enhance this code to compensate for that, but I leave that to you!

Download Source

Exit mobile version