In the flipside view controller, I added image view and text view objects to provide some basic game-play instructions, also shown in Figure 14-2.
Figure 14-2. Initial and flipside interface design
If you were developing this project yourself, you would:
1. Create a new project based on the Utility iOS app template
a. Set the class prefix to ST
b. Make sure Use Core Data is not checked
2. Add the image resources in the SunTouch (Resources) folder to your Images.xcassets image catalog. Drop the icon resources in the SunTouch (Icons) folder into the catalog’s AppIcon group.
3. In the Main_iPhone.xib (or _iPad) file, find the flipside view and follow these steps:
a. If you’re developing the iPad version, the flipside view is presented in a popover. Begin by selecting the Flipside View Controller and, using the attributes inspector, set its simulated metrics size toFreeform. Select the root view and, using the size inspector, set its height to 500.
b. Add image view and text view objects as shown in Figure 14-2. The image resource files used are Strike.png, SunHot.png, and SunCold.png. The text is white, with a black background that’s 50%transparent.
c. Add one more image view object, set its image to Starfield.png, its mode to Aspect Fill, and resize it to fill the view. With the image view selected, choose Edit ➤ Arrange ➤ Send to Back. This will put thestar image behind the other view objects.
d. Pin the height and the width of the image view with the Strike image.
For the background image view, add constraints so its top, bottom, left, and right edges are flush (0 pixels from) with the Top Layout Guide, Bottom Layout Guide, leading container, and trailingcontainer,
respectively. If you arrange the other views so they’re clearly visible on a 3.5” iPhone, you don’t need any other constraints.
4. In the main view controller:
a. Add two button objects, labeled Single Player and Two Player. Set their shadow color to White Color. (This makes the button text easier to read on the dark background.)
b. Add a Vertical Spacing constraint from the lower button to the Bottom Layout Guide, another from the upper button to the lower one, and then horizontally center both buttons in the container view.
c. Add an image view object, set its image to Billboard-iPhone.png, and resize it to fill the view. Arrange it behind the other views. Use the Editor
➤ Pin submenu to pin its top, bottom, leading, and trailing space to its
superview.
d. Select the Main View Controller (iPhone version only) and use the attributes inspector to set its status bar option to None. This will hide the status bar information (battery, Wi-Fi indicator, and soone) that’s normally at the top of the display.
e. In the iPad version, change the title of the “Info” navigation bar button to “Instructions.”
Run the project and test the flipside view, as shown in Figure 14-3. The code that accomplishes this is supplied by the template, and can be found in the STMainViewController and
STFlipsideViewController classes.
Figure 14-3. Testing the game instructions
So far, the game is looking pretty snazzy. It’s a shame there’s no actual game yet. The next step is to create the single-player version of the game. This will become the foundation for integrating with Game Center and addingnetworking.
Creating the Single Player Version
The code for the single player game is in the Learn iOS Development Projects ➤ Ch 14 ➤ SunTouch-2
folder. This version of the project adds 12 files:
STGameDefs.h
STGameViewController.h, STGameViewController.m, STGameViewController.xib STGameView.h, STGameView.m
STStrike.h, STStrike.m STSun.h, STSun.m STGame.h, STGame.m
The STGameDefs.h is a header file containing constants, macros, and in-line functions used by most of the other files. In larger projects, it’s common to collect all of the globally relevant definitions into a single file that can beimported by whatever modules need them.
The game starts when the user taps the “single player” button in the main storyboard. A new view controller was added to the storyboard and its class changed to STGameViewController, as shown in Figure 14-4. A modal seguewas added from the single player button to the new view controller.
The segue was given the identifier singlePlayer. The game starts when the STGameViewController
is presented.
Figure 14-4. View controllers in storyboard
Loading STGameViewController
This project has an unusual Interface Builder file organization. So far, you’ve developed projects where the interfaces were all designed in a single storyboard file. This project defines the interfaces for the initial view and theflipside view in the storyboard file. The view objects for the STGameViewController, however, are defined in a separate STGameViewController.xib file. A view controller can obtain its view objects from a scene in a storyboard, itsown .xib file, or can create them programmatically. Here’s how it works:
1. When a view controller is loaded from a storyboard, it and its view objects are (normally) created at the same time. The view controller’s view objects already exist when it’s time to present the interface, sothere’s nothing more to do. This is the typical arrangement when using storyboards.
2. If the view controller is asked to present its interface and it doesn’t have any view objects, it sends itself a -loadView message. The -loadView method first looks for the Interface Builder resource file thecontroller was initialized with. This applies when you programmatically create a view controller using the-initWithNibName:bundle: method. When creating view controller this way, it’s recommended that you explicitly tell the view controller the name of the file that contains its interface.
3. If the view controller doesn’t have an explicit .xib filename, it tries to load the interface file with the same name as its class, which in this case is STGameViewController.xib. This is howSTGameViewController loads its interface in SunTouch.
4. Finally, if there were no views in the storyboard file, and no.xib file can be loaded,the -loadView method creates an empty UIView object as its view.
In SunTouch you get the STGameViewController to load its interface from the STGameViewController.xib file by deleting its interface in the storyboard. Figure 14-5 shows the root view object for the STGameViewController being deleted in Interface Builder. Once deleted, the view controller appears hollow, as shown on the right in Figure 14-5.
Figure 14-5. Deleting STGameViewController’s view objects
So why did I do this? When using storyboards for a universal app, you must lay out your interface twice: once for the iPhone and again for the iPad. For interfaces like the game instructions, this is great, since the iPhone and iPad versionare substantially different. The interface for STGameViewController, however, works equally well on the iPhone and iPad. By deleting the interface in the storyboard files, and supplying an STGameViewController.xib file, both the iPhone andiPad version load the same Interface Builder file. Now you have a single STGameViewController.xib file to maintain. You’ll see where this reduces the work you have to do when you get to the two-player version of the game.
How SunTouch Works
I’m not going to explain everything in detail, but here’s an overview of how the game works. The
-viewDidAppear: method in STGameViewController starts everything when it sends itself the -startGame
message. -startGame creates an STGame object (the game engine), connects it to the STGameView
object, and then starts the game engine and the strike preview animation.
Gameplay works through messages sent to the STGame object. When the user touches the screen, a
-touchInGame:event: action is sent to the game view controller. The controller determines where the user touched and sends a -strike:radius:inView: message to the game engine.
The game engine maintains the list of hidden suns. It uses the strike coordinates and radius to determine if a strike will capture a sun. These strike and capture events are communicated
to the game view via notifications (kGameStrikeNotification and kGameSunCaptureNotification). The game view observes these notifications and creates the animations that you see on the screen.
The game engine also posts a kGameScoreDidChangeNotification notification whenever the score changes, and a kGameDidEndNotification notification when it’s all over. The game and main
view controllers observe these notifications to update the score view and dismiss the game view controller at the end. The game view controller also keeps two other animations going: the score weight is periodically updatedusing a timer (NSTimer) and the strike preview animation is restarted after each strike.
There are two interesting aspects of the game’s design. First, there’s the game space coordinate system. The location of the hidden suns, the coordinates of strikes, the size of the strike radius, and so on are stored andcalculated using a logical coordinate system with values and distances between 0.0 and 1.0. “Why” you ask? Because the two-player game must translate between the coordinates of two iOS devices. The two players couldbe using different size devices, possibly in different orientations. By performing all game-play calculations in a unit coordinate system, these differences can be ignored. A sun at unit coordinates (0.25,0.25) is in the upper-leftquadrant of
the screen, regardless if that screen is an iPod Touch in landscape orientation or an iPad in portrait orientation. Methods in STGameView (-pointFromUnitPoint:, and so on) translate between game unit and view coordinates.
Customizing Core Animations
The other features you may want to look at are the animations. SunTouch uses several Core Animation sequences. Many animations use the block-based methods you learned in Chapter 11, but sometimes you need ananimation that doesn’t run in a straight line or uses one of the simple animation curves (ease in, ease out, ease in-out, or linear). In these situations, you need to create a CAAnimation object yourself.
Look at the code in -startStrikeGrowAnimation that you’ll find in STGameViewController.m. This code creates an animation that changes the size of the strike preview image view object over time:
NSMutableArray *times = [NSMutableArray new]; NSMutableArray *values = [NSMutableArray new]; CGRect rect;
for ( float time=0.0f; time<=1.0f; time+=0.1f )
{
CGFloat r = STFloor((maxRadius-kStrikePreviewMinRadius)
*STSquareRoot(time)
+kStrikePreviewMinRadius);
rect = CGRectMake(0,0,r*2,r*2); [times addObject:@(time)];
[values addObject:[NSValue valueWithCGRect:rect]];
}
CAKeyframeAnimation* animation;
animation = [CAKeyframeAnimation animationWithKeyPath:@"bounds"]; animation.duration = kStrikePreviewGrowDuration; animation.beginTime = 0;
animation.calculationMode = kCAAnimationCubic; animation.keyTimes = times;
animation.values = values;
[previewView.layer addAnimation:animation forKey:@"grow"];
This code creates a keyframe animation (CAKeyframeAnimation) object. CAKeyframeAnimation is a subclass of CAAnimation, used to manage an animation sequence. A keyframe animation defines several referencevalues at specific times during the animation. The animation object can then calculate a continuous curve of values by interpolating between keyframe values.
A CAKeyframeAnimation object can animate almost any property of the view object: its frame, center, background color, rotation, scaling, transparency, drop shadow, a Core Image color filter, and so on. By creating asequence of keyframe values, you can create any animation curve you want. You can make the view bounce, wink in and out, loop in a circle, pulse, or swing like a pendulum.
In this app, the keyframe defines a logarithmic size change. The code calculates 11 keyframe values at equidistant times (0.0 to 1.0, in 0.1 increments). The value of each keyframe is the view’s bounds, which is scaled based onthe elapsed time, squared. Intermediate values are calculated using cubic interpolation, which will closely approximate to the actual logarithmic curve; it’s not perfect, but it’s good enough.
Once the animation object is configured with the list of keyframe values and times, it is attached to the layer property of the view object. Remember (from Chapter 11) that UIView objects are built from CALayer objects. It’s theCALayer object that actually appears in the interface, and is the object that can be animated.
Playing the Game
Run the app and give it a try, as shown in Figure 14-6. The single-player game will run in the simulator or on any provisioned device.
Figure 14-6. Single player game
I recommend that you spend a little time exploring this project. Start by observing how the interface elements work: the strike animation, the hole left behind afterwards, the sun capture animation,
the updating score and weight labels, and the strike size preview. Then trace the messages that make those things happen until you’re comfortable with how the whole app works. Understanding how strikes are sent to thegame (STGame) and how the game sends sun capture messages will be important when you get to the two-player version.
The next step is to add the GameKit to your app and integrate it with the Game Center.
Plugging into Game Center
Game Center is a service, provided by Apple, to enhance your game with social networking. Apps that work with Game Center are said to be Game Center–aware. The most visible part of the Game Center is its leaderboard, apublic scoreboard displaying the highest scoring players from around the world. Game milestones, called achievements, that you’ve accomplished are also announced here.
Multi-player games can use Game Center to invite, and connect, with other players. This process is called matchmaking. Matchmaking can happen over the Internet at large, for slow games that can be played over arbitrary distances. Alternatively, your app can pair with iOS devices in your immediate vicinity (technically, on the same Wi-Fi subnet or within Bluetooth range), creating direct data connections for playing real-time action games.
It’s your choice what Game Center features you support in your game. You can add all of these features, or just one. For SunTouch, you’re going to add two: leaderboard scores and local matchmaking. For this to work, youmust enable your app to use Game Center and configure Game Center for your game.
Configuring a Game Center–aware app
Enabling Game Center in your app is a multi-step process that involves configuring your app’s project, configuring the iTunes Store, and adding specific code to your app. Specifically, you must:
Assign your app a unique ID Register your unique ID with Apple
Register your app with Apple and assign it that unique ID
Configure the Game Center with the leaderboards and achievements your app will use
Add the necessary digital certificates required for your app to use the Game Center servers
Link your app to the GameKit framework Add “gamekit” as a capability of your app Add code to log the current player in
Add a button so the user can access the Game Center leaderboards from within your app
Request matchmaking when starting a multi-player game Send scores and achievements to Game Center
Create a test player account and test your game in the sandbox
That sounds like a lot of steps, but none of them are particularly difficult and Xcode will do a lot of them for you.
Start with your app’s project. Select the project in the navigator and switch to General tab and find the Identity group, as shown in Figure 14-7.
It should be right at the top.
Figure 14-7. Editing the app ID
The bundle identifier uniquely identifies your app, in the universe of all iOS apps. The identifier can be any (RFC1034 compliant) name. If you (or your company) own an Internet domain, it’s recommended that you base your app identifiers on that domain name, reducing the chance that someone else might try to use the same identifier. You can also add sub-domains to help you organize your apps into groups.
Enabling Game Center
While still in the SunTouch target’s properties, switch to the Capabilities tab, as shown in Figure 14-8.
Locate the Game Center group and turn it on. With that single click, Xcode does the following for you: Generates a unique app ID, based on your app’s bundle identifier
Connects with the iOS Dev Center and registers the new ID with Apple Enables Game Center services for the new ID
Downloads the necessary Game Center entitlements and digital certificates, installing those resources into your app’s project
Adds the “gamekit” key to your app’s required device capabilities Links your app to the GameKit framework
Figure 14-8. Enabling Game Center
See, I told you a lot of the steps were easy. If you want to see what Xcode did in the Dev Center, log into http://developer.apple.com/devcenter/ios, click on the Certificates, Identifiers & Profiles section, and click on Identifiers. Thedeveloper portal will list all of the identifiers registered to your account. Click on the identifier generated by Xcode, as shown in Figure 14-9.
Figure 14-9. Registered App ID
Your app’s full ID consists of the unique Prefix (generated by Apple) and its app ID, concatenated together. Notice that Game Center services have already been enabled for use with this app ID. The name of your ID (Xcode iOS App IDcom apress learniosapps SunTouch) that was generated by Xcode is awkward, but you can change that at any time by clicking the Edit button. The name of an identifier
is solely for managing IDs in the iOS Dev Center; it doesn’t appear anywhere in your app or to the user.
In the edit ID page, you can also manually disable or enable services associated with this ID.
The next step is to configure Game Center with the leaderboards you want. A leaderboard is where game scores are posted. But before you can get to that, you must create an app in the iTunes App Store.








No comments:
Post a Comment