Monday, February 25, 2008 @ 11:43 AM
Part 10: That's All Folks!

Well, our two week developer's feature has come to an end. I hope you all enjoyed the various discussions and behind-the-scene tips and tricks. Maybe we'll do this again in the future.
Without further ado, here's a link to the final game:
I've also embedded the game below (though it's more fun to play on the iPhone):
Here are some things to keep in mind while playing the game. If the page gets refreshed mid-game, you'll have to start over again. Try not to open new Safari windows when playing on an iPhone or iPod Touch. If you need to open other windows, return to the game window before exiting Safari or turning off your phone, otherwise the page will automatically refresh when you come back to the game after returning to Safari. Also, two clues are repeated in the puzzle. This is not a glitch. Get creative and think about what the two answers might be based on the size of the words you're working with.
UPDATE: It appears that the 1.1.4 iPhone and iPod Touch firmware update preserves the state of Safari "tabs/windows." Meaning, you can start the crossword game in one window and open another without having to worry about loosing your place in the game and starting all over again. I'd encourage everyone to download the 1.1.4 update.
Enjoy!
// Ryan Jennings
Labels: crossword, game, how to, iphone development
MindComet at 11:43 AM - View Post
|
5 comments
Sunday, February 24, 2008 @ 6:30 PM
Part 9: Gratuitous Eye-Candy

Games just aren't interesting without snazzy graphics. But graphics need to be downloaded, and you want to limit as many unnecessary downloads as possible when developing applications for the iPhone.
Until now, our game required only two images. The background image, and the image border used for grid highlights. Together these assets weigh in at about 24.5K. We also embedded a number of images in Javascript, which beefed up that file. All together the images, HTML file (which includes CSS) and Javascript file amount to 50K. That's really good for a complete game and means that the game will load quickly if you need to access it using EDGE.
But of all the things that irk me in life, only one is intolerable. A shitty ending to a video game. I mean you spend 40+ hours of your life (many of which are extremely aggravating) glued to the game. Is it too much to ask for a slick 5+ minute movie ending? Something brilliant that wraps up everything at the end. It only seems appropriate. So, I think it's important to give the winner of our puzzle something nice to look at when they're done.
End Screen:
Okay, it's not much, but hey, this game is being developed for demonstration purposes. Still, I think it satisfies the "snazzy graphics" requirement. Keep in mind that by the time you see the curl, the grid will be filled with letters. I didn't want to give away all of the words so I left the grid empty.In my "Preloading Commonly Used Game Assets" post I mentioned that it would not make sense to embed all images in Javascript using URI Kitchen. The curl PNG weighs 69K. That's more than the entire game weighed up until this point. So, is it worth forcing the user to wait for this image to download when they won't even see it until the end of the game? Sure it is. Because we're not going to "force them to wait."
Since this image isn't required until the very end of the game (and it would probably take anyone at least 15 mins to solve the puzzle), we're going to load the image behind the scenes while the user is playing the game. Here's how we'll do it:
First, we set the game up. This includes waiting for all of the assets (except the curl) to download. Once the HTML has been parsed, Javascript hides the iPhone address bar, reads the game's XML file and builds the game's grid. The game is now ready to be played.
At this point we execute the following Javascript:
setTimeout(function() {
var curl = new Image();
curl.src = 'curl.png';
curl.onload = function() {
var img = document.createElement('img');
img.id = 'curl';
img.src = curl.src;
document.getElementById('body').appendChild(img);
img.onclick = function() { resetBoard(across, down); };
};
}, 30000);Again, the above script will not execute until the game has completely downloaded and is playable by the user. This script then waits 30 seconds before it downloads and sets up the curl image, giving the game more than enough time to prepare the asset before it's required.
For dramatic effect, we're going to fade the curl in when the user has completed the puzzle. There are a number of Javascript resources you can utilize to create fades. MooTools is a great option. But since we're not relying on MooTools to manage the styles or effects of any of the other elements that make up the game, it doesn't make sense to include the MooTools Javascript library (an extra download) only to access it for one effect. There's a simpler way.
The Mac software company Panic has, for a long time, been a leader in creating compelling, and shockingly easy to use, Web applications (they of course make brilliant Mac applications as well). On their site I found a small snippet of math which we can use to fade the curl.
Javascript:
function cubicOut(t, b, c, d) { return c*((t = t/d-1)*t*t+1)+b; }Using the cubicOut function, we can do the following:
var curlanim = { time:0, begin:0, change:0.0, duration:0.0, timer:null };
function curlFade(start, end, duration) {
if (end == 1) document.getElementById('curl').style.visibility = 'visible';
if (curlanim.timer != null) { clearInterval(curlanim.timer); curlanim.timer = null; }
curlanim.time = 0;
curlanim.begin = start;
curlanim.change = end-start;
curlanim.duration = duration;
curlanim.timer = setInterval(function() { fadeAnimDo(end) }, 15);
}
function fadeAnimDo(e) {
if (curlanim.time > curlanim.duration) {
clearInterval(curlanim.timer);
curlanim.timer = null;
if (e == 0) document.getElementById('curl').style.visibility = 'hidden';
} else {
var alpha = cubicOut(curlanim.time, curlanim.begin, curlanim.change, curlanim.duration);
document.getElementById('curl').style.opacity = alpha;
curlanim.time++;
}
}In the last post I mentioned that the matrix array keeps track of whether or not correct letters have been added to the 225 different spaces that make up the puzzle. If it is determined that the puzzle is filled with correct letters (using the matrix array), then the game has been won and we initiate the curl fade with the following code: curlFade(0, 1, 50).
And that's it! The tutorial portion of this feature is complete. Although we didn't post every bit of the game's Javascript, I hope we've explained enough to provide a good sense as to how everything was developed. Come back tomorrow for a link to the working game!
// Ryan Jennings
Labels: crossword, game, how to, iphone development, javascript
MindComet at 6:30 PM - View Post
|
0 comments
Friday, February 22, 2008 @ 5:24 PM
Part 8: Maximizing Screen Real Estate

In the previous post I included a new image of the game. Let me explain how the user is going to interact with the game grid.
Pressing on any square will active a selection (see image below) focusing on whatever horizontal (across) word includes that square. The actual square pressed will turn blue. Pressing anywhere on the now visible selection will rotate it 90° (using the blue square as a control point) to focus on the vertical (down) word. Pressing the selection a second time will deactivate it. You can also deactivate the selection at any time by pressing outside of the selection.
A clue will only be visible underneath the puzzle while a selection is activated. It will initially read something like this:
Press here to answer.
I decided early on that I didn't want to continually display an input field for answering. Rather, I only wanted to display it when the user was actually ready to answer.
Since iPhone applications are dynamic, we can make smart use of the screen real estate and only display certain UI elements when necessary. Here's how I implemented the "now-you-see-it-now-you-don't" input field:
HTML:
<span id="outer-answer"><input type="text" id="answer" value="" /><span style="text-decoration:underline">Press here to answer.</span></span>
CSS:
#outer-answer { position:relative; }
#answer {
width: 208px;
height: 20px;
border: none;
padding: 0;
margin: 0;
position: absolute;
opacity: 0;
text-align: center;
line-height: 20px;
margin-left: 56px;
font: bold 13px Georgia,serif;
}Javascript:
document.getElementById('answer').onfocus = function() {
this.style.opacity = 1;
};
document.getElementById('answer').onblur = function() {
if (this.value != '') {
var letters = this.value.split('');
var correct = xmlhttp.responseXML.getElementsByTagName(node)[0].getAttribute('a').split('');
var numCorrect = 0;
for (var i = 0; i < selected.length; i++) {
if (letters[i]) {
if (letters[i].toUpperCase() == correct[i]) {
eval('ctx.drawImage(i'+letters[i].toLowerCase()+'b, '+((selected[i].id%15)*18)+', '+(Math.floor(selected[i].id/15)*18)+')');
matrix[selected[i].id] = 1;
numCorrect++;
} else {
matrix[selected[i].id] = 0;
}
}
}
if (numCorrect == correct.length) {
alert('Correct!');
clearSelection();
} else if (numCorrect == 0) {
alert('Incorrect, try again.');
document.getElementById('answer').value = '';
document.getElementById('answer').focus();
} else if (numCorrect != correct.length) {
alert('Only some letters are correct.');
clearSelection();
}
checkForWin();
}
};The input field is actually always present (positioned on top of the "press here" text), but it starts off invisible. When you press to answer the field becomes active and the iPhone displays its keyboard. Press the keyboard "Done" button or anywhere on the grid to commit your answer.
So, that's how it's done. Before I wrap up this post, I'll explain some of the other things that are happening in the Javascript above.
Once the user clicks the iPhone's "Done" button we first check to make sure they have actually entered text. If they have, we create an array of the text and match it against an array of the letters that make up the correct answer to the clue. We check each letter one by one. If the letters match, we add the letter to the game grid. The matrix array keeps track of whether or not correct letters have been added to the 225 different spaces that make up the puzzle. Ultimately if all letters are correct, you've won the game.
// Ryan Jennings
Labels: crossword, game, how to, iphone development, javascript
MindComet at 5:24 PM - View Post
|
0 comments
Thursday, February 21, 2008 @ 2:53 AM
Part 7: Taking Advantage of Web Kit CSS Styles

One of the biggest benefits of designing Web applications specifically for the iPhone is that you have access to many Web Kit CSS properties that have not yet been supported in today's other popular browsers, including Firefox.
Things like:
- Borders with rounded corners
- Image borders
- Box shadows
- Multiple background images
The buttons used in iUI all rely on image borders. Image borders make it easy to create scalable image-based buttons (with rounded corners and all types of other snazzy eye candy). Accomplishing something like this previously required 4+ nested elements (plus 4+ images) each responsible for the rendering a specific corner of the button. Now you need only one element and one image and two CSS attributes.
Here's the CSS:
.button {
border-width: 0 5px;
-webkit-border-image: url(toolButton.png) 0 5 0 5;
}
| When using -webkit-border-image you first specify the image to use, then set the areas that will act as your borders. In the example above, we're only going to scale the asset horizontally, so we'll only need a border of 5 pixels on the left and right. The top and bottom do not require a border. | Click Me |
For more information on image borders check out Apple's Safari CSS Reference: Supported CSS Properties.
In the crossword puzzle game we'll use an image border to highlight the currently selected squares in the puzzle grid. Here's what it will look like:
Using an image border is convienent because we can scale the border horizontally and vertically based on the length of the word we're working with. After entering my answer, in this case "CAL," the letters would appear in the highlighted area on the grid.// Ryan Jennings
Labels: crossword, css, game, how to, iphone development, iui, javascript, web kit
MindComet at 2:53 AM - View Post
|
0 comments
Tuesday, February 19, 2008 @ 8:09 PM
Part 6: Taming XML

Though it's easy to get Javascript to read from an XML file, pulling out the appropriate data can sometimes be tricky. Here are some tips to help you tame the XML beast.
Refer to the code we posted yesterday. If the XMLHttpRequest loads without error, then we can use the xmlhttp variable to access the contents of the loaded XML file. To understand how to work with xmlhttp (or whatever you named the XMLHttpRequest instance), relate it to Javascript's document variable.
document.getElementsByName('menu') will return an array of the elements on your page that all share the name "menu."
xmlhttp.responseXML.getElementsByTagName('menu') will return an array of the "menu" XML nodes (tags).
Now, nodes can have both attributes and values. In the following example, "Burns or Byron" is the c attribute of the a1 node and "Timothy Parker" is the value of the editor node.
XML Example:
<?xml version="1.0" encoding="UTF-8"?>
<editor>Timothy Parker</editor>
<across>
<a1 a="POET" c="Burns or Byron" n="1" cn="1" />
</across>
getElementsByTagName will always return an array. In the example above there is only one a1 node, therefore there's no reason to keep an array of a1 nodes. Using the code below, we can save to variable only the first returned node (since that's all that exists).
var a1 = xmlhttp.responseXML.getElementsByTagName('a1')[0];Now, access the c attribute like this:
var c = a1.getAttribute('c');Doing that is easy, but accessing node values is a little more confusing. Here's the code to access the editor node's value:
var editor = xmlhttp.responseXML.getElementsByTagName('editor')[0];
var editorValue = editor.firstChild.nodeValue;The firstChild method gives you access to a node's first child. But the editor node does not appear to have any children. Well, it apparently (or not so apparently) does. When attempting to access the value of a node, imagine the value text as being a node itself... access the nodeValue of the "text node" and you'll get the result you're looking for. Or, in more simple terms, always use .firstChild.nodeValue to access the value of a node.
Another XML Example:
<?xml version="1.0" encoding="UTF-8"?>
<across>
<a1 a="POET" c="Burns or Byron" n="1" cn="1" />
<a2 a="BLAB" c="Give everything away" n="6" cn="5" />
<a3 a="TALKS" c="Gives everything away" n="11" cn="9" />
<a4 a="ALSO" c="Too" n="16" cn="14" />
<a5 a="YOHO" c="Exclamation by Captain Jack Sparrow" n="21" cn="15" />
<a6 a="ELIOT" c="''A Cooking Egg'' writer" n="26" cn="16" />
<a7 a="LIAR" c="Ananias, for one" n="31" cn="17" />
<a8 a="PREY" c="Target in the wild" n="36" cn="18" />
<a9 a="ALONE" c="In isolation" n="41" cn="19" />
</across>
In the above example, all of the across child nodes are named differently, so it would be cumbersome to "getElementsByTagName" each one separately. Instead, take advantage of the childNodes collection to return an array of the nodes.
var across = xmlhttp.responseXML.getElementsByTagName('across')[0].childNodes;There is more to learn about XMLHttpRequest, but by simply knowing how to use the getElementsByTagName, getAttribute, firstChild and nodeValue methods and the childNodes collection, you'll have an easy time accessing all types of data from XML documents.
Before I close this lengthy post, there is one more thing I'd like to mention with regards to accessing XML files. It appears that you can not use Javascript to access local XML files using XMLHttpRequest, you can only access files found on a domain. I am completely perplexed as to why this is and if anyone out there has knowledge of the reason, or knows a workaround, I'd love to hear from you.
// Ryan Jennings
Labels: crossword, game, how to, iphone development, javascript, xml
MindComet at 8:09 PM - View Post
|
0 comments
@ 1:16 AM
Part 5: Importing Data From an XML File

Most programs, including games, require data. More often than not this data must be updated regularly so as to sustain the usefulness of the application. This type of data is usually stored externally (out of the application's main code) since it makes very little sense to require the application's user to download a new version of the program every day in order to receive the latest and greatest data. Therefore, with respect to our game, it makes a great deal of sense to store the data for each crossword puzzle in an external XML file. This way puzzles can easily be loaded individually by referencing a different XML file.
To import data from an XML file, we use the XMLHttpRequest Javascript object as follows:
var url = 'xml/070814.xml';
var xmlhttp = new XMLHttpRequest();
if (xmlhttp != null) {
xmlhttp.onreadystatechange = stateChange;
xmlhttp.open('GET', url, true);
xmlhttp.send(null);
} else {
alert('Your browser does not support XMLHTTP.'); }
}
function stateChange() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
/*
A status of 200 means that the XML file was
loaded and parsed without error. At this point
you'll want to sort through all of the data so
that it can be used by your program. I'll give
you some tips on how to do this tomorrow.
*/
} else {
alert('Problem retrieving XML data.');
}
}
}
We'll talk a little more about reading from XML files tomorrow.
// Ryan Jennings
Labels: crossword, game, how to, iphone development, javascript, xml
MindComet at 1:16 AM - View Post
|
0 comments
Thursday, February 14, 2008 @ 8:15 PM
Part 4: Preloading Commonly Used Game Assets

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: crossword, game, how to, iphone development, javascript, preload, URI Kitchen
MindComet at 8:15 PM - View Post
|
1 comments
Wednesday, February 13, 2008 @ 12:50 PM
Part 3: Jumping Into Code

Okay, let's start programming this game. A couple of weeks ago... no wait, a little over a month ago... I posted about the canvas. The canvas is a really great way to draw to (or animate) a Web page. So, since the iPhone does not yet support Flash, utilizing the canvas makes a lot of sense.
Let's code the grid. There are two ways we can display it. We can use the canvas to draw the grid. Or we can create 225 17x17 pixel DIVs and float them all to the left within a 270x270 pixel parent DIV. The first option sounds easier, but we're actually going to do a little of both.
First we'll use the canvas to draw the representation of the grid. Here is some simplified code:
HTML
<div id="squares"></div>
<canvas id="crossword" width="269" height="269"></canvas>
Javascript
var ctx = document.getElementById('crossword').getContext('2d');
ctx.fillStyle = '#ffffff';
for (var i = 0; i < 225; i++) {
ctx.fillRect((i-Math.floor(i/15)*15)*18, Math.floor(i/15)*18, 17, 17);
}The code above will simply draw out 225 white squares, positioned exactly where we want them on the grid. It does not yet determine which squares should be black (the regions of the grid that are not part of the puzzle). We're ultimately going to read from an XML file to understand which squares are white and which are black. We'll get to that later.
The user will be interacting with the grid in order to read and solve clues, so we also need a separate clickable region for each of the 225 inner squares. That's where the second option comes into play. Let's add that logic to the for loop:
Javascript
for (var i = 0; i < 225; i++) {
ctx.fillRect((i-Math.floor(i/15)*15)*18, Math.floor(i/15)*18, 17, 17);
var newSquare = document.createElement('DIV');
document.getElementById('squares').appendChild(newSquare);
newSquare.className = 'square';
newSquare.id = i;
newSquare.name = i;
newSquare.onclick = function() {
// code to execute onclick
};
}
We've given each "pressable" DIV an id and name so that "onclick" we can figure out which clues they belong to. We'll get to that later as well.
For today, that is all. We're going to start slow and ramp up towards the end. Tomorrow I'll provide a neat trick for embedding images into Javascript so that you don't have to wait for them to individually download. A great way to preload images. It's very cool.
// Ryan Jennings
Labels: crossword, game, how to, iphone development, javascript
MindComet at 12:50 PM - View Post
|
0 comments
@ 2:08 AM
Part 2: Design Considerations

Earlier today news of an imminent Flash upgrade from the iPhone was flooding the Internet, though no concrete dates were specified. When a Flash plug-in is released it will open the doors for a lot of game programmers who are unfamiliar with coding using Javascript and the HTML DOM. But for now, this is all that's available. So, let's continue with our tutorial...
When designing games for the iPhone keep in mind that although the screen's resolution is 320x480 pixels, some of the vertical pixels are lost to the status bar, address bar and lower toolbar... 64 pixels are lost, to be exact. So, if you want your entire game to display "above the fold," design it to be 320x416 pixels. (Above the fold is a reference web designers throw around a lot to appear cool. It refers to the topmost part of a Web page -- the area that is initially viewable. The content that shows up as you scroll down the page is "below the fold.")

If you look at a printed crossword puzzle you'll notice that the game consists of two main parts: 1) the grid, and 2) the "across" and "down" clues. Both take up a lot of real estate. So how do we fit everything onto the iPhone screen?
First let's discuss the grid (or board, whatever you'd like to call it). The squares that make up the grid need to be small enough so that a 15x15 matrix will fit within the design. They also need to be large enough so that even a person with fat fingers -- *cough* Scott *cough -- can press a single square. After mocking up a number of grid sizes I realized that although I could theoretically size each individual square at 19x19 pixels and still fit all 225 (15 rows x 15 columns) on the screen, I didn't have much room for anything else. So I settled on 17x17. This means that we loose 271x271 pixels to the grid.
Since a title is required for each puzzle, very little room is left for the clues. It will be impossible to display them all at once, so instead let's display relevant clues when the user clicks on a particular row/column. We'll talk about how this is going to work later.
That's all for today. Coding goodies will come tomorrow.
// Ryan Jennings
Labels: crossword, design, game, how to, iphone development
MindComet at 2:08 AM - View Post
|
0 comments
Monday, February 11, 2008 @ 3:47 PM
iPhone Minds Developer's Journal

Though I don't frequent other iPhone development type blogs much, I will say that the ones I have checked out skimp on the information you really want. They'll cover mundane issues like how to hide Safari's address bar, or how to change your wallpaper, or how to create a web clip bookmark... you know... beginner's stuff. What? That's all that we've been posting? Uhhh... ummmm... well, I guess it's time to up the education.
Over the next two weeks we're going to walk you through the development of a complete and working game for the iPhone. Not a stupid "move-around-the-pieces-of-this-image-and-try-to-put-them-in-order" game. We're going to build a fully functional crossword puzzle game. We'll discuss the best way to approach design and usability, provide coding tips (as well as some source code), and suggest solutions to many of the obstacles you will face along the way. So, without further ado, here is Part 1 of our ten part series.
Part 1: Things to Keep In Mind
There are a couple of things to keep in mind when considering iPhone game development. The most important is that iPhone developers currently do not have access to many of the usability features that make the iPhone great -- things like pinch, expand, slide, drag, drop, etc. That may change when the SDK is announced later this month, but for now all we have is press (click).
Additionally, all of the applications must be built in Safari. Don't get me wrong, I for one am more than happy to use Safari as my development environment. After all, HTML/Javascript development is what I know. It's what I've spent the last 10 years working with. So I know how to do really amazing things with that medium. Still, Safari on the iPhone is less responsive than it is on your Mac or PC. For instance, there is a lag between when you press something on the page and when you can press something else on the page. The lag is only about a second, but it should be kept in mind when you begin thinking about the type of game that you want to create. Because of the lag, slower-paced games make more sense on the iPhone. Therefore developing a puzzle game for this tutorial was a no brainer. After all, there's not much need to race your way through a crossword puzzle.
Besides the fact that a crossword puzzle was a slower-paced game, this type of game also provided some interesting usability dilemmas, but we'll get into those tomorrow. We'll also discuss design considerations tomorrow. For now, take a look at the near-finished design below. Though I've started some of the development of this game, there is much yet to still do so things may change over the next two weeks.

I originally got the idea for this game after seeing the daily puzzle on USA Today's site, so it made sense to try and repurpose the online version of their game in an iPhone format. DO NOT get all of your game ideas from copyright sources. I'm simply doing this because though I want to code and design the game, I don't want to create each puzzle myself, so I'm going to use the XML feed that their Flash game uses in order to pull individual puzzles.
That's all for today. Feel free to email us at ask@iphoneminds.com with questions or comments regarding game development. Come back tomorrow when we'll discuss design considerations.
// Ryan Jennings
Labels: crossword, game, how to, iphone development
MindComet at 3:47 PM - View Post
|
0 comments


