Building HTML5 Metro Games For Windows 8
About two months ago I did one of my HTML5 game development workshops at Microsoft’s NYC office. It was a huge success with over 100 registered attendees. One of the highlights of my workshop was showing people just how easy it is to build an HTML5 game for Win8 in just a few minutes. By leveraging the Impact game framework, it is easy and fun to build a Metro game with very little modification to the core source code. I figured I would go through what I did before the workshop to get Super Resident Raver, a modified version of the game I show people how to build in my workshops and book, running on Win8.
Metro HTML5 Apps
One of the most exciting aspects of development for Windows 8 is the ability to build a native app using nothing but HTML and JS. I think this is a huge advantage over other platforms, and one that will help liberate HTML apps from the browser and bring them to the desktop in a way that no other platform has been able to do. All of this is made possible by Windows Runtime (WinRT), which is built into the core of the operating system.
As you can see, there are now three pillars for building Win8 apps: C++/XAML, C#/XAML and JS/HTML. It’s this last pillar that enables us to take any existing HTML5 Canvas-based game and turn it into a native Metro app with very little modification at all. In addition to simply being able to port over your JS game to a Metro app, Win8 provides an entire JS runtime with hooks into the OS via the WinJS library. These hooks allow you to extend your HTML5 app even further and blend it seamlessly into the OS. For the purpose of porting over Impact games to Win8, I am not going to touch on WinJS, but you should read more about it since your game will probably need to hook into Win8 core systems such as the file system, screen resize events, application focus events and any Metro-style controls you may want as part of your game’s UI.
In addition to the power of running HTML5 games natively on Win8, Visual Studio 11 also got a huge update to help support building JS applications. VS is now on par with the likes of WebStorm and other powerful HTML5 IDEs by proving code completion, refactoring and support for Metro-specific hooks provided by the WinJS runtime. I highly suggest giving VS a try since it’s the best and only way to build Win8 apps right now but, as the platform matures, VS is going to end up being one of the best HTML IDEs out there. I loved using VS for C# WP7 dev and am really excited about the new HTML, JS and CSS support MS is adding into it.
Getting Up And Running
Once I had a basic Impact game ready to go, it was incredibly easy to get it set up in Visual Studio. I simply created a new JS-based Metro project and copied over my code into the project.
One I created the project, I copied over my game’s lib and media directories.
Don’t forget that you need to manually add your files to the project. You do this easily by following selecting show all files.
Now you can see all the hidden files which apear with grayed out icons. Simply select the files or folders you want in your project then right click and pick “Include In Project”
Once all your Impact files are included in the project, you will need to set up the default.html file to import and load up your Impact code. I simply copied over the contents of my Impact index.html files over to the default.html and everything worked great. One thing to keep in mind is that by replacing the contents of defult.html you lose the references to the WinJS runtime so becarfuul as you copy your code over. I would take a look at the default.js file to see the hooks for handling launching, exiting and resuming your game as part of the Metro App’s lifecycle.
Now, with everything linked up, you can compile your game and test it out.
The app should run great, but there are a few more things you may want to consider when moving forward:
It’s really easy to set up Metro live tiles, which represent the icon of your game on the Win8 launcher screen. You have a lot of freedom when it comes to designing these, so check out this article to learn more about how to set them up.
Metro apps have a minimum resolution of 1024×768 but actually support many different resolutions larger than this. It is good to think through how your application is going to scale across different screen sizes by checking out the following article.
Check out the WinJS APIs and map out what features you want to support in your game. This may be especially helpful for UI or saving files to the local storage system.
In the end, once you have linked up your Impact code to the default.html file, you should have everything you need to run, debug and test your game. From there you will need to add support for keyboard/touch controls, optimization and eventually look into publishing your app to the Win8 Store, which you can learn more about here.
Here is a screen shot of the game running with touch controls so you can play it on Window 8 Slates and I also have the Impact profiler running to test out performance.
As you can see the game is running smoothly at 60 fps on the preview device I got at the Microsoft Build conference.
After I had my game set up in Visual Studio and everything was compiling, I started to notice some performance issues. Out of the box my game was running at 30-40 FPS, but I wasn’t very happy with the performance. My game was skipping frames and sometimes the system lag would lock up the game. What was confusing me was that the draw calls in the game were being executed incredibly fast. Canvas, by default in Win8, is hardware accelerated. At first I attributed this to the higher resolution but, after some research, I started to learn that Win8 games run slow if their game loop relies on setInterval instead of requestAnimationFrame.
Unfortunately this wasn’t an easy fix. This required patching one of the core classes in Impact to make the modification. Dominic, who created Impact, used to use requestAnimationFrame earlier on in the framework’s development but pulled it out. I reached out to him and he gave me the following plugin which I was able to use in order to patch the framework to use requestAnimationFrame. Once I loaded this plugin into my Win8 version of the game I saw an incredible boost in performance. Dominic is aware of the issue and will hopefully add support for requestAnimationFrame in future builds of the framework.
I also want to point out that the slowdowns weren’t solely related to requestAnimationFrame; my game was not optimized at all at this point. Before I started building the Win8 build of my game, I had only focused on desktop with no mobile optimizations at all. While Win8 on my development devices is as powerful as a desktop computer, you really need to think of these new computers as mobile devices. This means that any optimizations you would normally make to an Impact game to run on iOS’s browser will make a huge difference in the performance of your game on Win8. Part of the issue is the incredibly high screen resolution of Win8 apps. The goal really is to limit the number of draw calls your game is making. Here is a list of optimizations I performed, which drastically improved the performance of my game:
Pre-Render Layers – Make sure your map layers have “Pre-Render in Game” selected, which will speed up the rendering by creating larger images of the tiles resulting in less draw calls. The only down side is that you will not be able to have animated background tiles, but the increase in performance is noticeable.
Limit Entities On-Screen – I started relying on lots of object pooling and limited the number of entities being spawned at any one time. This was especially expensive with all my blood particles that were getting created when entities would die. If I had a level with 10-20 zombies, and a grenade would go off killing most of them, it would spawn almost 20 blood entity particles per zombie. By reducing that to around five, I dramatically increased the responsiveness of the game when lots of entities would die at the same time.
Limit Weapon Fire Rate – This is along the same lines as limiting the number of entities on the screen, but I wanted to call it out specifically. I went through and added object pooling into my weapon classes and also limited the number of projectiles per weapon. So, guns could only shoot three bullets at a time, shotguns could only do one bullet at a time and I restricted the player from throwing more than one grenade or land mine at a time, since they tended to kill more than one entity, which contributed to the blood particle slowdowns.
Remove Text Where Possible – Text ended up being the biggest rendering issue I found in Impact. Every text field you render out incurs a draw per character so, if you have a HUD with the score and other stats at the top of the screen, you could end up with an additional 50 draw calls that will bog down your game. I removed the stats from the top of the game and put them in the pause screen. So, when you pause the game and all the entities stop drawing, the game has enough resources to render out all the text.
Pause Entities – The last optimization I did was to add logic to correctly pause or suspend my entities when I needed to. Every time pause or game-over screens come up I still need to call draw on all the entities, but I added a flag to each one that lets the render loop know if it should pause or ignore the pause. This is helpful when you have menus that rely on entities to render out text or images but you want the rest of the game to be suspended behind the screen. Also, make sure you take into account any timers you may have running when the game pauses and restore them correctly or your game may get out of sync.
While this may seem like a long list of optimizations you need to make to your game, realistically you should already be doing this kind of stuff in order to support other slower platforms such as mobile. Win8 is going to be a huge mental shift for desktop and Web developers since you can no longer throw anything at the application and assume it will run. Win8 is going to be on high-end hardware as well as low-end mobile devices, so it’s incredibly important for your game to scale accordingly. That means building for the lowest common denominator first if you want to have the broadest reach possible. Unfortunately, I have not been able to test my game’s performance on an AMR device, but all the optimization tips I have outlined above will help keep your game running smoothly on any device.
I wanted to talk a little bit about some of the specific IE hacks I had to do in order to run my game. While Microsoft touts IE10, which is the backbone of HTML5 Metro apps, as being standards compliant there is a lot of gray area in their interpretation of “compliant.” While it is true that IE10 is light years ahead of IE8 and some aspects of IE9, the fact still remains that in order to access a lot of features WebKit browsers take for granted you will need to use MS namespaces in front of specific hooks in IE. The two biggest offenders are touch events and requestAnimationFrame.
I briefly talked about needing to use requestAnimationFrame above in my optimization section and, while this is becoming a standard across all browsers, MS still uses its own implementation of the feature via the msRequestAnimationFrame hook. While this is easily fixed with a polyfill and some conditional magic, the fact still remains that even with IE10′s support for some of the new standards being proposed as part of the HTML5 spec, you should still expect to have to preface your API calls with MS namespaces.
While requestAnimationFrame was easy to fix, adding touch events to an existing Impact game was a little bit more of a chore. IE does not support the WebKit implementation of touch events and has its own completely different API. This meant that I had to hack Impact’s input class specifically for IE10 on Metro. Here is a sample of how I was able to handle touch events:
I found this really annoying because, while touch events aren’t standardized yet as part of the spec, I consider mobile WebKit to be the standard seeing how iOS, Android and even BlackBerry all implement it. MS should have tried to build off the predominant API instead of introducing their own system. This means that you will not be able to support touch events out of the box or with a simple polyfill, so be prepared to have to tailor your touch events specifically to IE10 until Dominic modifies Impact’s core to support IE10 when it eventually launches.
The last MS-specific issue is that it’s incredibly difficult to determine what platform Win8 is really running on. Is it a touch device or does it have a keyboard? Is it a desktop or a mobile device? These questions are incredibly difficult to answer without doing a lot of testing and, even after polling the browser to figure it out, you still don’t have a clear idea of what the processing power of the Win8 device is. This means you need to support everything out the gate. So, when I would normally disable touch events on desktop and enable them on mobile WebKit, I just end up leaving all the events in because at any point you could turn a Win8 touch device into a desktop by docking it and adding a keyboard. Hopefully how to differentiate devices will become easier over time as MS fine-tunes the OS, but right now without any real devices to test with it’s going to be a lot of trial and error optimizing your games on all the different types of devices that will support Win8 at launch.
While I focus on the trouble spot I had with porting over my game to highlight issues you need to take into consideration, I don’t want to overshadow how incredibly cool it is to actually get my HTML5 game up and running on a desktop with very little additional work. Most of the issues I had can be quickly patched in Impact and, if you are not considering doing multi-platform deployment with your Impact game, then it should be really easy to get your game up and running in no time on Win8. I was really blown away by the level of performance I was able to get out of my HTML5 Metro game right out of the box, and Microsoft really nailed the tools/workflow for creating Metro apps with HTML/JS. I couldn’t have asked for anything better and, over time as the tools and OS get refined, it’s just going to get better and better.
I am really looking forward to seeing how Win8 runs on ARM devices, and I think that it’s clear this is the direction MS wants to take the OS. Make it as fast and portable as possible. It should help liberate Windows from the desktop and give iOS a run for its money. I am confident that Microsoft will be able to get the performance of ARM devices to be impressive. Right now I am already getting 60 FPS on iOS in the browser with my Impact games, so I don’t see why ARM-powered Win8 devices will be any different.
Right now I would like MS to support more of the WebKit standards in order to help accelerate porting of existing HTML5 apps and games over to Win8. While they have made some incredible headway with IE10, all the MS-specific hacks I have to do in my game make me feel a little dirty inside. It also makes it incredibly hard to deploy my game on different browsers and OSs, which may also be MS’s intent. I didn’t hook into any of the WinJS APIs since they are tied specifically to Win8 and, since IE10 doesn’t run on Macs or Linux, you will always be stuck in Windows from development to deployment. If Win8 takes off then this will be a moot point, but right now the spotlight is on iOS and it’s clearly the leader of the pack. Most, if not all the clients I deal with, have iOS first Web strategies. MS is going to have a lot of convincing to do in order to win back developers who lived through the IE6 Web app days.
Hopefully it’s not too late for Microsoft to catch up but, given the number of Windows computers in the world, even if a small percentage of existing users adopt Win8 we will see massive gains in penetration numbers for the fledgling OS. That means the potential to distribute your app and monetize it is going to be incredible. I truly believe that Windows 8 is going to be the catalyst we have been waiting for to see HTML5 games come into their own. Since HTML5 Metro apps are as responsive as native C# apps, it’s an incredible opportunity to translate your Web skills into desktop development. Now is a great time to get ready for Win8′s launch, so start working on your HTML5 games now!