Chapter 4. Building Novelty Apps

In This Chapter

Programming: iFlame

Programming: iDrum

Programming: Bonfire

Analyzing business aspects

The shortest distance between any two points is always a straight line. The shortest distance between you and making your first 99 cents on the App Store is always by making a novelty application. Most iPhone novelty apps tend to be one-trick ponies. For example, you can find applications to allow your iPhone to feature any of the following: strobe light effects, a desk clock, a virtual drink, and much more. And of course, there are the many infamous iPhone farting applications.

We think everyone should try their hand at creating an iPhone novelty application of their own. Even if the application already exists, there is a lot of value in creating an application for yourself. Take a moment to come up with a list of potential iPhone novelty applications of your own. Then compare this list to ours and see if you come up with any more ideas. Great ideas eventually grow up to become great applications.

Here is a list of some of our iPhone novelty application ideas to help get you started thinking of your own:

  • Snow Fall. Imagine a snow globe on your iPhone. You could let users create virtual wind on the screen by blowing on the microphone. And you could use the accelerometer to have the snow always float back down.

  • Sleep Sound. Have the iPhone play a white noise audio file in a loop. Maybe allow the user to set an alarm after a certain amount of time or for a certain length of time.

  • Bubbles. Create an image of a bubble and then randomly display bubbles on the screen for the user to pop. The user's goal is to never let there be more than 10 bubbles on the screen at a time.

  • Hypno. Hypnotic spinning spirals in different sizes and colors appear all over the screen. The user's goal is to tap all the red ones before it is too late. You might have a time limit to encourage users to hurry.

  • iMood. Any time the user touches the screen, the entire screen—or just the area of the screen the user touched—changes colors, similar to either a mood ring or a heat-sensitive object.

  • Fractalious. A living fractal that constantly changes size, shape, and color is displayed on the screen. Maybe the user can pinch the screen to zoom in and out using the iPhone's Multi-Touch capabilities.

  • Fire Wall. A wall of animated fire is shown on the screen. No matter which way the iPhone is held, the fire always burns in an upward direction.

  • Sound Board. This app could have lots of buttons with matching sound effects for the user to play as needed. Maybe there would be a nice round of applause or the sound of a jeering crowd, ready on cue.

  • Star Field. Think of this as a screensaver for your iPhone. Almost any good idea for a screensaver is a good idea for an iPhone novelty application.

Note

Check out Appendix B for details on the 31 iPhone apps we created in one month, including Snow Fall, Sleep Sound, and more.

Programming: iFlame

The application you are going to create is called iFlame, which is a virtual lighter for the iPhone. The idea is to create an application that people can safely use anytime and anywhere instead of having to carry around a separate physical lighter with them. This could be very useful for concerts or karaoke events. See Figure 4.1 for the iTunes listing for iFlame.

When we originally released our iFlame application in August 2008, it was one of the first, if not the first, virtual lighter applications for the iPhone. Today there are probably over a dozen. When you are coming up with your next great iPhone application, it helps if you are one of the first to the market. A good idea can go far; a good original idea can go farther. Even today, almost a year later, we still receive many requests for downloads of our iFlame application on a daily basis.

Another thing you can do to help your application stand out in a crowd is to have unique features. For iFlame we decided to create four unique variations that users can select from. We were also sure to include these details on the App Store. We even renamed the application to "iFlame—Multi Effect Concert Buddy" to make sure we got this key selling point across to potential app purchasers.

Here are the available iFlame effect modes:

  • Normal. In normal mode, iFlame displays a standard traditional flame that waves and flickers over time.

  • Tiles. In tiles mode, the flame is much smaller and the video is repeated in a 6 × 6 grid.

  • Cube. The cube mode shows the flame in a video cube effect. Each face of the cube displays the flame video while the cube rotates.

  • Strobe. In strobe mode, while the flame video plays the screen fades from the dark video to pure white, creating a strobe effect.

iFlame—Multi Effect Concert Buddy

Figure 4.1. iFlame—Multi Effect Concert Buddy

Sometimes magic tricks lose their magic once you understand how a trick works. Take a look at the iFlame application, shown in Figure 4.2. See if you can figure out what the trick is that makes the iFlame application work. Here's a clue: The iFlame application does not generate its images programmatically. Keep reading to learn the secret.

To begin creating a new iPhone application, open Xcode and choose File

iFlame—Multi Effect Concert Buddy

Name the new project iFlame and then click the Save button in the bottom right of the dialog box. You should now have a new Xcode iPhone OS application named iFlame.

Note

The secret to how the iFlame application is able to create such a photorealistic flame is that the application is actually playing a video loop of a real lighter's flame. All we did to create the flame video was to take a lighter into a windowless room and record it with a digital video recorder.

What's the secret behind the iFlame application?

Figure 4.2. What's the secret behind the iFlame application?

It was very important for the video of the flame to have a seamless loop. This means that when you watch the flame you never see the flame reset with the video loop repeated from the end of the loop back to the beginning. This is another one of our behind-the-scenes iFlame tricks. Can you guess how we did it? No, we did not record hours and hours of video and find a section of video that just happened to match up over a reasonable interval of time. Here's how we did it: Imagine you have a short video loop that consists of five frames. You could imagine that the following numbers represent those five frames: 1, 2, 3, 4, and 5. Now if you took that video loop and reversed and then pasted it after the original video loop, you would end up with something like this: 1, 2, 3, 4, 5, 5, 4, 3, 2, 1.

New Project dialog box

Figure 4.3. New Project dialog box

This would technically be a seamless video loop, but it has a couple of problems. The number 5 frame is repeated twice, which will make that frame appear to last twice as long to viewers. And since the first frame is frame 1, and the last frame is frame 1, whenever the video loops back from the end to the beginning, frame 1 will appear to take twice as long as well. This is easy to fix with the following corrections: 1, 2, 3, 4, 5, 4, 3, 2. Notice all we had to do was remove the repeated frames: frames 1 and 5.

While this trick will make any video technically seamless, it is really only useful with video of things that look the same whether the video is being played forward or backward. All it would have taken to ruin this effect for us would have been for the flame to create smoke while it burned. Half the time the smoke would have floated away from the fire, while the other half of the time the smoke would have floated toward the flame. This would have completely destroyed the viewer's suspension of disbelief.

As you can see in Figure 4.4, if you have three frames of video and you want to create a seamless video loop, you will need to take the original three frames and reverse them, and then remove the duplicate first and last frames. Oftentimes with larger amounts of video you will not have to remove these overlapping frames.

Simple three-frame seamless video

Figure 4.4. Simple three-frame seamless video

You can either create your own flame video, which we recommend you try at some point, or use one of ours. There is a lot of video-editing software out there that you can use to create your videos. Start with products like iMovie, since it is free and should already be installed on your machine. You might also want to consider QuickTime Pro, which is affordable (less than $50 at the time of this writing) and powerful. It can open and save video from and to almost any video format, including the iPhone-compatible M4V format. It can even convert videos to sequences of images and vice versa. The iPhone lets only one video play at a time, and it will fill the screen. If you convert your videos to images and then play them as animations, you can have a lot more freedom. The tradeoff is that when videos are converted to images, they usually need more storage space.

For example, this would be a great answer if you had a dozen videos, any one of which the user can play full-screen, but you want the user to be able to see live, independently controlled thumbnails of all the videos at the same time.

You will need to use the MPMoviePlayerController class to play video on the iPhone. The MPMoviePlayerController is a full-screen movie player. If that does not meet your needs, you will have to find a way to convert your video to a sequence of images and then display them on the iPhone as an animation. You could use QuickTime Pro to convert your videos to image sequences.

Also note that the MPMoviePlayerController class can play local movies stored on the iPhone or remote movies from a network-based URL. If you decide to use remote movies, consider saving your movie files in the iPhone Cellular format of 3gp. Again, you can use QuickTime Pro to accomplish this feat. The 3gp format is optimized for the iPhone and for retrieval over cellular connections.

Tip

If your application is larger than 10MB, users will not be able to download it from the App Store using cellular connections. Instead, a Wi-Fi connection will be required. Consider streaming larger videos from remote servers to keep app file size down.

The MPMoviePlayerController class allows you to play any movie or audio format that is already supported on the iPhone. This means if it already works on the device, it will work in your application—or more specifically, files with the following extensions will work in your application: MOV, MP4, MPV, and 3gp.

Any time you are working with a new class, it's a good idea to research it first in Xcode's Help menu. Go ahead and take a few minutes to look up MPMoviePlayerController in Xcode's API Reference. One easy way to do this is to type MPMoviePlayerController in Xcode and then right-click the text and choose Find Selected Text in API Reference.

Also consider using the Reference Assistant located under Xcode's Help menu. This gives you real-time, context-sensitive help as you work in Xcode. Finally, you can right-click MPMoviePlayerController and choose Jump to Definition. This takes you directly to the real code that makes up the MPMoviePlayerController class. Not only can you learn more about the MPMoviePlayerController class, but this is a great way to learn more about how to program correctly.

You will need to add the MediaPlayer framework to your iFlame Xcode project. To do this, find the Frameworks folder, which is located under the iFlame project in the Groups & Files panel of Xcode, and double-click on the folder to expand it (Figure 4.5).

Right-click on the Frameworks folder and choose the Existing Frameworks option from the Add sub-menu. You will now see a folder listing; find the folder named Frameworks and double-click it to expand it. You will see a listing of a dozen or more framework folders. Once you locate the MediaPlayer.framework folder, select it and then click the Add button in the bottom right.

Note that depending upon a number of factors, such as the current SDK version installed and whether the Developer Tools were already installed, you may not be placed in the correct Framework folder by default when trying to add an existing framework. If this happens to you, you will need to browse up a parent folder or two and find the correct version of the framework. The full location for the MediaPlayer.framework is Developer

Simple three-frame seamless video
The Frameworks folder

Figure 4.5. The Frameworks folder

Another screen appears, similar to Figure 4.6. Confirm that Reference Type is set to Default and Text Encoding is set to Unicode (UTF-8). The Add To Targets panel should have iFlame listed with a check box next to it. Click the Add button to proceed. These are the default settings, so you should only have to double-click to confirm them.

You now have added a reference to the MediaPlayer.framework to your iFlame project. The next step is to update your iFlameAppDelegate.h file so that it will use this framework. You can find the iFlameAppDelegate.h file in Xcode under the Classes folder beneath the iFlame root project folder. You can do this by adding a simple import statement to the top of the file:

#import <MediaPlayer/MediaPlayer.h>
Adding a new framework to the iFlame app

Figure 4.6. Adding a new framework to the iFlame app

Once you have added this line, your iFlameAppDelegate.h file should look like the following:

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
@class iFlameViewController;
@interface iFlameAppDelegate : NSObject <UIApplicationDelegate>
{
   IBOutlet UIWindow *window;
}
@property (nonatomic, retain) UIWindow *window;
@end

Next, you will need to create the actual MPMoviePlayerController object instance. This will go under IBOutlet declaration line that is located near the middle of the file. After this you will need to add an NSURL object to help keep track of movie URL:

MPMoviePlayerController *mMoviePlayer;
   NSURL *mMovieURL;

Note

You can use the MPMoviePlayerController to play audio as well as video. The only drawback is the user will be presented with a rather dull screen, with, at most, basic playback controls, while the audio plays.

You will now need to add a couple of notification callback methods so that the movie player object and the iFlame application can load the movie and handle when the movie is done playing. You should add these items right before the @end statement:

-(NSURL *)movieURL;
-(void)initMoviePlayer;
-(void)moviePlayBackDidFinish: (NSNotification*)notification;

Once you have performed these changes, your iFlameAppDelegate.h file should look like the following:

#import <MediaPlayer/MediaPlayer.h>

@class MainViewController;
@interface iFlameAppDelegate : NSObject <UIApplicationDelegate> {
 UIWindow *window;
   MPMoviePlayerController *mMoviePlayer;
   NSURL *mMovieURL;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) MainViewController *mainViewController;
-(NSURL *)movieURL;
-(void)initMoviePlayer;
-(void)moviePlayBackDidFinish: (NSNotification*)notification;
@end

If you look back in the iFlameAppDelegate.h file, you will see that the iFlameAppDelegate implements the UIApplicationDelegate, which, according to the API Reference, means there is an optional applicationDidFinishLaunching event that is called when the application has finished launching. You will use this event to start your video.

Now you will move on to updating the corresponding iFlameAppDelegate.m file. Start by updating the applicationDidFinishLaunching method. Make the changes required so that your applicationDidFinishLaunching method matches the following:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    [self initMoviePlayer];
    [window makeKeyAndVisible];
}

Tip

The media player always does a fade to black whenever a video finishes playing. To avoid this you can copy and paste your video multiple times, even hundreds of times, in QuickTime Pro; while the play time will increase, the file size will not.

Now when the iFlame application finishes loading, it will call your applicationDidFinishLaunching method, which is set to then call the initMoviePlayer method. You will now add the following initMoviePlayer method to your code by modifying the current initMoviePlayer method to match this one:

-(void)initMoviePlayer
{
mMoviePlayer = [[MPMoviePlayerController alloc]
   initWithContentURL:[self movieURL]];
[[NSNotificationCenter defaultCenter] addObserver:self
   selector:@selector(moviePlayBackDidFinish:)
   name:MPMoviePlayerPlaybackDidFinishNotification
   object:mMoviePlayer];
mMoviePlayer.scalingMode = MPMovieScalingModeAspectFill;
mMoviePlayer.movieControlMode = MPMovieControlModeHidden;
mMoviePlayer.backgroundColor = [UIColor blackColor];
[mMoviePlayer play];
}

There's a lot going on in this method, so take a moment to review it now.

The following line of code creates a new MPMoviePlayerController object and assigns it to our mMoviePlayer object. It also initializes the newly created MPMoviePlayerController object with the movie stored at the movieURL location:

mMoviePlayer = [[MPMoviePlayerController alloc]
   initWithContentURL:[self movieURL]];

The purpose of the following line of code is to tell the MPMoviePlayerController object that we want to be notified when the movie finishes playback. The name of this notification is MPMoviePlayerPlaybackDidFinishNotification, and it is now set to call our moviePlayBackDidFinish method once the movie is done:

[[NSNotificationCenter defaultCenter] addObserver:self
   selector:@selector(moviePlayBackDidFinish:)
   name:MPMoviePlayerPlaybackDidFinishNotification
   object:mMoviePlayer];

There are two other notifications available on the MPMoviePlayerController:

  • The MPMoviePlayerContentPreloadDidFinishNotification event occurs once the movie has been loaded into memory and is ready to play.

  • The MPMoviePlayerScalingModeDidChangeNotification event occurs if the screen is rotated and so on.

Tip

Consider using MPMoviePlayerContentPreloadDidFinishNotification so you can display a loading screen until the movie player is able to load the movie into memory.

Scaling mode determines how any movie that does not exactly fit the screen will be scaled to fill the screen. We went with MPMovieScalingModeAspectFill because it was okay if the black around the flame went off the screen and got cropped off.

Here are all the valid scaling modes for displaying movies for MPMovieScalingMode:

  • MPMovieScalingModeNone. Do not scale the movie.

  • MPMovieScalingModeAspectFit. Scale the movie until one dimension fits on the screen exactly. In the other dimension, the region between the edge of the movie and the edge of the screen is filled with a black bar. The aspect ratio of the movie is preserved.

  • MPMovieScalingModeAspectFill. Scale the movie until the movie fills the entire screen. Content at the edges of the larger of the two dimensions is clipped so that the other dimension fits the screen exactly. The aspect ratio of the movie is preserved.

  • MPMovieScalingModeFill. Scale the movie until both dimensions fit the screen exactly. The aspect ratio of the movie is not preserved.

Sometimes it really helps to see the code behind a feature you are working with even if only for reference. So here is the source code for the MPMovieScalingMode:

typedef enum
{
// No scaling applied at all.
MPMovieScalingModeNone,
// Uniform scale until one dimension fits. One dimension may be
// filled with bars the color of the backgroundColor property.
MPMovieScalingModeAspectFit,
// Uniform scale until the movie fills the visible bounds. One
// dimension may have clipped contents.
MPMovieScalingModeAspectFill,
// Non-uniform scale. Both render dimensions will exactly match
// the visible bounds.
MPMovieScalingModeFill
} MPMovieScalingMode;

Note

Be careful when using the MPMovieScalingModeFill, as it is the only scaling mode that does not preserve the video's aspect ratio. Using this may cause displayed video to appear distorted.

In this case, you will want to use the MPMovieControlModeHidden movie control mode because showing any movie controls will give away the trick to the watcher.

mMoviePlayer.movieControlMode = MPMovieControlModeHidden;

Here is the source code for the MPMovieControlMode enumeration. This should help prove the value of reading through a class's source code to learn more about its inner workings:

typedef enum
{
// Standard controls (e.g. play/pause, volume slider, timeline) are
// visible
MPMovieControlModeDefault,
// Only the volume control is visible
MPMovieControlModeVolumeOnly,
// No controls are visible
MPMovieControlModeHidden
} MPMovieControlMode;

Here are all the valid movie control modes for MPMovieControlMode:

  • MPMovieControlModeDefault. Display the standard controls for controlling playback. This includes play/pause controls, a volume slider, and a timeline control.

  • MPMovieControlModeVolumeOnly. Display volume controls only.

  • MPMovieControlModeHidden. Do not display any controls. This mode prevents the user from controlling playback. Use this mode any time you only want the user to be able to see the video. A virtual aquarium video application, for example, would not appear realistic behind a set of playback controls.

The background is used for any area on the MPMoviePlayerController that is not filled by the video due to choices made for MPMovieScalingMode and so on. In this case you will want to use black. This way if there is any area not covered by the video it will match the black background used in the video:

mMoviePlayer.backgroundColor = [UIColor blackColor];

Note

The movie player's background color is also the color that the screen will fade to and from whenever the video begins or ends. By default, the movie background color is black.

Finally, the simple play command is passed to the movie player object and the magic begins. You can also call stop at any point to pause the video playback and re-call play to resume playback.

Next, you should add the moviePlayBackDidFinish notification method. Since you are using a seamless video loop, whenever the video finishes playback you will simply play it again. Here is the code to make that happen:

-(void)moviePlayBackDidFinish: (NSNotification*)notification
{
   MPMoviePlayerController* theMovie=[notification object];
   [theMovie play];
}

The notification object that is passed to the moviePlayBackDidFinish method is the MPMoviePlayerController object we assigned to be notified on finishing movie playback. You just need to convert it back to an MPMoviePlayerController object and call the object's play method.

We now have most of the plumbing we need for our iFlame project. One thing that is missing is a way for the application to determine what video it should play. Add the following code, which does that, and then review it yourself before proceeding:

// return a URL for the movie file in our bundle
-(NSURL *)movieURL
{
    if (mMovieURL == nil)
    {
        NSBundle *bundle = [NSBundle mainBundle];
        if (bundle)
        {
NSString *moviePath = [bundle pathForResource:@"movie" ofType:@"m4v"];
            if (moviePath)
            {
                mMovieURL = [NSURL fileURLWithPath:moviePath];
                [mMovieURL retain];
            }
        }
    }

    return mMovieURL;
}

First, you check to see if mMovieURL has already been set. If it is nil, this is the first time this method has been called and you will need to assign a value to mMovieURL. Next, check that the iFlame project has an NSBundle. It will as long as you remember to add a video to the iFlame project. The NSBundle object is a powerful class that helps developers to not rely on hard coded paths. This class will find your application's location on the device file system so you can easily access files and resources.

Use the pathForResource method to obtain the movie.M4V file's path. If the path exists, assign it to the mMovieURL string. The last thing is to simply return it back to the calling method.

Note

Always be sure to test that variables are valid before calling any related methods. A simple if variable != nil is sometimes all it takes to avoid a crashing application.

When the application is done running, it will call dealloc, so be sure to clean up any variables you created there. Since you allocated the memory for the mMoviePlayer and mMovieURL objects, you will need to make sure you deallocate the memory before the application is done. Here is the basic code that is required to do that:

- (void)dealloc
{
   [mMoviePlayer release];
   [mMovieURL release];
   [window release];
   [super dealloc];
}

There is one important task remaining before you can try out this application. You have to add the movie.mv4 to the project's resources. From Xcode, find the Resources folder under the iFlame project in the Groups & Files panel. Right-click on the folder and choose Add

Adding a new framework to the iFlame app

Locate the video you wish to use and select it, then click the Add button. You can use one we have provided in this chapter's sample code, or use one of your own. In the next dialog box, be sure to check the Copy items into the destination group's folder check box. Confirm that Reference Type is set to Default and Text Encoding is set to Unicode (UTF-8). Then click the Add button.

Be sure to set Xcode to Simulator | Distribution and then click the Build and Go button. The application should now load up in the Simulator and run. You should see the iFlame application as shown in Figure 4.7.

Any time you finish an application you should take a step back and perform a quick mental post-mortem. What went right? What went wrong? What could you have done better? What will you do differently next time? Also take some time and think about where you will go from here. We recommend taking the iFlame application you have and creating some new effects of your own. For example, you could create a campfire application or a fireplace application for the iPhone. Maybe you could blow out the fire in the fireplace by blowing on the iPhone's microphone. Users would enjoy this because it would remind them of the famous Three Little Pigs children's story.

The final iFlame application running in the Simulator

Figure 4.7. The final iFlame application running in the Simulator

Since you now have a solid template for playing videos in your applications, another enhancement idea you can consider for the application, and for others you may create, is to create a video splash screen that you play when the user first runs your application. People have come to expect this high level of professionalism from movies, but it is still rare in iPhone applications. Instead of boring text that tells users about your other products, have you considered creating exciting 10-second video commercials? You would only need to add a new screen, then have some thumbnails to allow viewers to pick which of your applications they are interested in.

Programming: iDrum

Let's now take a look at creating another novelty application. This time you will create a virtual drum for the iPhone. The iDrum features a great graphic and sound effect of a drum. You can use the ones we provide or ones of your own. When you are done, you should end up with an application that looks something like the one in Figure 4.8.

To create a virtual drum for the iPhone, follow these steps:

  1. Open Xcode and choose File

    Programming: iDrum
  2. You will use the Utility Application project template that can be found under the iPhone OS application. Select the Utility Application project template and click the Choose button at the bottom right.

  3. Save the new project in a location to your liking and name it iDrum.

  4. Locate the Default.png file that is included with the chapter's materials.

  5. Expand the Resources folder that is located in the Groups & Files panel on the left side of Xcode. Right-click on this folder and choose Add

    Programming: iDrum
  6. Locate the drumbeat.caf file that should also be included in this chapter's materials where you found the Default.png. This is the sound that the iDrum makes when the user taps it. Repeat the same process as before to add the drumbeat.caf to your iDrum project's resources.

  7. Do the same for the drum.png and the drumIcon.png files.

You should always include a Default.png in all of your applications. The iPhone displays the Default.png during the time it takes to load the application. This keeps the user from seeing a blank black screen and wondering if the application is locked up. You can either use the Default.png as an application splash screen as we have done (Figure 4.9), or you can use it to make the application appear to load faster.

You can see a good example of this effect in Apple's iPhone applications; in particular, the Clock application. When you first start the iPhone's Clock application, for the first second or two what you see is actually an image that is being used as the Clock's Default.png on application startup. You can see this image in Figure 4.10. It might not look like much, but this screen is very similar to what the iPhone's Clock application looks like when it is running. Basically all of the background elements for the Clock application are drawn to the screen so it is almost ready even before the application starts.

The iDrum application

Figure 4.8. The iDrum application

The iDrum's Default.png

Figure 4.9. The iDrum's Default.png

Once the Clock application has finished loading, it takes over screen output and you finally see the actual Clock application running on your device, similar to Figure 4.11. This is a great effect, and from the user's point of the view, the iPhone seems to be opening most applications almost instantly.

The native audio format that Apple uses for sounds on the iPhone is the CAF audio format. You can convert your existing MP3, WAV, AAC, AIFF, and other audio files to the CAF format using iTunes.

The iPhone Clock application's Default.png

Figure 4.10. The iPhone Clock application's Default.png

The iPhone Clock application

Figure 4.11. The iPhone Clock application

To convert to CAF, follow these steps:

  1. Set your Import Settings in iTunes to Import Using: AIFF Encoder. Open iTunes Preferences and choose Under General Settings

    The iPhone Clock application
  2. Convert the audio file you want to AIFF. Select the song in iTunes, and choose

    The iPhone Clock application
  3. Rename the audio file to CAF. Drag the newly created song to your desktop and rename the AIFF extension to CAF.

A large part of effectively using the iPhone SDK is learning about all the frameworks that are available for you to take advantage of. Instead of you having to create something from scratch, in many cases these frameworks can do the work for you. The following device framework listing summarizes all the device frameworks that are available:

  • AddressBook.framework. Contains functions for accessing the user's contacts database directly.

  • AddressBookUI.framework. Contains classes for displaying the system-defined people picker and editor interfaces.

  • AudioToolbox.framework. Contains the interfaces for handling audio stream data and for playing and recording audio.

  • AudioUnit.framework. Contains the interfaces for loading and using audio units.

  • CFNetwork.framework. Contains interfaces for accessing the network via the Wi-Fi and cellular radios.

  • CoreAudio.framework. Provides the data types used throughout Core Audio.

  • CoreFoundation.framework. Provides fundamental software services, including abstractions for common data types, string utilities, collection utilities, resource management, and preferences.

  • CoreGraphics.framework. Contains the interfaces for Quartz 2-D.

  • CoreLocation.framework. Contains the interfaces for determining the user's location.

  • Foundation.framework. Contains the classes and methods for the Cocoa Foundation layer.

  • CoreLocation.framework. Contains the interfaces for determining the user's location.

  • IOKit.framework. Contains interfaces used by the device. Do not include this framework directly.

  • MediaPlayer.framework. Contains interfaces for playing full-screen video.

  • OpenAL.framework. Contains the interfaces for OpenAL, a cross-platform positional audio library.

  • OpenGLES.framework. Contains the interfaces for OpenGL ES, an embedded version of the OpenGL cross-platform 2-D and 3-D graphics-rendering library.

  • QuartzCore.framework. Contains the Core Animation interfaces.

  • Security.framework. Contains interfaces for managing certificates, public and private keys, and trust policies.

  • SystemConfiguration.framework. Contains interfaces for determining the network configuration of a device.

  • UIKit.framework. Contains classes and methods for the iPhone application user-interface layer.

iDrum is a good example of an application that uses many existing frameworks to do the work for it. You will need to add the following frameworks to your iDrum project:

  • AudioToolbox

  • CoreAudio

  • OpenAL

  • Foundation

The Frameworks folder can be found under the iDrum project in the Groups & Files panel of Xcode. Right-click on the folder to locate the Existing Frameworks menu item, which is found under the Add menu. Click the Existing Frameworks menu item, and then open the selected Frameworks folder. The full location for these frameworks is Developer

The iPhone Clock application

With the Frameworks folder open, you can begin adding the required frameworks. You'll need to add these one at a time since Xcode does not support multiple selections in this dialog box. After you have added all the required files and frameworks, your project should look like Figure 4.12.

iPhone SDK frameworks added to the iDrum application

Figure 4.12. iPhone SDK frameworks added to the iDrum application

Expand the Main View folder under Groups & Files below the iDrum project. Open the MainView.h file in Xcode. You will need to add an import line to include the SoundEngine.h file:

#import "SoundEngine.h"

You will also add a define directive that will declare a constant for setting the listener distance:

// Used for creating a realistic sound field
#define kListenerDistance         1.0

Next you will need to add an IBAction to capture touches on the drum image and a startBackgroundMusic:

- (IBAction)drum;
- (void) startBackgroundMusic;

Once you are done making all of these changes to your MainView.h file, it should look something like this:

#import <UIKit/UIKit.h>
#import "SoundEngine.h"
// Used for creating a realistic sound field
#define kListenerDistance         1.0
@interface MainView : UIView
{
}
- (IBAction)drum;
- (void) startBackgroundMusic;
@end

You should finish building the screen in Interface Builder before beginning work on the matching MainView.m file. In the Groups & Files panel, find the Resources folder and expand it. Inside you should be able to locate the MainView.xib file. Double-click this file to open it in Interface Builder. Open Interface Builder's Library by choosing Tools

iPhone SDK frameworks added to the iDrum application

Take the Image View and resize it to fill the entire screen. Now open Interface Builder's Inspector tool by choosing Tools

iPhone SDK frameworks added to the iDrum application

Using the pull-down menu, assign the drum.png file to the Image field, and set the Mode to Scale To Fill. This ensures that the image expands to fill all available space. Set Alpha to 1.00 so the image will be completely opaque (Figure 4.13).

Main View Attributes dialog box

Figure 4.13. Main View Attributes dialog box

Now select the Main View window itself. The Inspector window should be titled Main View Attributes. Again, set the Mode to Scale To Fill and Alpha to 1.00. Set the background color to Iron from the color list. Under the Drawing section, check the Opaque check box, and under the Interaction section, check the User Interaction Enabled check box.

At the top of the Inspector window, click on the fourth tab named Main View Identity. Under Class Actions, click the small plus button to add a new Action named drum. Now you will open the MainView.m file. First, you need to add a new sound enumeration to the top of this file:

enum
{
   kSound_Drumbeat = 0,
   kNumSounds
};

The purpose of this enumeration is to simply keep track of how many sounds there are in the application and which one to play at any given time. In this case, the iDrum application has only the drumbeat sound, which is located at index 0. Since the drumbeat sound is set to 1, and kNumSounds is set to 1, everything matches and you have the correct number of sounds available.

Next, you need to add an internal sound variable to track the current playing sound:

UInt32 _sounds[kNumSounds];

For this application it makes sense to have some background music playing in an infinite loop. This way the user has something playing to add to instead of being responsible for everything. You start the background music when the Main View window is loaded:

-(void)awakeFromNib
{
   [self startBackgroundMusic];
}

Now when the application is started and it loads the Main View window, this in turn calls the startBackgroundMusic method on the view:

- (void) startBackgroundMusic
{
NSBundle* bundle = [NSBundle mainBundle];
// Note that each of the Sound Engine functions defined in
// SoundEngine.h returns an OSStatus value.
// Although the code in this application does not check for errors,
// you'll want to add error checking code
// in your own application, particularly during development.
//Setup sound engine. Run it at 44Khz to match the sound files
SoundEngine_Initialize(44100);
// Assume the listener is in the center at the start. The sound
// will pan as the position of the rocket changes.
SoundEngine_SetListenerPosition(0.0, 0.0, kListenerDistance);
// Load each of the four sounds used in the game.
SoundEngine_LoadEffect([[bundle pathForResource:@"background" ofType:@"caf"] UTF8String], &_sounds[kSound_Drumbeat]);
//Play start sound
SoundEngine_StartEffect( _sounds[0]);
}

Now you add the keystone piece. The touchesBegan method triggers the drumbeat sound any time the Main View is touched:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   SoundEngine_StartEffect( _sounds[kSound_Drumbeat]);
}

Be sure to set Xcode to Simulator | Distribution and then click the Build and Go button. The application should now load in the Simulator and run. You should see the iDrum application, as shown in Figure 4.14.

The final iDrum application running in the Simulator

Figure 4.14. The final iDrum application running in the Simulator

The application is mostly done now and just needs some finishing touches. You should create a nice About Us screen for it, and you will need to come up with a great iPhone application icon for users to see both on the App Store and on the iPhone. You might want to consider using the image of the drum itself and then simply resizing it as needed to make your icon.

There are quite a few virtual drum applications on the App Store. What can you do to this application to make it stand out? Well you could add a setting to let people decide what kind of drum they want to play. You could have a standard drum, a Jamaican drum, or a Congo drum for starters.

Tip

The iPhone is a very feature-rich device, and you should always try to use its capabilities to surprise and delight your application's users. If you make your applications high quality and offer great user experiences, people will come back for more. Any time you raise the bar for what people can expect, you have gone from having a customer to having a fan—and you can never have too many of those.

What if when the user tapped the drum the physical iPhone device itself vibrated? In order for an iPhone SDK application to be able to make the device vibrate, the application must include a reference to the AudioToolbox framework. This is not a problem for the iDrum application because it already includes this reference. But you will want to remember this for the next application you write that will support vibration. It will be a real pain if you overlook this detail.

It only takes one line of code to make the iPhone vibrate:

AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

Locate the touchesBegan method in your MainView.m file. It should match the following code:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   SoundEngine_StartEffect( _sounds[kSound_Drumbeat]);
}

You will need to update this method so that it calls the vibration code listed earlier, as follows:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   SoundEngine_StartEffect( _sounds[kSound_Drumbeat]);
   AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}

And there you go—you now have a virtual drum with a force feedback feature, all implemented in one line of code in less than a few minutes' time.

Wouldn't it be great if the drum had a quick animation that played whenever the user tapped it? This would make it much more realistic. What if you create a screen where the user could pick a song and the drum would automatically play it, kind of like how the old player pianos could do? You probably have some ideas of your own as well. What are you waiting for—seize the day!

Programming: Bonfire

The last novelty you are going to create in this chapter is Bonfire. Bonfire is meant to be a virtual campfire that users can carry with them anywhere. And at least with this campfire, nobody has to worry about burning down the forest. When you are finished creating Bonfire, you will end up with an application that looks something like Figure 4.15.

The Bonfire application

Figure 4.15. The Bonfire application

Once again, open Xcode and create a new project using the iPhone OS Utility Application template. Name this new project Bonfire. Go ahead and create a Default.png now and add it to your Bonfire project. To do this, right-click on the Resources folder below the Bonfire project folder in the Groups & Files panel in Xcode. Choose Add

The Bonfire application

This time we choose to let the Default.png file we created match the first frame of the Bonfire animation. This way the application appears to load faster (almost instantaneously) for the end user. You can see the Default.png file we used in Figure 4.16. You can either use the one we provided or create one of your own if you want something more like a splash screen to show.

The Bonfire application's Default.png

Figure 4.16. The Bonfire application's Default.png

It is always best to add a Default.png early on in the iPhone application-making process, even if you only make a temporary Default.png image that has the text "Temporary Default.png" on it, because that way you are less likely to forget to create one in the end. Once you get more involved in the application-making business, it's easy to overlook little details such as including the Default.png image file.

When you created the iFlame application earlier in this chapter, you used the MPMoviePlayerController class to play videos, but we mentioned that you could create animations and play movies that way as long as you had an animation image sequence available of the movie. The Bonfire iPhone application takes this approach to movie playing so you can see how it's done.

The key to making Bonfire is creating the animation image sequence. There are many ways you can create an animation image sequence. One way is to use QuickTime Pro, as we mentioned earlier, to convert an existing video into a sequence of images. You could also take an animated GIF file that you have rights to use and use a program that can pull out each frame of the animation and save it as a separate image.

Of course, you can either have someone create the animation for you or create one of your own. You might think hand-drawn animation would not have the quality required for an iPhone application. But there are many iPhone applications coming out that focus on the fact that they are hand drawn and the characters are stick figures. It has become a genre and style all its own.

Once you have the image sequence you are going to use for Bonfire, you will need to add these images to the Bonfire project. We created an animation sequence consisting of 17 images that, when played in a loop, creates a great animation of a burning campfire. Feel free to use this animation sequence for your own Bonfire application.

You may want to create a new folder to keep all of these animation images in. To add a new folder in Xcode, right-click on the Bonfire project's Resource folder and choose Add

The Bonfire application's Default.png

After you have prepared your Bonfire project with all the resources you need to create the Bonfire iPhone application, your main task is to add the code required to make the Bonfire animation play. Open the MainViewController.m file in Xcode, located under the Main View folder under the Bonfire project in the Groups & Files panel. Find the viewDidLoad method. The viewDidLoad method is implemented by all UIViewController objects, of which the MainViewController class you are in is one. This method is invoked or called when the view is finished loading.

Tip

Don't forget you can use transparency in your animations. You can use images that contain both opaque areas and transparent areas. You can even use images with partial transparency and alpha blended components. This can create some truly stunning effects.

The viewDidLoad method should look like the following code:

/*
If you need to do additional setup after loading the view, override viewDidLoad.
 - (void)viewDidLoad {
 }
*/
Xcode project with all images added

Figure 4.17. Xcode project with all images added

Modify the viewDidLoad until it matches the following version:

- (void)viewDidLoad
{
// create the view that will execute our animation
UIImageView* campFireView = [[UIImageView alloc]
initWithFrame:self.view.frame];
// load all the frames of our animation
campFireView.animationImages = [NSArray arrayWithObjects:
    [UIImage imageNamed:@"campFire01.gif"],
    [UIImage imageNamed:@"campFire02.gif"],
    [UIImage imageNamed:@"campFire03.gif"],
    [UIImage imageNamed:@"campFire04.gif"],
    [UIImage imageNamed:@"campFire05.gif"],
    [UIImage imageNamed:@"campFire06.gif"],
    [UIImage imageNamed:@"campFire07.gif"],
    [UIImage imageNamed:@"campFire08.gif"],
    [UIImage imageNamed:@"campFire09.gif"],
    [UIImage imageNamed:@"campFire10.gif"],
    [UIImage imageNamed:@"campFire11.gif"],
    [UIImage imageNamed:@"campFire12.gif"],
    [UIImage imageNamed:@"campFire13.gif"],
    [UIImage imageNamed:@"campFire14.gif"],
    [UIImage imageNamed:@"campFire15.gif"],
    [UIImage imageNamed:@"campFire16.gif"],
    [UIImage imageNamed:@"campFire17.gif"], nil];
// all frames will execute in 1.75 seconds
campFireView.animationDuration = 1.75;
// repeat the annimation forever
campFireView.animationRepeatCount = 0;
// start animating
[campFireView startAnimating];
// add the animation view to the main window
[self.view addSubview:campFireView];
[campFireView release];
}

Now you should review this code and learn more about how it works.

Here you create a UIImageView and allocate memory for it. On the next line you assign the Main View's frame to the campFireView. The Main View's frame is the view that users see whenever they are on the Main View window. When you modify this view, users automatically see any change you make to it:

// create the view that will execute our animation
UIImageView* campFireView = [[UIImageView alloc]
initWithFrame:self.view.frame];

The UIImageView named campFireView is the real workhorse of this application. Be sure to look up the UIImageView class in Xcode's API Reference. Take a moment and right-click on the text UIImageView and then click Find Selected Text in API Reference and see for yourself. Basically, UIImageView is good for displaying a single image or a series of images as an animation. The documentation covers the details on how to perform many tasks with the UIImageView class, including initializing a UIImageView, animating images with a UIImageView, and enabling and disabling user interaction on UIImageViews.

In this step you are loading all the animation images from the resource image file you added earlier. The animationImages property of UIImageView expects an NSArray of UIImage objects. You must set the last element of the NSArray to nil so that the array will know when the collection ends:

// load all the frames of our animation
campFireView.animationImages = [NSArray arrayWithObjects:
    [UIImage imageNamed:@"campFire01.gif"],
    [UIImage imageNamed:@"campFire02.gif"],
    [UIImage imageNamed:@"campFire03.gif"],
    [UIImage imageNamed:@"campFire04.gif"],
    [UIImage imageNamed:@"campFire05.gif"],
    [UIImage imageNamed:@"campFire06.gif"],
    [UIImage imageNamed:@"campFire07.gif"],
    [UIImage imageNamed:@"campFire08.gif"],
    [UIImage imageNamed:@"campFire09.gif"],
    [UIImage imageNamed:@"campFire10.gif"],
    [UIImage imageNamed:@"campFire11.gif"],
    [UIImage imageNamed:@"campFire12.gif"],
    [UIImage imageNamed:@"campFire13.gif"],
    [UIImage imageNamed:@"campFire14.gif"],
    [UIImage imageNamed:@"campFire15.gif"],
    [UIImage imageNamed:@"campFire16.gif"],
    [UIImage imageNamed:@"campFire17.gif"], nil];

In this line you are informing the iPhone SDK how long you want it to take to play the animation you loaded in the previous step. This can be a bit of a trial-and-error process, but it is simple and direct and usually works out very well. Many times you already have numbers you need either from the original video or animated GIF file:

// all frames will execute in 1.75 seconds
campFireView.animationDuration = 1.75;

Tip

Consider using variables to keep track of your animation durations. This way you can create multipliers that speed up or slow down your animations. On level one all animations take x seconds, but on level two all animations take x * level modifier seconds. This is an easy way to create slow motion and bullet time effects.

If you do the math, the 17 frames you have are being played in an animation of 1.75 seconds. You are basically getting about 10 frames per second here. That's a little low, but if you watch the animation itself, it seems to work out just fine. A possible enhancement to this application would be to add more frames to the animation, but the tradeoff would be a larger final application size.

In the following code, you will set the animation repeat count, start the animation, and assign it to the application's Main View. This line sets the animation repeat count, which does exactly what you would expect. By setting it to 0 you are telling the iPhone SDK to repeat the animation forever:

// repeat the annimation forever
campFireView.animationRepeatCount = 0;

The UIImageView's method startAnimating is used to start the animation playing. You can also call stopAnimating if you wish to stop an animation. And there is an isAnimating instance method you can call in case you need to query the run-time to find out if the animation is still running:

// start animating
[campFireView startAnimating];

Now you need to take the animation you have created and add it to the main window:

// add the animation view to the main window
[self.view addSubview:campFireView];

Finally, you need to make sure that the iPhone SDK knows you are done using the campFireView so that it will release the memory for it when it finishes playing the animation or the application ends:

[campFireView release];

Tip

You can create multiple NSArray objects with different sets of images for your animations. This way when you create a new blue Bonfire animation, it's a simple matter to change all the animations over to use the new images.

It does not make sense to do so in this application, but keep in mind that you can create UIImageView definitions that have animations and that move around the screen. This is a great way to create more advanced game elements to use in other games you may create someday.

Set Xcode to Simulator | Distribution and click the Build and Go button. The application loads up in the Simulator and runs, and you should see the Bonfire application as shown in Figure 4.18.

As always, you want to look back at the path you have taken to get this application to where it is today and decide where you will take it tomorrow. You have a great reusable iPhone animation application template; as long as you can find and come up with great animations, you can keep creating exciting new iPhone applications with minimal effort. It's kind of like once you have a soda factory there is very little stopping you from creating new sodas with different flavors. The hard part is already behind you. Now all you need to do is come up with your own recipe for success.

Screensavers are great sources of inspirations for these types of applications. For example, you could create a little virtual world application that plays an animation of a daytime fantasy world during the daytime and plays a nighttime fantasy world animation at night. Even better would be to have different animations for different weather conditions and play the matching one for the user's location.

Many games have been created by a judicious usage of animations overlaid on one another. Just take animated player characters fighting animated opponents, moving over animated environments in front of animated backgrounds, and you have the makings of a truly great iPhone game.

Almost every application in this book and every application you will create or use could be enhanced and improved by the wise usage of UIImageView animation. Make a point of learning and mastering this technique so you can use it in the next iPhone application you create.

The final Bonfire application running in the Simulator

Figure 4.18. The final Bonfire application running in the Simulator

Analyzing Business Aspects

Novelty applications tend to be smaller and easier applications than most game, business, or even utility applications. Many developers cut their teeth by making a simple novelty application their first application. It can be a great way to ramp up your knowledge of iPhone SDK programming.

Ideally, when you create a new iPhone novelty application, it should be a truly new iPhone application. If your application is really one of a kind and people enjoy the experience of it, it will do much better than if your application is just another face in the crowd. Try to forge new ground and provide people with new experiences whenever possible.

Be sure to add variety to your novelty application whenever you can. Sometimes this can be as simple as creating different skins for your application. For example, for the iDrum you could create a Jamaican drum setting with appropriate matching sound effects. These types of small, easy changes can take an application from mediocre to great.

People love to be surprised, and so they love novelty applications that have surprises in them. Imagine how users would react to finding out that there is an update for the iFlame that allows them to blow out the flame using the microphone. It's a new experience that helps bring their new digital world back into the real world they are familiar with.

Summary

In this chapter you reviewed and created a list of potential iPhone novelty applications that you should now be prepared to begin writing. You reviewed the iFlame application and what you would have to do to re-create this application. You learned to try to always favor original ideas or add a new twist to an existing application idea. You also discovered that it is beneficial to add new features and clever effects to apps. You learned all about seamless video loops and how to create them on your own. You worked with the MPMoviePlayerController to create a movie player of your own to play video in your iFlame application, and you learned about the various video player scaling and control modes.

Next, you reviewed the iDrum application and began re-creating it on your own. You made sure to include a Default.png to avoid showing your users a blank screen on application startup. You learned a lot about how to play audio files on the iPhone using the iPhone SDK's sound engine. And you discovered how to convert various audio file types to the CAF format, which is the native audio format of the iPhone. While re-creating the iDrum application, you learned more about the iPhone's sound engine and the Interface Builder. You got to add both graphic resources and audio resources to your iFlame app and the iDrum project. Then you used these resources to add visuals and audios to your application.

You then learned all the details of creating your own animations using the UIImageView's animation capabilities in the Bonfire app. You learned how to create your own animation image sequences and how to add these UIImages to the animationImages property of the UIImageView. Finally, you discovered how to use and set the various options on the UIImageView so the animation would run according to your wishes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset