Porting Impact Games to
Windows 8

As you can see from the activity on my blog and twitter feed I have settled nicely into my new job at Microsoft and am starting to produce lots of content around building HTML5 game for Windows 8. A big part of this content is going to revolve around all the work I have been doing on ImpactJS and making sure my existing games run well on Windows 8. I have also been doing these workshops and have my book out so there is a wealth of content I have on making Impact games but not very much on getting them to run on Windows 8. I actually did a post when I first started playing around with HTML5 Win8 games but figured I should do a proper tutorial on getting the demo game I wrote for my Impact book up and running on Windows 8.

After joining Microsoft, I went back and cleaned up my slides from my HTML5 gaming talk and my HTML5 Impact Workshop. Before we dig into how to port over an Impact game I thought it would good to share this new material with you. Also make sure you check out my events page to learn more about talks I’ll be giving on HTML5 games, HTML5 games on Windows 8 and new workshops. I’ll be speaking at Web Unleashed in Boston in November covering a 2 part workshop on building a game with Impact and then how to port it over to Window 8. I will also be updating my book with a new chapter covering the following tutorial in more detail as well as how to publish your game to the Windows Store along with optimization tips to help keep your game running at the highest possible frame rate.

So if you are new to Impact, check out these slides to learn more about the framework or pick up a copy of my book.

Now let’s check out how to port an Impact game over to Windows 8. In my Impact book, I walk you through how to create a simple game called Resident Raver. It’s a basic side scroller with zombies and does a great job of showing off how to actually build a full game with Start Screen, multiple levels, monsters, and a game over screen. It’s important to highlight that you will need a copy of Impact in order to get the game running which you can buy here. Once you have Impact, you can get the source code for Resident Raver, along with all the code from my book here. The following tutorial assumes that you have already been able to run Resident Raver in the browser and are ready to port it over to Windows 8. You will also need a copy of Visual Studio Express which is free and once you are ready to publish your game you will need a Windows Store developer account which is only $50. Let’s get started!

Once you have Visual Studio installed and all of the source code running, you will need to create a new project. As you can see I have called my project ResidentRaverWin8 and I am actually putting it into my kyDrive directory. You may remember that I was previously using DropBox for all my development but have decided to dogfood SkyDrive and haven’t had sa single problem over the last 2 months.

Once you have the new project setup, copy over lib, media, index.html and weltmeister.html to the VS project folder. We actually don’t need the tools directory since we will not be “baking” the game when we publish it.

In Visual Studio select Show All Files in Solution Explorer. This part always trips me up. Visual Studio needs to manage references to your files so you have to explicitly add them to the project or they will be ignored.

Select lib, media and index.html then right click and add them to the project.

Open up the package.appmanifest file and change the Start page to index.html. Also select landscape and set the background colors to black.

If you compile the app, by clicking on the green arrow next to Local Machine, you will see your game run. It may take a long time for the Impact game to fully load depending on the amount of artwork you have to upscale. Remember that the scale factor of your game determines if Impact will resample the artwork when it loads up. I’ll talk more about optimization in a future post.

Now we need to add the following into our index.html head tag just above the two script tags that load up impact.js and main.js:

<!-- WinJS references -->
<link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.1.0/js/base.js"></script>
<script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
 
<!-- ResidentRaverWin8 references -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/default.js"></script>

This will include the core WinJS library, add some CSS and link up the default.js which we will use in order to correctly load the game up during the Win8 application life cycle. Now with the default.css file included we can copy over our css at the top of the index.html file and override the default values. Make sure you also delete the css we copy over from the index.html.

Now we need to modify the way our game starts up. First, open up default.js and where it says

// your application here.

Replace with the following line of code

ig.startNewGame();

Next we will need to modify our main.js file. Open it up and let’s change the constructor from:

ig.main( '#canvas', StartScreen, 60, 320, 240, 2 );
To the following:
var scale = 5;
var maxWidth = (window.innerWidth > 1366) ? 1366 : window.innerWidth;
var maxHeight = (window.innerHeight > 786) ? 786 : window.innerHeight;
var width = Math.floor(maxWidth / scale) - 1;
var height = Math.floor(maxHeight / scale) - 1;
 
ig.startNewGame = function () { ig.main('#canvas', StartScreen, 60, width, height, scale, ig.ImpactSplashLoader); };

This will make sure that when the games starts, it is set to the correct resolution. As you can see, we determine the maximum width and height by looking at the inner width and height values to determine if the display will fit within 1366 x 786 which is the default resolution for Win8 devices. If your game needs to maintain a different aspect ratio then you should modify these values. Resident Raver will automatically center the camera so it will fill the display. The one thing we don’t want to do though is allow the game to grow beyond 1366×786 so we don’t jeopardize performance. Imagine if this game was to upscale itself to a 27” monitor, that could be problematic.

Now that the game correctly scales and is playable, we need to add support for touch controls. In our main.js file add the following code before the game constructor:

ig.Input.inject({
bindTouch: function (selector, action) {
       	var element = ig.$(selector);
 
       	var that = this;
       	element.addEventListener('MSPointerDown', function (ev) {
       	that.touchStart(ev, action);
              }, false);
 
              element.addEventListener('MSPointerUp', function (ev) {
                 that.touchEnd(ev, action);
              }, false);
      },
})

This will patch Impact’s touch class to support MSPointer events for touch, mouse and even pen support. We can also remove the following code from the main.js since it is no longer needed and was a hack to Impact from crashing on browsers that don’t support the audio tag such as Safari on iOS and Chrome on Android.

if( ig.ua.mobile ) {
    // Disable sound for all mobile devices
    ig.Sound.enabled = false;
}

Now we need to add some basic touch controls. Open up the default.css file and add the following:

#controls
{
    height: 96px;
    margin-top: -100px;
    position: relative;
    overflow: hidden;
}
 
.button {
    width: 80px;
    height: 96px;
    position: relative;
    opacity: .2;
}
 
#buttonLeft { 
    float:left; 
    background-color: red; 
}
 
#buttonRight { 
    float:left; 
    background-color: red;
}
 
#buttonShoot { 
    float:right; 
    background-color: blue;
}
 
#buttonJump { 
    float:right;
    background-color: green;
}

Also we will comment out all the styles inside of the #canvas selector for now:

#canvas {
	/*position: absolute;
	left: 0;
	right: 0;
	top: 0;
	bottom: 0;
	margin: auto;
	border: 1px solid #555;*/
}

Next we’ll need to add the button divs to the index.html right below our canvas tag:

<div id="controls">
<div class="button" id="buttonLeft"></div>
       <div class="button" id="buttonRight"></div>
       <div class="button" id="buttonJump"></div>
       <div class="button" id="buttonShoot"></div>
</div>

Now let’s connect up the controls. Open the main.js file and go to line 27. Add the following below the calls to ig.input.bind:

// Touch Controls
if (window.navigator.msPointerEnabled) {
ig.input.bindTouch("#buttonLeft", "left");
ig.input.bindTouch("#buttonRight", "right");
       ig.input.bindTouch("#buttonJump", "jump");
       ig.input.bindTouch("#buttonShoot", "shoot");
       ig.input.bindTouch("#canvas", "continue");
}

This allows us to bind the touch controls to the button divs we created in the previous step. You’ll note that we are keeping the keyboard bindings since Windows 8 apps need to always support keyboard and mouse/touch. We also do a test for .msPointerEnabled which will tell the game if it actually supports touch on the device playing it. One of the advantages of MSPointer is that you can also use the mouse to test out touch support if your device doesn’t have a touch screen. Simply comment out the test for .msPointerEnabled and you’ll be able to simulate touch with your mouse cursors. The only issue you will run into is multi-touch since you only have one mouse pointer. Now we need to make one more modification to fully support touch. There are two more places where we call ig.input.bind in the StartScreen & GameOverScreen. Do a search for the following:

ig.input.bind( ig.KEY.SPACE, 'start');

We will want to add the following right below both locations:

if (window.navigator.msPointerEnabled) {
	ig.input.bindTouch("#canvas", "start");
}

Now we should be ready to test out our touch controls. This will allow the player to actually click on the game to start it and restart it on the game over screen. The one button we didn’t create is one to switch weapons but now that you see how to do the rest of the controls it shouldn’t be too hard. I would suggest making a small button on the upper right hand corner of the screen so it is out of the way so the player doesn’t accidently hit it.

Now we just need to handle screen resizes. We will need to patch the main game class. Add the following above MyGame:

ig.Game.inject({
    // Default init function for all game classes
    init: function () {
 
        // Reset all input bindings
        ig.input.unbindAll();
 
        // Add event listner to make sure we capture resize events
        window.addEventListener("resize", this.onViewStateChanged);
 
    },
    onViewStateChanged: function (eventArgs) {
 
        var viewStates = Windows.UI.ViewManagement.ApplicationViewState;
        var newViewState = Windows.UI.ViewManagement.ApplicationView.value;
 
        var scale = 5;
        var maxWidth = (window.innerWidth > 1366) ? 1366 : window.innerWidth;
        var maxHeight = (window.innerHeight > 786) ? 786 : window.innerHeight;
        var width = Math.floor(maxWidth / scale) - 1;
        var height = Math.floor(maxHeight / scale) - 1;
 
        var controls = document.getElementById("controls");
 
        ig.system.resize(width, height, scale);
 
        if (newViewState === viewStates.snapped) {
            // is snapped
            document.getElementById('controls').style.visibility = "hidden";
        } else if (newViewState === viewStates.filled) {
            // is filled
            if (window.navigator.msPointerEnabled)
                document.getElementById('controls').style.visibility = "visible";
        } else if (newViewState === viewStates.fullScreenLandscape) {
            // is full screen
            if (window.navigator.msPointerEnabled)
                document.getElementById('controls').style.visibility = "visible";
        }
    }
})

It is important to make sure that this code is above the MyGame, StartScreen and GameOverScreen since it will inject new code into the ig.Game class and we want to make sure all the classes that extend from ig.Game receive the updates. Since we are now adding new logic to the init() function of ig.Game we will have to make sure to add the following line at the top of our init() function in the MyGame, StartScreen and GameOverScreen:

this.parent();

This will allow our custom classes that extend ig.Game to correctly call the parent init() function and thus setting up the screen resize logic. So now our newly modified ig.Game class will clear all bound event from the controls which will help when moving from screen to screen to avoid conflicting touch bindings as well as logic to resize the game based on the correct resolution. I also added in some code to hide and show the controls based on view state. In Snap view the game is unplayable so why should we show the controls? To also help with this, we should add the following to our controls selector in the default.css:

visibility: hidden;

This will automatically hide the controls during the loading screen since we don’t need to display them. We’ll also want to modify the MyGame, StartScreen and GameOverScreen to correctly hide and show the controls as needed. First start with the MyGame class and add the following to the init() function:

if (window.navigator.msPointerEnabled)
	document.getElementById('controls').style.visibility = "visible";

And you can add this to the init() functions of StartScreen and GameOverScreen which will hide the controls in case they are visible:

document.getElementById('controls').style.visibility = "hidden";

Now if you run the game you should only see the button divs while playing the game. You should also test out resizing the game by adding a snap view app to the side of the game or by making your game snap. Right now everything should resize correctly but for a real game you would want to add a pause function and maybe display some text in snap view that has stats and a message asking the player to unsnap the game in order to continue playing. To force the app to unsnap you can always call

Windows.UI.ViewManagement.ApplicationView.tryUnsnap();

So while this ended up being a lengthy post, you may have noticed there wasn’t really a whole lot of code we needed to change to get an Impact game up and running on Window8. I basically had my game up and running in about 30 minutes and after following this tutorial you should have enough info to get your own Impact game running on windows 8 in no time. Looking back, I have covered porting your game over to a Visual Studio project, adding touch controls and handling screen resolution changes. You may also want to think about adding support for saving data locally to the player’s computer and creating a live tile with details about the game’s stats and player progress. If you need some inspiration, take a look at some of the games in the Windows Store to see how other games handle live tiles as well as snap view. I’ll continue to post more about how to integrate HTML5 games into Windows 8 and make sure you check out my upcoming talks and workshops.

Subscribe To My Mailing List

Want to learn how to make a game? Not sure where to start? Even if you are a seasoned game maker there is still a lot you can learn from my free 15 page guide on how to build, release and market a game.

Simply sign up for my mailing list and also get access to great tips and advice on how to make better games. I promise to not spam your inbox!

Join Now

More in Articles, Game Dev (47 of 72 articles)
game-panel-feature