How to Create an Interactive Children’s Book for the iPad
Learn how to create your own beautiful animated interactive children’s book for the iPad! By Tammy Coron.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How to Create an Interactive Children’s Book for the iPad
45 mins
- Getting Started
- Adding the Title Page
- Adding the Book Title
- Adding Animation to Objects
- Adding Sound to Your Story
- Detecting Touch Events
- Adding the Next Scene
- Adding Content to the First Page
- Adding the Navigation Controls
- Adding The Main Character
- An Introduction to Physics
- Handling Touches and Moving the Hat
- Adding Page Two
- Adding Page Three
- Where To Go From Here?
Adding Sound to Your Story
There are several methods to add music and other sounds to your book, but in this tutorial you’ll just focus on two methods, one for adding the background music, and the other for adding the narration and sound effects.
Head back to Scene00.m and add the following import statement:
@import AVFoundation;
Add the following private instance variables to Scene00.m
at the spot indicated by the comment /* set up your instance variables here */
:
AVAudioPlayer *_backgroundMusicPlayer;
SKSpriteNode *_btnSound;
BOOL _soundOff;
Next, add the following two lines of code just before the line that creates background
in locate initWithSize:
:
_soundOff = [[NSUserDefaults standardUserDefaults] boolForKey:@"pref_sound"];
[self playBackgroundMusic:@"title_bgMusic.mp3"];
This code retrieves the BOOL
value that represents the user’s preference for having the sound on or off and assigns it to the _soundOff
instance variable.
Now add the following block of code to playBackgroundMusic:
:
NSError *error;
NSURL *backgroundMusicURL = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
_backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:&error];
_backgroundMusicPlayer.numberOfLoops = -1;
_backgroundMusicPlayer.volume = 1.0;
[_backgroundMusicPlayer prepareToPlay];
playBackgroundMusic:
plays the background music using a AVAudioPlayer
object.
AVAudioPlayer
isn’t specific to Sprite Kit, so it won’t be covered in detail here. For more detail on AVAudioPlayer
, check out the Audio Tutorial for iOS.
Okay — you have some code to handle the user preference for enabling or disabling sound in your book. You should probably add a control to let the user set this preference! :]
Still working in Scene00.m
, add the code below to setUpSoundButton
:
if (_soundOff)
{
// NSLog(@"_soundOff");
[_btnSound removeFromParent];
_btnSound = [SKSpriteNode spriteNodeWithImageNamed:@"button_sound_off"];
_btnSound.position = CGPointMake(980, 38);
[self addChild:_btnSound];
[_backgroundMusicPlayer stop];
}
else
{
// NSLog(@"_soundOn");
[_btnSound removeFromParent];
_btnSound = [SKSpriteNode spriteNodeWithImageNamed:@"button_sound_on"];
_btnSound.position = CGPointMake(980, 38);
[self addChild:_btnSound];
[_backgroundMusicPlayer play];
}
The above code sets the texture of the _btnSound
SKSpriteNode
to the appropriate image depending on the user’s stored preference. It then checks _soundOff
and, regardless of its value, removes the sprite from the screen and initializes a new sprite with the appropriate on or off image. Then it sets the sprite’s position, adds it to the parent view, and finally plays or stops the music depending on the user’s preference.
There are a number of ways to handle changing a sprite’s image. The above method is only one way to accomplish this; the next section shows you another way to manage sprite images. The next section shows you another way to accomplish the same thing.
For now, build and run the app, and the background music should play. Tapping the button won’t do anything yet though.
Detecting Touch Events
The reason you can’t currently toggle the control is that the sprite doesn’t have any touch event handlers. So let’s add that next.
Add the following code to touchesBegan:withEvent:
in Scene00.m:
/* Called when a touch begins */
for (UITouch *touch in touches)
{
CGPoint location = [touch locationInNode:self];
// NSLog(@"** TOUCH LOCATION ** \nx: %f / y: %f", location.x, location.y);
if([_btnSound containsPoint:location])
{
// NSLog(@"xxxxxxxxxxxxxxxxxxx sound toggle");
[self showSoundButtonForTogglePosition:_soundOff];
}
}
touchesBegan:withEvent:
is part of the UIResponder
class which all SKNode
s extend. It tells the receiver when one or more fingers begin touching the view. In this method you’re able to capture the location of the touch and respond to it accordingly.
SKNode
extends UIResponder
, you can implement touch handling directly in your sprites. This tutorial performs all touch event handling in the scene nodes simply to keep the number of classes more manageable. However, in a production app it would likely make more sense to create an SKSpriteNode
subclass, such as SoundToggleButton
, and have that subclass handle its own touch events.Look at the if
statement above; you’ll see that if the touch location is on the sound button, you call showSoundButtonForTogglePosition:
.
Now would be a great time to write that method! :]
Add the following code to showSoundButtonForTogglePosition:
in Scene00.m:
// NSLog(@"togglePosition: %i", togglePosition);
if (togglePosition)
{
_btnSound.texture = [SKTexture textureWithImageNamed:@"button_sound_on"];
_soundOff = NO;
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"pref_sound"];
[[NSUserDefaults standardUserDefaults] synchronize];
[_backgroundMusicPlayer play];
}
else
{
_btnSound.texture = [SKTexture textureWithImageNamed:@"button_sound_off"];
_soundOff = YES;
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"pref_sound"];
[[NSUserDefaults standardUserDefaults] synchronize];
[_backgroundMusicPlayer stop];
}
The method above sets the appropriate texture for the SKSpriteNode
that is held in _btnSound
— much as you did in setUpSoundButton
. Once the texture has been set, you can store the user’s selection and either play or stop the music accordingly.
SKTexture
object stores a reference to the graphical data in memory that a sprite renders.Build and run, and now you should be able to tap the sound button to turn the background music on and off.
Adding the Next Scene
Add the following import to the top of Scene00.m:
#import "Scene01.h"
You’ll need this to present the next scene; this is Page 1 of the book and is controlled by the Scene01
class.
Still working in Scene00.m, add the following code to setUpBookTitle
just after the line that creates actionMoveDownFast
, but before the line that calls runAction:
on bookTitle
:
SKAction *wait = [SKAction waitForDuration:0.75];
SKAction *showButton = [SKAction runBlock:^{
SKSpriteNode *buttonStart = [SKSpriteNode spriteNodeWithImageNamed:@"button_read"];
buttonStart.name = @"buttonStart";
buttonStart.position = CGPointMake(425,460);
[self addChild:buttonStart];
[buttonStart runAction:[SKAction playSoundFileNamed:@"thompsonman_pop.wav" waitForCompletion:NO]];
}];
The code above creates a new action block which creates a sprite for the start button and plays a sound. By putting the code to create the sprite and play a sound inside an action, you can easily make this code run in a particular point in a sequence of actions.
As you may have figured out by now, there is usually more than one way to skin a cat — or code your children’s book!
Replace the line in setUpBookTitle
that calls runAction:
on bookTitle
with the following code:
[bookTitle runAction:[SKAction sequence:@[actionMoveDown, actionMoveUp, actionMoveDownFast, wait, showButton]]];
This simply adds the new action to the sequence that bookTitle
runs when called.
The next step is to modify the touch handling in touchesBegan:withEvent:
.
Add the following line to the top of touchesBegan:withEvent:
SKNode *startButton = [self childNodeWithName:@"buttonStart"];
This assigns the button – added earlier in the showButton
action – to the node.
Add the following else if
clause after the if
statement in touchesBegan:withEvent:
:
else if([startButton containsPoint:location])
{
[_backgroundMusicPlayer stop];
// NSLog(@"xxxxxxxxxxxxxxxxxxx touched read button");
Scene01 *scene = [[Scene01 alloc] initWithSize:self.size];
SKTransition *sceneTransition = [SKTransition fadeWithColor:[UIColor darkGrayColor] duration:1];
[self.view presentScene:scene transition:sceneTransition];
}
The above code adds a new scene and presents it with a new transition when it detects a user tap on the “Read Story” button.
Build and run your project. After the initial animation, you should see the new “Read Story” button, as shown below:
Tap the “Read Story” button and the next scene presents itself on-screen. You won’t see a whole lot at this point — your next task is add some content to the first page.