May, 2012

  • DaveDev

    How to get the Windows 8 Camp presentations, code samples and hands on labs

    • 4 Comments

    Win8CampInABox

    Great news!  The Windows 8 Camp in a Box is now available for download.  It includes all of the presentations, code samples, and hands on labs I showed off during the Windows 8 Camps and NYC Windows 8 Developer Event.  The content is available in both XAML/C# and HTML/JavaScript versions.  

    If you have been looking for an opportunity to develop an application step by step this it!  Full source code and instructions are provided in both html and docx formats.  So print them out, pull up a chair, and code up the Contoso Cookbook sample at your own pace.

    Labs

    The Windows 8 Camps are still ongoing (across the globe!) too so if you haven’t attended one yet be sure to sign up or register for the upcoming MSDN Webcast Windows 8 Development series.  Once you are settled into coding your next masterpiece let me know about it so I can help you get a Windows Store token.

  • DaveDev

    Handling Fullscreen, Snapped and Filled states in Windows 8 Metro Style apps using CSS3 and JavaScript

    • 3 Comments

     

    Overview

    Attention – the code in this post has been updated to work with Windows 8 Release Preview.  To find out more details on migrating your app from CP to RP read my post here.

     

    In my last blog post I discussed the importance of supporting the numerous shapes and sizes Windows 8 devices will be in our Metro Style Apps.  This post will cover how to handle viewstate changes in our game which happens when the user runs our app side by side with another Metro Style App.

    Scaling to Different Screens

     

     

    The Guidelines for snapped and fill views define three states we will need to handle.  The first, full screen, is the default state for all Metro Style Apps.  When a user drags another window onto the screen they have the option of having it become the current running app, snapping the new app to the side, or running it filled.  In the case of a full screen app only one application would be visible so if the user dragged another app onto the screen our application would go into suspend mode after 10 seconds of inactivity (more on app lifecycle in another post).  If they snapped the app our game would go into filled mode.  If they snapped our game then the app they dragged over would move into snapped mode.

    Here are what the three different states look like:

    Viewstate

    In the below example my game is running full screen as a normal Metro Style App.

     

    Full screen

    FullScreen

     

    In the snap example I dragged over Internet Explorer onto the screen and was given a slider bar in between both apps.  By moving the slider over to the left I was able to have the game run in a small window and our browser in a larger window.  In this scenario our game will report a snapped Viewstate and Internet Explorer will report Filled.


    Snap

    Snapped

     

    If I wanted more screen space for my game I could drag the slider bar over to the right.  This would then send our game into a Filled state and our Internet Explorer window into a Snapped state. 

    Fill

    Filled

     

    It is important to point out I can also rearrange these windows by grabbing the snapped Internet Explorer window and moving it to the left.  This will automatically move our game filled window to the right.  Grabbing either window and moving it off of the bottom of the screen will return the remaining app to full screen mode.

     

    Detecting Viewstate changes

    The first thing we need to do is define how wide these new screen states will be.  The good news is that Snapped view will always be 320px in width which will make adjusting our game coordinate system much easier.  Filled state will always be the width of the screen minus 320px and snapped state will always be 320px wide.  Let’s go ahead and add a variable to handle the size of snapped view in our calculations.

    var SNAPPED_VIEW = 320;


    Next we need to set up the event handler for any Viewstate changes.  This is done via the ApplicationView class for the current view.  In the below example I am assigning the viewstatechanged event of the current application view to my own onViewStateChanged function. This got a lot simpler for the Windows 8 Release Preview.  We need only add an event listener to the window resize event like so:

    window.addEventListener("resize", onViewStateChanged);

     

    When onViewStateChanged runs it enumerates through all available viewstates and passes the current view state to a custom function I call showMenu.

    function onViewStateChanged(eventArgs) {
            var viewStates = Windows.UI.ViewManagement.ApplicationViewState, msg;
            var newViewState = Windows.UI.ViewManagement.ApplicationView.value;
            if (newViewState === viewStates.snapped) {
                showMenu('snapped');
            } else if (newViewState === viewStates.filled) {
                showMenu('filled');
            } else if (newViewState === viewStates.fullScreenLandscape) {
                showMenu('landscape');
            } else if (newViewState === viewStates.fullScreenPortrait) {
                //Currently not supported
            }
            
        }

     

    Handling layout changes

    showMenu is the same function I call when my game is first loaded or the user clicks on the AppBar to return to the menu.  This will pause the game for our user when they are dragging in another app to work with.  They can then continue game play when they are ready.  The full updated showMenu function is as follows:

    //Set Up Menu Screen UI Elements
     function showMenu(event) {
         menuEnabled = true;
     
         txtPlayerName.style.visibility = "hidden";
         txtScore.style.visibility = "hidden";
         imgPlayer.style.visibility = "hidden";
         imgMenu.style.visibility = "visible";
         btnStart.style.visibility = "visible";
         txtVersion.innerHTML = GAME_VERSION;
         txtVersion.style.visibility = "visible";
         txtLevel.style.visibility = "hidden";
     
         //Detect View State
         if (event === 'snapped') {
             canvas.width = SNAPPED_VIEW;
         }
         else if (event === 'filled') {
             canvas.width = FULLSCREEN_WIDTH - SNAPPED_VIEW;
         }
         else {
             canvas.width = FULLSCREEN_WIDTH;
         }
         //Readjust canvas for Snapped/Filled modes
         canvas.height = window.innerHeight;
         SCREEN_HEIGHT = canvas.height;
         SCREEN_WIDTH = canvas.width;
     
         //Set boundries to be one ship size
         MAX_X = canvas.width - (SHIP_WIDTH + 20);
         MAX_Y = canvas.height - (SHIP_HEIGHT + 50);
         
     
         var menuX, btnX, btnY;
         menuX = (SCREEN_WIDTH - imgMenu.width) / 2;
         btnX = (SCREEN_WIDTH - btnStart.clientWidth) / 2;
         btnY = (SCREEN_HEIGHT - btnStart.clientHeight) / 2;
     
         imgMenu.style.posLeft = menuX;
         btnStart.style.posLeft = btnX;
         btnStart.style.posTop = btnY;
     
         //clear screen
         ctx.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
     
         musicGame.pause();
         musicMenu.play();
      
     }

     

    Specifically this function changes the width of our game screen and then re-calculates the size of the screen so that our ships will disappear when they hit the edge.  This is done by grabbing the width of the current screen and then calculating in SNAPPED_VIEW.

    //Detect View State
    if (event === 'snapped') {
        canvas.width = SNAPPED_VIEW;
    }
    else if (event === 'filled') {
        canvas.width = FULLSCREEN_WIDTH - SNAPPED_VIEW;
    }
    else {
        canvas.width = FULLSCREEN_WIDTH;
    }
    //Readjust canvas for Snapped/Filled modes
    canvas.height = window.innerHeight;
    SCREEN_HEIGHT = canvas.height;
    SCREEN_WIDTH = canvas.width;

     

    Now that we are properly handling viewstate changes and adjusted our coordinate system correctly we need to update our game user interface.  All Metro Style Apps will have predefined layouts for their viewstates thanks to CSS3 Media Queries.  If you haven’t worked with CSS3 Media Queries much before I highly recommend Responsive Web Design by Ethan Marcotte.  He takes you through designing a website application that adapts its screen layout based on different screen sizes and device form factors.  

    The default Metro Style App templates automatically do this for us by seting up media queries inside the default.css file.  This is where you can adjust layout for all viewstates as well as portrait and landscape.

    @media screen and (-ms-view-state: fullscreen-landscape) {
    }
     
    @media screen and (-ms-view-state: filled) {
    }
     
    @media screen and (-ms-view-state: snapped) {
        #imgMenu {
            -ms-transform: translate(0px, 0px) rotate(0deg) scale(0.50);
        }
        
        #btnStart {
            -ms-transform: translate(0px, 0px) rotate(0deg) scale(0.60);
        }
        
        #txtNewLevel {
            -ms-transform: translate(0px, 0px) rotate(0deg) scale(0.30);
        }
     
        #imgPlayer {
            opacity: 0;
        }
     
        #txtLevel {
            -ms-transform: translate(-120px, 0px) rotate(0deg) scale(0.30);
        }
     
        #txtPlayerName {
            -ms-transform: translate(70px, 0px) rotate(0deg) scale(0.30);
        }
     
        #txtScore {
            -ms-transform: translate(0px, 0px) rotate(0deg) scale(0.30);
        }
          
    }
     
    @media screen and (-ms-view-state: fullscreen-portrait) {
    }

     

    Due to Filled viewstate only shrinking by 320px I found all of my on screen elements to look fine as is. 

    Snapped mode presented some challenges as I needed to shrink both the gamescore, player name, and level texts.  A lot of what you will do here is through trial and error.  I kept tweaking the scale until it “felt right.”  I chose to use CSS3 2D Transforms to scale out the text so that it filled the screen correctly at the same time remaining readable.  I chose to drop the player image when in this mode as it became too small to be of any value.  Here is a screenshot of the new snapped user interface layout while the game is being played.

    Snapped

    You will notice I kept the sizes of the ships the same.  I am currently debating whether I should scale them down or change the direction of the ships to vertical.  This would almost give a different game experience when in snapped mode.  That is the beauty of CSS3 Media Queries in action as we can completely change what elements look like based on the screen size.

     

    Conclusion

    I hope this post has given you an idea of how easy it is to handle Viewstate changes in your Metro Style App using CSS3 and JavaScript.  If you are currently working on a Windows 8 app and want to get into the Windows Store I would love to hear about it!

    You may also want to check out my previous Windows 8 Metro Style Development Tips:

  • DaveDev

    Connecting to WCF RIA Services in a Windows 8 Metro Style App using Upshot.js and Knockout.js

    • 2 Comments

    Overview

    After messing around with KnockoutJS inside of Metro Style Apps I decided to dive a little deeper and see what Single Page Applications (particularly Upshot.js) could offer.  I’ve gotten asked by more than a few developers how best to connect to their existing WCF RIA Services inside of Metro Style Apps.  The approach I took here is one possible solution to help get your started.

    UpshotOverview

     

    For those not familiar with Upshot it is a JavaScript Library that allows you to connect to WCF RIA Services.  It is by the same great wizards who wrote ASP.NET MVC4 Single Page Applications. and included already in Single Page App templates! 

    I also came across two really great posts you should check out that helped me get my head around things:

    Upshot.js & Knockout.js: The HTML5 Client for WCF RIA Services

    Building Single Page Apps with ASP.NET MVC4 - Part 1 - Basic Desktop Application

    If you just want to grab the MVC4 and Windows 8 Metro Style App source code you can download them here:

    DownloadExample

     

    Setting up the MVC 4 Environment

    In order to get the MVC4 Single Page Application Templates I downloaded and installed Visual Studio 2011 Beta Ultimate (currently freely available here).  I am running everything local: MVC4 Website is using IIS Express and the data is stored in SQL Server 2008 R2 Express( the one that comes with the Web Platform Installer).  The code that I used was based of a great sample Bart Jolling wrote on his blog here

    The example is a simple Deliverytracker SIngle Page Application that looks like this:

    SPA-MVC4 

    To  keep things simple I am running everything local with integrated security on IIS Express and SQL Server Express.
     
    Also take note of our DomainModel as we will need to manually set up MetaData for this later.
    public class Customer
    {
        public int CustomerId { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
    }
     
    public class Delivery
    {
        public int DeliveryId { get; set; }
        public virtual int CustomerId { get; set; }
        public virtual Customer Customer { get; set; }
     
        public string Description { get; set; }
        public bool IsDelivered { get; set; }
    }

     

    Setting up the Metro Style App to use Upshot.js

    I then created a new JavaScript based Metro Style App like usual and selected the Tools – > Library Package Manager – > Manage NuGet Packages for Solution menu and searched for UpShot.

    GrabUpshot

    This will bring down all the required scripts you need for using Upshot.js in your application.

    InstalledScripts

    Because the package installer assumes we are inside of an MVC application it will write everything into a new /scripts folder.  For simplicity sake I removed the /scripts folder and copied all of the JavaScript files into our existing /js folder.

     

    Declaration and Initialization

    We now reference these new JavaScript Libraries like usual inside of our default.html.

    <script type="text/javascript" src="js/jquery-1.6.4.js"></script>
    <script type="text/javascript" src="js/knockout.debug.js"></script>
    <script type="text/javascript" src="js/knockout.js"></script>
    <script type="text/javascript" src="js/DeliveriesViewModel.js"></script>
    <script type="text/javascript" src="js/upshot.js"></script>
    <script type="text/javascript" src="js/upshot.compat.knockout.js"></script>
    <script type="text/javascript" src="js/upshot.knockout.extensions.js"></script>
    <script type="text/javascript" src="js/arrayUtils.js"></script>

    There are two additional scripts here arrayUtils.js and DeliveriesViewModel.js that I copied over from the MVC4 Single Page Application DeliveryTracker example  mentioned previously.  arrayUtils is a helper function we can leave as is and DeliveriesViewModel will be how we wire up to our service. 

    The next step was to take the code from our MVC4 app’s Home View located in /Views/Home/Index.cshtml and move it into our Metro Style App.

    <section>
    <div>
        <h3>Deliveries</h3>
     
        <button data-bind="click: saveAll">Save All</button>
        <button data-bind="click: revertAll">Revert All</button>
     
        <label>
            <input data-bind="checked: excludeDelivered" type="checkbox" />
             Exclude delivered items</label>
     
        <ol data-bind="foreach: deliveries">
            <li data-bind="css: { delivered: IsDelivered, 
                                            updated: IsUpdated}">
                <strong data-bind="text: Description"></strong>
                is for <em data-bind="text: Customer().Name"></em>
                <label><input data-bind="checked: IsDelivered"
                      type="checkbox"/>Delivered</label>
            </li>
        </ol>
     
        <h3>Customers</h3>
        <ul data-bind="foreach: deliveriesForCustomer">
            <li>
                <div>Name: <strong data-bind="text: key.Name"></strong>
                </div>
                <ul data-bind="foreach: values">
                    <li data-bind="text: Description, 
                        css: { delivered: IsDelivered,
                                 updated: IsUpdated}">                
                    </li>
                </ul>
            </li>    
        </ul>
    </div>
    </section>

     

    All of this gets done inside our default.html:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>UpshotWin8</title>
     
        <!-- WinJS references -->
        <link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet">
        <script src="//Microsoft.WinJS.0.6/js/base.js"></script>
     1:  
     2:     <script src="//Microsoft.WinJS.0.6/js/ui.js">
     1: </script>
     2:  
     3:     <script type="text/javascript" src="js/jquery-1.6.4.js">
     1: </script>
     2:     <script type="text/javascript" src="js/knockout.debug.js">
     1: </script>
     2:     <script type="text/javascript" src="js/knockout.js">
     1: </script>
     2:     <script type="text/javascript" src="js/DeliveriesViewModel.js">
     1: </script>
     2:     <script type="text/javascript" src="js/upshot.js">
     1: </script>
     2:     <script type="text/javascript" src="js/upshot.compat.knockout.js">
     1: </script>
     2:     <script type="text/javascript" src="js/upshot.knockout.extensions.js">
     1: </script>
     2:     <script type="text/javascript" src="js/arrayUtils.js">
     1: </script>
     2:  
     3:  
     4:     <!-- UpshotWin8 references -->
     5:     <link href="/css/default.css" rel="stylesheet">
     6:     <script src="/js/default.js">
    </script>
     
     
    </head>
    <body>
     
    <div >
        <h3>Deliveries</h3>
     
        <button data-bind="click: saveAll">Save All</button>
        <button data-bind="click: revertAll">Revert All</button>
     
        <label>
            <input data-bind="checked: excludeDelivered" type="checkbox" />
             Exclude delivered items</label>
     
        <ol data-bind="foreach: deliveries">
            <li data-bind="css: { delivered: IsDelivered, 
                                            updated: IsUpdated}">
                <strong data-bind="text: Description"></strong>
                is for <em data-bind="text: Customer().Name"></em>
                <label><input data-bind="checked: IsDelivered"
                      type="checkbox"/>Delivered</label>
            </li>
        </ol>
     
        <h3>Customers</h3>
        <ul data-bind="foreach: deliveriesForCustomer">
            <li>
                <div>Name: <strong data-bind="text: key.Name"></strong>
                </div>
                <ul data-bind="foreach: values">
                    <li data-bind="text: Description, 
                        css: { delivered: IsDelivered,
                                 updated: IsUpdated}">                
                    </li>
                </ul>
            </li>    
        </ul>
    </div>
     
    </body>
    </html>

     

    Once we have our view code wired up we now need to call out to the service and databind everything.  Just like my previous KnockoutJS examples I wire up everything after the DomContentLoaded Event has fired using a custom function called initialize.

    document.addEventListener("DOMContentLoaded", initialize);


    Initialize will then tell our app about the fields returned by our Domain Service.  In order to do this we need to call the upshot.metadata function and map values manually based on their original DomainModel source types.  The basic formatting used here is Classname#Namespace.  Once you get your head around that it’s pretty easy to map everything (although laborious).  I also set the key to be based of DeliveryID.  

    After our mapping are set we’ll tell KnockoutJS to bind everything using the provided DeliveriesViewModel function.

    function initialize() {
          
     
        upshot.metadata({
            "Delivery:#DeliveryTracker.Models": {
                "key": ["DeliveryId"],
                "fields": {
                    "DeliveryId": { "type": "Int32:#System" },
                    "CustomerId": { "type": "Int32:#System" },
                    "Customer": { "type": "Customer#DeliveryTrack.Models" },
                    "Description": { "type": "String:#System" },
                    "isDelivered": { "type": "Int32:#System" }
                }
            }
        });
     
        ko.applyBindings( new DeliveriesViewModel( ));
     
    }

     

    The last step now is to edit our DeliveriesViewModel.js file with the location of our Domain Service.  This will be different for everyone but on my local machine the service runs at http://localhost:61907//api/DataService.

    function DeliveriesViewModel() {
        // Private
     
        var dataSourceOptions = {
            providerParameters: {
                url: "http://localhost:61907//api/DataService",
                operationName: "GetDeliveriesForToday"
            },
            entityType: "Delivery:#DeliveryTracker.Models",
            bufferChanges: true,
            mapping: Delivery
        };
     
        // Public Properties
        this.dataSource = new upshot.RemoteDataSource(dataSourceOptions).refresh();
        this.localDataSource = upshot.LocalDataSource({ source: this.dataSource,
            autoRefresh: true
        });
     
        this.deliveries = this.localDataSource.getEntities();
        this.deliveriesForCustomer = this.deliveries.groupBy("Customer");
        this.excludeDelivered = ko.observable(false);
     
        // Operations
        this.saveAll = function () { this.dataSource.commitChanges() }
        this.revertAll = function () { this.dataSource.revertChanges() }
     
        // Delegates
        this.excludeDelivered.subscribe(function (shouldExcludeDelivered) {
            var filterRule = shouldExcludeDelivered
                ? { property: "IsDelivered", operation: "==", value: false }
                : null;
            this.localDataSource.setFilter(filterRule);
            this.localDataSource.refresh();
        });
    }
     
    function Customer (data) {
     
        this.CustomerId = ko.observable(data.CustomerId);
        this.Name = ko.observable(data.Name);
        this.Address = ko.observable(data.Address);
        upshot.addEntityProperties(this, "Customer:#DeliveryTracker.Models");
    }
     
    function Delivery (data) {
      
     
        this.DeliveryId = ko.observable(data.DeliveryId);
        this.CustomerId = ko.observable(data.CustomerId);
        this.Customer = ko.observable(data.Customer);
        this.Description = ko.observable(data.Description);
        this.IsDelivered = ko.observable(data.IsDelivered);
        upshot.addEntityProperties(this, "Delivery:#DeliveryTracker.Models");
    }

     

    Other than the service location I did not need to modify the function in any way from the original MVC4 DeliveryTracker example.

    We now have the Metro Style App binding to the same Domain Service and being fully interactive. 

    RunningMetroApp

     

     

    Conclusion

    Obviously we would need to style the application to make it feel like a native Metro Style App but the hard plumbing work has been done.  We were able to keep a majority of the MVC4 code, from both the views and the model, to get us started with our Windows 8 Metro Style App! 

     

    If you are currently working on a Windows 8 app I would love to hear about it.  You may also want to check out my previous Windows 8 Metro Style Development Tips:

  • DaveDev

    Defining Layout in a Windows 8 Metro Style App using CSS3, HTML and JavaScript

    • 2 Comments

    Overview

    I have been coding a Windows 8 Metro Style App using the new Windows 8 Release Preview bits and Visual Studio Express 2012 RC.  The app is going to be a retro shooter that takes advantage of HTML5 Canvas for the main game engine along with several Windows 8 Metro Style App Features.  This post is going to cover how to layout the elements of your game interface on the screen. 

    My game’s Layout is made up of two screens: a Main Menu (which is the default screen upon loading for first time) and then an actual Game Screen where gameplay takes place.  I used CSS3 (specifically floats) to align my Player Score, Name, Level and other screen elementals.  Let’s dive into how each screen is set up.


    Main Menu

    The Main Menu displays current game version number, game title and a button to begin game play.  It also includes an AppBar Menu (not shown in the screenshots below) that can be accessed at any time.  Here is what the Main Menu looks like:

     

    FullScreen 

    Filled

    Snapped

    You will notice that I am playing the game along side another application (IE 10) like some of my players will most likely do.  The screen can be rendered in three different states based which are named fullscreen, filled or snapped mode.  I want to point out that having your application support multiple screen sizes and Viewstates is a very important feature of all Metro Style Apps.  If you haven't already read it definitely check out the Scaling to Different Screens post on the official Windows 8 Blog.

    Windows8Devices

     

    Since this is such an important topic broke out this topic into two posts.  We will cover layout in this post and how to detect and scale for the different Viewstates here.  In the interest of simplicity this post will concentrate on just getting the elements lined up in the fullscreen mode (the default for all Metro Style Apps).  Let’s take a look at how we do that:  

    Inside of my default.html page we see that the title image, game version and play button are just standard html elements wrapped inside a <Div> tag I call divMenu.

    <div id="divMenu">
            <img id="imgMenu" src="/images/menutitle.png" />
            <div id="txtVersion"></div>
            <button id="btnStart">PLAY</button>
     <div>


    All of our custom layout occurs in a css file called space.css we reference in our default.html like so:

    <!-- App references -->
    <link href="/css/default.css" rel="stylesheet">
    <link href="/css/space.css" rel="stylesheet"/>
    <script src="/js/default.js"></script>
    <script src="/js/sound.js"></script>
    <script src="/js/ship.js"></script>
    <script src="/js/starField.js"></script>

     

    Thanks to CSS3 Web Fonts we can easily assign different type faces to our screen elements.  For my game I downloaded the Final Frontier Old Style font a royalty free font available off the web.  I then tell both the version text and button text to use this font.  Each of the elements I assign the maximum width and height I would like along with the text font size.  imgMenu is also told to be aligned 120px down from the top of the screen.

    @font-face {
        font-family: 'Final Frontier Old Style'; 
        src: url( '/fonts/finalold.ttf');
    }
     
    #imgMenu {
        position:absolute;
        max-width: 555px; 
        max-height: 118px; 
        top: 120px;
    }
     
    #txtVersion {
        position:absolute;
        bottom:0;
        right:0;
        font-family: 'Final Frontier Old Style'; 
        font-size: 20px;
        color: #ffd800;
    }
     
    #btnStart {
        position:absolute;
        width: 300px;
        height: 150px;
        font-family: 'Final Frontier Old Style'; 
        font-size: 30px;  
        z-index: 100;
    }
     

     

    Remembering that Windows 8 devices come in all different shapes and sizes I programmatically set the  menu elements up on the center of the screen at runtime.  This happens in the showMenu function inside my default.js file.  I calculate the exact center of the screen and then set the x and y coordinates of my elements like you see below.

    //Set Up Menu Screen UI Elements
    function showMenu(event) {
        menuEnabled = true;
     
        txtPlayerName.style.visibility = "hidden";
        txtScore.style.visibility = "hidden";
        imgPlayer.style.visibility = "hidden";
        imgMenu.style.visibility = "visible";
        btnStart.style.visibility = "visible";
        txtVersion.innerHTML = GAME_VERSION;
        txtVersion.style.visibility = "visible";
        txtLevel.style.visibility = "hidden";
        
     
        var menuX, btnX, btnY;
        menuX = (SCREEN_WIDTH - imgMenu.width) / 2;
        btnX = (SCREEN_WIDTH - btnStart.clientWidth) / 2;
        btnY = (SCREEN_HEIGHT - btnStart.clientHeight) / 2;
     
        imgMenu.style.posLeft = menuX;
        btnStart.style.posLeft = btnX;
        btnStart.style.posTop = btnY;
     
        musicGame.pause();
        musicMenu.play();
     
    }

     

    Game Screen

    The Game Screen  displays the player’s score, level, name and picture.  This is also where we are declaring our HTML5 Canvas tag.  Similarly to the Main Menu screen it can appear in all three Viewstates but we will focus on the Fullscreen mode for this post.

    Fullscreen

    Filled

    Snapped

     

    All of these elements (except for the player image) are standard <div> tags wrapped inside a main <div> tag we call divGame  inside of our space.css file.

    <div id="divGame">
            <div id="txtScore">Score: 0</div>    
            <div id="txtLevel">Level: 0</div>
            <div id="divPlayer">
                 <div id="txtPlayerName">Player1</div>
                 <img id="imgPlayer" src="/images/helmet.png" />
             </div>
    <div>  
     
    <div id="txtNewLevel"></div>
     
    <div id="divRoot" data-win-control="WinJS.UI.ViewBox">
        <canvas id="canvas" ></canvas>
    </div>
     

     

    Just like the Main Menu we assign the custom Font to our text elements and position them on screen using floats. 

    @font-face {
        font-family: 'Final Frontier Old Style'; 
        src: url( '/fonts/finalold.ttf');
    }
     
    #txtScore {
        font-family: 'Final Frontier Old Style';
        font-size: 50px;
        color: #ffd800;
        text-align: left;
        margin-left: 10px;
    }
     
    #txtPlayerName {
        font-family: 'Final Frontier Old Style'; 
        font-size: 50px;
        color: #ffd800;
        float:left;
        margin-right:20px;
    }
     
    #txtLevel {
        font-family: 'Final Frontier Old Style'; 
        font-size: 50px;
        color: #ffd800;
        position:absolute;
        top: 0;
    }
     
    #divPlayer {
        position: absolute; 
        top: 0; 
        right: 0; 
        text-align:right;
    }
     
    #imgPlayer {
        max-width: 100px; 
        max-height: 50px;
        float:left;
        margin-right:10px;
    }
     
    #txtNewLevel {
        position:absolute;
        font-family: 'Final Frontier Old Style'; 
        font-size: 100px;
        visibility: hidden;
    }

     

    Finally we set up all of our on screen elements through the startGame function once the player clicks on the Play button to begin.  

    //Set up Game Screen UI Elements
     function startGame(event) {
         txtPlayerName.style.visibility="visible";
         txtScore.style.visibility="visible";
         imgPlayer.style.visibility = "visible";
         imgMenu.style.visibility = "hidden";
         btnStart.style.visibility = "hidden";
         txtVersion.style.visibility = "hidden";
         txtLevel.style.visibility = "visible";
     
         var lvlX = (SCREEN_WIDTH - txtLevel.clientWidth) / 2;
         txtLevel.style.posLeft = lvlX;
     
         musicMenu.pause();
         musicGame.play();
     
         menuEnabled = false;
         
     }

     

    Game Coordinate System

    The last piece we need to set up is a coordinate system for our game.  This includes the size of each ship, the area of the screen they can be drawn on before appearing on the opposite side, and then the current width and height of the screen.  The screen width and height will determine how big our Canvas element needs to be rendered at as well.

    I use four different variables inside the default.js file for this with the ships width and height remaining constant (I created all of my ship images to be this size) and then the screen width and height to change based on the resolution of our current Windows 8 device.

    var SCREEN_WIDTH = 1366;
    var SCREEN_HEIGHT = 768;
    var SHIP_WIDTH = 190;
    var SHIP_HEIGHT = 100;

     

    We then calculate what the size of our canvas should be during our initialize function:

    //Init Canvas
    canvas = document.getElementById("canvas");
    ctx = canvas.getContext("2d");
     
    //Set up Coordinates for Screen Size
    //Adjust for different screen sizes
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    SCREEN_HEIGHT = canvas.height;
    SCREEN_WIDTH = canvas.width;
     
    //Set boundries to be one ship size
    MAX_X = canvas.width - (SHIP_WIDTH + 20);
    MAX_Y = canvas.height - (SHIP_HEIGHT + 50);

     

    By setting up the coordinate system at run time we can support multiple resolutions and even dynamically scale to fit higher resolutions if the user changes them (for example docking a tablet and attaching a bigger monitor).  Here is an example of our game running on a 1366x768 tablet size screen as well as a 2560x1440 which you would typically see in a 27” inch all in one pc.

    1366x768

    2560x1440 

    All of the elements align directly center with the version showing up in the bottom right.  I also have the ability to scale up the image and button size when in a different resolution.  I am not doing that in the screen shot above but will show you how using CSS3 transforms in my next post covering Viewstates.

     

    Conclusion

    I hope this post has given you an idea of how easy it is to lay out interface elements in your Metro Style App using CSS3, HTML5 and JavaScript.  If you are currently working on a Windows 8 app and want to get into the Windows Store I would love to hear about it!

    You may also want to check out my previous Windows 8 Metro Style Development Tips:

Page 1 of 4 (14 items) 1234