Friday, October 14, 2011

Loading HTML5 Game Assets

Before diving into HTML5 game development, I built a few conventional web sites (like this one - nice snapshots of the Blue Ridge). With conventional web design, page assets like images are loaded once the page loads, slowly filling out the blank screen with colorful pictures. This works well for web pages, since you can immediately begin reading the content and hardly notice the small delay as the images are painted in.

However, the wait for in-game assets can be especially long when downloading 10MB worth of images and sounds for a game like Entanglement. With Entanglement, the first issue I came across was that I couldn't draw a beautiful wooden tile to the gameboard canvas if the wooden tile image hadn't been downloaded yet.

My first attempt to solve this problem was to throw a JavaScript try/catch block around the drawImage calls so they wouldn't break the game if the image wasn't available yet. This resulted in the game starting immediately, but the gameboard slowly appeared as the images were downloaded. This is fine behavior for a web page but seemed a bit ugly for a web game.

My second attempt was a bit better: I included all the images in the html document as invisible <img> tags. This ensures that the images are indeed loaded before the game began but had the unfortunate side effect that JavaScript processing didn't start until the entire page was downloaded (including all the referenced images). This caused the long wait at a "Loading..." screen that couldn't be dynamically updated with a progress bar since JavaScript wasn't running yet.
It's doing something but we're not sure what nor how long it's going to take.
Enter the Asset Loader! This tool allows larger assets to be loaded after the page loads and the JavaScript processing begins. We're in the prototype stage of our next game, and I took this opportunity to build a proper asset loader. Seth Ladd wrote a wonderful tutorial on the basic steps to set up a simple asset manager. Using his insight and including a bit more code to handle audio assets, we created an asset loader that loads assets as well as calls two functions we can supply to track progress: what to do when a single asset is finished loading and what to do when all the assets are finished loading.
function loadAssets(assetList, onAssetLoaded, onAllAssetsLoaded){...}
The next piece we want is a nice progress bar. The <progress> HTML5 element has two properties we care about for keeping tabs on our loaded assets: max and value. Using these two properties we can create a very simple progress bar class to hand off to the asset loader that might look something like this:
function progressBar(parent){
 this.element = document.createElement('progress');
 parent.appendChild(this.element);
 
 // initialize the progress bar at zero percent
 this.element.setAttribute('value', 0);
 this.element.setAttribute('max', 1000);
 
 // for this example, progress will be some value [0,1]
 this.update = function (progress) {
  this.element.setAttribute('value', progress * 1000);
 };
};
We can then set up our asset loader to update the progress bar each time an asset is finished loading, by feeding the progressBar's update function the current state of loaded assets. In our asset loader, the "ratio" value shown below is simply the number of assets loaded divided by the total number of assets.
var assetProgress = new progressBar(document.getElementById('loading-screen'));
loadAssets(assetList, function(ratio){assetProgress.update(ratio);}, startGame);

We've already implemented the progress bar in the latest builds of both Thwack!! and Entanglement if you care to see it in action!

Thursday, September 29, 2011

Google In-App Payments: Convenient for buyers and developers

Todd and I are always looking for good ways to monetize our web games so we can continue doing what we love: making more games! With Entanglement, we created extended content that players can purchase if they really enjoy the game, and with our latest creation, Thwack!!, we created a reward system using tokens that can be won by playing the game or purchased for a few cents.

Back in January when we first released our Sakura Grove Expansion for Entanglement, we implemented an email and key system for purchasing: to access the expansion set for the first time, a player would make the purchase, wait for the confirmation email to arrive, and follow the instructions to get back into Entanglement with the key to unlock their purchase. Not only was the process indirect and inconvenient for purchasing a digital good, but it also took us quite a bit of time to develop and debug.

In developing our latest game, Thwack!!, we decided to implement Google In-App Payments. In-app payments are ideal for selling digital goods and the small 5% transaction fee is wonderful for the small transactions common to games.

Once our game's store interface was set up, I was pleasantly surprised to find integrating in-app payments very quick and straight-forward. In fact, I first began reading the documentation early one morning, and by following the very concise step-by-step instructions I had in-app payments implemented in Thwack!! by lunch time!

We were quite pleased with both the appearance and implementation for Thwack!! so converting Entanglement’s purchase process to Google In-App Payments was a natural next step. However, setting up in-app payments for two separate games on one seller account highlighted something I would need to change with my initially simplistic Thwack!! integration, where I had implemented the entire process, including the postback URL, through the web game itself.

Since I was adding a second game on the same seller account, I had to separate the postback process from Thwack!!. After a bit of restructuring, and less than a day’s work, I had In-App Payments running in both Thwack!! and Entanglement with a separate service that tracks orders apart from the games as shown below.

We now have Google In-App Payments running in both games in less than two days’ worth of programming with the additional benefit of a separate central location to track orders.

We found that Google In-App Payments is not only convenient for our game players by allowing them to remain in the game experience while making their purchase, it is also convenient for us as game developers by making the integration process quick and easy to implement.

Tuesday, September 27, 2011

HTML5 AppCache and Keeping Clients Updated

If you've played Entanglement or Thwack!!, you may notice that it takes a while to load the first time. Fortunately, if you've installed Entanglement as a web app, or played Thwack!! more than once, you may have also noticed that subsequent visits require much less time to load. This is thanks to the HTML5 application cache.

The application cache (or "appcache" for short) allows us to store the game and all of its audio and graphics files locally on your computer (here's a nice tutorial on implementing an appcache). Next time you play the game, the application cache loads the files from your computer rather than pull them from the Internet. The beauty of this is two-fold. First, the game can start loading quickly since it doesn't need to check for anything online first. Second, the game can load without a connection to the Internet at all!

One drawback to this is that if someone plays the game and then returns some time later, the next time they play the game their browser loads a version of the game that's potentially weeks or even months old. If there's an updated version, appcache will load the files in the background to prepare for the next time the game is loaded, but the version the player is currently experiencing is the old version until they reload the page. This isn't too much of a problem with Entanglement where changes from one version of Entanglement to another do not negatively effect the experience.

What a player sees if running an old version
However, with the online multiplayer aspect of Thwack!! it's a bit more disruptive. With Thwack!!, each client independently calculates the results of a given turn, and those results have to match up with each other. For instance (not connected to reality... ...okay maybe a little), if Todd decides on a whim to change all of the discs' sizes, weights, and damping, the new version he deploys will calculate a different result for a turn than an older version stored in appcache. This effectively breaks the experience for not only the player whose browser loaded an old version of Thwack!! but also all of the players connected to that particular game.

The fix is fortunately quite simple. When a new version has loaded in the background, we know that we're not running the latest version. We can check this by implementing the following event listener:

var newVersionWaiting = false;
var updateReady = function()
{
    newVersionWaiting = true;
};

window.applicationCache.addEventListener('updateready', updateReady, false);

Now that we're aware of a new version waiting on the sideline, we can notify the player that they're running an outdated version before we let them in on a multiplayer game. Additionally, we attach a page refresh call to the message dialog's "OK" button to make it even easier for them to get the most updated version. Here's a snippet from Thwack!! where "messageBox" creates the dialog you see in the screenshot above. The first parameter is the message and second parameter, a function, is executed by clicking "OK":

if(newVersionWaiting)
{
    messageBox(RELOAD_THWACK, function(){window.location.reload();});
}

Monday, September 19, 2011

Edison Project Win!

A few weeks ago I mentioned we were one of 9 contenders in a local business competition called the Edison Project. We achieved second place! It was a tough competition, but we lauded the virtues of HTML5 and threw in a bunch of games to give us an edge.

Thanks to: Danny Hearn and the Catawba Chamber for putting this competition together; the sponsors: Alex Lee, CenturyLink, CVCC, Catawba County Government, and the Committee of 100 for making it a reality; and Bill Parrish of the SBTDC who worked with us and gave us invaluable feedback as we put together our business plan and presentations!

Todd's response to seeing a check this large for the first time.
We also want to congratulate the first place winner, David Washco, with Price Drive. He doesn't have his product out yet, but he has a very compelling idea that we hope to see come to life soon. The third place winner, Peter Lohr, with Advanced Hydrogen Technologies Corporation, also has a brilliant idea that could fundamentally change car fuel systems.

Until the official news release gets out, hopefully this picture of Todd will suffice to show our excitement in the recognized feasibility of our business plan... ...and winning a check that's taller than my sons.

Update: Hickory Daily Record article


Tuesday, August 30, 2011

Changing an Icon


Today I came across a useful tip for developers submitting applications to the Chrome Web Store.

Recently we created a new vector-based icon for Entanglement and decided to use the new version in the Chrome Web Store. (There are a lot of square icons in the store, and hexagons are so cool.) Doing so updates the icon on everyone's "new tab" home page as well, which in turn sparked renewed interest in Entanglement. Notice a snapshot of our Entanglement web analytics above: a bump of approximately 60% more visitors on Monday (the day we uploaded the new icon) than the days before.

Up to now, we were not sure how to best reach people who have installed one of our apps and let them know that we have rolled out a major update. It seems a very easy, and almost elegant, way to do so is to simply change the app icon!

Monday, August 29, 2011

The Edison Project

Last month we were selected as a finalist in an entrepreneurial competition held by our local chamber of commerce: it's titled "The Edison Project" and is designed to help folks turn their creative business ideas into reality. This has been a great opportunity for Todd and I to take a look at the business side of things and think strategically about how we can make a livable income doing what we love: making games for you! Regardless of who wins, having a chance to create and work through a business plan has been a great learning experience.

Here are the other eight businesses that were selected as finalists:
The competition consists of three parts: our business plan, a presentation to a few local business leaders this week, and finally a presentation to a public audience. If you live in Hickory, NC, or the surrounding area, come and check it out! It's at the SALT Block Auditorium from 4-6pm on September 19th, 2011. There is no charge and you can vote on your favorite presentation. We can chat afterward about HTML5, game design, or why Todd no longer participates in motorized crowd surfing.

Update: We achieved second place!

Thursday, July 21, 2011

Key Frames Are Cool

Open Prize BallWe are planning to give away new discs (that players can collect) when games are won in Thwack!! (You can't get prizes just yet, so don't be too disappointed if you beat the skill shots and receive nothing.)

Todd thought a prize ball would be an exciting way to deliver these prizes. We could use canvas to do this, but today, just for fun, I decided to experiment with CSS key frames and use the DOM instead.

I had read about these on several occasions, but haven't tried them yet. It was much simpler to implement than similar code I could conjure up in JavaScript to do the same thing (example is for webkit browsers):

@-webkit-keyframes ballroll {
  from {left: -25%; -webkit-transform:rotate(-1440deg);}
  50% {left: 125%; -webkit-transform:rotate(0deg);}
  to {left: -25%; -webkit-transform:rotate(-1440deg);}
}

.prize-ball-roll {
  position: absolute;
  height: 75px;
  width: 75px;
  bottom: 0px;
  left: -25%;
  z-index: 20;
  -webkit-animation: ballroll 4s ease-in-out infinite;
}

If you are viewing this post in a browser that supports key frames, you should see a prize ball rolling across the blog. How cool is that!?!