Fire phone represents an incredible opportunity for HTML5 developers to create new experiences. Developers now have direct access to the hardware sensors that power Fire’s Dynamic Perspective, which opens up all kinds of new ways to let users interact with your web app content. Just like native devs, Fire phone’s four dedicated cameras offer x, y and z data that you can access directly to determine where the player’s head is looking at the screen, and shift the perspective to reveal new angles on what would have otherwise been a flat web page.
Over the course of this tutorial, we will walk through how to create a simple splash screen for a game in Phaser (a popular open source game framework). We’ll also cover how to take advantage of the ability to run web apps next to native ones on the Fire phone and how to add Dynamic Perspective to create a parallax layering effect which gives the scene more of an immersive experience. Before we get started, let’s take a quick look at the splash screen we’ll be creating:
Here you can see a standard splash screen for a game where the main player will float up and down, giving the scene some sense of motion. The start text also blinks to let the player know what action they should take.
To start, download my Phaser Project Template from https://github.com/gamecook/phaser-project-template. You will need to have the following setup on your computer:
This project will give you everything you need to run our project and has step-by-step instructions on how to get everything configured to run locally. Once you have everything set up, rename the Phaser Project Template to DynamicPerspectivePhaserDemo, then navigate into it via the command line. You’ll want to run the following command to get everything configured:
> npm install
Once that is done running, you should be able to launch the project by typing in the following:
> grunt
This will start a local server and open up your browser to http://localhost:8080.
Now we have everything up and running to build our Phaser splash screen. Just download the artwork from here. You’ll need to create an assets folder inside of the deploy directory of the Phaser Project Template. Once that is created, put all of the artwork you just downloaded into it.
One note: if you are using WebStorm, you will want to exclude the deploy/js folder from the Directories setting so you don’t have any performance issues as our grunt script automatically rebuilds the JS code for us.
Step 1. Let’s create a clean slate to work from by opening our main.js file in the src/game folder of the Phaser Project Template. Once you have it open, simply delete all the boilerplate code in that file.
Step 2. Next we are going to create our new state object and Phaser game instance from scratch by typing out the following:
var state = { preload: function () { }, create: function () { }, update: function(){ } } // Create new game instance var game = new Phaser.Game( 800, 480, Phaser.AUTO, 'game', state )
Step 3. Once you have all the artwork in your assets folder, we can add it to our preload function:
preload: function () { this.load.image("mask", "/assets/background-mask.png"); this.load.image("background", "/assets/background-image.png"); this.load.image("title", "/assets/title.png"); this.load.image("start", "/assets/start-text-touch.png"); this.load.spritesheet("player", "/assets/player-sprites.png", 385, 412); }
Here you can see we are simply loading everything up as an image with the exception of the player, which will be animated. That means we can use the dedicated sprite sheet loader.
Step 4. In our create() function, let’s setup the scaleMode to give us full screen on different device resolutions:
create: function () { this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; this.scale.pageAlignHorizontally = true; this.scale.pageAlignVertically = true; this.scale.setScreenSize(true); ...
Step 5. We can start blocking out how the scene will be laid out. Inside of our create() method, add the following:
// Calculate center point for laying scene out var centerOffset = {x: (this.world.width - 679) * .5, y: (this.world.height - 466) *.5}; // Create background image this.background = this.add.image(centerOffset.x, centerOffset.y, "background"); // Save bg position this.bgPos = this.background.position.clone(); } // end create
This will calculate where we will center the background image. We’ll also save out the value for the background in order to use it as a reference point later on.
Step 6. If we refresh the browser, we’ll see our first glimpse at how the splash screen will look:
Step 7. Let’s get back into our code now and add in the player as well as the title and other elements that will help complete the scene. In our create() function. Below the background code we just added, put the following code:
create: function () { ... // Create player this.player = this.add.sprite(this.bgPos.x + 20, this.bgPos.y + 20, 'player'); this.player.animations.add('fly', [0, 1, 2, 3], 10, true); this.player.animations.play("fly"); this.playerStartPos = this.player.position.clone();
Here you can see we are setting up our player as well as creating and setting a fly animation. We also save out our player’s start position, which we will use later on when we start modifying it based on the Dynamic Perspective code we’ll add for Fire.
Step 8. Now we can wrap this up with the last bit of layout code:
// Add mask, title and start images this.mask = this.add.image(this.background.position.x-50, this.background.position.y + 280, "mask"); this.title = this.add.image(this.bgPos.x + 370, this.bgPos.y+295, "title"); this.start = this.add.image(this.bgPos.x + 405, this.bgPos.y+385, "start"); } // end create
Here we add the background mask, the title and the start text.
Step 9. If you refresh the browser you will now see our scene:
While this is really easy to setup, it looks a little boring. Let’s add some animation to it.
Step 10. In our update() function, add the following code:
// Make player float up and down this.player.y = (this.playerStartPos.y / 2) + 8 * Math.cos(this.time.now / 200) + 20; // make start text blink this.start.visible = Math.round(this.time.now/500) % 2 ? true : false;
This code will make the player float up and down as well as make the start text blink. You can test this by refreshing the browser again.
At this point, we have our entire splash screen laid out. Let’s talk about how to set up the Web App Tester on Fire phone to get our splash screen ready for adding the Dynamic Perspective APIs.
Just like you can currently do on the Kindle Fire, you’ll need to download the Web App Tester on the Fire phone for this next part of the tutorial. You can get the latest build from the Amazon Appstore here.
Step 11. Once you have the Web App Tester installed, you’ll want to look up your computer’s IP address.
Step 12. When you have the IP address, you can enter that into the URL field and save it.
Step 13. Now you can pull up the Amazon WebView to make sure everything is working. Once it’s loaded, you should see the splash screen running at full screen on the device. One thing to note is that we are not locking the rotation in this simple demo, so make sure you are holding the phone in landscape. Here is the splash screen being rendered at full 720P resolution on the Fire phone:
As you can see, the process for installing and testing hosted web apps on Fire phone is straight forward. We’ll be using the Web App Tester and Fire phone for the remainder of our tutorial to make sure we can properly test the Dynamic Perspective APIs.
The good news is that the Dynamic Perspective APIs are built into the Amazon WebView we’ll be testing within the Web App Tester. That means that you don’t have to add in any extra JavaScript libraries to start using Dynamic Perspective in your own HTML5 apps and games, it’s ready for you right out of the box. Let’s get started:
Step 14. We are going to want to make some global variables to store the motion tracking data points we’ll be using in this example. At the very top of our project above where we declared our state object, add the following:
var dpX = 0; var dpY = 0; var faceDetected = false; var scale = 2;
Here we are going to store the x, y values for the Dynamic Perspective x and 7 axis, whether facial detection is working, and a scale factor to help us manipulate the raw data into something more manageable.
Step 15. Now at the very end of our create() function add the head tracking event listener:
addEventListener('amazonheadtracking', this.handleAmazonHeadTracking);
As you can see, we’ll be using a standard event listener to implement the Dynamic Perspective APIs in our web app.
Step 16. After our create() function, add the following:
handleAmazonHeadTracking: function(event){ dpX = event.x_mm/scale; dpY = event.y_mm/scale; faceDetected = event.isFaceDetected; },
This will save the head tracking position values into our global variables that we set up previously. You’ll also see that we are dividing it by our scale to reduce the value a little so we don’t see large x, y values shifts since the original artwork is being scaled up to 1280 x 720 from 854 x 480. Remember that the data returned is relative to the size of the phone’s renderable screen area - not your game - if it’s up-scaled like we are doing here. You may want to modify these factors by the games scale factor instead. Here I am simply dividing them in half.
Step 17. Now let’s calculate the new position we’ll use to apply to each of our layers. Add the following to the top of our update() function:
var newPositionY = Phaser.Math.clamp(dpX, -30, 30); var newPositionX = Phaser.Math.clamp(dpY, -30, 30); this.background.x = this.bgPos.x + newPositionX/5; this.background.y = this.bgPos.y + newPositionY/5;
Here we are using a method called clamp() which is part of the Phaer.Math lib. We supply our Dynamic Perspective x and y values along with a limit so it stays within the specified range. One thing to note is that since this splash screen is designed to run in landscape we need to swap the Head Tracking x and y values since they don’t change based on the phone’s orientation.
Now if you run the game on Fire phone and look at the device as well as move it around, you’ll see the background now subtly shifts in response to your head movement.
Step 18. Let’s add the same effect to our player. You’ll want to replace the current this.player.y line of code where we calculate the floating animation with the following:
this.player.x = this.playerStartPos.x + newPositionX; this.player.y = (this.playerStartPos.y / 2) + 8 * Math.cos(this.time.now / 200) + (20 + newPositionY);
Now we are modifying the player’s x position and adding the newPoistionY to the end of where we calculate the up and down value to create some additional movement along the Y position. You may also notice that we are not dividing the new x and y values by 5 like we did in the background. This allows us to give the layers a parallax effect so that the background will move at a slower rate.
Step 19. Run the scene again on Fire phone and you’ll see the final effect.
If you have previously published a web app to the Amazon Appstore, you can follow the same process. For those who are new to this, there are 3 easy steps after you have set up your free developer account and specified that you want to create a new app in the portal:
Step 1: Verifying Your Web App’s URL
You can now validate your web app’s URL right from the developer portal.
Simply put in the URL for your web app or game with the Fire phone code and click the verify button and the tool will let you know if the contents of the URL pass the preliminary submission requirements.
Step 2: Declaring Web App’s Permissions
Once your URL has been verified, you can select your app’s permission. Simply check off the options that apply to your app.
Step 3: Select Compatible Platforms
Then you can define which devices this web app can be published on.
While the Kindle Fire HD, HDX and Fire phone devices offer the best performance for web apps, make sure you test your web app on older devices to ensure the performance is ideal for your users. Intensive web games and anything using WebGL should be distributed on Kindle Fire HD and above.
While you can install web apps in the Amazon Appstore on any Android device that has the store installed, it will default to the native WebView on that device. This means that your app will not have access to the Dynamic Perspective APIs on other Android phones.
Step 4: Certification of Distribution Rights
Finally, certify that have the necessary rights to publish your web app.
As you can see, not only can you easily publish HTML5 apps and games alongside native Android apps through the Amazon Appstore, you also get access to the Fire’s Dynamic Perspective API just like native Android apps do. So be sure to submit your app to the Amazon Appstore to tap into millions of potential new customers.
Related links:
- Jesse Freeman (@jessefreeman)