in Development log

Good Things Take Time

If you’ve read this blog recently, you probably know that Miguel and I are busy working on the iPhone version of Casey’s Contraptions. What may be surprising is that we’ve been working on it for over three weeks and we’re still not done. After all, to make an iPhone version all we have to do is make the project Universal, recompile, and done, right?

Preview CaseyOniPhone

Are we slacking? Sipping piƱa coladas by the beach? Did we grow complacent with the successful launch of Casey’s Contraptions on the iPad?

5862132784 aa27e193f4

The reason it’s taking so long is that we’re not putting out a rushed version of Casey’s Contraptions on the iPhone. Instead, we’re taking the time to re-work every screen to fit the smaller screen. Even if we could just cram everything into the screen, fingers don’t get any smaller on the iPhone, so the target areas need to be just as easy to touch.

This goes beyond just every UI screen. Quick, name a popular iPhone game that can’t be played with just your thumbs. I’m drawing a blank, and that’s for a good reason. The gold standard for iPhone games is whether it can be played with two thumbs. If it can’t, then it’s probably a bad design. So even though the levels are the same, we’re having to make major changes to how objects are manipulated.

In other words, good things take time.

Which reminds me of this wonderful quote from the Mythical Man Month:

Good cooking takes time. If you are made to wait, it is to serve you better, and to please you. Menu of Restaurant Antoine, New Orleans

All The Little Details

It’s more than just doing a good job though. There’s often a surprisingly large amount of work involved implementing small parts of a game. Things that, when you do them right, go completely unnoticed, but when you don’t, are jarring and irritating. Games are full of examples of things like that, from AI to menu screens.

In this case, I’ve spent a whole day and a half getting the behavior of the toolbox area working correctly on the iPhone. On the iPad, the toolbox area is the bottom wooden box that holds the items you can use in the game.

Ipad toolbox

On the iPhone, since we’re dealing with a different screen aspect ratio, we decided to spend all our screen real estate on the game area, and keep the toolbox hidden. (And yes, since you asked, you can zoom and pan on the game area). Whenever you want to use the toolbox, you press the button and it slides out. Easy isn’t it? How could that possibly take a day and a half?

Iphone toolbox1
Iphone toolbox2

That’s one of those cases where the devil is in the details.

  • Apart from pushing the button, the player can also tap it and slide in and out. When that happens, we need to detect what you mean with that gesture and finish opening/closing the toolbox after you release the touch.
  • Whenever the player grabs an item out of the toolbox, we need to close the toolbox so it’s not in the way.
  • Whenever the player grabs an item in game and drag it near the toolbox, it needs to open so you can drop it there.
  • But dragging an item towards the edge of the screen indicates that you want to move it outsize the zoomed area, so we don’t always want to open the toolbox. Only when the player drags it near the button that opens the toolbox.
  • But perhaps it wasn’t possible to scroll down any further (either because we’re zoomed out all the way, or we’ve moved the camera as far down as it goes), in which case dragging any object anywhere near the bottom of the screen indicates we should open the toolbox.
  • Of course, it’s possible that the player just grabbed an object out of the toolbox, the toolbox closed automatically, and he didn’t move the touch near the bottom of the screen. In that case, we want to be aware of that and not open the toolbox.
  • Dragging an item towards the toolbox, and then away from it should close it since it means the player changed his mind and doesn’t want to get rid of it yet.

Take all those cases, and make them work with and without zoom. And there are even a few more weird combinations we need to deal with, but you get the idea. If that sounds like crazy, well, it is kind of crazy. Fortunately it was something I was able to implement writing unit tests, so it’s pretty easy to modify and update as we need to change things.

For the curious, this is what just a couple of the unit tests look like:

struct F
{
	F()
	{
		camera.pixelSpaceWidth = GameParams::WorldWidthInPixels;
		camera.centerSS = Vec2(0.5f*GameParams::WorldWidthInPixels, 0.5f*GameParams::WorldHeightInPixels);
	}

	Camera camera;
	ActionQueue actionQueue;
};

TEST_FIXTURE(F, ItemOnBottomRightCornerDoesNotOpenToolbox)
{
	camera.zoomFactor = 2.0f;
	camera.centerSS = ScreenCenter;
	CameraUtils::Update(0.02f, camera, true, Vec2(ScreenCenter.x + 0.5f*ScreenCenter.x, ScreenCenter.y - 0.5f*ScreenCenter.y), false, actionQueue);
	CHECK(camera.triggeredToolboxOpen == false);
	CHECK_EQUAL(0, actionQueue.count);
}

TEST_FIXTURE(F, ItemOnBottomLeftCornerOpensToolbox)
{
	camera.centerSS = ScreenCenter;
	CameraUtils::Update(0.02f, camera, true, Vec2(10, 10), false, actionQueue);
	CHECK(camera.triggeredToolboxOpen == true);
	CHECK_EQUAL(1, actionQueue.count);
	CHECK_EQUAL(ActionType::OpenToolbox, actionQueue.actions[0].type);
}

TEST_FIXTURE(F, ItemOnBottomRightCornerOpensToolboxIfCantScroll)
{
	camera.centerSS = ScreenCenter;
	CameraUtils::Update(0.02f, camera, true, Vec2(GameParams::WorldWidthInPixels, 0), false, actionQueue);
	CHECK(camera.triggeredToolboxOpen == true);
	CHECK_EQUAL(1, actionQueue.count);
	CHECK_EQUAL(ActionType::OpenToolbox, actionQueue.actions[0].type);
}

TEST_FIXTURE(F, ItemOnBottomLeftCornerWithZoomOpensToolbox)
{
	camera.zoomFactor = 2.0f;
	camera.centerSS = ScreenCenter;
	CameraUtils::Update(0.02f, camera, true, Vec2(ScreenCenter.x - 0.5f*ScreenCenter.x, ScreenCenter.y - 0.5f*ScreenCenter.y), false, actionQueue);
	CHECK(camera.triggeredToolboxOpen == true);
	CHECK_EQUAL(1, actionQueue.count);
	CHECK_EQUAL(ActionType::OpenToolbox, actionQueue.actions[0].type);
}

When it’s all working, if we did our job correctly, all that players will think about is using their toolbox items and none of those weird cases will cross their mind. Things will just work as expected.

One More Thing

Here’s another example of another task with “hidden” work to behave as expected. When moving object in place in Casey’s Contraptions, and releasing the touch, how many times did the item move slightly because your finger grazed the screen as you released it? I hope the answer is never (or not very often). That’s not coincidence. We have some logic in place to detect those really annoying, but very common touch movements as people lift their fingers from the screen. Without it in place, it was pretty frustrating placing pieces accurately. With it, nobody notices because it works as expected.

So next time you find yourself using a smooth user interface, take a second to consider all the work that went into making it as transparent as possible and thank those poor developers.

Next week we’ll have a post showing some of the specific changes we had to make for the iPhone and comparing screenshots side by side (let’s see if I can get Miguel to write that one).

We’re convinced that the update will be well worth the wait. To tie you over, I leave you with a video from our friends at Bolt Creative.

  • UseCase

    I’ll say it again, I for one applaud the fact that you guys decided to actually release 2 distinct versions instead of a single univers version. Most of the time, different form factors require different UX.

  • Nick

    Thank you for posting the unit tests. I have always been curious about the things you do and do not unit test in programming games.

  • Peter

    @UseCase: How does a Universal version preclude dedicated interfaces?

    The question is: Is it worth charging twice for these interfaces if it’s actually the same game? Or make the user chose on which device to play?

    • A universal version doesn’t preclude custom interfaces. I think UseCase might be referring to the fact that a lot of universal apps didn’t really customize the UI very much, so they’re lacking on one of the two platforms.

      As a matter of fact, the plan is to make Casey’s Contraptions HD universal, and then having a separate iPhone/iPod Touch only version. So you get the best of both worlds and you don’t have to pay for it again.

    • UseCase

      Indeed, but most universal apps I have purchased barely/don’t balance the ui to match both form factors. Often the game plays beautifully in one form factor and less than stellar on the other. I also think that for some the decision to go universal is an after thought. Im working on something right now for IGF that is great playing on the iPad but not on the smaller iPod/iPhone form factor. I finally figured out that the iPhone version could be similarly themed but should be a completely different game. I decided to focus on finishing the iPad version strong instead of splitting my attention even though my partner/artist really wants playability on both form factors simultaneously.

  • My favorite iPhone game is still Cross Fingers, which requires more than just two thumbs, but point taken.

  • interesting point about the two thumbs thing, never really thought about it. is there an equivalent axiom for games in portrait mode?

    • For portrait mode I might even go as far as to say it needs to be playable with the hand holding the phone (i.e. one thumb + tilt). Obviously, it’s not mandatory, but I think it makes it much more accessible.

      • makes sense

      • aa

        yup

      • cc

        what?

      • btw that update song is freekin’ hilarious. lol. been singing it all morning.