Game On! With HTML5
AUTHD on oreilly.com
How a Game Works Time Passed Frame 1 Frame 2 Frame 3Frame 4
The Canvas Element
DOM Structure # container # game_canvas # snowball_btn DOM Structure
DOM – Code Example
Resize with { width: device-width; height: device-height; } screen and (orientation: portrait) { width: 768px; height: 1366px; } /* CSS for portrait layout goes here */ }
Initialize, Update, Draw pattern All systems in the game have an Initialize, Update, and Draw method: Initialize, Update, Draw pattern
Drawing the Snowball to the canvas. canvascontext.drawImage( image, //image (‘snowball.png’); 0, 0, //source position 256, 261, //source size 50, 100, //destination position(canvas) 256, 261); //destination size 256px 261px 50px 100px 256px 261px Source Drawing Images to a Canvas Example
Keyboard Input Animation Logic Inputs Entities Collision Building Blocks
Entities
Update Collision Not colliding.Colliding.
var audiosample = new Audio("media/Sounds/path.mp3"); audiosample.play(); Sound
Only Draw what you Need: Any call to the canvas draw is expensive. The best way to optimize drawing is to draw less. Hikers are composited with their custom face image to make only one draw call instead of two. The sky is just applied to the background-img property because it is static. Re-use Objects: Re-using objects instead of deleting them minimizes calls to the garbage collector. Pass only integers to the canvas draw API: Floats cause anti-aliasing to trigger. Performance
Watch out for Audio: Audio tags take up memory that could be used for gameplay Read as little as possible, and never read from the same canvas Using image data is much faster than drawing Test, test, test: Test on many devices with different processors (don’t forget about Atom and ARM) test, test, test: Really, test at every stage! Performance
demo
Page Structure
Navigation Project Template
WinJS
WinJS.Utilities.query("a").listen("click", function (evt) { // dont load this link in the main window evt.preventDefault(); // get target element var link = evt.target; //call navigate and pass the href of the link WinJS.Navigation.navigate(link.href); }); Overriding Link Behavior
WinJS.UI.Pages.define WinJS.UI.Pages.define("/home.html", { // This function is called whenever a user navigates to this page. ready: function (element, options) { //run code unique to this page } }); WinJS.UI.Pages.define
Data Binding with WinJS.Binding.List var hikerArray = [{ title: 'John Smith', color:'#333333', body_img:'/images/body_ png', face_img:'/images/default_face.png', }, { title: 'Erin Dodge', color:'#00c0ac', body_img: '/images/body_00c0ac.png', face_img:'/images/default_face.png', }, { title: 'James Parker', … } ]; var hikerBindingList = new WinJS.Binding.List(hikerArr); Data Binding with WinJS.Binding.List
WinJS.Namespace.define var publicMembers = { itemList: hikerBindingList }; WinJS.Namespace.define("DataHikers", publicMembers); WinJS.Namespace.define
WinJS.UI.ListView
<div id="hikerListView" data-win- control="WinJS.UI.ListView" data-win-options="{ itemDataSource: DataHikers.itemList.dataSource, itemTemplate: select(‘#hikersTemplate’) }“ > WinJS.UI.ListView
Define the template Define the Template
WinJS.UI.processAll(); Define the template Define the Template
WinJS.UI.AppBar WinJS.UI.AppBar
Adding commands to the AppBar Adding Commands to the AppBar
Command options Command Options
Adding Functionality // get add command element var cmdAdd = document.getElementById('cmdAdd'); cmdAdd.addEventListener('click', function (ev) { // respond to add hiker command }); Adding Functionality
The Accelerometer accelerometer.addEventListener("readingchanged", function(evt){ // handle change });
When the Application loads, we need to setup the accelerometer device. This is done in the app.onactivated event. The report interval specifies in milliseconds how often the device will update the accelerometer data. accelerometer = Windows.Devices.Sensors.Accelerometer.getDefault(); if (accelerometer !== null) { //accelerometer available on device // Establish the report interval var minimumReportInterval = accelerometer.minimumReportInterval; var reportInterval = minimumReportInterval > 16 ? minimumReportInterval : 16; accelerometer.reportInterval = reportInterval; } Accelerometer Setup
Displaying Snapped View #snappedview { display:none; screen and (-ms-view-state: snapped) { #contentHost {/*hide main content*/ display:none; } #snappedview {/*show snapped view content*/ display:block; }
var viewStates = Windows.UI.ViewManagement.ApplicationViewState; var newViewState = Windows.UI.ViewManagement.ApplicationView.value; if (newViewState === viewStates.snapped) {... //Application is in snapped view }; Custom Logic for Snapview
var userInformation = Windows.System.UserProfile.UserInformation; var userPic = userInformation.getAccountPicture(); var img = new Image(); var imgurl = URL.createObjectURL(userPic); img.src = imgurl; Getting User Profile Data
The contact picker launches a UI that will return a single contact. Using ContactPicker
// get reference to ContactPicker var picker = Windows.ApplicationModel.Contacts.ContactPicker(); // open the picker picker.pickSingleContactAsync().then(function (contact) { // handle contact information }); Open the contact picker and handle the result
Getting contact thumbnails contact.getThumbnailAsync().done(function (thumbnail) { // generate a URL for the thumbnail image thumbURL = URL.createObjectURL(thumbnail); // use thumbURL to update the src of an image for // display face_img.src = thumbURL; }); Getting contact thumbnails
Download the Microsoft Ad SDK: <div id="ad_bottom_rail“ data-win-control="MicrosoftNSJS.Advertising.AdControl" data-win-options="{applicationId: 'd25517cb-12d bdc-52040c712cab', adUnitId: ' '}"> Implementing Ads using the Microsoft SDK
var notifications = Windows.UI.Notifications; var template = notifications.TileTemplateType.tileWideSmallImageAndText02; var tileXml = notifications.TileUpdateManager.getTemplateContent(template); var line1 = tileXml.getElementsByTagName("text")[0]; line1.appendChild(tileXml.createTextNode(“Yeti Stats")); Live Tile
var tileNotification = new notifications.TileNotification(tileXml); notifications.TileUpdateManager.createTileUpdaterForApplication().update(tileNotification); Creating a Notification