Blog Archives

Making 12 Games in One Year?!

About a week ago I signed up for One Game a Month, a challenge to make twelve games in 2013, roughly one per month. I already planned to release five new iPhone and iPad games on App Store in the first half of this year, so adding another seven isn’t such a big deal. :-)

This is a screenshot of the game I made for January, Galaxy Apocalypse:

Galaxy Apocalypse Screenshot

It’s a pretty simple game where you have to swipe planets into portals of the matching color before those portals run out of power and the whole galaxy explodes. You don’t want that to happen on your watch…

The game took five days to make from scratch to finish. If I had more time I would polish it more and put it on the App Store. In its current shape it’s not a bad game but still a bit below the level of what I think is good enough for the App Store, so I will clean up the source code (it’s quite messy right now) and put it on Github as a programming example.

Update: Here’s the code, github.com/hollance/GalaxyApocalypse

Here is a video of the game in action:

I have to say I like these sorts of challenges. I’ve done similar challenges in the past, such as composing at least one piece of piano music or coming up with at least one app idea each day for 30 days in a row. It’s a lot of work but it also pushes your creativity to higher levels.

When you limit yourself to making a game in a very short time, then by necessity you have to limit the scope of the game. Such constraints can be quite inspirational. How small can you make a game that is still interesting?

One of my most successful games, Ultimate Countdown (now removed from the App Store but coming back later this year in an all-new version), was done in a single weekend as a similar kind of challenge. It ended up being downloaded over 250,000 times, which I found quite impressive back in 2008, even for a free game.

So if you’re into game development — or if making games is something you’ve always dreamed of — then head on over to www.onegameamonth.com and sign up! Make games, not excuses. :-)

Communicate between objects using channels

When you have two objects A and B, say two view controllers, that you want to make talk to each other, you can choose from the following options:

  • NSNotificationCenter. This is anonymous one-to-many communication. Object A posts a notification to the NSNotificationCenter, which then distributes it to any other objects listening for that notification, including Object B. A and B do not have to know anything about each other, so this is a very loose coupling. Maybe a little too loose…
  • KVO (Key-Value Observing). One object observes the properties of another. This is a very tight coupling, because Object B is now peeking directly into Object A. The advantage of KVO is that Object A doesn’t have to be aware of this at all, and therefore does not need to send out any notifications — the KVO mechanism takes care of this behind the scenes.
  • Direct pointers. Object A has a pointer to Object B and directly sends it messages when something of interest happens. This is the tightest coupling possible because A and B cannot function without each other. In the case of view controllers you generally want to avoid this.
  • Delegates. Object B is a delegate of Object A. In this scenario, Object A does not know anything about Object B. It just knows that some object performs the role of its delegate and it will happily send messages to that delegate, but it doesn’t know — or care — that this is Object B. The delegate pattern is often the preferred way to communicate between view controllers, but it takes some work to set up.
  • Blocks. Essentially the same approach as delegates, except that Object B now gives Object A one or more blocks (closures) to be executed when certain events take place. There is no formal delegate protocol and the only thing that Object A sees of Object B is the blocks it is given.

That is quite a few possibilities, each with its advantages and disadvantages, and the trick is to pick the one that is best suited for the particular communication problem you’re trying to solve.

In the end, they are all variations on the observer-notifier pattern. And if none fit, you can always write your own version. :-)

Choose your channels

I was playing with another mechanism that I call “channels” that is a mix of NSNotificationCenter, delegates and blocks. Rather than making Objects A and B communicate directly, they do this through an intermediary, the channel:

Object A and Object B communicate through a channel

This is perfectly achievable using NSNotificationCenter (either the global one or a private one for each channel), but I wanted something a bit more lightweight that is simpler to use.

A channel is identified simply by a name, an NSString. If two or more objects use the same channel name, then they are communicating. An object can post a message to the channel and/or listen for messages from other objects.

To listen to a channel you simply do:

[self mh_listenOnChannel:@"MyChannel" block:^(id sender, NSDictionary *dict)
{
    // do something with the dictionary
}];

To post a message to that same channel:

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:...];
[self mh_post:dictionary toChannel:@"MyChannel"];

Or with the new Objective-C literal syntax:

[self mh_post:@{ @"Success" : @YES } toChannel:@"MyChannel"];

The dictionary contains any data that you wish to send along. For example, a view controller that is closing could set a field that indicates which button the user tapped, Cancel or Save.

And that’s all you have to do to make these two objects communicate. When an object calls mh_post:toChannel:, any blocks that were registered by listeners for that channel will be executed.

There is no need to unregister from a channel (although you can if you want to). The channel only keeps weak references to its listeners, so if a listener gets deallocated the channel will no longer try to send it notifications.

This functionality is implemented as a category on NSObject. You can find the source code at Github.

Transparent JPEG Images

When you distribute images with your app you usually pick the PNG or JPEG format. The advantage of JPEG is that it often compresses better — especially for photos — but unlike PNG it unfortunately does not support transparency.

The transparency in a PNG file comes from the so-called “alpha channel”. For every pixel not only red, green and blue values are stored but also an “alpha” value that determines how transparent that pixel is. A value of 255 means this pixel is fully opaque, 0 is fully transparent, and anything in between will mix the pixel’s RGB values with the underlying color.

This is probably an old trick, but by saving a JPEG image not as one but as two image files you can still have transparent images. The first image is the regular JPEG with as much compression as you can get away with, the second image is the alpha channel. This is a grayscale image with black representing fully transparent, white fully opaque, and gray everything in between.

 

Source image and its alpha channel
We can combine these two images at runtime to make the image transparent again. Because of the JPEG compression we lose a little bit of clarity but if you tweak the compression settings you can usually get away with it.

I wrote a simple category on UIImage that lets you do this.

Preparing your images

1) Export your image from Photoshop as a PNG with transparency.

2) Export the image again as a JPEG, using suitable compression settings. The background should have a solid color, typically white or black but any color will do.

3) Save the alpha channel to a separate JPEG or PNG image. I couldn’t find an easy way to do this from Photoshop, but the ImageMagick tool can do it without problems.

If you have ImageMagick installed, open a Terminal and go to the folder that contains the exported PNG image. Then type:

convert -alpha Extract -type optimize -strip -quality 60 +dither Source.png Alpha.jpg

This extracts the alpha channel from the PNG image and saves it as a JPEG file. You can tweak the level of compression with the -quality parameter. If you specify “Alpha.png” instead of “Alpha.jpg”, ImageMagick saves the alpha channel as a grayscale PNG-8 file. You should use whichever one makes the smallest file size.

Combining the images

1) Add the two JPEG images (the non-transparent source image and the alpha channel) to the app.

2) At some point, call the mh_combineWithAlphaImage:backgroundColor: method to combine these two images into a new, transparent, image.

3) Depending on your app you may want to do this only once and then store the transparent image as a PNG in your app’s Caches folder.

That’s it, quite easy.

Some notes

The alpha image does not have to be a JPEG, it can also be a PNG file. If it is a JPEG then it can have different quality/compression settings from the main image.

The current implementation works well but is not as fast as it could be. It also uses more memory than is strictly necessary. I might rewrite this at some point to use the Accelerate framework or Core Image.

Not all images compress better as JPEG. You should use JPEG only where it makes sense.

Check out the source code at Github.

Bird image by Sias van Schalkwyk

MHTabBarController – A custom tab bar for iOS 5 using the new container APIs

Creating your own container view controllers, i.e. view controllers that can contain other view controllers, used to be a pain but now iOS 5 makes it a lot easier.

Especially for iPad apps that is great, because all of that screen space means you probably want to divide it up amongst more than one view controller.

Today I was messing around with these new container APIs and built my own tab bar controller. It works just like a regular UITabBarController, except the tabs look quite different and the pages slide in and out of the screen with a nice animation.

Screenshot of MHTabBarController in the demo app
If you want to learn more about how to do this, then check out the source code or get the iOS 5 by Tutorials ebook. It has a full chapter on these new view controller containment APIs, plus twenty or so other chapters on more iOS 5 goodness!

MHLazyTableImages – Efficiently Load Images for Large Tables

The iOS Developer Library has a sample project named LazyTableImages that demonstrates how to load images asynchronously for a table with many rows.

The app first downloads the list of top paid apps from iTunes (this is an XML file) and shows the list of apps in a UITableView. Then it downloads the icons for the apps in the background and displays them as they become available. Until the icon is loaded, a placeholder image is visible instead.

Only the icons for the visible rows are downloaded; when you scroll the table to make new rows visible, it downloads the icons for these new rows (but only when you are done scrolling).

Screenshot of the MHLazyTableImages demo project

For a recent client project, I needed to do something similar on several different screens. I took the code from this sample project and rewrote it so it was more generic and could be reused among my different view controllers. Today I decided to refactor this some more and make the code available as an open source component. That component is named MHLazyTableImages and you can download it at github.

To demonstrate how to use this class, I modified Apple’s original LazyTableImages sample. The logic for downloading the images is now handled by the MHLazyTableImages and MHImageCache classes. The table view controller only has to create an instance of MHLazyTableImages and connect its data model and table view to it.

To put an image into a table view cell, you simply call -addLazyImageForCell:withIndexPath:. This will first see if the image is already present in the cache and will download it if not.

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
	UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:...];
	if (cell == nil)
		cell = [[[UITableViewCell alloc] initWithStyle:...];
 
	cell.textLabel.text = ...;
	[lazyImages addLazyImageForCell:cell withIndexPath:indexPath];
}

Of course, you need to tell MHLazyTableImages about the URL for the image. That happens in a delegate callback method:

- (NSURL*)lazyImageURLForIndexPath:(NSIndexPath*)indexPath
{
	AppRecord* appRecord = [self.entries objectAtIndex:indexPath.row];
	return [NSURL URLWithString:appRecord.imageURLString];
}

I used a delegate — rather than telling MHLazyTableImages directly what the URL should be for the cell — in order to accommodate scrolling. While scrolling, we don’t want the images to load yet. We will defer downloading until the user stops scrolling. What that happens, -lazyImageURLForIndexPath: is automatically called for the newly visible rows.

There are a few more things that need to happen to make it all work, but that is the gist of it.

Just for fun, I also replaced the original networking code with ASIHTTPRequest. I was already using this class in MHImageCache, and it allowed me to use blocks instead of delegates. That means the demo project will work only on OS 4 and up.

Check out the demo project (RootViewController in particular) to see how everything works in detail.