|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta name=viewport content="width=device-width, initial-scale=1"> |
|
<meta name="apple-mobile-web-app-capable" content="yes"> |
|
<meta name="mobile-web-app-capable" content="yes"> |
|
|
|
<title>PubMote - Smartphone Controller</title> |
|
|
|
|
|
<script src="bower_components/webcomponentsjs/webcomponents.min.js"></script> |
|
<link rel="import" href="bower_components/paper-button/paper-button.html"> |
|
<link rel="import" href="bower_components/paper-fab/paper-fab.html"> |
|
<link rel="import" href="bower_components/core-icons/core-icons.html"> |
|
<link rel="import" href="bower_components/core-icons/hardware-icons.html"> |
|
<link rel="import" href="bower_components/pubnub-element/pubnub-element.html"> |
|
|
|
|
|
<style> |
|
#arrow-btns, #action-btns { |
|
text-align: center; |
|
} |
|
|
|
paper-button{ |
|
background: rgba(217, 217, 217, 1); |
|
padding: 3px 15px; |
|
margin: 5px; |
|
} |
|
|
|
paper-fab{ |
|
margin: 5px 10px; |
|
} |
|
|
|
.fullscreen { |
|
padding-top: 25px; |
|
width: 100%; |
|
height: 100vh; |
|
} |
|
.fullscreen img{ |
|
margin: 50px; |
|
} |
|
|
|
#channel { |
|
padding:20em; |
|
font-size: 15px; |
|
margin: 0 auto; |
|
} |
|
|
|
.card { |
|
margin:auto; |
|
margin-top:5px; |
|
background-color:#FFFFFF; |
|
border-radius:2px; |
|
color:#000000; |
|
border:1px solid #d8d8d8; |
|
padding:10px; |
|
text-align:center; |
|
position:relative; |
|
} |
|
</style> |
|
</head> |
|
|
|
<!-- Body tags fullbreed ensures that the template takes the entire screen, unresolved prevents FUOC --> |
|
<body fullbreed unresolved> |
|
<!-- Create a template to handle the controller's functions --> |
|
<template is="auto-binding" id="controller-template"> |
|
<paper-shadow id="gamepad" z="1" class="card"> |
|
<template if="{{isConfigured}}" id=channel> <!-- Only shows when boolean is true. --> |
|
<p style="text-align: center;"><i>Channel: {{channel}}</i></p> |
|
</template> |
|
|
|
<!-- The arrow buttons of the game pad. Use HTML5 data-* to tell which button is clicked --> |
|
<div id="arrow-btns"> |
|
<!-- Uses Polymer's on-tap to link the template's function handleButton() --> |
|
<paper-button data-key="UP" on-tap="{{handleButton}}"> |
|
<core-icon data-key="UP" icon="hardware:keyboard-arrow-up"></core-icon> |
|
</paper-button> <br> |
|
|
|
<paper-button data-key="LEFT" on-tap="{{handleButton}}"> |
|
<core-icon data-key="LEFT" icon="hardware:keyboard-arrow-left"></core-icon> |
|
</paper-button> |
|
<paper-button data-key="RIGHT" on-tap="{{handleButton}}"> |
|
<core-icon data-key="RIGHT" icon="hardware:keyboard-arrow-right"></core-icon> |
|
</paper-button> <br/> |
|
|
|
<paper-button data-key="DOWN" on-tap="{{handleButton}}"> |
|
<core-icon data-key="DOWN" icon="hardware:keyboard-arrow-down"></core-icon> |
|
</paper-button> <br> |
|
<!-- Your custom controller icon --> |
|
<img src="pubnub.png" style="width:100px; margin: 50px;"> |
|
</div> |
|
|
|
<!-- The three floating action buttons, X O and choose channel --> |
|
<div id="action-btns"> |
|
<paper-fab icon="close" data-key="X" on-tap="{{handleButton}}"></paper-fab> |
|
<paper-fab icon="radio-button-off" data-key="O" on-tap="{{handleButton}}"></paper-fab> |
|
<br> |
|
<paper-fab mini icon="polymer" style="background:black" on-tap="{{changeChannel}}"></paper-fab> |
|
</div> |
|
</paper-shadow> |
|
<!-- The PubNub Polymer element, handles push and sucscribe from one element --> |
|
<core-pubnub publish_key="pub-c-3a6515b4-cc50-4515-82ea-80d76f361027" subscribe_key="sub-c-a6b102dc-00a0-11e5-8fd4-0619f8945a4f"> |
|
<core-pubnub-publish id="pub" channel="{{channel}}" message="test"></core-pubnub-publish> |
|
</core-pubnub> |
|
</template> |
|
</body> |
|
|
|
<script src="http://cdn.pubnub.com/pubnub-3.7.1.min.js"></script> |
|
|
|
<script type="text/javascript"> |
|
var controller = document.querySelector('#controller-template'); |
|
controller.isConfigured = false; |
|
controller.channel="demo"; |
|
controller.aX=0; |
|
controller.aY=0; |
|
controller.aZ=0; |
|
controller.speed=0; |
|
controller.handleButton = function(e) { |
|
this.$.pub.message = {"type":"button", "data":e.target.getAttribute('data-key') }; |
|
this.$.pub.publish(); |
|
}; |
|
controller.changeChannel = function(e){ // Prompt a user to change the channel |
|
this.isConfigured = true; |
|
var channel = prompt("Enter a channel: "); // Creates the prompt |
|
if (channel == "" || channel == null) channel="demo"; |
|
this.channel = channel; // Ignores the change if null or empty |
|
} |
|
controller.ready = function() { // This code executes once the controller template is loaded |
|
var iOS = /(iPad|iPhone|iPod)/g.test( navigator.userAgent ); |
|
var lastUpdate = Date.now(); // Last update to threshold PubNub publishes |
|
var SHAKE_THRESHOLD = 1250; // Change this value depending on what you consider a shake |
|
|
|
if (window.DeviceMotionEvent == undefined) { |
|
//No accelerometer is present. Can only use buttons. |
|
alert("no accelerometer"); |
|
} |
|
else { |
|
// Device has an accelerometer. Can use everything. |
|
alert("accelerometer found"); |
|
window.addEventListener("devicemotion", accelerometerUpdate, true); |
|
} |
|
|
|
function accelerometerUpdate(e) { // The eventListener function that updates the aX value and shake |
|
if (Date.now() - lastUpdate > 100) { // Only checks the accelerometer value ever 100ms |
|
lastUpdate = timeNow; |
|
var aX = event.accelerationIncludingGravity.x*1; // Used for tilt |
|
var aY = event.accelerationIncludingGravity.y*1; |
|
var aZ = event.accelerationIncludingGravity.z*1; |
|
|
|
// Since iOS flips the value, this will flip them to an Android standard |
|
aX = iOS ? -1*aX : aX; |
|
|
|
// Calculate the change in X, Y, and Z. Used to check if there was a shake. |
|
var dX = Math.abs(aX - controller.aX); |
|
var dY = Math.abs(aY - controller.aY); |
|
var dZ = Math.abs(aZ - controller.aZ); |
|
|
|
// Only change if the dX was large enough, avoids noise. Publish if there was a change. |
|
if (dX > 0.45) { |
|
controller.aX = Math.floor(aX*2)/2.0; // Floor to the nearest half. |
|
controller.$.pub.message = {'type':'aX', 'data':controller.aX}; |
|
controller.$.pub.publish(); |
|
} |
|
if (dY > 0.45) controller.aY = Math.floor(aY*2)/2.0; |
|
if (dZ > 0.45) controller.aZ = Math.floor(aZ*2)/2.0; |
|
|
|
// Calculate the controller's total speed. This will tell whether there was a shake. |
|
controller.speed = Math.abs(aX + aY + aZ - controller.aX - controller.aY - controller.aZ)/ timeDiff * 10000; |
|
|
|
// Play around with SHAKE_THRESHOLD. If speed is larger than ST, publish a shake. |
|
if (controller.speed > SHAKE_THRESHOLD) { |
|
controller.$.pub.message = {'type':'shake', 'data':controller.speed}; |
|
controller.$.pub.publish(); |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
</script> |
|
</html> |