iphone development blog

Thursday, February 14, 2008 @ 8:15 PM

Part 4: Preloading Commonly Used Game Assets

iPhone Minds Developer's Journal - Crossword Puzzle
Imagine playing The Legend of Zelda on your iPhone. Awesome, right? Well now imagine opening a treasure chest and finding this inside: . What the hell? Looks like the image of your treasure hasn't loaded yet! (Okay, that's actually the icon to represent that an image can't be found, but play along with me.) Similar things could happen in your game if your assets are not downloaded by the time they need to be. Fortunately, there's a trick to prevent this from happening.

If you've ever used Dreamweaver, you're probably familiar with the code that's used to preload images:

function simplePreload() {
var args = simplePreload.arguments;
document.imageArray = new Array(args.length);
for (var i = 0; i < args.length; i++) {


document.imageArray[i] = new Image;

document.imageArray[i].src = args[i];
}
}


Look at the highlighted line. In Javascript you can create Image objects. By doing so, you can store images in the DOMs memory and quickly access them later. But preloading images in this fashion still requires an HTTP call out to the image so that it can be downloaded. When designing games for the iPhone, we want to limit the number of HTTP requests as much as possible. There's actually a way to embed some of your images in your Javascript file so that there's no need to download them.

If you've ever tried to open a GIF or JPEG in a text editor you'll notice that the guts of the image are a bunch of letters, numbers and symbols. There's a free program online, called the URI Kitchen that will read an image and print out the letter/number/symbol/gremlin guts for you.

To use the program, go to URI Kitchen, upload a file and then copy the resulting data from the address bar. Here's the data I got when feeding the program the above question mark image:

data:image/gif,GIF89a%10%10%D5*%80%C1.%8A%C9%2C%86%C5!o%B4%2B%83%C3-%88%C7%2C%86%C6%2C%85%C5%90%AE%D3j%92%C3)%7F%C0%26y%BC%8E%BD%E0%8A%AA%D0%92%AF%D44%7F%BF%87%A7%CFm%94%C4%25v%BA%84%A5%CE%7D%A0%CB%80%A2%CC*%81%C2%8D%AC%D2(%7D%BE%D3%E3%F1z%9E%CAs%99%C7%23s%B7%D3%E4%F1p%96%C6)%7D%BF'%7C%BEv%9B%C8%E3%EF%F7.%89%C8%C6%DD%EE%8C%B8%DCS%95%CA%B9%D6%ECT%98%CCF%91%C8*%83%C2%8D%BB%DDR%95%CA%9B%C2%E16%86%C2)%80%C0F%92%CA%2B%84%C4%9C%C6%E3%F1%F7%FB%8D%BC%DE(%7D%BF%24t%B8%25w%BA%23r%B7'z%BD%2F%8C%CA%22p%B5%94%B1%D4h%90%C2%FF%FF%FF!%F9%04%2C%10%10%06%AE%40%9EpH%2C%F2%1C%BE%A4r%B9t%20%7C%BA%A8t%1A%F5!.%BE%80%D6%608x%0D%23%AD%EF%D2%F0%15%0A1%0B%83q%92%C1%2Cg_%03%E2%13%08T4%D1%2B%E5%13)%EC%3E%10%13%3E%04%04(%2B5.%3E3%18%85%3E%13%15%3E%0A%1F%1F%18-%24%269%94%3E%15%14%3E5%A35%20%2C%25%0B%0B%20%A3%3E%14%1A%3E9%B19%12%0F%0F%12%B29%3E%1A!%3E7%BE7%1C%1D%1D%1C%BF7%3E!%1B%3E6%CB6%3B%19%19%3B%CC6%3E%1B%1E%3E8%D88%03%DB%03%D98%3E%1E%11%3E%3B%E4%E5%E6%E4%3E%11%09L%ECJ%09%3D%F0%F1%F2%F3%3DA%3B

Pretty, huh? Now, take that data, and use it as follows:

var questionMark = new Image();
questionMark.src = 'data:image/gif,GIF89a%10%10%D5*%80%C1.%8A%C9%2C%86%C5!o%B4%2B%83%C3-%88%C7%2C%86%C6%2C%85%C5%90%AE%D3j%92%C3)%7F%C0%26y%BC%8E%BD%E0%8A%AA%D0%92%AF%D44%7F%BF%87%A7%CFm%94%C4%25v%BA%84%A5%CE%7D%A0%CB%80%A2%CC*%81%C2%8D%AC%D2(%7D%BE%D3%E3%F1z%9E%CAs%99%C7%23s%B7%D3%E4%F1p%96%C6)%7D%BF'%7C%BEv%9B%C8%E3%EF%F7.%89%C8%C6%DD%EE%8C%B8%DCS%95%CA%B9%D6%ECT%98%CCF%91%C8*%83%C2%8D%BB%DDR%95%CA%9B%C2%E16%86%C2)%80%C0F%92%CA%2B%84%C4%9C%C6%E3%F1%F7%FB%8D%BC%DE(%7D%BF%24t%B8%25w%BA%23r%B7'z%BD%2F%8C%CA%22p%B5%94%B1%D4h%90%C2%FF%FF%FF!%F9%04%2C%10%10%06%AE%40%9EpH%2C%F2%1C%BE%A4r%B9t%20%7C%BA%A8t%1A%F5!.%BE%80%D6%608x%0D%23%AD%EF%D2%F0%15%0A1%0B%83q%92%C1%2Cg_%03%E2%13%08T4%D1%2B%E5%13)%EC%3E%10%13%3E%04%04(%2B5.%3E3%18%85%3E%13%15%3E%0A%1F%1F%18-%24%269%94%3E%15%14%3E5%A35%20%2C%25%0B%0B%20%A3%3E%14%1A%3E9%B19%12%0F%0F%12%B29%3E%1A!%3E7%BE7%1C%1D%1D%1C%BF7%3E!%1B%3E6%CB6%3B%19%19%3B%CC6%3E%1B%1E%3E8%D88%03%DB%03%D98%3E%1E%11%3E%3B%E4%E5%E6%E4%3E%11%09L%ECJ%09%3D%F0%F1%F2%F3%3DA%3B';

I can now access questionMark anytime I want to load that image in my game. And I can draw the image to the canvas (at coordinate 100,50) like this:

ctx.drawImage(questionMark, 100, 50);

Now, you won't want to use this approach for every image in your game. You'll still have to elegantly handle load times for large images. But this approach works great for smaller, commonly used images. What are the most commonly used assets in a crossword puzzle? The numbers used to label the grid, and the letters that will spell out each word. And those are the exact images that we'll "preload" into Javascript using this method.

// Ryan Jennings

Labels: , , , , , ,


MindComet at 8:15 PM - View Post | 0 comments