HTML5 Zone is brought to you in partnership with:

Raymond Camden is a developer evangelist for Adobe. His work focuses on web standards, mobile development and Cold Fusion. He's a published author and presents at conferences and user groups on a variety of topics. He is the happily married proud father of three kids and is somewhat of a Star Wars nut. Raymond can be reached via his blog at www.raymondcamden.com or via email at raymondcamden@gmail.com Raymond is a DZone MVB and is not an employee of DZone and has posted 254 posts at DZone. You can read more from them at their website. View Full User Profile

PhoneGap Sample - Shake to Roll

01.17.2013
| 2867 views |
  • submit to reddit

Sorry for being so quiet lately. I've got three presentations this week and two brand new ones in two weeks. Mentally - it has been killing me. As with all things - it will pass. (And I think I'm building some good new presentations as well!) In the meantime, I thought I'd share a simple PhoneGap application I built for my four hour lab in Ohio a few days back.

The idea behind the application was to demonstrate the Accelerometer API. This returns movement information along three different axis.

By itself, the API is easy enough to use. What I was having difficulty with was coming up with a practical example of it. I thought I'd create a simple application that mimicked rolling a die. I'd start off by selecting a random number between one and six. I'd display this on the screen like so.

(What you're seeing here is the Ripple emulator. I plan on talking about this in a few days.)

The code for picking and displaying a random number was trivial.

function shuffleNumber() {
  var newNum = getRandomInt(1,6);
	document.querySelector("#die").innerHTML = newNum;
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

What was more difficult was figuring out how to respond to a shake. I mean, seriously, what is a shake, in code terms?

I did some Googling and discovered that most people simply tracked the X/Y/Z values and then compared them to historical values. I came up with this solution (which is based on what I saw so this isn't some brilliant discovery of mine).

var lastX,lastY,lastZ;
var moveCounter = 0;

function onDeviceReady() {
  shuffleNumber();
	navigator.accelerometer.watchAcceleration(gotMovement, errHandler,{frequency:200});	
}

function gotMovement(a) {
	if(!lastX) {
		lastX = a.x;
		lastY = a.y;
		lastZ = a.z;
		return;
	}

	var deltaX, deltaY, deltaZ;
	deltaX = Math.abs(a.x-lastX);
	deltaY = Math.abs(a.y-lastY);
	deltaZ = Math.abs(a.z-lastZ);

	if(deltaX + deltaY + deltaZ > 3) {
		moveCounter++;
	} else {
		moveCounter = Math.max(0, --moveCounter);
	}

	if(deltaX !=0 || deltaY != 0 || deltaZ != 0) console.log(deltaX,deltaY,deltaZ,moveCounter);

	if(moveCounter > 1) { shuffleNumber(); moveCounter=0; }

	lastX = a.x;
	lastY = a.y;
	lastZ = a.z;

}

I then used the Ripple emulator to test, and slowly tweaked the numbers until it "felt" right to me. You can see the result below.

For the full source code (there really isn't much to it), you can see the code in the GitHub repo for the presentation: DevelopingMobileAppsWithPhoneGap/tree/master/labs/6_accelerometer



Published at DZone with permission of Raymond Camden, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)