Releasing HTML5 Games for Windows 8 (2013)
Chapter 5. Debugging and Optimization
One of the most rewarding parts about building HTML5 games for Windows 8 is the fact that, if your game is already running in the browser on the desktop, chances are good that it will run perfectly as a Windows Store app. Of course, in the real world, nothing works exactly like you expect it to. This chapter will go over some of the best ways to optimize your game so that it runs well on your computer and all the other Windows 8 devices out there.
Using the Console
If you are a fan of console.log(), you’ll be happy to know that all of your log traces will still show up in Visual Studio’s console window. This means the quickest way to debug your app is probably to throw a console.log() statement in there and see what’s happening. There are a few things that Visual Studio doesn’t support in the console output, which you may be used to in a browser log window:
§ Visual Studio will not output the structure of an object. This means you simply get a string equivalent of the object. For exploring objects, you will need to use the debugger and a breakpoint, which we will talk about next.
§ The console also doesn’t automatically add spaces to multiple items separated by a comma. So, if you do console.log(“show”, “me”, “this”) in the console, you will see “showmethis.” In WebKit browsers, the console would give you “show me this.” It’s not a deal breaker but something to keep in mind if you spend a lot of time trying to output multiple items in a single log statement.
Finally, the most important feature of the console is the ability to execute code or modify values while your app is running. Simply type into the console window and you will be able to test code by hand, just like you would do in a browser’s console window.
Debugging and Breakpoints
For heavy-duty debugging, I would use breakpoints and Visual Studio’s debugger. Hopefully you are familiar with how breakpoints work. For a quick refresher, you simply make a line of code where it should pause when executing. This allows you to explore the state of the application and view any objects in memory. To add a breakpoint, left click in the grey area on the left-hand side of the line numbers running down the editor (Figure 5-1).
Figure 5-1. Here is what a breakpoint looks like when the code is executed and stopped for you to debug it.
Once you do this a red dot will show up. When you run the app, the debugger will pause on that line and throw you back into Visual Studio. At this point you can start exploring the objects in your game. Simply roll over an element, such as the argument being passed into a function, and you will be able to see everything within that scope (Figure 5-2).
Figure 5-2. Once the debugger has stopped at a breakpoint, you can explore any object in the code to see its properties and methods.
This is incredibly helpful since you can see the properties of an object and also all of the methods associated with it.
If you are doing lots of object inspection and need to keep track of each one, try adding them to a watch list. Right click on an object in the debugger when at a breakpoint and you will get a contextual menu with additonal debugger features to track that instance while your game is running in debug mode (Figure 5-3).
Figure 5-3. You can also add objects to a watch list for easy reference as you explore other parts of the application.
Once you watch an object it will be added to the watch panel (Figure 5-4).
Figure 5-4. Here is the object in the watch panel.
Now you can continue moving throuh multiple breakpoints and still keep an eye on how an instance of an object or varible is behaving. To move forward through the debug process, use the buttons at the top of the Visual Studio toolbar (Figure 5-5).
Figure 5-5. Once your game is running, the compile toolbar changes to the debug panel with new options.
From left to right: pause, stop, restart, refresh, next statement, step into, step over, and step out. As you can see, the debugger is an incredibly powerful tool and much better than simply using the console to log text.
The DOM Explorer is one of the most powerful tools you have when it comes to inspecting HTML markup structure and CSS styling for Windows 8 apps. It is similar to the F12 tools you would find in IE. To activate it, simply go to Debug -> Windows -> DOM Explorer (Figure 5-6).
Figure 5-6. You can easily pull up the DOM Explorer via the debug menu.
Once it opens, you will be presented with the currently running HTML page and its elements (Figure 5-7). You can explore them and view styles just like you would in IE.
Figure 5-7. The DOM Explorer is incredibly powerful, especially if you are doing any HTML-based layout in your game.
One of the most important ways to test out the performance of your game is to run it on other devices. Luckily you can do this easily by setting up a Windows 8 device for remote debugging. To get started you are going to need to download the Remote Tools for Visual Studio, which you can find here.
You will see under the Remote Tools for Visual Studio tab three different builds: one for x86, one for x64, and one for ARM. Once you have this app installed on your remote test device, load it up and go back into Visual Studio. From there you can select Remote Machine from the build drop down (Figure 5-8).
Figure 5-8. The different deployment options in Visual Studio.
Visual Studio will now ask you to configure the remote machine (Figure 5-9).
Figure 5-9. Setting up a remote machine for debugging.
This will bring open a configuration panel (Figure 5-10) with options for what happens when you do a remote deploy. You can configure if the app will automatically launch on the test device, give the device a name, and some other non-critical options.
Figure 5-10. Configuring the remote deployment options in Visual Studio.
To set up the Machine Name, you will need to click on the empty name field and then you will be able to scan the local network for any Windows 8 devices running the remote tools (Figure 5-11).
Figure 5-11. Visual Studio has found the remote machine.
Once you have found your device, simply select it and its name will automatically be filled into the empty field you saw on the previous window (Figure 5-12).
Figure 5-12. Once selected, the remote machine’s name will show up.
From here you will need to set up a developer license, which is automated for you via the dialog box that pops up (Figure 5-13).
Figure 5-13. You will need to set up a developer license once everything is connected up.
Now you should be ready to deploy to the remote device. Simply hit compile (Figure 5-14) like you normally would with a local build and the game will show up on the remote device and automatically load up the game for you to start testing.
Figure 5-14. Now you can deploy your game to the remote machine inside of Visual Studio.
The best part about remote deploying is that you continue to use all of the same debugging tools I outlined previously in the chapter over the network connection. If you are working on a single monitor setup, this will allow you to continue testing the game out on one device while still being able to debug it on your main development computer.
I have already talked about ways to get the best-looking visuals out of you games, but I wanted to dig in a little deeper to a way of optimizing your artwork. The first thing you should do is optimize the artwork itself. Image editors, such as Photoshop and Fireworks, offer ways of compressing artwork for the Web, and I highly suggest looking into these solutions. Most of the time, the difference between using 8-bit PNGs versus 24-bit PNGs can make all the difference between how long a game loads up on the Web and on Windows 8.
Another solution, which I talked about at the end of Chapter 3 was using something called texture atlases. Texture atlases are similar to sprite sheets in that you group a lot of artwork into a single image. Texture atlases, however, rely on another file, the atlas, which defines the x,y (width and height) of the actual sprite in the texture image. What is great about using texture atlases is that you can include images that are not perfectly square in the same sheet. Sprites generally are divisible by their width and height; images in texture atlases can be any size. Let’s look at an example (Figure 5-15).
Figure 5-15. An example of a texture atlas for Super Jetroid.
And here is a sample of the JSON data I use to pull out each sprite.
"filename": "alert-icon-air-on.png", "rotated": false,"trimmed": true,
The other advantage of texture atlases is not having to load in lots of individual sprite sheets for your game. Since I can put all of my entity and UI artwork in the same texture, I can dramatically cut down on my game’s loading time. While most browsers cap out at six connections at a time, being able to put all of your artwork into less images, even if they are larger, will make your game load faster. Also, when you have all of your artwork in a single image, you can perform more advanced compression on the entire set, helping bring down your artwork size even more.
Figure 5-16 is a snapshot of the amount of requests my game was making before moving over to texture atlases. Figure 5-17 shows the optimized build where about 90 percent of the artwork is now being loaded via texture atlases.
Figure 5-16. Here you can see the total number of connections before moving over to texture atlases.
Figure 5-17. The number of connections is now lower after moving over to texture atlases.
As you can see when comparing Figure 5-16’s Items count to Figure 5-17, I was able to cut down 12 percent of my requests going from 200 down to 176. While that may not sound like a big savings, check out the size of the game. My game went from 6.8mb down to 4.9mb, which is almost a 23 percent reduction in file size. This is huge if you are trying to run your HTML5 game on mobile browsers and also improves the memory footprint on any platform.
All of these Web-based optimizations directly translate into performance improvements on the Windows 8 side of things as well. The reduction in file size makes it easier for users to download your game and store it on their computer, and it lowers the overall memory footprint as well. This last point is especially critical on lower-powered Windows 8 devices that may only have 32 or 64 gigs of storage and only two gigs of memory.
There are a lot of great texture packagers out there and some are free, such as ShoeBox, while others cost money but are more robust, such as TexturePacker.
§ Always use multiplication instead of division and avoid other complex math equations, such as square roots, unless it is absolutely needed.
§ Avoid complex, deeply nested loops. If you have multiple nested loops, try to simplify them and see if you can get away with a single loop. Loops are code blockers, meaning nothing can execute until they complete, so try to limit or avoid them where possible.
§ Use RequestAnimationFrame instead of SetInterval for your game loop. I had a dramatic speed increase in my own games by making this switch, and it should help anyone making a Windows 8 game or even a Web version of their game on modern browsers.
For the difficult-to-track-down performance issues, I suggest taking advantage of Visual Studio’s Performance Explorer, which you can find under the Analyze -> Window menu. Figure 5-18 shows when I run my own game.
Figure 5-18. Here you can see the Performance Explorer running for my game.
There isn’t much out of the ordinary in here but, as you can see, my game loop’s two main functions (draw and update) are in the “Hot Path” showing what methods are taking up a lot of resources. There is not much I can do about this outside of trying to lower the number of executions in these two calls, but you may see something else showing up on here that you may have overlooked when building the game for the browser.
Optimizing for the Lowest Common Denominator
This is a common technique when building any type of game; you always want to build for the lowest end of your game’s specs. More times than not, your audience will be using slower computers than what you are developing on. Even if your game runs great on a top-of-the-line gaming PC, you still need to take into account the slower end of the computing spectrum: budget PCs. One of the best ways to test is to have a device of your own. In the beginning of the book I talked about different form factors, but here is a basic breakdown of processors you will want to support:
§ ARM – The slowest Windows 8 devices, these are basically mobile devices. These will be on par with other mobile devices, such as phones and tablets. They also have the lowest resolution.
§ Low-Power x86 Chips – These are Atom-class processors and are faster than ARM but still have issues with very taxing graphics and calculations. These devices have similar resolutions as ARM-based devices.
§ High-Power x86 and x64 Chips – These are top-of-the-line processors you would find in full desktops, laptops, and even some Windows 8 tablets, such as the Surface Pro. These can be paired with integrated graphics chips or full standalone GPUs.
I tend to code for the ARM devices. My goal is that if it doesn’t run on ARM then the game is not shippable. Of course you can simply publish an x86- or x64-based game, but you are limiting your reach across the full Windows 8 platform. I highly suggest testing on an ARM device as much as possible while getting your game up and running on Windows 8. If your game works on ARM, you can probably skip the low-powered processors as long as your main develop machine has one of the higher-end processors.
Tips and Tricks for Further Optimization
Debug Builds Are Slower Than Production Builds
As you end up testing your game on your local computer or on a remote device, you may notice some serious performance slowdowns depending on the hardware running the game. At first you may get nervous and think your game isn’t going to run well in production, but I have noticed these slowdowns on slower hardware. If you are doing testing and need to use the debugger, see if you can work through the slowdowns. If you don’t need to debug, I suggest exiting the game by stopping the Visual Studio build, closing the game, and reopening it from the start screen. It will run at full speed and you will hopefully see a dramatic difference in performance.
Avoid Multiple Draw Calls to the Canvas
You should be keeping track of the number of draw calls you make to Canvas. Every draw call has the potential of slowing down your game. Unfortunately, there aren’t any debug tools to help optimize rendering performance in your game unless the game framework you are using has it built in. Limit the number of draw calls by caching complex renderings to an off-screen canvas ahead of time or by trying to pre-render graphics wherever possible. A good example of something that may cause performance problems would be manually rendering pixel fonts. If every letter is a draw to Canvas, large text or text in the UI can quickly slow down your game’s performance. Speaking of fonts, I would also avoid drawing Canvas fonts as well.
Use Best Practices