Processing raw physical events

Accelerometer events are complex, reporting three main pieces of information—tilt vector, motion vector, and whether or not the event has been identified as a shake of the device—contained in seven different fields. However, we're interested in only two and a limited aspect of those at that; shake recognition, and the angle of the device to the horizontal (actually two angles; the side-to-side and front-to-back tilts). So we'll attach a listener that processes these events on Runtime and sends simplified events with the information in the form we want to deal with.

Getting ready

A little more explanation is in order for this task. The actual math required to get the desired information (the two angles by which the device is off the horizontal plane) only takes two lines of code, but understanding why this math achieves the desired result is less simple.

Getting ready

Corona represents gravity in three vectors; a direction and magnitude in three dimensions, broken into its three Cartesian coordinates. Imagine an arrow pointing from the middle of your phone or tablet towards the focus of gravity, that is, the center of the Earth.

Note

If you're not on the Earth, the arrow will be pointing somewhere else, and might be longer or shorter. This is probably not a concern for most of our readers.

The coordinates of the end of the arrow are provided in the event as if the device were lying flat at the center of the universe; that is, even though—from the outside—we see the Earth as standing still and the device as turning over, from the accelerometer's viewpoint, the x, y, and z axes are fixed to the device and the arrow pointing out gravity is rotating across them.

While the exact length of the arrow may vary—depending on where you are, what device you're using, and from moment to moment—most of the time, we're only interested in its direction. This can be determined from the proportions of the various vector components, regardless of the total vector length; since they're all perpendicular, applying trigonometry is fairly easy. We can look at any two components as being the opposite and adjacent sides of the vector's angle in that plane. The opposite side from a corner of a right triangle divided by the adjacent side to that corner gives you the tangent of the angle of that corner. So, you can feed the ratio of the zGravity (opposite) and yGravity (adjacent) components to math.atan (or more often, give the two separate numbers to math.atan2, which is easier and gives more reliable results) to determine the angle by which the device is tipped front-to-back off the horizontal. We can replace yGravity with xGravity to determine the sideways tilt.

Getting on with it

Create a new file, input.lua, in the top level of your project directory, and open it for editing.

  1. Create the skeleton of a new listener function, and register it to respond to accelerometer events on the Runtime target:
    local function processor(event)
    end
    
    Runtime:addEventListener('accelerometer', processor)
    
  2. The code will calculate the angles between the device's z axis and the vertical according to gravity, along the device's x and y axes, and the results will be posted back to Runtime in a new event named Tilt:
    local function processor(event)
      local theta = math.atan2(event.yGravity, -event.zGravity)
      local phi = math.atan2(event.xGravity, -event.zGravity)
      Runtime:dispatchEvent{name='Tilt'; lateral = phi, vertical = theta}
    end
  3. The listener will also post a custom event called Shake if the device is being shaken. Exactly what this means is up to the host operating system and hardware.
      Runtime:dispatchEvent{name='Tilt'; lateral = phi, vertical = theta}
      if event.isShake then
        Runtime:dispatchEvent{name = 'Shake'}
      end
    end
  4. As a last courtesy, the module will return this new listener if the host code wants to be able to turn it on and off (we won't need to in this project):
    Runtime:addEventListener('accelerometer', processor)
    
    return processor
    
  5. Save input.lua. In order to have this listener loaded and ready in the rest of our code, open main.lua and load the input module at the top:
    display.setStatusBar(display.HiddenStatusBar)
    
    require "input"
    
    local storyboard = require "storyboard"

What did we do?

We created an adapter layer to present the information provided by Corona in a form more easily usable to us. This very simple code extension is flexible enough to be reused in other projects.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.239.41