Learning Cocos2D

This book teaches you how to use Cocos2D to make your own games, taking you step by step through the process of making an actual game.

Rod Strougo, Ray Wenderlich

634 Pages

33652 Reads



PDF Format

5.64 MB

Game Development

Download PDF format

  • Rod Strougo, Ray Wenderlich   
  • 634 Pages   
  • 19 Feb 2015
  • Page - 1

    read more..

  • Page - 2

    Praise for Learning Cocos2D“If you’re looking to create an iPhone or iPad game, Learning Cocos2D should be the first book on your shopping list. Rod and Ray do a phenomenal job of taking you through the entire process from concept to app, clearly explaining both how to do each step as well as why you’re dong it.”—Jeff LaMarche, Principal, MartianCraft, LLC, and coauthor of Beginning iPhone Development (Apress, 2009)“This book provides an excellent introduction to iOS 2D game read more..

  • Page - 3

    This page intentionally left blank read more..

  • Page - 4

    Learning Cocos2D read more..

  • Page - 5

    read more..

  • Page - 6

    Learning Cocos2DA Hands-On Guide to Building iOS Games with Cocos2D, Box2D, and ChipmunkRod StrougoRay WenderlichUpper Saddle River, NJ • Boston • Indianapolis • San FranciscoNew York • Toronto • Montreal • London • Munich • Paris • MadridCapetown • Sydney • Tokyo • Singapore • Mexico City read more..

  • Page - 7

    Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and the pub-lisher was aware of a trademark claim, the designations have been printed with initial capital letters or in all capitals.The authors and publisher have taken care in the preparation of this book, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is read more..

  • Page - 8

    ❖Dedicated to my wife, Agata.—RodDedicated to my wife, Vicki.—Ray❖ read more..

  • Page - 9

    This page intentionally left blank read more..

  • Page - 10

    Contents at a Glance Preface xxi Acknowledgments xxxiii About the Authors xxxviiI Getting Started with Cocos2D 1 1 Hello, Cocos2D 3 2 Hello, Space Viking 23 3 Introduction to Cocos2D Animations and Actions 57 4 Simple Collision Detection and the First Enemy 83II More Enemies and More Fun 115 5 More Actions, Effects, and Cocos2D Scheduler 117 6 Text, Fonts, and the Written Word 151III From Level to Game 167 7 Main Menu, Level Completed, and Credits Scenes 169 8 Pump Up the Volume! read more..

  • Page - 11

    Contents at a GlancexV Particle Systems, Game Center, and Performance 479 14 Particle Systems: Creating Fire, Snow, Ice, and More 481 15 Achievements and Leaderboards with Game Center 495 16 Performance Optimizations 545 17 Conclusion 565 A Principal Classes of Cocos2D 569 Index 571 read more..

  • Page - 12

    Contents actionGoTo:22, actionGoTo:22,Preface actionGoTo:22, actionGoTo:22,xxi actionGoTo:34, actionGoTo:34,Acknowledgments actionGoTo:34, actionGoTo:34,xxxiii actionGoTo:38,About the Authors actionGoTo:38, actionGoTo:38,xxxviiactionGoTo:40,I actionGoTo:40,Getting Started with Cocos2D actionGoTo:40, actionGoTo:40,1actionGoTo:42, 1 Hello,actionGoTo:42, actionGoTo:42,Cocos2D actionGoTo:42, 3actionGoTo:43,Downloading and Installing CactionGoTo:43,ocos2D actionGoTo:43, read more..

  • Page - 13

    ContentsxiiactionGoTo:73,Commanding the Cocos2D actionGoTo:73,Director actionGoTo:73, actionGoTo:73,34actionGoTo:74,AddingactionGoTo:74, MovementactionGoTo:74, actionGoTo:74, actionGoTo:74,35Importing the Joystick Classes 35Adding the Joystick and Buttons 36Applying Joystick Movements to Ole the Viking 40actionGoTo:83,Texture Atlases actionGoTo:83, actionGoTo:83,44Technical Details of Textures and Texture Atlases 45Creating the Scene 1 Texture Atlas 48Adding the Scene 1 Texture Atlas to read more..

  • Page - 14

    ContentsxiiiactionGoTo:151,Summary actionGoTo:151, 112actionGoTo:152,ChallengesactionGoTo:152, actionGoTo:152, 113actionGoTo:154,II actionGoTo:154,MoreactionGoTo:154, Enemies and MactionGoTo:154,oreactionGoTo:154, Fun actionGoTo:154, actionGoTo:154,115 actionGoTo:156,5 actionGoTo:156,MoreactionGoTo:156, Actions, EffeactionGoTo:156,cts, and Cocos2D actionGoTo:156,Scheduler actionGoTo:156, 117actionGoTo:157,Power-UpsactionGoTo:157, actionGoTo:157, 118Mallet Power-Up 118Health Power-Up read more..

  • Page - 15

    ContentsxivactionGoTo:206,III actionGoTo:206,From Level toactionGoTo:206, Game actionGoTo:206, actionGoTo:206,167 actionGoTo:208,7 actionGoTo:208,Main Menu, Level CactionGoTo:208,ompleted, and Credits actionGoTo:208,ScenesactionGoTo:208, actionGoTo:208, 169actionGoTo:208,ScenesactionGoTo:208, in Cocos2D actionGoTo:208, actionGoTo:208,169actionGoTo:209,Introducing the GameManager actionGoTo:209, actionGoTo:209,170Creating the GameManager 172actionGoTo:218,Menus in Cocos2D actionGoTo:218, read more..

  • Page - 16

    ContentsxvactionGoTo:261,Adding Sound Effects to OlactionGoTo:261,e the Viking actionGoTo:261, actionGoTo:261,222Adding the Sound Method Calls in changeState for Ole 226actionGoTo:267,AddingactionGoTo:267, Music to the actionGoTo:267,Menu ScreenactionGoTo:267, actionGoTo:267, actionGoTo:267,228Adding Music to Gameplay 228Adding Music to the MainMenu 228actionGoTo:268,For the MoreactionGoTo:268, Curious: IfactionGoTo:268, You NeedactionGoTo:268, MoreactionGoTo:268, Audio read more..

  • Page - 17

    ContentsxviAdding Box2D Files to Your Project 284Box2D Units 288actionGoTo:328,Hello,actionGoTo:328, Box2D!actionGoTo:328, actionGoTo:328, actionGoTo:328,289Creating a Box2D Object 292Box2D Debug Drawing 295Putting It All Together 296Creating Ground 299actionGoTo:341,Basic Box2D InteracactionGoTo:341,tion and DecoratioactionGoTo:341,nactionGoTo:341, actionGoTo:341, actionGoTo:341,302Dragging Objects 304Mass, Density, Friction, and Restitution 309Decorating Your Box2D Bodies with read more..

  • Page - 18

    Contentsxvii actionGoTo:414,12actionGoTo:414, actionGoTo:414,AdvancedactionGoTo:414, GameactionGoTo:414, Physics:actionGoTo:414, EvenactionGoTo:414, BetteractionGoTo:414, thanactionGoTo:414, theactionGoTo:414, Real actionGoTo:414,Thing actionGoTo:414, 375actionGoTo:415,JointsactionGoTo:415, and Ragdolls: BactionGoTo:415,ringingactionGoTo:415, Ole BackactionGoTo:415, actionGoTo:415,into ActionactionGoTo:415, actionGoTo:415, actionGoTo:415,376Restricting Revolute Joints 376Using Prismatic read more..

  • Page - 19

    ContentsxviiiactionGoTo:506,The Great Escape! actionGoTo:506, actionGoTo:506,467Following Ole 467Laying Out the Platforms 468Animating Ole 469Music and Sound Effects 473Adding the Background 474Adding Win/Lose Conditions 476actionGoTo:516,Summary actionGoTo:516, 477actionGoTo:516,ChallengesactionGoTo:516, actionGoTo:516, 477actionGoTo:518,V actionGoTo:518,Particle Systems, Game Center, actionGoTo:518,and actionGoTo:518,Performance actionGoTo:518, 479 actionGoTo:520,14actionGoTo:520, read more..

  • Page - 20

    ContentsxixTry to Authenticate the Player 507Keep Informed If Authentication Status Changes 508The Implementation 508actionGoTo:554,Setting Up Achievements actionGoTo:554, actionGoTo:554,515Adding Achievements into iTunes Connect 515How Achievements Work 517actionGoTo:557,ImplementingactionGoTo:557, AchievementsactionGoTo:557, actionGoTo:557, actionGoTo:557,518Creating a Game State Class 519Creating Helper Functions to Load and Save Data 522Modifying GCHelper to Send Achievements read more..

  • Page - 21

    ContentsxxactionGoTo:604, 17actionGoTo:604, actionGoTo:604,ConclusionactionGoTo:604, actionGoTo:604, actionGoTo:604,565actionGoTo:606,WhereactionGoTo:606, toactionGoTo:606, GoactionGoTo:606, fromactionGoTo:606, HereactionGoTo:606, actionGoTo:606, actionGoTo:606,567actionGoTo:606,Android and BeyondactionGoTo:606, actionGoTo:606, actionGoTo:606,567actionGoTo:607,Final Thoughts actionGoTo:607, actionGoTo:607,568 actionGoTo:608,A actionGoTo:608,PrincipalactionGoTo:608, Classes read more..

  • Page - 22

    actionGoTo:12,PrefaceSo you want to be a game developer?Developing games for the iPhone or iPad can be a lot of fun. It is one of the few things we can do to feel like a kid again. Everyone, it seems, has an idea for a game, and what better platform to develop for than the iPhone and iPad?What stops most people from actually developing a game, though, is that game devel-opment covers a wide swath of computer science skills—graphics, audio, networking—and at times it can seem like you are read more..

  • Page - 23

    Prefacexxiithrough this book, you’ll have made a complete game. Best of all, you’ll have the con-fidence and knowledge it takes to make your own.Each chapter describes in detail a specific component within the game along with the technology required to support it, be it a tile map editor or some effect we’re cre-ating with Cocos2D, Box2D, or Chipmunk. Once an introduction to the functional-ity and technology is complete, the chapter provides details on how the component has been read more..

  • Page - 24

    Prefacexxiiiyou. Other useful utilities include font rendering, sprite sheets, a robust sound system, and many more. Cocos2D is a great prototyping tool. You can quickly make a game in as little as an hour (or however long it takes you to read Chapter 2). You are reading this book because you want to make games for the iPhone and iPad, and using Cocos2D is the quickest way to get there—bar none.Cocos2D Key FeaturesStill unsure if Cocos2D is right for you? Well, check out some of these amazing read more..

  • Page - 25

    PrefacexxivAn Extensive Effects LibraryCocos2D includes a powerful particle system that makes it easy to add cool effects such as smoke, fire, rain, and snow to your games. Also, Cocos2D includes built-in effects, such as f lip and fading, to transition between screens in your game.Great for TileMap GamesCocos2D includes built-in support for tile-mapped games, which is great when you have a large game world made up of small reusable images. Cocos2D also makes it easy to move the camera around to read more..

  • Page - 26

    PrefacexxvOpenGL ESOpenGL ES is a mobile version (ES stands for Embedded Systems) of the Open Graph-ics Language (OpenGL). It is the closest you can get on the iPhone or iPad to sending zeros and ones to the GPU. OpenGL ES is the fastest way to render graphics on the iPhone or iPad, and due to its origin, it is a low-level API. If you are new to game development, OpenGL ES can have a steep learning curve, but luckily you don’t need to know OpenGL ES to use Cocos2D. The two versions of OpenGL read more..

  • Page - 27

    PrefacexxviThis book teaches you how to use all of the features and capabilities of Cocos2D, but more important, how to apply them to a real game. By the time you are done, you will have the knowledge and experience needed to get your own game in the App Store. The concepts you learn from building Space Viking apply to a variety of games from action to puzzle.Space Viking’s StoryEvery game starts in the depths of your imagination, with a character and storyline that gets transformed into a read more..

  • Page - 28

    Prefacexxviiconcept art that Eric Stevens, a graphic artist and fellow game devotee, developed ear-lier when we were discussing game ideas to make next. Space Viking consists of a number of levels, each of which demonstrates a specific area of Cocos2D or gameplay type. For example, the first level is a side-scrolling beat ’em up, and the fourth level is a mine cart racing level that shows off the game physics found in Box2D and Chipmunk. Our hope is that you can reuse parts of Space Viking to read more..

  • Page - 29

    PrefacexxviiinChapter 3: Introduction to Cocos2D Animations and ActionsIn this chapter, you learn how to make the game look much more realistic by adding animations to Ole as he moves around the scene. nChapter 4: Simple Collision Detection and the First EnemyIn this chapter, you learn how to implement simple collision detection and add the first enemy to your Space Viking game, so Ole can start to fight his way off the planet!nPart II: More Enemies and More FunLearn how to create more complex read more..

  • Page - 30

    PrefacexxixnPart IV: Physics EnginesWith the Box2D and Chipmunk physics engines that come with Cocos2D, you can add some amazing effects to your games, such as gravity, realistic collisions, and even ragdoll effects! In these chapters you get a chance to add some physics-based levels to Space Viking, from simple to advanced! nChapter 10: Basic Game Physics: Adding Realism with Box2DJust as Cocos2D makes it easy to make games for the iPhone without know-ing low-level OpenGL details, Box2D makes read more..

  • Page - 31

    PrefacexxxnChapter 16: Performance OptimizationsIn this chapter, you learn how to tackle some of the most common chal-lenges and issues you will face in optimizing and getting the most out of your Cocos2D game. You get hands-on experience debugging the most common performance issues and applying solutions.nChapter 17: ConclusionThis final chapter recaps what you learned and describes where you can go next: into 3D, using Cocos2D on other platforms such as Android, and more advanced read more..

  • Page - 32

    PrefacexxxiIt is expected that before you read this book you are already familiar with Objective-C, C, Xcode, and Interface Builder. While the implementations described in this book have been kept as simple as possible, and the use of C is limited, a firm foundation in these languages is required.The following books can help provide you with the grounding you need to work through this book:nCocoa Programming for Mac OS X, Third Edition, by Aaron Hillegass (Addison-Wesley, 2008)nLearning read more..

  • Page - 33

    This page intentionally left blank read more..

  • Page - 34

    actionGoTo:12,AcknowledgmentsThis book would not have been possible without the hard work, support, and kindness of the following people:nFirst of all, thanks to our editor, Chuck Toporek, and his assistant, Olivia Basegio. Chuck patiently helped and encouraged us during the entire process (even though we are both first-time authors!) and has managed all of the work it takes to convert a simple Word document into the actual book you’re holding today. Olivia was extremely helpful through the read more..

  • Page - 35

    Acknowledgmentsxxxivthe chapter on audio. Steve’s work has allowed many game developers to quickly and easily add music and sound effects to their games.nEric Stevens is an American fine artist who moonlights as a game illustrator. Years of good times and bad music contributed to the initial concept of Space Viking. Eric worked closely with us to bring Ole and everything you see in Space Viking to life. Eric maintains an illustration site at read more..

  • Page - 36

    AcknowledgmentsxxxvFinally, I thank all of the readers and supporters of my iOS tutorial blog at actionURI(www.raywenderlich.com):www.actionURI(www.raywenderlich.com):raywenderlich.com. Without your interest, encouragement, and support, I wouldn’t have been as motivated to keep writing all the tutorials and might have never had the opportunity to write this book. Thank you so much for making this possible, and I hope you enjoy this book! read more..

  • Page - 37

    This page intentionally left blank read more..

  • Page - 38

    actionGoTo:12,About the AuthorsRod Strougo is the founder and lead developer of the studio Prop Group at actionURI(www.prop.gr):www.prop.gr. Rod’s journey in physics and games started way back with an Apple ][, writing games in Basic. From the early passion in games, Rod’s career moved to enter-prise software development, spending 10 years writing software for IBM and recently for a large telecom company. These days Rod enjoys helping others get started on their paths to making games. read more..

  • Page - 39

    This page intentionally left blank read more..

  • Page - 40

    actionGoTo:12,PartactionGoTo:12, IactionGoTo:12,Getting Started with actionGoTo:12,Cocos2DLearn how to install Cocos2D and start using it to create Space Viking.Learn how to add animations and movements to Ole the Viking and his enemies.nChapter 1: “Hello, Cocos2D”nChapter 2: “Hello, Space Viking”nChapter 3: “Introduction to Cocos2D Animations and Actions”nChapter 4: “Simple Collision Detection and the First Enemy” read more..

  • Page - 41

    This page intentionally left blank read more..

  • Page - 42

    actionGoTo:12,1actionGoTo:12,Hello,actionGoTo:12, Cocos2DCocos2D is incredibly fun and easy to use. In this chapter you will learn how to install Cocos2D, integrate it with Xcode, and make a simple HelloWorld app. You’ll then add a space cargo ship to the app and have it move around the screen, with just a few lines of code, as shown in Figure 1.1.Figure 1.1 The space cargo ship that you will add to your HelloWorld appAfter you create this simple app, you will get a chance to go behind the read more..

  • Page - 43

    Chapter 1 Hello, Cocos2D4This chapter walks you through the process of downloading and installing Cocos2D and inte-grating it with Xcode. Once Cocos2D is installed, you’ll build a simple HelloWorld app and test it in the iPhone Simulator. You will learn exactly what each line in the HelloWorld program does as well as how to get HelloWorld on your iOS device. Ready? Okay then, let’s get started!actionGoTo:12,Downloading and InstalliactionGoTo:12,ng Cocos2DThis section walks you through the read more..

  • Page - 44

    Downloading and Installing Cocos2D5In this subfolder is where you will find the install_templates.sh script that you need to run next.NoteYou have two paths to get Cocos2D on your system: you can go with the latest stable branch at the Cocos2D homepage, shown on the previous page, or with the latest develop branch by using Git. The newest features always start life in the develop branch, in the same way as Apple releases the new versions of iOS as beta. Which mechanism you choose is up to read more..

  • Page - 45

    Chapter 1 Hello, Cocos2D6The install-templates.sh script copies the three Cocos2D templates into the Xcode folder. That is all it takes to install the Cocos2D templates. Restart Xcode if you had it running while installing the templates, and you will be ready to create a Cocos2D HelloWorld in the next section.actionGoTo:12,Creating Your First CocactionGoTo:12,os2DactionGoTo:12, HelloWorldNo more delays: time to dive in to the code. In this section you will learn to use the Cocos2D templates that read more..

  • Page - 46

    Creating Your First Cocos2D HelloWorld7The three Cocos2D templates provide three different versions of a simple HelloWorld application. The Cocos2D Application template has just Cocos2D and is what you will use to create the HelloWorld app. The Box2D template creates a mini Box2D HelloWorld where you can drop boxes into the screen with physics simulation. The Chipmunk template creates a mini Chipmunk project where you can create multiple bodies and try out collisions.When you are building your read more..

  • Page - 47

    Chapter 1 Hello, Cocos2D8Figure 1.6 Showing the CCHelloWorld and iPhone Simulator on the Scheme dropdown4. In Xcode on the Scheme dropdown, select CCHelloWorld and the iPhone Simulator (4.2 or the latest iOS you have installed on your system), as shown in Figure 1.6.Figure 1.7 The Cocos2D HelloWorld app running in the iPhone Simulator5. In Xcode, click Run.You now have a fully functional Cocos2D HelloWorld app running in the iPhone Simulator, as shown in Figure 1.7.The Cocos2D CCHelloWorld read more..

  • Page - 48

    Creating Your First Cocos2D HelloWorld9Taking HelloWorld FurtherWhile displaying “Hello World” on the screen is a good first step, you are learning about Cocos2D to create games, so why not add a quick space cargo ship here and make it move?To start, locate the SpaceCargoShip folder included with the resources for this chap-ter. The SpaceCargoShip folder contains the SpaceCargoShip.png, which is the image of—what else?—the alien’s space cargo ship.In Xcode with the HelloWorld project read more..

  • Page - 49

    Chapter 1 Hello, Cocos2D10Click Run, and you should see the space cargo ship in the middle of the screen, as shown in Figure 1.9.Figure 1.9 Space cargo ship in HelloWorldOnly three lines of code, and you already have a space cargo ship on your iOS device. You will learn in-depth about the details behind the lines in Listing 1.1 in the next chapters.Adding MovementA ship is supposed to move around, and moving sprites in Cocos2D is really easy. Add the lines shown in Listing 1.2 right below the read more..

  • Page - 50

    For the More Curious: Understanding the Cocos2D HelloWorld11Hopefully, this has been one of the simplest HelloWorld programs you have tried out: you only had to type five lines of code. Getting started with Cocos2D is easy, and you can render some amazing effects and graphics with very little code. In the next chapter you will start building Space Viking by putting Ole the Viking and the controls on the screen. You will go from this HelloWorld to a Viking you can move on the screen in one short read more..

  • Page - 51

    Chapter 1 Hello, Cocos2D12Each scene in Cocos2D consists of one or more layers, which are composited on top of each other. For example, in building Space Viking you will create two layers in the first scene: one on the bottom to contain the background, and one on the top to con-tain the moving characters and action.Each layer (CCLayer) can in turn have sprites (CCSprite), labels (CCLabel), and other objects you want to display onscreen. If you remember, when you added SpaceCargoShip, you created read more..

  • Page - 52

    For the More Curious: Understanding the Cocos2D HelloWorld13Open up HelloWorldScene.m and find the scene method that creates a new scene, as shown in Listing 1.3.Listing 1.3 Inside the HelloWorldScene.m +(id)scene method+(id) scene{// 'scene' is an autorelease object.CCScene *scene = [CCScene node];// 'layer' is an autorelease object.HelloWorld *layer = [HelloWorld node];// add layer as a child to scene [scene addChild: layer];// return the scenereturn scene;}The first line of code creates a read more..

  • Page - 53

    Chapter 1 Hello, Cocos2D14So in summary, the CCDirector needs to know which scene to run. Inside of applicationDidFinishLaunching, the template calls the [HelloWorld scene]method to create a new CCScene with a single layer as a child—the HelloWorldlayer. The init function of the HelloWorld layer creates a label and adds it as a child of the layer. At that point, you have “Hello World” showing onscreen.From the BeginningAt this point we’ve covered the most critical parts of the read more..

  • Page - 54

    For the More Curious: Understanding the Cocos2D HelloWorld15// attach the openglView to the director [director setOpenGLView:glView]; // By default, this template only supports Landscape orientations.// Edit the RootViewController.m file to edit the supported // orientations. #if GAME_AUTOROTATION == kGameAutorotationUIViewController [director setDeviceOrientation:kCCDeviceOrientationPortrait]; #else [director setDeviceOrientation:kCCDeviceOrientationLandscapeLeft]; read more..

  • Page - 55

    Chapter 1 Hello, Cocos2D164. Creates the EAGLView, which is used to render your game. Cocos2D will use the EAGLView to send the OpenGL ES commands to the OpenGL ES driver.5. Sets the orientation to either portrait or landscape. If you are using the View Controller created by the Cocos2D template, you will need to modify the shouldAutorotateToInterfaceOrientation in the RootViewController.mclass to support the orientations you need in your game.6. Sets the animation interval to 60 times per read more..

  • Page - 56

    For the More Curious: Understanding the Cocos2D HelloWorld17- (void)applicationDidBecomeActive:(UIApplication *)application { [[CCDirector sharedDirector] resume];// 2}- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { [[CCDirector sharedDirector] purgeCachedData];// 3}- (void)applicationWillTerminate:(UIApplication *)application {CCDirector *director = [CCDirector sharedDirector]; [[director openGLView] removeFromSuperview]; [viewController release]; read more..

  • Page - 57

    Chapter 1 Hello, Cocos2D184. Ends the director and detaches the EAGLView from the application’s UIWindow.This ends the game loop, removes all textures from memory, and clears all of the scheduler timers. This command also forces the director to deallocate the currently running scene, including all of its layers and sprites. The applicationWillTerminate event is called when the user quits the game.5. Sets the delta time between the last event call and the current event call to zero. This method read more..

  • Page - 58

    For the More Curious: Understanding the Cocos2D HelloWorld19To see the Jump to Def inition in action:1. Open the HelloWorldScene.m file.2. On line 18, select the node method and right-click.3. In the Xcode pop-up menu, select Jump to Def inition. Xcode should open CCNode.m for you and show you the code in Listing 1.7.Listing 1.7 The node method inside of CCNode.m#pragma mark CCNode - Init & cleanup+(id) node{return [[[self alloc] init] autorelease];}Cocos2D has a large collection of utility read more..

  • Page - 59

    Chapter 1 Hello, Cocos2D20The ccp macro is one you will use numerous times, and it is just a shortcut to the CGPointMake method. The following is the code behind the ccp macro./** Helper macro that creates a CGPoint @return CGPoint @since v0.7.2 */#define ccp(__X__,__Y__) CGPointMake(__X__,__Y__)If you see an unknown method or macro, do not hesitate to jump to the definition of that bit of code. The Cocos2D source is well documented and is easy to understand with some practice. Knowing the read more..

  • Page - 60

    Getting CCHelloWorld on Your iPhone or iPad21simulator, only to have to deal with code signing in order to get the game on an actual device. Apple has made this process a lot simpler starting with Xcode 3.2.3. To let Xcode configure the provisioning profiles on your behalf:1. Make sure your iPhone or iPad is connected via USB.2. In the Xcode menu, select Window > Organizer.3. Select the Devices section.4. Press the button marked Use for Development.5. When prompted, enter your credentials for read more..

  • Page - 61

    Chapter 1 Hello, Cocos2D22actionGoTo:12,SummaryIn this chapter you downloaded the source code for Cocos2D and installed the Cocos2D templates into Xcode. You quickly created a HelloWorld app and added a moving Space Cargo Ship in just a few lines of code. Additionally, you covered the basics of Cocos2D Director, scenes, and layers, and what the Cocos2D templates provide. In the next chapter you get a chance to dive deeper into Cocos2D and start build-ing the Space Viking game. If you are ready, read more..

  • Page - 62

    actionGoTo:12,2actionGoTo:12,Hello,actionGoTo:12, SpaceactionGoTo:12, VikingIn the previous chapter you installed Cocos2D on your system, including the templates that are used by Xcode. You also learned about some of the companion tools you will be using in later chapters. Now it is time to start your journey creating Space Viking by putting Ole the Viking onscreen and moving him around. In this chapter you will deal only with the iPad version of Space Viking; later in the book you will cover in read more..

  • Page - 63

    Chapter 2 Hello, Space Viking24These are the same two steps you performed in Chapter 1, “Hello, Cocos2D,” and if you press Run in Xcode, you will see the Cocos2D HelloWorld sample. You will be creating Space Viking specifically for the iPad, and you will learn how to scale it down for the iPhone in later chapters. The Cocos2D templates are set up to create an iPhone game by default, requiring you to quickly transition the project in Xcode before get-ting started with the read more..

  • Page - 64

    Creating the Space Viking Classes255. With the SpaceViking project opened in Xcode, drag the Images folder from a Finder window into your SpaceViking project. 6. On the sheet that drops down, make sure that the Copy items into destina-tion group’s folder is checked and click Finish, as shown in Figure 2.2.Figure 2.2 Xcode Add Files dialog with the copy items checkbox turned ONWarningThe Copy items into destination group’s folder option is needed when you want to copy files to your project read more..

  • Page - 65

    Chapter 2 Hello, Space Viking26NoteThe Images folder you copied into the Space Viking Xcode project contains the various icon file images used for Space Viking’s app icon. The Cocos2D templates already contain icon.png, Icon@2x.png, Icon-Small.png, Icon-Small@2x.png, Icon-Small-50.png, Icon-72.png, and Default.png files in the Resources folder, so you need to delete them from the project before proceeding.actionGoTo:12,Creating the Background LactionGoTo:12,ayerAs noted earlier, the Cocos2D read more..

  • Page - 66

    Creating the Background Layer27Open the BackgroundLayer.h header file.Add a #import line for Cocos2D, and change the BackgroundLayer class to inherit from CCLayer instead of NSObject. Listing 2.1 shows the complete BackgroundLayer.h file.Listing 2.1 BackgroundLayer.h#import <Foundation/Foundation.h>#import "cocos2d.h"@interface BackgroundLayer : CCLayer {}@endSwitch to the BackgroundLayer.m implementation file so you can add the initmethod and the background sprite.TipWhether read more..

  • Page - 67

    Chapter 2 Hello, Space Viking28Open the BackgroundLayer.m implementation file and add the –(id)init method, as shown in Listing 2.2.Listing 2.2 BackgroundLayer.m// BackgroundLayer.m// SpaceViking#import "BackgroundLayer.h"@implementation BackgroundLayer-(id)init { self = [super init]; // 1if (self != nil) { // 2// 3CCSprite *backgroundImage; if (UI_USER_INTERFACE_IDIOM() == read more..

  • Page - 68

    The Gameplay Layer: Adding Ole the Viking to the Game29inside of the Images/Backgrounds folder you copied into your project, you will see there are two iPhone backgrounds, backgroundIiPhone.png and backgroundiPhone-hd.png. Cocos2D automatically detects the iPhone 4 Retina display and will use the higher resolution image. The spriteWithFile method call creates a texture from the image file and associates it with the CCSprite object. The sprite’s dimensions and corresponding geometry are set to read more..

  • Page - 69

    Chapter 2 Hello, Space Viking301. In Xcode, select and right-click on the SpaceViking Classes folder.2. Choose New File and select iOS\Cocoa Touch\Objective-C class as the type.3. For the Subclass field, enter CCLayer and click Next.4. Enter GameplayLayer.m for the filename, and click Save. Xcode automatically creates the header file for you, setting up the basics so that all you need to do is add any instance variables or properties to the header file.5. Open the GameplayLayer.h header file and read more..

  • Page - 70

    The GameScene Class: Connecting the Layers in a Scene31// In your games, use this to load art sized for the device [vikingSprite setScaleX:screenSize.width/1024.0f]; [vikingSprite setScaleY:screenSize.height/768.0f]; } }return self;}@endNow let’s take a look at what’s happening in Listing 2.4:1. Gets the screen size from the Cocos2D Director. On the iPad, this returns 1024 × 768 pixels.2. Informs Cocos2D that the gameplayLayer will receive touch events.3. read more..

  • Page - 71

    Chapter 2 Hello, Space Viking32particular scene. At the moment, your game will have just one scene, the GameScene.You’ll see how to add more scenes to Cocos2D and transition between them in Chap-ter 7, “Main Menu, Level Completed, and Credit Scenes.”Creating the GameSceneSelect and right-click on the Classes folder, and then choose New File.Select the iOS\Cocoa Touch\Objective-C class and click Next. For the Sub-class field, enter CCScene and click Next. Type in GameScene.m under the File read more..

  • Page - 72

    The GameScene Class: Connecting the Layers in a Scene332. Adds the backgroundLayer to the scene with a z value of zero.3. Instantiates the gameplayLayer object.4. Adds the gameplayLayer object to the scene with a z value of 5. Since the zvalue of the gameplayLayer is higher than the z value of backgroundLayer,it will be composited in front of the backgroundLayer.As you can see in Listing 2.6, Cocos2D scenes can be pretty simple, acting as a container for the CCLayers in your game. Most of the read more..

  • Page - 73

    Chapter 2 Hello, Space Viking34actionGoTo:13,Commanding the Cocos2D actionGoTo:13,DirectorIn the SpaceViking project, the Cocos2D Director is set to instantiate and run the HelloWorld scene. You need to change the director call so that it runs the GameS-cene instead.1. Open the SpaceVikingAppDelegate.m implementation file.2. At the top of the file, add an import for the GameScene class in the SpaceVikingAppDelegate.m implementation file, as shown in Listing 2.7.Listing 2.7 read more..

  • Page - 74

    Adding Movement35If you select the iPad Simulator from the Scheme dropdown and click Run, you will see the Space Viking game with Ole the Viking in the middle of the alien world background. Figure 2.6 shows Space Viking running on the iPad Simulator.Figure 2.6 Space Viking running on the iPad SimulatoractionGoTo:13,AddingactionGoTo:13, MovementIt took only a few pages to get your Viking and background on the iPad screen. Now you have to work on getting Ole to move around. Luckily, Cocos2D makes read more..

  • Page - 75

    Chapter 2 Hello, Space Viking363. Browse to the location of the Resources folder you downloaded for this chapter and select the JoystickClasses folder.4. Ensure that Copy items into destination group’s folder is selected, and click Add.Now that you have the SneakyInput joystick classes in your SpaceViking project, the next step is to utilize those classes in the GameplayLayer class.NoteThe SneakyInput joystick classes are not part of the main Cocos2D distribution at this time. The read more..

  • Page - 76

    Adding Movement37Listing 2.9 GameplayLayer.m –(void)initJoystickAndButtons()-(void)initJoystickAndButtons {CGSize screenSize = [CCDirector sharedDirector].winSize;// 1CGRect joystickBaseDimensions = CGRectMake(0, 0, 128.0f, 128.0f); // 2CGRect jumpButtonDimensions = CGRectMake(0, 0, 64.0f, 64.0f);CGRect attackButtonDimensions = CGRectMake(0, 0, 64.0f, 64.0f); CGPoint joystickBasePosition; // 3CGPoint read more..

  • Page - 77

    Chapter 2 Hello, Space Viking38leftJoystick = [joystickBase.joystick retain];// 10 [self addChild:joystickBase];// 11SneakyButtonSkinnedBase *jumpButtonBase = [[[SneakyButtonSkinnedBase alloc] init] autorelease];// 12 jumpButtonBase.position = jumpButtonPosition;// 13 jumpButtonBase.defaultSprite = [CCSprite spriteWithFile:@"jumpUp.png"];// 14 jumpButtonBase.activatedSprite = [CCSprite spriteWithFile:@"jumpDown.png"];// 15 jumpButtonBase.pressSprite read more..

  • Page - 78

    Adding Movement394. Determines if Space Viking is running on an iPad or iPhone/iPod touch. In iOS 3.2 and later, this is the best way to determine what device your game is running on. Depending on whether the iPad or iPhone/iPod touch is detected, the posi-tions for the joystick and buttons are set up. This if/else block uses a calculation for the values so that if the iPad dimensions change, the joystick and buttons will still be in their proper place.5. Allocates and initializes a joystick read more..

  • Page - 79

    Chapter 2 Hello, Space Viking40chapter, you will query the jumpButton object to determine if the player is pressing the button.19. Sets this button to not act as a toggle. If a button has isToggleable set to YES, pressing it alternates the button state from ON to OFF. If the button has isToggleable set to NO, it turns OFF as soon as the player lifts his or her finger from it.20. Adds the jump button base to the GameplayLayer instance, making it visible on the lower-right portion of the read more..

  • Page - 80

    Adding Movement41by different factors to make Ole the Viking move faster or slower in relation to the movement of the joystick.2. Creates a new position based on the current tempNode position, the joystick velocity, and how much time has elapsed between the last time this method was called and now. In Listing 2.11 you will see that tempNode contains a reference to the vikingSprite instance variable.3. Sets the tempNode position to the newly calculated position. Here tempNodeis really a reference read more..

  • Page - 81

    Chapter 2 Hello, Space Viking42Finally, it is time to add the last bit of code that initializes the buttons and calls the update method before each frame is rendered. In the init method of GameplayLayer,add the following two lines right after [self addChild:vikingSprite]; as shown in Listing 2.12. Listing 2.12 Joystick initialization and update scheduler setup in init inside of gameplayLayer.m [self initJoystickAndButtons];// 7 [self scheduleUpdate];// 8Line 7 calls the read more..

  • Page - 82

    Adding Movement43A Word on Instance VariablesYou may have noticed that you used a vikingSprite instance variable to keep track of Ole’s sprite object. You then kept the instance variable pointing to the viking-Sprite so that you could update his position. Cocos2D automatically retains the sprites that are added as children to the layers and optionally can mark each sprite with a unique integer tag. You can use this tag mechanism to avoid having to keep instance variables of your character read more..

  • Page - 83

    Chapter 2 Hello, Space Viking44nTexture Atlas or Sprite SheetIn order to save on memory and reduce the amount of wasted empty space in your textures, you want to combine them into one larger texture, called a texture atlas. The texture atlas is simply a large texture, containing your images, from which smaller textures for each of your images can be cut or extracted from. Imagine a large sheet of paper with photographs glued to it. You can cut out each of the photographs from the single larger read more..

  • Page - 84

    Texture Atlases45Here is a way to visualize all of this. Think of yourself in the role of OpenGL ES, and the game needs you to draw a scene of a typical beach. This scene has the sand, the water, and some beach umbrellas. If the game is just using CCSprites, then it has to first give you the image for the sand and ask you to draw it, then give you the image of the ocean and ask you to draw it. It would continue like this until all of the images are drawn/rendered onscreen. This quickly becomes read more..

  • Page - 85

    Chapter 2 Hello, Space Viking46sprite inside of a 256 × 256 texture. Regardless of the bit depth of your images, only about one-quarter of the memory this image is using is actually utilized to display anything—the rest is wasted. By utilizing tightly packed texture atlases you can avoid this wasted space.Every byte of texture memory has to be copied from one location in memory that the CPU addresses to the area used by the GPU. Using extra texture memory has a lot of negative effects, and as read more..

  • Page - 86

    Texture Atlases47The combined wasted memory from using individual textures as well as the indi-vidual OpenGL ES bind texture calls can really work against you and slow down your game. Figure 2.9 illustrates how individual Viking and Radar Dish textures are stored in comparison with a texture atlas combining all of the textures needed for this scene in Space Viking.Figure 2.9 Example of wasted memory with individual images versus a texture atlasThere is one more key advantage of using a texture read more..

  • Page - 87

    Chapter 2 Hello, Space Viking48Top Reasons to Use a Texture Atlas/Sprite Sheet1. Reduced OpenGL ES bind calls—the more images contained in the texture atlas, the greater the reduction.2. Reduced memory footprint for the images stored as textures in memory.3. Easy method to trim and save on transparent space in your images, allowing for more images/texture in the same space.4. Zwoptex and TexturePacker are fully supported by Cocos2D, so creating and using texture atlases is painless.NoteFor the read more..

  • Page - 88

    Texture Atlases49PowerUpsRadarSpaceCargoShipTeleport EffectsVikingBe sure to use the Add Images button and not the Add Folders button, so that TexturePacker does not include the path as the key to the image coordinates.3. In the toolbar to the left, make sure that the Data Format is set to cocos2d.4. Click Publish, and when prompted for a name, enter scene1atlas. It will save two files (scene1atlas.png and scene1atlas.plist) to the folder you choose, so note where you save it for use later (see read more..

  • Page - 89

    Chapter 2 Hello, Space Viking50DetriusEnemyRobotImpactEffectsPowerUpsRadarSpaceCargoShipTeleport EffectsViking4. Change the Canvas dimensions to have a width of 2048 pixels and height of 2048 pixels.5. Select Max Rect as the algorithm on the left panel.6. Set the padding to 1 pixel, by entering 1px on the padding text box.7. Click the Apply button so that Zwoptex lays out your images.8. Select File > Save and name this Texture Atlas scene1atlas.9. Click Publish on the menu, and then click read more..

  • Page - 90

    Texture Atlases51You will need two more texture atlases for when Space Viking is running on the iPhone and on the iPhone 4’s retina display. You can create them following the same steps, except they should be named scene1atlasiPhone and scene1atlasiPhone-hd (png and plist files). You can find all of the completed texture atlases in the resources folder for this chapter.If you are wondering how Cocos2D knows to extract your individual images from the texture atlas, the coordinates plist file is read more..

  • Page - 91

    Chapter 2 Hello, Space Viking52actionGoTo:13,For the More CuractionGoTo:13,ious: Testing Out actionGoTo:13,CCSpriteBatchNodeWhile Chapter 4 goes into detail on how to set up and use CCSpriteBatchNode,you might be interested in getting it working now. It is very simple, and you can do it with just five lines of code.In the init method of GameplayLayer.m:1. Comment out the lines marked //3 and //5, which previously created the Viking CCSprite and added it to the GameplayLayer.2. Add the lines read more..

  • Page - 92

    Fixing Slow Performance on iPhone 3G and Older Devices 53The new lines you added (3.1 through 3.5) work as follows: 3.1 Loads the CCSpriteFrames into the Cocos2D cache. The frames are the dimensions and location of all of the images inside of the texture atlas. This plistis what allows Cocos2D to extract the images from the texture atlas PNG and render them onscreen. The frames also allow Cocos2D to recreate the trimmed transparent space that Zwoptex or TexturePacker removed in creating the read more..

  • Page - 93

    Chapter 2 Hello, Space Viking54default setting, then Cocos2D will render as if it is in the portrait orientation and leave it up the UIViewController to rotate the rendered content. While not a problem on newer devices, on the iPhone 3G and older devices, it causes quite a bit of overhead, capping your maximum frames per second at 40 instead of the full 60fps. You can eas-ily change this setting so that Cocos2D Director handles the rotation, and have your game running at 60fps even on the read more..

  • Page - 94

    Challenges55HintYou need to remove deltaTime from this line: CGPoint newPosition = ccp(tempNode.position.x + scaledVelocity.x * deltaTime, tempNode.position.y + scaledVelocity.y * deltaTime); // 23. Add left and right limits for Ole the Viking so he does not move offscreen even if the player moves the joystick left or right continuously. (Hint: vikingSprite’s x coordinate is the variable you have to limit.)BonusModify the applyJoystick method in GameplayLayer so the joystick only read more..

  • Page - 95

    This page intentionally left blank read more..

  • Page - 96

    actionGoTo:13,3actionGoTo:13,IntroductionactionGoTo:13, toactionGoTo:13, Cocos2DactionGoTo:13, actionGoTo:13,AnimationsactionGoTo:13, andactionGoTo:13, ActionsIn Chapter 2, “Hello, Space Viking,” you learned the basics of Cocos2D and created a scene with two layers: background and gameplay. You got a Viking sprite moving around on the screen, and hopefully, you whet your appetite for continuing on to the full-featured game. In this chapter you will learn about actions and animations and in read more..

  • Page - 97

    Chapter 3 Introduction to Cocos2D Animations and Actions58To recap, you first create a CCAnimation to store the frames or images in your animation. You then create a CCAnimate action to run the animation.The easiest way to understand how this works is to try out two quick examples. Don’t worry, the first example is short, just a few lines of code. 1. Open the SpaceViking project in Xcode.2. Drag the an1_anim_1, 2, 3, and 4 png files from the Resources/Enemy Robot Animation folder for this read more..

  • Page - 98

    Animations in Cocos2D593. Adds the animatingRobot to the GameplayLayer. Up to this point the steps in creating and adding a CCSprite to a CCLayer should be familiar, as you learned it in the previous chapter.4. Creates and initializes a new CCAnimation named robotAnim. In this line the robotAnim is created but empty.5. Adds the animation frames to the robotAnim animation. Three frames are added by passing in the filenames for each. 6. Creates the robotAnimationAction that is responsible for read more..

  • Page - 99

    Chapter 3 Introduction to Cocos2D Animations and Actions60As you can see, creating animations in Cocos2D is easy. The code in Listing 3.1 works with regular CCSprites, but if your CCSprites are being rendered by a CCSpriteBatchNode, the code requires a couple of modifications. The CCSprite-Frames you use for your animation must get their textures from the texture atlas used by the CCSpriteBatchNode. The best way to understand this is to see it in action. Copy the contents of Listing 3.2 directly read more..

  • Page - 100

    Animations in Cocos2D61Once the CCAnimation object is populated, the rest of the code is the same, set-ting up an action to play the animation and assigning it to the vikingSprite.The important takeaway here is that when you are creating animations for sprites using a texture atlas, the animation frames must come from the same texture atlas. If you want to animate a sprite, make sure you put all of the frames of the animation in the same sprite sheet—otherwise it will not work.Note on read more..

  • Page - 101

    Chapter 3 Introduction to Cocos2D Animations and Actions62NoteBefore moving on, be sure to comment out the lines of code you added from Listings 3.1 and 3.2: they are examples only and are not used in the rest of the book.For the More Curious: CCAnimationCacheCocos2D comes bundled with a CCAnimationCache singleton that can cache all of your animations. Instead of storing the animations as instance variables, you can store them in the CCAnimationCache and retrieve them as needed. This is really read more..

  • Page - 102

    Space Viking Design Basics63Cocos2D and also to provide a sample game with code you can reuse in your own games.Each game object in Space Viking has some logic behind it, not just the graphical sprite/image component. Enemies have to have a primitive artificial intelligence (AI) and be able to patrol the scene, attack Ole the Viking, and react to attacks. In addi-tion to enemies, there are power-ups for better weapons and health and other objects. Instead of having all of the logic in one read more..

  • Page - 103

    Chapter 3 Introduction to Cocos2D Animations and Actions64In Space Viking each game object has its own class, which encapsulates the AI needed by that object. The objects share common methods that they can use to query each other as to their state, present location, and other attributes. To understand how all of these objects fit together, it is best to start with the topmost object in the hierar-chy, the GameObject:nGameObjectThe GameObject class inherits from CCSprite and contains methods read more..

  • Page - 104

    Space Viking Design Basics65nHealthThe Health class represents the health power-ups in Space Viking. Even though Ole is a mighty Viking, he does get hungry after fighting, and the health power-ups restore Ole’s health. The Health class inherits from the GameObject class.NoteYou will create these classes for Space Viking in this chapter. In Chapter 4, you will add the enemy robot and phaser beams that the robot fires at Ole. The actions and animation system in Cocos2D is used extensively by the read more..

  • Page - 105

    Chapter 3 Introduction to Cocos2D Animations and Actions66actionGoTo:13,Actions and Animation actionGoTo:13,Basics in Cocos2DActions are a powerful mechanism in Cocos2D to control the movement, transi-tion, and effects of your objects. All CCNode objects are able to run actions, and since CCSprites inherit from CCNodes, all Cocos2D actions can be run on CCSprites.The Viking and RadarDish objects inherit from GameCharacter, which in turns inherits from GameObject and CCSprite, allowing your read more..

  • Page - 106

    Using Property List Files to Store Animation Data67nCCRepeatForeverRepeats the action indefinitely. It has the effect of running an action on an infi-nite loop until stopAction: or stopAllActions is called.nCCSequenceSequences two or more actions together so that after the first action completes, the second action is run. nCCSpawnFires off two or more actions simultaneously. CCSpawn is very useful for com-bining actions, such as a jump animation with the CCJumpBy action.In this chapter you will read more..

  • Page - 107

    Chapter 3 Introduction to Cocos2D Animations and Actions683. Selecting the Plists group, right- or Control-click and select New File.4. Select the Resource section under iOS on the left, and then select Property List for the type of file and click Next.5. Enter RadarDish.plist for the filename, and then click Finish.Xcode creates and opens the RadarDish.plist file for you. The next step is to add the items needed for a particular RadarDish animation. Figure 3.4 shows the RadarDish.plist file you read more..

  • Page - 108

    Organization, Constants, and Common Protocols694. Click the + button next to the tiltingAnim key to add a row to the tiltingAnim dictionary.5. Click on the Key field and enter animationFrames.6. Leave the type as String.7. In the Value field, enter 1,2,3,4,5,5,4,3,2,1,2,3,4,5.8. Add another item under tiltingAnim by clicking the + sign next to the animationFrames field, set the key in the new row to delay, the type to Number, and the value to 0.25.9. Create a final item under tiltingAnim, read more..

  • Page - 109

    Chapter 3 Introduction to Cocos2D Animations and Actions701. Open Xcode, and under the Groups and Files section, select the Classes folder.2. With the Classes folder selected, you can either press Option-z-N or right-click on the Classes folder and select New Group from the contextual menu. Create the following groups:nConstantsnScenesnLayersnGameObjectsnEnemyObjectsnPowerUpsnSingletons3. Drag the GameScene.h and GameScene.m files into the Scenes group.4. Drag the BackgroundLayer and read more..

  • Page - 110

    Organization, Constants, and Common Protocols71Creating the Constants FileSpace Viking has some static values that you will want to use in more than one class. For this purpose, you create a Constants.h header file, which contains all of the #define statements and other constants used by more than one class in Space Viking.Now that you have the groups in place to keep Space Viking organized, it is time to add the Constants and CommonProtocol classes.1. In Xcode, select the Constants group read more..

  • Page - 111

    Chapter 3 Introduction to Cocos2D Animations and Actions72breathing action to entice the player to keep going. The tags are just unique integer values you can assign to any CCNode and use the values to retrieve a reference to the CCNode from their parent class.Common Protocols FileProtocols in Objective-C are similar to interfaces in other languages such as Java. To put it simply, protocols allow you to specify the methods that a class will respond to, without knowing how those methods are read more..

  • Page - 112

    Organization, Constants, and Common Protocols73 kStateTakingDamage, kStateDead, kStateTraveling, kStateRotating, kStateDrilling, kStateAfterJumping} CharacterStates; // 1typedef enum { kObjectTypeNone, kPowerUpTypeHealth, kPowerUpTypeMallet, kEnemyTypeRadarDish, kEnemyTypeSpaceCargoShip, kEnemyTypeAlienRobot, kEnemyTypePhaser, kVikingType, kSkullType, kRockType, kMeteorType, kFrozenVikingType, kIceType, kLongBlockType, kCartType, read more..

  • Page - 113

    Chapter 3 Introduction to Cocos2D Animations and Actions74The GameplayLayerDelegate protocol defines two methods that the characters in Space Viking will use. In particular, the SpaceCargoShip and the EnemyRobotuse these methods to have the GameplayLayer create the power-ups and the phaser bullets. The SpaceCargoShip does not have to know anything further about the GameplayLayer, only that it responds to these two methods. Using protocols can hide the complexity of the implementation and allow read more..

  • Page - 114

    The GameObject and GameCharacter Classes75#import <Foundation/Foundation.h>#import "cocos2d.h"#import "Constants.h"#import "CommonProtocols.h"@interface GameObject : CCSprite {BOOL isActive;BOOL reactsToScreenBoundaries;CGSize screenSize;GameObjectType gameObjectType;}@property (readwrite) BOOL isActive;@property (readwrite) BOOL reactsToScreenBoundaries;@property (readwrite) CGSize screenSize;@property (readwrite) GameObjectType read more..

  • Page - 115

    Chapter 3 Introduction to Cocos2D Animations and Actions76-(id) init {if((self=[super init])){CCLOG(@"GameObject init");screenSize = [CCDirector sharedDirector].winSize;isActive = TRUE;gameObjectType = kObjectTypeNone; }return self;}-(void)changeState:(CharacterStates)newState {CCLOG(@"GameObject->changeState method should be overridden");}-(void)updateStateWithDeltaTime:(ccTime)deltaTimeandListOfGameObjects:(CCArray*)listOfGameObjects { read more..

  • Page - 116

    The GameObject and GameCharacter Classes77include these transparent pixels, and your collision detection would be inaccurate. Objects in your game would come into contact before the meaningful/nontranparent part of the graphics ever touched.Figure 3.6 Transparent space around the Viking sprite/image A Word on Bounding BoxesThe bounding boxes in Cocos2D are actually what are referred to as axis-aligned bound-ing boxes, or AABB for short. This is simply a box around your sprite texture (your read more..

  • Page - 117

    Chapter 3 Introduction to Cocos2D Animations and Actions78 NSUserDomainMask, YES) objectAtIndex:0]; plistPath = [rootPath stringByAppendingPathComponent:fullFileName];if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) { plistPath = [[NSBundle mainBundle]pathForResource:className ofType:@"plist"]; }// 2: Read in the plist fileNSDictionary *plistDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];// 3: If the plistDictionary was null, read more..

  • Page - 118

    The GameObject and GameCharacter Classes79return animationToReturn;}@endNow let’s examine the sections in Listing 3.7, as noted by the numbered comment lines in the code:nSections 1 and 2 are from the standard Apple templates on reading property list files:nSection 1 tries to get the actual file system path to the property list file. This is where the className that was passed into the method is used to try to determine the path from the application bundle.nSection 2 uses built-in methods to read more..

  • Page - 119

    Chapter 3 Introduction to Cocos2D Animations and Actions80At the end of each section in this chapter, it is good practice for you to build the project and ensure you have not introduced any typos or errors. Use c-B or select Build from the Product menu to build the project.Creating the GameCharacter ClassIn Space Viking, power-ups and the SpaceCargoShip inherit directly from GameObject, as their behavior is very simple. The other objects in Space Vikinginherit from the GameCharacter class, read more..

  • Page - 120

    The GameObject and GameCharacter Classes81Listing 3.9 GameCharacter.m implementation file// GameCharacter.m// SpaceViking#import "GameCharacter.h"@implementation GameCharacter@synthesize characterHealth;@synthesize characterState; -(void) dealloc { [super dealloc];}-(int)getWeaponDamage { // Default to zero damage CCLOG(@"getWeaponDamage should be overridden");return 0;}-(void)checkAndClampSpritePosition { CGPoint currentSpritePosition = [self position];if read more..

  • Page - 121

    Chapter 3 Introduction to Cocos2D Animations and Actions82the object if it is too far to the left or right of the screen. This is useful for keeping Ole the Viking and his enemies onscreen at all times. By having this method in the GameCharacter class, you can avoid typing redundant code in each of your game character classes.Tip on Points Versus PixelsRemember that Cocos2D uses a point system to help position objects on the normal iPhone display (480 × 320 pixels) and the retina display (960 read more..

  • Page - 122

    actionGoTo:13,4actionGoTo:13,Simple Collision DeactionGoTo:13,tection and actionGoTo:13,the First EnemyIn the previous chapter you learned the basics of Cocos2D animations and actions. You also started building a flexible framework for Space Viking. In this chapter you go further and create the first enemy for Ole to do battle with. In the process you learn how to implement a simple sys-tem for collision detection and the artificial intelligence brain of the enemies in Space Viking.There is a read more..

  • Page - 123

    Chapter 4 Simple Collision Detection and the First Enemy843. For the Subclass field, enter GameCharacter and click Next.4. Enter RadarDish for the filename and click Finish.Open the RadarDish.h header file and change the contents to match the code in Listing 4.1.Listing 4.1 RadarDish.h header file// RadarDish.h// SpaceViking//#import <Foundation/Foundation.h>#import "GameCharacter.h"@interface RadarDish : GameCharacter {CCAnimation *tiltingAnim;CCAnimation read more..

  • Page - 124

    Creating the Radar Dish and Viking Classes85function fine, since that new main character class too would, presumably, be derived from the GameCharacter class.Listings 4.2, 4.3, and 4.4 show the contents of the RadarDish.m implementation file. The changeState and updateStateWithDelta time methods are crucial to under-stand, as they are the most basic versions of what you will find in all of the characters in Space Viking. While reading this code, keep in mind that the RadarDish is a simple enemy read more..

  • Page - 125

    Chapter 4 Simple Collision Detection and the First Enemy86case kStateIdle:CCLOG(@"RadarDish->Changing State to Idle"); action = [CCAnimate actionWithAnimation:transmittingAnimrestoreOriginalFrame:NO];break;case kStateTakingDamage:CCLOG(@"RadarDish->Changing State to TakingDamage");characterHealth = characterHealth - [vikingCharacter getWeaponDamage];if (characterHealth <= 0.0f) { [self changeState:kStateDead]; } else { read more..

  • Page - 126

    Creating the Radar Dish and Viking Classes87nSpawning (kStateSpawning)Starts up the RadarDish with the tilting animation, which is the dish moving up and down.nIdle (kStateIdle)Runs the transmitting animation, which is the RadarDish blinking.nTaking Damage (kStateTakingDamage)Runs the taking damage animation, showing a hit to the RadarDish. The RadarDish health is reduced according to the type of weapon being used against it.nDead (kStateDead)The RadarDish plays a death animation of it blowing read more..

  • Page - 127

    Chapter 4 Simple Collision Detection and the First Enemy88if (([self numberOfRunningActions] == 0) && (characterState != kStateDead)) { CCLOG(@"Going to Idle"); [self changeState:kStateIdle];// 6return; }}Now let’s examine the numbered lines of the code:1. Checks if the RadarDish is already dead. If it is, this method is short-circuited and returned. If the RadarDish is dead, there is nothing to update.2. Gets the Viking character object from the read more..

  • Page - 128

    Creating the Radar Dish and Viking Classes89 [self setTransmittingAnim: [self loadPlistForAnimationWithName:@"transmittingAnim"andClassName:NSStringFromClass([self class])]]; [self setTakingAHitAnim: [self loadPlistForAnimationWithName:@"takingAHitAnim"andClassName:NSStringFromClass([self class])]]; [self setBlowingUpAnim: [self loadPlistForAnimationWithName:@"blowingUpAnim" andClassName:NSStringFromClass([self class])]];}-(id) init {if( read more..

  • Page - 129

    Chapter 4 Simple Collision Detection and the First Enemy90AI brain. These same two methods are used to drive the brain of all of the other game characters, including Ole the Viking.actionGoTo:13,Creating the Viking ClassIn the previous chapter, Ole the Viking was nothing more than a CCSprite. In this chapter you pull him out into his own class complete with animations and a state machine to transition him through his various states. If the Viking class code starts to look daunting, refer back to read more..

  • Page - 130

    Creating the Viking Class91 // Crouching, standing up, and JumpingCCAnimation *crouchingAnim;CCAnimation *crouchingMalletAnim;CCAnimation *standingUpAnim;CCAnimation *standingUpMalletAnim;CCAnimation *jumpingAnim;CCAnimation *jumpingMalletAnim;CCAnimation *afterJumpingAnim;CCAnimation *afterJumpingMalletAnim; // PunchingCCAnimation *rightPunchAnim;CCAnimation *leftPunchAnim;CCAnimation *malletPunchAnim; // Taking Damage and DeathCCAnimation *phaserShockAnim;CCAnimation read more..

  • Page - 131

    Chapter 4 Simple Collision Detection and the First Enemy92// Taking Damage and Death@property (nonatomic, retain) CCAnimation *phaserShockAnim;@property (nonatomic, retain) CCAnimation *deathAnim;@property (nonatomic,assign) SneakyJoystick *joystick;@property (nonatomic,assign) SneakyButton *jumpButton;@property (nonatomic,assign) SneakyButton *attackButton;@endListing 4.5 shows the large number of animations that are possible with the Vikingcharacter as well as instance variables to point to read more..

  • Page - 132

    Creating the Viking Class93@synthesize leftPunchAnim;@synthesize malletPunchAnim;// Taking Damage and Death@synthesize phaserShockAnim;@synthesize deathAnim;- (void) dealloc {joystick = nil;jumpButton = nil;attackButton = nil; [breathingAnim release]; [breathingMalletAnim release]; [walkingAnim release]; [walkingMalletAnim release]; [crouchingAnim release]; [crouchingMalletAnim release]; [standingUpAnim release]; [standingUpMalletAnim release]; [jumpingAnim release]; read more..

  • Page - 133

    Chapter 4 Simple Collision Detection and the First Enemy94 ccp(oldPosition.x + scaledVelocity.x * deltaTime, oldPosition.y);// 1 [self setPosition:newPosition];// 2if (oldPosition.x > newPosition.x) {self.flipX = YES;// 3 } else {self.flipX = NO; }}-(void)checkAndClampSpritePosition {if (self.characterState != kStateJumping) {if ([self position].y > 110.0f) [self setPosition:ccp([self position].x,110.0f)]; } [super read more..

  • Page - 134

    Creating the Viking Class95Cocos2D has two built-in functions you will make use of frequently: flipX and flipY. These functions f lip the pixels of a texture along the x- or y-axis, allowing you to display a mirror image of your graphics without having to have left- and right-facing copies of each image for each character. Figure 4.1 shows the effect of flipXon the Viking texture. This is a really handy feature to have, since it helps reduce the size of your application, and it keeps you from read more..

  • Page - 135

    Chapter 4 Simple Collision Detection and the First Enemy96case kStateWalking:if (isCarryingMallet) { action = [CCAnimate actionWithAnimation:walkingMalletAnimrestoreOriginalFrame:NO]; } else { action = [CCAnimate actionWithAnimation:walkingAnimrestoreOriginalFrame:NO]; }break;case kStateCrouching:if (isCarryingMallet) { action = [CCAnimate read more..

  • Page - 136

    Creating the Viking Class97 case kStateJumping:newPosition = ccp(screenSize.width * 0.2f, 0.0f);if ([self flipX] == YES) { newPosition = ccp(newPosition.x * -1.0f, 0.0f); } movementAction = [CCJumpBy actionWithDuration:0.5fposition:newPosition height:160.0f jumps:1];if (isCarryingMallet) {// Viking Jumping animation with the Mallet read more..

  • Page - 137

    Chapter 4 Simple Collision Detection and the First Enemy98 action = [CCAnimateactionWithAnimation:malletPunchAnimrestoreOriginalFrame:YES]; } else {if (kLeftHook == myLastPunch) {// Execute a right hookmyLastPunch = kRightHook; action = [CCAnimateactionWithAnimation:rightPunchAnimrestoreOriginalFrame:NO]; } else {// Execute a left hookmyLastPunch = kLeftHook; action = read more..

  • Page - 138

    Creating the Viking Class991. Method variables cannot be declared inside a switch statement, as they would be out of scope as soon as the code exited the switch statement. Your id action variable is declared above the switch statement but initialized inside the switch branches.2. Most of the states have two animations: one for the Viking with the Malletand one without. The isCarryingMallet Boolean instance variable is key in determining which animation to play.3. An action in Cocos2D can be made read more..

  • Page - 139

    Chapter 4 Simple Collision Detection and the First Enemy100The next section of the Viking.m file covers the updateStateWithDeltaTimeand the adjustedBoundingBox methods. Copy the contents of Listing 4.8 into your Viking.m file immediately following the changeState method.Listing 4.8 Viking.m implementation file (part 3 of 4)#pragma mark --(void)updateStateWithDeltaTime:(ccTime)deltaTimeandListOfGameObjects:(CCArray*)listOfGameObjects {if (self.characterState == kStateDead)return; // Nothing to do read more..

  • Page - 140

    Creating the Viking Class101 [self checkAndClampSpritePosition];if ((self.characterState == kStateIdle) || (self.characterState == kStateWalking) || (self.characterState == kStateCrouching) || (self.characterState == kStateStandingUp) || (self.characterState == kStateBreathing)) {if (jumpButton.active) { [self changeState:kStateJumping]; } else if (attackButton.active) { [self changeState:kStateAttacking]; } else if read more..

  • Page - 141

    Chapter 4 Simple Collision Detection and the First Enemy102CGRect vikingBoundingBox = [self boundingBox];float xOffset;float xCropAmount = vikingBoundingBox.size.width * 0.5482f;float yCropAmount = vikingBoundingBox.size.height * 0.095f;if ([self flipX] == NO) {// Viking is facing to the rigth, back is on the left xOffset = vikingBoundingBox.size.width * 0.1566f; } else {// Viking is facing to the left; back is facing right xOffset = vikingBoundingBox.size.width * 0.4217f; } read more..

  • Page - 142

    Creating the Viking Class103The next if statement block checks the state of the joystick, jump, and attack but-tons and changes the state of the Viking to ref lect which controls are being pressed. The if statement executes only if the Viking is not currently carrying out a blocking animation, such as jumping.Lastly the Viking class reaches a section of the updateStateWithDeltaTimemethod that handles what happens when there are no animations currently running. Cocos2D has a convenience method on read more..

  • Page - 143

    Chapter 4 Simple Collision Detection and the First Enemy104 [self setWalkingAnim:[self loadPlistForAnimationWithName:@"walkingAnim" andClassName:NSStringFromClass([self class])]]; [self setWalkingMalletAnim:[self loadPlistForAnimationWithName:@"walkingMalletAnim" andClassName:NSStringFromClass([self class])]]; [self setCrouchingAnim:[self loadPlistForAnimationWithName:@"crouchingAnim" andClassName:NSStringFromClass([self class])]]; [self read more..

  • Page - 144

    Final Steps105#pragma mark --(id) init {if( (self=[super init]) ) {joystick = nil;jumpButton = nil;attackButton = nil; self.gameObjectType = kVikingType;myLastPunch = kRightHook;millisecondsStayingIdle = 0.0f;isCarryingMallet = NO; [self initAnimations]; }return self;}@endThe initAnimation method, while quite long, is very basic in that it only initial-izes all of the Viking animations based on the display frames already loaded from the scene1atlas.plist file in the read more..

  • Page - 145

    Chapter 4 Simple Collision Detection and the First Enemy106#import "SneakyButton.h"#import "SneakyButtonSkinnedBase.h"#import "SneakyJoystickSkinnedBase.h"#import "Constants.h"#import "CommonProtocols.h"#import "RadarDish.h"#import "Viking.h"@interface GameplayLayer : CCLayer <GameplayLayerDelegate> { CCSprite *vikingSprite;SneakyJoystick *leftJoystick;SneakyButton *jumpButton;SneakyButton *attackButton; read more..

  • Page - 146

    Final Steps107CGPoint jumpButtonPosition;CGPoint attackButtonPosition; // 4if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { // The device is an iPad running iPhone 3.2 or later.CCLOG(@"Positioning Joystick and Buttons for iPad"); joystickBasePosition = ccp(screenSize.width*0.0625f, screenSize.height*0.052f); jumpButtonPosition = ccp(screenSize.width*0.946f, screenSize.height*0.052f); read more..

  • Page - 147

    Chapter 4 Simple Collision Detection and the First Enemy108 jumpButtonBase.pressSprite = [CCSprite spriteWithFile:@"jumpDown.png"]; jumpButtonBase.button = [[SneakyButton alloc]initWithRect:jumpButtonDimensions];jumpButton = [jumpButtonBase.button retain];jumpButton.isToggleable = NO; [self addChild:jumpButtonBase];SneakyButtonSkinnedBase *attackButtonBase = [[[SneakyButtonSkinnedBasealloc] init] autorelease]; attackButtonBase.position = attackButtonPosition; read more..

  • Page - 148

    Final Steps1091. Gets the list of all of the children CCSprites rendered by the CCSpriteBatch-Node. In Space Viking this is a list of all of the GameCharacters, including the Viking and his enemies.2. Iterates through each of the Game Characters, calls their updateStateWith-DeltaTime method, and passes a pointer to the list of all Game Characters. If you look back at the updateStateWithDeltaTime code in Viking.m, you can see the list of Game Characters used to check for power-ups and phaser read more..

  • Page - 149

    Chapter 4 Simple Collision Detection and the First Enemy110Chapter 5, “More Actions, Effects, and Cocos2D Scheduler,” to include the other enemies in the Space Viking world.The last code listing for GameplayLayer.m covers the init method. Copy the con-tents of Listing 4.14 into your GameplayLayer.m file.Listing 4.14 GameplayLayer.m implementation file (part 4 of 4)-(id)init {self = [super init];if (self != nil) {CGSize screenSize = [CCDirector sharedDirector].winSize;// enable read more..

  • Page - 150

    Final Steps111 [self createObjectOfType:kEnemyTypeRadarDishwithHealth:100 atLocation:ccp(screenSize.width * 0.878f, screenSize.height * 0.13f)withZValue:10];// 7 [self scheduleUpdate];// 8 }return self;}@endSome key lines have been added since Chapter 2; they support the use of the CCSpriteBatchNode class and texture atlas:1. Adds all of the frame dimensions specified in scene1atlas.plist to the Cocos2D Sprite Frame Cache. read more..

  • Page - 151

    Chapter 4 Simple Collision Detection and the First Enemy112ratios between the iPhones and iPad are a little different, they are close enough to work for the placement of objects in Space Viking.8. Sets up a scheduler call that will fire the update method in GameplayLayer.m on every frame.Now that you have added code to handle the RadarDish, the Viking, and the texture atlas, it is time to test out Space Viking. If you select Run from Xcode, you should see the Space Viking game in the iPad read more..

  • Page - 152

    Challenges113call will allow for the enemy objects to send messages to each other and even coordi-nate attacks against the Viking.Since you just wrote so much code, you might want to take a few moments to examine the code in more detail and make sure you understand how it all fits together. It’s important to make sure you understand how things work so far, since you’ll be building more on top of what you’ve built here in the rest of the chapters.In the next chapter, you will dive deeper read more..

  • Page - 153

    This page intentionally left blank read more..

  • Page - 154

    actionGoTo:14,PartactionGoTo:14, IIactionGoTo:14,More Enemies and actionGoTo:14,MoreactionGoTo:14, FunLearn how to create more complex enemies for Ole to battle and in the process learn about Cocos2D actions and effects. Finish up with a live, onscreen debugging system using Cocos2D text capabilities.nChapter 5: “More Actions, Effects, and Cocos2D Scheduler”nChapter 6: “Text, Fonts, and the Written Word” read more..

  • Page - 155

    This page intentionally left blank read more..

  • Page - 156

    actionGoTo:14,5actionGoTo:14,MoreactionGoTo:14, Actions,actionGoTo:14, Effects,actionGoTo:14, andactionGoTo:14, actionGoTo:14,Cocos2DactionGoTo:14, SchedulerIn Chapters 3 and 4 you created the foundation for the Space Viking game, added Ole the Viking and a radar dish to the scene, and wired up all of the controls. In this chapter you will add an enemy robot, the massive space cargo ship, and several power-ups to help Ole. You will learn how to create a complex enemy that can chase after and read more..

  • Page - 157

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler118CCLayer, you would just need to ensure that it too responds to the one method required by the EnemyRobot, defined in the GameplayLayerDelegateprotocol.nDelegatesDelegates are classes that carry out specific functionality on behalf of other classes. In SpaceViking the GameplayLayer will act as a delegate for the SpaceCargoShip and EnemyRobot. The GameplayLayer will cre-ate power-ups and PhaserBullets on behalf of the SpaceCargoShip and read more..

  • Page - 158

    Power-Ups119@interface Mallet : GameObject {CCAnimation *malletAnim;}@property (nonatomic, retain) CCAnimation *malletAnim;@endThe power-up objects in Space Viking are very simple, consisting of nothing more than a simple animation. As you can see in Listing 5.1, the Mallet object inher-its from GameObject and contains a single animation stored in the malletAniminstance variable. The Mallet implementation is equally short: switch to the Mallet.mimplementation file and replace the contents with read more..

  • Page - 159

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler120-(void)initAnimations { [self setMalletAnim: [self loadPlistForAnimationWithName:@"malletAnim" andClassName:NSStringFromClass([self class])]];}-(id) init{if( (self=[super init]) ) {screenSize = [CCDirector sharedDirector].winSize;gameObjectType = kPowerUpTypeMallet; [self initAnimations]; [self changeState:kStateSpawning]; }return self;}@endThe Mallet is initialized by first calling initAnimations read more..

  • Page - 160

    Power-Ups1213. Enter Health.m for the filename and ensure that the “Also create Health.h” checkbox is selected. Click Finish.Replace the contents of the Health.h header file with the code in Listing 5.3.Listing 5.3 Health.h header file// Health.h// SpaceViking//#import <Foundation/Foundation.h>#import "GameObject.h"@interface Health : GameObject {CCAnimation *healthAnim;}@property (nonatomic, retain) CCAnimation *healthAnim;@endOpen the Health.m implementation file and read more..

  • Page - 161

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler122-(void)updateStateWithDeltaTime:(ccTime)deltaTimeandListOfGameObjects:(CCArray*)listOfGameObjects {float groundHeight = screenSize.height * 0.065f;if ([self position].y > groundHeight) [self setPosition:ccp([self position].x, [self position].y - 5.0f)];}-(void)initAnimations { [self setHealthAnim: [self loadPlistForAnimationWithName:@"healthAnim" read more..

  • Page - 162

    Power-Ups123Replace the contents of the SpaceCargoShip.h header file with the code in Listing 5.5.Listing 5.5 SpaceCargoShip.h header file// SpaceCargoShip.h// SpaceViking//#import <Foundation/Foundation.h>#import "GameObject.h"@interface SpaceCargoShip : GameObject {BOOL hasDroppedMallet;id <GameplayLayerDelegate> delegate;}@property (nonatomic,assign) id <GameplayLayerDelegate> delegate;@endThe SpaceCargoShip does not contain any animations; instead it uses a set read more..

  • Page - 163

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler124hasDroppedMallet = YES; [delegate createObjectOfType:kPowerUpTypeMallet withHealth:0.0fatLocation:cargoDropPosition withZValue:50]; } else {CCLOG(@"SpaceCargoShip --> Health Powerup was created!"); [delegate createObjectOfType:kPowerUpTypeHealth withHealth:0.0fatLocation:cargoDropPosition withZValue:50]; }}-(id) init{if( (self=[super init]) ) {CCLOG(@"SpaceCargoShip init");hasDroppedMallet = read more..

  • Page - 164

    Enemy Robot125 [CCCallFunc actionWithTarget:self selector:@selector(dropCargo)], [CCMoveTo actionWithDuration:0.0fposition:offScreen],nil] ]; [self runAction:action]; }return self;}@endThe dropCargo method of the space cargo ship gets called when the ship is clos-est to the viewer. This method checks to see if the Mallet has been dropped; if not, it calls on the GameplayDelegate to drop the Mallet. If the Mallet has been read more..

  • Page - 165

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler126Creating the Enemy RobotThe EnemyRobot is set up just like the RadarDish enemy you created in the previ-ous chapter. It has all of the AI included in a single EnemyRobot class that inherits from GameCharacter.1. Right-click on the EnemyObjects folder and select New File.2. Select the Cocoa Touch category under iOS and the Objective-C class type and click Next.3. For the Subclass field, enter GameCharacter and click Next.4. Enter read more..

  • Page - 166

    Enemy Robot127@property (nonatomic, retain) CCAnimation *headHitAnim;@property (nonatomic, retain) CCAnimation *robotDeathAnim;-(void)initAnimations;@endThe first part of Listing 5.7 is very similar to what you saw on RadarDish, as the EnemyRobot class inherits from GameCharacter class and has a set of instance variables for the animations. Toward the end of Listing 5.7 is the <GameplayLayer-Delegate> instance variable of type id. In the previous chapter in Listing 4.2, you created a read more..

  • Page - 167

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler128@synthesize lowerPhaserAnim;@synthesize torsoHitAnim;@synthesize headHitAnim;@synthesize robotDeathAnim;-(void) dealloc {delegate = nil; [robotWalkingAnim release]; [raisePhaserAnim release]; [shootPhaserAnim release]; [lowerPhaserAnim release]; [torsoHitAnim release]; [headHitAnim release]; [robotDeathAnim release]; [super dealloc];}-(void)shootPhaser {CGPoint phaserFiringPosition;PhaserDirection phaserDir;CGRect read more..

  • Page - 168

    Enemy Robot129 robotBoundingBox.size.width*3.0f, robotBoundingBox.size.height); } else { robotSightBoundingBox = CGRectMake(robotBoundingBox.origin.x - (robotBoundingBox.size.width*2.0f), robotBoundingBox.origin.y, robotBoundingBox.size.width*3.0f, robotBoundingBox.size.height); }return robotSightBoundingBox;}The EnemyRobot implementation file starts with the @synthesize statement for the read more..

  • Page - 169

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler130// Fades out the sprite if it was visible before [self setDisplayFrame: [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:@"teleport.png"]]; action = [CCSpawn actions: [CCRotateBy actionWithDuration:1.5f angle:360], [CCFadeIn actionWithDuration:1.5f],nil];break;case kStateIdle:CCLOG(@"EnemyRobot->Changing State to Idle"); read more..

  • Page - 170

    Enemy Robot131case kStateAttacking:CCLOG(@"EnemyRobot->Changing State to Attacking"); action = [CCSequence actions: [CCAnimate actionWithAnimation:raisePhaserAnimrestoreOriginalFrame:NO], [CCDelayTime actionWithDuration:1.0f], [CCAnimate actionWithAnimation:shootPhaserAnimrestoreOriginalFrame:NO], [CCCallFunc actionWithTarget:selfselector:@selector(shootPhaser)], read more..

  • Page - 171

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler132if (action != nil) [self runAction:action];}The first part of the changeState method checks to make sure the EnemyRobotis not dead. If the robot is dead, the method does nothing. Otherwise, any currently running actions are also stopped, since the EnemyRobot is about to transition to a new state. After these setup lines, the method drops into a switch statement that carries out the particular logic depending on which state the read more..

  • Page - 172

    Enemy Robot133tells the gameplayLayer to create a phaser beam and send it off toward the Viking.After firing, the EnemyRobot lowers the gun and pauses for another 2 seconds. NoteCCCallFunc is a special action that can call a method in any object. It is useful when you want to call some portion of your code before, during, or after an action sequence. Along with CCCallFunc are CCCallFuncN, which passes along the CCNode as a parameter, and CCCallFuncND, which passes along the CCNode and a pointer read more..

  • Page - 173

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler134if ((isVikingWithinBoundingBox) && ([vikingCharacter characterState] == kStateAttacking)) {// Viking is attacking this robotif ((characterState != kStateTakingDamage) && (characterState != kStateDead)) { [self setCharacterHealth: [self characterHealth] – [vikingCharacter getWeaponDamage]];if (characterHealth > 0) { [self read more..

  • Page - 174

    Enemy Robot135children. By having the kVikingSpriteTagValue as a constant, each of the children of the CCSpriteSheet can call it and retrieve a pointer to the Viking character. The next three lines create three CGRects that are used to determine where the Viking is in relation to the EnemyRobot and if the EnemyRobot can see the Viking.If Statement ShortcutsThe two lines with the ternary “?” operator in EnemyRobot.m are a simple shortcut way to combine an if statement and an assignment read more..

  • Page - 175

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler136adjusted bounding box and initialize the animations. Copy the contents of Listing 5.11 and paste it below the updateStateWithDelta time in EnemyRobot.m.Listing 5.11 EnemyRobot.m implementation file (part 4 of 4)-(CGRect)AdjustedBoundingBox {// Shrink the bounding box by 18% on the X axis, and move it to the // right by 18% and crop it by 5% on the Y Axis. // On the iPad this is 30 pixels on the X axis and // 10 pixels from the top read more..

  • Page - 176

    Adding the PhaserBullet137 [self setRobotDeathAnim: [self loadPlistForAnimationWithName:@"robotDeathAnim" andClassName:NSStringFromClass([self class])]];}-(id) init{if( (self=[super init]) ) {isVikingWithinBoundingBox = NO;isVikingWithinSight = NO;gameObjectType = kEnemyTypeAlienRobot; [self initAnimations];srandom(time(NULL)); }return self;}@endThe AdjustedBoundingBox method does exactly what the name implies: it takes the EnemyRobot’s bounding box and read more..

  • Page - 177

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler138The PhaserBullet is a simple class; to create it in your SpaceViking project:1. Right-click on EnemyObjects group and click New File.2. Select Cocoa Touch category under iOS and Objective-C class as the file type and click Next.3. For the Subclass field, enter GameCharacter.4. Enter PhaserBullet.m for the filename and click Save.Open the PhaserBullet.h header file and replace it with the contents of Listing 5.12.Listing 5.12 PhaserBullet.h read more..

  • Page - 178

    Adding the PhaserBullet139 [super dealloc];}-(void)changeState:(CharacterStates)newState { [self stopAllActions];id action = nil;characterState = newState;switch (newState) {case kStateSpawning:CCLOG(@"Phaser->Changed state to Spawning"); action = [CCAnimate actionWithAnimation:firingAnimrestoreOriginalFrame:NO];break;case kStateTraveling:CCLOG(@"Phaser->Changed state to Traveling");CGPoint endLocation;if (myDirection == kDirectionLeft) read more..

  • Page - 179

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler140if ((currentSpritePosition.x < 0.0f) || ( currentSpritePosition.x > screenSize.width)) { [self changeState:kStateDead];return YES; }return NO;}-(void)updateStateWithDeltaTime:(ccTime)deltaTimeandListOfGameObjects:(CCArray*)listOfGameObjects {if ([self isOutsideOfScreen])return;if ([self numberOfRunningActions] == 0) {if (characterState == kStateSpawning) { [self changeState:kStateTraveling];return; read more..

  • Page - 180

    GameplayLayer and Viking Updates141The PhaserBullet is a simple character that moves from the firing location to either the left or right side of the screen. If it comes in contact with Ole, the Viking will change the PhaserBullet’s state to dead, as it absorbs the hit. If the Phaser-Bullet travels outside of the screen boundaries, it removes itself from the game. This wraps up what you need to do to create the EnemyRobot. The next step is to add a little bit of code in GameplayLayer to create read more..

  • Page - 181

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler142 } else if (kEnemyTypeAlienRobot == objectType) {CCLOG(@"Creating the Alien Robot");EnemyRobot *enemyRobot = [[EnemyRobot alloc] initWithSpriteFrameName:@"an1_anim1.png"]; [enemyRobot setCharacterHealth:initialHealth]; [enemyRobot setPosition:spawnLocation]; [enemyRobot changeState:kStateSpawning]; [sceneSpriteBatchNode addChild:enemyRobot z:ZValue]; [enemyRobot read more..

  • Page - 182

    GameplayLayer and Viking Updates143Listing 5.16 GameplayLayer.m createPhaserWithDirection method-(void)createPhaserWithDirection:(PhaserDirection)phaserDirectionandPosition:(CGPoint)spawnPosition {PhaserBullet *phaserBullet = [[PhaserBullet alloc] initWithSpriteFrameName:@"beam_1.png"]; [phaserBullet setPosition:spawnPosition]; [phaserBullet setMyDirection:phaserDirection]; [phaserBullet setCharacterState:kStateSpawning]; [sceneSpriteBatchNode addChild:phaserBullet]; read more..

  • Page - 183

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler144EnemyRobot. If the RadarDish is dead, the GameplayLayer will unschedule the timer calling this method.The final glue in GameplayLayer are a few lines to add in the init method. Add the lines shown in Listing 5.18 immediately after the [self scheduleUpdate] call.Listing 5.18 GameplayLayer.m init method additions[self schedule:@selector(addEnemy) interval:10.0f];[self createObjectOfType:kEnemyTypeSpaceCargoShip withHealth:0 read more..

  • Page - 184

    For the More Curious: Effects in Cocos2D145If you have any trouble running Space Viking, go back and check your code against the listings in this chapter. Make sure you have included all of the classes and code in your copy of Space Viking. While playing the game, be sure to try out the crouching move to avoid those pesky phaser bullets. A Word on Cocos2D’s SchedulerThe Cocos2D Scheduler provides your game with timed events and calls. All CCNodeobjects know how to schedule and unschedule read more..

  • Page - 185

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler146Finally, if you apply the effect to the CCLayer, everything in the layer will have the effect applied.You don’t have to know exactly how the vertex array is stored in the FBO, although you are free to see the implementation details in the Cocos2D source code. The important points to remember are that there is a grid of image data in the FBO, and the effect actions act on this grid.Within the Cocos2D effects there are two subtypes: a read more..

  • Page - 186

    For the More Curious: Effects in Cocos2D147Listing 5.20 GameplayLayer.m waves actionid wavesAction = [CCWaves actionWithWaves:5 amplitude:20 horizontal:NOvertical:YES grid:ccg(15,10) duration:20]; [sceneSpriteBatchNode runAction: [CCRepeatForever actionWithAction:wavesAction]];This is setting up a CCWaves action against the CCSpriteBatchNode that is used to render the Viking and all of the enemies onscreen. If you click Run, you should see an image similar to Figure 5.5. Pay close read more..

  • Page - 187

    Chapter 5 More Actions, Effects, and Cocos2D Scheduler148Running the EffectsTest Navigate to the directory where you downloaded Cocos2D back in Chapter 1, “Hello, Cocos2D,” and open the cocos2d-iphone project. With the cocos2d-iphone project opened, set the Scheme dropdown to EffectsTest, as shown in Figure 5.6.Figure 5.5 CCWaves action applied to the CCSpriteBatchNode in Space VikingFigure 5.6 EffectsTest selected under the Scheme dropdown in XcodeSelect Run in Xcode, and you should see the read more..

  • Page - 188

    Exercises and Challenges149Returning Sprites and Objects Back to NormalOnce you start playing with effects, you will notice that they stay applied to the CCSprites and other objects even after you stop the action. To return your CCSpriteto its normal, nonaltered state, you need to call the special StopGrid action. For example, if you wanted to stop the CCWaves action applied to the CCSpriteBatch-Node in Space Viking, you would need:[sceneSpriteBatchNode runAction:[CCStopGrid read more..

  • Page - 189

    This page intentionally left blank read more..

  • Page - 190

    actionGoTo:14,6actionGoTo:14,Text, Fonts, and tactionGoTo:14,he actionGoTo:14,WrittenactionGoTo:14, WordIn the last two chapters, you learned how to add artificial intelligence, animations, and enemies to your game. In this chapter you get to have a reprieve from the complexities of game mechanics and focus on the text rendering available in Cocos2D. Cocos2D has extensive support for all of the built-in iOS fonts as well as embedded TrueType fonts. The text system allows you to add labels and read more..

  • Page - 191

    Chapter 6 Text, Fonts, and the Written Word 152Adding a Start Banner to Space VikingTo better understand how to use a CCLabelTTF, you will create a quick “Game Start” banner when the Space Viking game play first starts. This banner will be centered on the screen and will zoom and fade out over the course of 2 seconds. To get started, open the SpaceViking project and the GameplayLayer.m implementation file.In the init method add the lines shown in Listing 6.1 before the [self scheduleUpdate] read more..

  • Page - 192

    Understanding Anchor Points and Alignment153actionGoTo:14,Understanding Anchor PointactionGoTo:14,s and AlignmentAll CCNodes from CCSprites to CCLabelTTF have anchor points to allow them to be positioned onscreen. Anchor points are useful in positioning and aligning your objects onscreen, especially labels. The anchor point is an offset into an object tex-ture—in other words, what point in the texture to use to place it onscreen. Cocos2D defaults to an anchor point in the middle of your read more..

  • Page - 193

    Chapter 6 Text, Fonts, and the Written Word 154Looking at Figure 6.2, you can see the default anchor point at the middle of the texture would have a value of (0.5,0.5). Look at anchor point values as percentages, with 1 being 100%, or all the way to the end of the texture. Take a close look at the bottom right of Figure 6.2, at the value (1,0). This anchor point (1,0) is all the way over on the x-axis of the texture, but at the start of the y-axis, so bottom right.On the top right you can see read more..

  • Page - 194

    CCLabelBMFont155Listing the Fonts Available in iOSThe CCLabelTTF class relies on the fonts available in the iOS, and Apple is always adding to the available fonts with each iOS release. The best way to know what fonts you can use is to query the iOS for available fonts under the UIFont class. Jonathan Saggau wrote an excellent bit of compact code to list out the fonts. A modified version of it is given here and can be dropped in the init method of GameScene.m to print out the available fonts to read more..

  • Page - 195

    Chapter 6 Text, Fonts, and the Written Word 156actionGoTo:14,Using Glyph DesignerGlyph Designer is a Mac OS X–based application for design font atlases developed by 71Squared. Unlike Hiero, it is a native Mac OS X application, offering better perfor-mance and compatibility with Mac OS X. In order to use Glyph Designer, you need to purchase it in the Mac App Store or aactionURI(http://glyphdesigner.71squared.com/):t http://glyphdesigner.71squared.com/.To create the font texture atlas:1. Start read more..

  • Page - 196

    Using the Hiero Font Builder Tool157WarningSafari’s default behavior is to just download the Hiero.jnpl file. You will need to double-click it in the Downloads window to launch Hiero.If prompted, accept the warning shown in Figure 6.4.Figure 6.3 Glyph DesignerFigure 6.4 Warning upon running Hiero read more..

  • Page - 197

    Chapter 6 Text, Fonts, and the Written Word 158Once Hiero is up and running, you will see a list of the fonts available in your sys-tem in the top left text box. To create the font atlas needed for Space Viking, follow these steps:1. In the top left font selection box, scroll down and pick Helvetica.2. In the Sample Text area, click on NEHE to have some sample characters entered in for you. If the text you need consists only of a few characters, you can type them here. 3. Under the Color, click read more..

  • Page - 198

    Using the Hiero Font Builder Tool159If you created your font texture atlas with Hiero, you will need to import the PNG and plist files into Xcode. Drag both the SpaceVikingFont.png and SpaceVikingFont.fntfiles into your SpaceViking project under the Images folder. NoteAll the characters you want to display have to be present in this font atlas. If you are using lowercase and uppercase versions of the characters, both need to be included. If you try to set the text to a character that is not in read more..

  • Page - 199

    Chapter 6 Text, Fonts, and the Written Word 160actionGoTo:14,For the More CuractionGoTo:14,ious: LiveactionGoTo:14, DebuggingAt this point you know how to add text labels into your games, so if you just are inter-ested in the basics, feel free to skip to the next chapter. But if you want to learn a cool way to use text labels to make debugging and developing your game easier, check out this section!In your games it is often useful to know what state each of the characters is in dur-ing game read more..

  • Page - 200

    For the More Curious: Live Debugging161BOOL isVikingWithinBoundingBox;BOOL isVikingWithinSight;GameCharacter *vikingCharacter;id <GameplayLayerDelegate> delegate;CCLabelBMFont *myDebugLabel;}@property (nonatomic,assign) id <GameplayLayerDelegate> delegate;@property (nonatomic, retain) CCAnimation *robotWalkingAnim;@property (nonatomic, retain) CCAnimation *raisePhaserAnim;@property (nonatomic, retain) CCAnimation *shootPhaserAnim;@property (nonatomic, retain) CCAnimation read more..

  • Page - 201

    Chapter 6 Text, Fonts, and the Written Word 162case kStateIdle: [myDebugLabel setString: [labelString stringByAppendingString:@" Idle"]];break;case kStateWalking: [myDebugLabel setString: [labelString stringByAppendingString:@" Walking"]];break;case kStateAttacking: [myDebugLabel setString: [labelString stringByAppendingString:@" Attacking"]];break;case kStateTakingDamage: [myDebugLabel read more..

  • Page - 202

    For the More Curious: Live Debugging163This one line will call the setDebugLabelTextAndPosition method and update the debug label on every frame. If you recall from Chapter 5, “More Actions, Effects, and Cocos2D Scheduler,” the EnemyRobot removes itself from the CCSpriteBatch-Node once it is done playing the death animation. When the EnemyRobot is removed from the CCSpriteBatchNode, it needs to inform the debug label to remove itself from the GameplayLayer. Open the dealloc method in the read more..

  • Page - 203

    Chapter 6 Text, Fonts, and the Written Word 164CCLabelBMFont *debugLabel = [CCLabelBMFontlabelWithString:@"NoneNone"fntFile:@"SpaceVikingFont.fnt"]; [self addChild:debugLabel]; [enemyRobot setMyDebugLabel:debugLabel]; [enemyRobot release]; }If you click Run now, you will see that the EnemyRobot characters have three lines of debug text above their heads indicating state and their current position. Figure 6.6 shows Space Viking on the iPad read more..

  • Page - 204

    Challenges165have even gone even further to show how much memory is free on the device as the game is being played to tip them off when they are about to encounter a low-memory condition or if they have memory leaks. actionGoTo:14,SummaryYou have learned about the font-rendering system in Cocos2D and the differences between using CCLabelTTF and CCLabelBMFont. You also learned about using text labels as a live debugging system for your games and implemented a debugging system for the EnemyRobot. read more..

  • Page - 205

    This page intentionally left blank read more..

  • Page - 206

    actionGoTo:15,PartactionGoTo:15, IIIactionGoTo:15,FromactionGoTo:15, Level to GamactionGoTo:15,eLearn how to expand the Space Viking level you have built into a full game by adding menus, using sound, and scrolling.nChapter 7: “Main Menu, Level Completed, and Credits Scenes”nChapter 8: “Pump Up the Volume!”nChapter 9: “When the World Gets Bigger: Adding Scrolling” read more..

  • Page - 207

    This page intentionally left blank read more..

  • Page - 208

    actionGoTo:15,7actionGoTo:15,Main Menu, Level actionGoTo:15,Completed, actionGoTo:15,and Credits ScenactionGoTo:15,esSo far in this book you have built a full working scene for Ole the Viking to explore. He has to battle evil robots and figure out a way to stop them from spawning. In this chapter you learn about Cocos2D menus and how to create and link multiple scenes. By the end of this chapter you will have Space Viking set up to start on a main menu, show three different levels for Ole to read more..

  • Page - 209

    Chapter 7 Main Menu, Level Completed, and Credits Scenes170nOptions MenuA menu screen that allows the user to turn music on/off and sound effects on/off, as well as an option to view the Space Viking credits.nCreditsA list of the people involved in bringing Space Viking to life.nLevel CompletedShown when the player completes a level or dies, indicating the player’s progress.nGameplayScenesA scene for each of the levels in Space Viking. You have already created the first gameplay scene, when read more..

  • Page - 210

    Introducing the GameManager171between scenes, you create a GameManager class to handle the task of asking the Cocos2D Director to switch CCScenes. The GameManager class will be a singleton class, so there will be only one instance of it during the lifetime of the Space Vikinggame, and it will be accessible from all the scenes. All of the scenes will know about the GameManager, and the GameManager will know about them, but the individual scenes will not know about each other. This way, each scene read more..

  • Page - 211

    Chapter 7 Main Menu, Level Completed, and Credits Scenes172// Debug Enemy States with Labels// 0 for OFF, 1 for ON#define ENEMY_STATE_DEBUG 0The SceneTypes is just an enumeration type that defines the scenes the Game-Manager will support switching between. You can see there are placeholders for game levels 2 through 5 that you have yet to create.The LinkTypes is a set of types that are used to determine what URL to open. In the Main Menu the user will have the choice to open this book’s site, read more..

  • Page - 212

    Introducing the GameManager173@property (readwrite) BOOL isMusicON;@property (readwrite) BOOL isSoundEffectsON;@property (readwrite) BOOL hasPlayerDied;+(GameManager*)sharedGameManager; // 1-(void)runSceneWithID:(SceneTypes)sceneID; // 2-(void)openSiteWithLinkType:(LinkTypes)linkTypeToOpen ; // 3@endIn Listing 7.2 pay close attention to the +(GameManager*)sharedManagermethod. The plus sign is key here—it indicates that the read more..

  • Page - 213

    Chapter 7 Main Menu, Level Completed, and Credits Scenes174Listing 7.3 GameManager.m implementation—singleton portion// GameManager.m// SpaceViking//#import "GameManager.h"#import "GameScene.h"#import "MainMenuScene.h"#import "OptionsScene.h"#import "CreditsScene.h"#import "IntroScene.h"#import "LevelCompleteScene.h"@implementation GameManagerstatic GameManager* _sharedGameManager = nil; // read more..

  • Page - 214

    Introducing the GameManager175CCLOG(@"Game Manager Singleton, init");isMusicON = YES;isSoundEffectsON = YES;hasPlayerDied = NO; currentScene = kNoSceneUninitialized; }return self;}The singleton code has one purpose, to ensure that there is only one instance of GameManager allocated and running in your game at any time; hence the “single” part of the name. The code lines in Listing 7.3 carry out the following:1. Declares a static object of type GameManager and initializes read more..

  • Page - 215

    Chapter 7 Main Menu, Level Completed, and Credits Scenes176When looking over Listing 7.3, keep in mind that a singleton is just like other classes, except that within your game there can be only one instance of the class. With the singleton portion out of the way, copy the contents of Listing 7.4 into GameManager’s init method.Listing 7.4 GameManager.m implementation—runSceneWithID-(void)runSceneWithID:(SceneTypes)sceneID { SceneTypes oldScene = currentScene; currentScene = sceneID;id read more..

  • Page - 216

    Introducing the GameManager177default: CCLOG(@"Unknown ID, cannot switch scenes");return;break; }if (sceneToRun == nil) {// Revert back, since no new scene was foundcurrentScene = oldScene;return; }// Menu Scenes have a value of < 100if (sceneID < 100) {if (UI_USER_INTERFACE_IDIOM() !=UIUserInterfaceIdiomPad) { CGSize screenSize = [CCDirector sharedDirector].winSizeInPixels;if (screenSize.width == 960.0f) { // iPhone 4 Retina read more..

  • Page - 217

    Chapter 7 Main Menu, Level Completed, and Credits Scenes178UI_USER_INTERFACE_IDIOM() determines if Space Viking is not running on the iPad and then applies a scaling down to the entire scene. Since the scene contains the layer and the sprites, everything gets scaled down in one call. The menu scenes contain very few images, so scaling down iPad-sized images provides a savings on the size of Space Viking. Unlike the other checks for UI_USER_INTERFACE_IDIOM(), here you are scaling if the game read more..

  • Page - 218

    Menus in Cocos2D179 } else { CCLOG(@"Defaulting to Cocos2DBook.com Blog Site");urlToOpen = [NSURL URLWithString:@"http://www.cocos2dbook.com"]; }if (![[UIApplication sharedApplication] openURL:urlToOpen]) { CCLOG(@"%@%@",@"Failed to open url:",[urlToOpen description]); [self runSceneWithID:kMainMenuScene]; }}@endThe openSiteWithLinkType method determines which URL to open via the linkTypeToOpen variable and makes a read more..

  • Page - 219

    Chapter 7 Main Menu, Level Completed, and Credits Scenes180nCCMenuItemFontA menu item class that can display a text string you want to display onscreen to act as a text button.nCCMenuItemImageAn image button composed of a normal and active/pressed-down image.nCCMenuItemLabelA button that uses a CCLabelTTF to display the text.nCCMenuItemSpriteSimilar to the CCMenuItemImage class except it uses already created CCSprites for the normal and active/pressed-down images.nCCMenuItemToggleA toggle switch read more..

  • Page - 220

    Scene Organization and Images181Adding Images and Fonts for the MenusThe various menus in Space Viking require a new set of images in addition to what you have used up to now. In the resources file you downloaded for this chapter, you will find two new folders: Menus and Fonts. Use the following steps to add the new images and new font atlas needed into your SpaceViking project.1. In Xcode, select the Images group, right-click, and select Add Files.2. Navigate to the directory where you read more..

  • Page - 221

    Chapter 7 Main Menu, Level Completed, and Credits Scenes182actionGoTo:15,Creating the Main MenuThe Main Menu serves as the model for the menus in Space Viking. Once you under-stand how it works, you can have confidence in adding menus to your own games. You will first create the CCMenuItems, and then a CCMenu object that represents the entire menu that will be created and added to your scenes.Creating the MainMenuSceneTo start, select the MainMenu group in the Groups and Files tab.1. Right-click read more..

  • Page - 222

    Creating the Main Menu183@interface MainMenuScene : CCScene {MainMenuLayer *mainMenuLayer;}@endThe MainMenu scene is just a container object to hold the MainMenuLayerclass. In the header file you can see the declaration for the MainMenuLayer instance variable.Switch to the MainMenu.m implementation file and copy the code in Listing 7.7 in place of the template-generated code.Listing 7.7 MainMenuScene.m implementation file// MainMenuScene.m// SpaceViking//#import read more..

  • Page - 223

    Chapter 7 Main Menu, Level Completed, and Credits Scenes184#import "Constants.h"#import "GameManager.h"@interface MainMenuLayer : CCLayer {CCMenu *mainMenu;CCMenu *sceneSelectMenu;}@endIn the header file of MainMenuLayer are two instance variables to cover the Main Menu and the scene selection menu. There is also an include of the GameManager.hheader file so that the MainMenuLayer can call GameManager directly. In the imple-mentation file is where everything comes together. read more..

  • Page - 224

    Creating the Main Menu185Listing 7.10 MainMenuLayer.m (part 2: buyBook, showOptions, playScene)-(void)buyBook { [[GameManager sharedGameManager]openSiteWithLinkType:kLinkTypeBookSite];}-(void)showOptions {CCLOG(@"Show the Options screen"); [[GameManager sharedGameManager] runSceneWithID:kOptionsScene];}-(void)playScene:(CCMenuItemFont*)itemPassedIn {if ([itemPassedIn tag] == 1) {CCLOG(@"Tag 1 found, Scene 1"); [[GameManager sharedGameManager] read more..

  • Page - 225

    Chapter 7 Main Menu, Level Completed, and Credits Scenes186CCMenuItemImage *buyBookButton = [CCMenuItemImageitemFromNormalImage:@"BuyBookButtonNormal.png" selectedImage:@"BuyBookButtonSelected.png" disabledImage:nil target:self selector:@selector(buyBook)];CCMenuItemImage *optionsButton = [CCMenuItemImageitemFromNormalImage:@"OptionsButtonNormal.png" selectedImage:@"OptionsButtonSelected.png" disabledImage:nil target:self read more..

  • Page - 226

    Creating the Main Menu187Listing 7.12 MainMenuLayer (part 4: displaySceneSelection)-(void)displaySceneSelection {CGSize screenSize = [CCDirector sharedDirector].winSize;if (mainMenu != nil) { [mainMenu removeFromParentAndCleanup:YES]; }CCLabelBMFont *playScene1Label = [CCLabelBMFont labelWithString:@"Ole Awakes!" fntFile:@"VikingSpeechFont64.fnt"];CCMenuItemLabel *playScene1 = [CCMenuItemLabel itemWithLabel:playScene1Label read more..

  • Page - 227

    Chapter 7 Main Menu, Level Completed, and Credits Scenes188CCLabelBMFont *backButtonLabel = [CCLabelBMFont labelWithString:@"Back"fntFile:@"VikingSpeechFont64.fnt"];CCMenuItemLabel *backButton = [CCMenuItemLabel itemWithLabel:backButtonLabel target:selfselector:@selector(displayMainMenu)];CCLabelBMFont *backButtonLabel = [CCLabelBMFont labelWithString:@"Back" fntFile:@"VikingSpeechFont64.fnt"];CCMenuItemLabel *backButton = read more..

  • Page - 228

    Creating the Main Menu189Listing 7.13 MainMenuLayer (part 5: init method)-(id)init {self = [super init];if (self != nil) {CGSize screenSize = [CCDirector sharedDirector].winSize;CCSprite *background = [CCSprite spriteWithFile:@"MainMenuBackground.png"]; [background setPosition:ccp(screenSize.width/2, screenSize.height/2)]; [self addChild:background]; [self displayMainMenu];CCSprite *viking = [CCSprite read more..

  • Page - 229

    Chapter 7 Main Menu, Level Completed, and Credits Scenes190running a CCSequenceAction, scaling up and then down, and at the same time run-ning a CCRotateBy action to cause him to spin around.actionGoTo:15,Additional Menus and GameactionGoTo:15,playLayerThe Intro, Credits, LevelComplete, and Options menus are set up in the same way as the MainMenu, each with its own CCScene and CCLayer classes. The Credits menu consists of just three links to the people who had a part in creating the Space Viking read more..

  • Page - 230

    Additional Menus and GameplayLayer191there was no code to transition out of game play if the Viking died or the RadarDishwas destroyed. To add these changes, start by opening the GameplayLayer.h header file.In the import section, add an import for the GameManager.h header file, so that you have this line among the other import statements:#import "GameManager.h"The import statement allows the GameplayLayer to call upon the GameManagersingleton and transition Space Viking from Gameplay read more..

  • Page - 231

    Chapter 7 Main Menu, Level Completed, and Credits Scenes192 [[GameManager sharedGameManager] setHasPlayerDied:YES]; [[GameManager sharedGameManager]runSceneWithID:kLevelCompleteScene]; } // Check to see if the RadarDish is dead tempChar = (GameCharacter*)[sceneSpriteBatchNodegetChildByTag:kRadarDishTagValue];if (([tempChar characterState] == kStateDead) && ([tempChar numberOfRunningActions] == 0)) { [[GameManager read more..

  • Page - 232

    For the More Curious: The IntroLayer and LevelComplete Classes193While you are in the SpaceVikingAppDelegate, you can remove the imports for HelloWorldScene and GameScene, as they are no longer called from the Application Delegate directly. With all of the changes in this chapter in place, click Run and test your SpaceVikingproject. It should start with the Main Menu with the Viking rotating around the logo. If you play the first level and destroy the RadarDish or Ole dies, you will see the read more..

  • Page - 233

    Chapter 7 Main Menu, Level Completed, and Credits Scenes194LevelCompleteLayer ClassThe LevelCompleteLayer is set up similarly to the IntroLayer. It also responds to touches by asking the GameManager to swap the MainMenu in place of Level-Complete. There is one benefit to having the GameManager singleton that has not yet been discussed, and that is to have it act as a single place to store what’s happen-ing in the game. Read that last line again: the GameManager singleton is the one place where read more..

  • Page - 234

    Challenges195The use of the Singleton pattern for a game manager can be greatly beneficial in keeping your game data in one place and at the same time accessible by any class in your game. If you want to save the player’s progress or create a new level based on how the player did on the previous level, you can do that with a singleton game manager.NoteWhile the CreditsScene and Layer classes are not covered in this chapter, they con-tain the same basic Cocos2D objects and calls you have read more..

  • Page - 235

    This page intentionally left blank read more..

  • Page - 236

    actionGoTo:15,8actionGoTo:15,Pump Up the VolumactionGoTo:15,e!In the last chapter you learned how to create menus and link scenes together in your games. Now it is time to head back into the gameplay and add music and sound effects to Space Viking. In this chapter you will learn how to use the audio engine included with Cocos2D and how you can add audio to your own games. Read on to hear what Ole the Viking sounds like, and find out what sounds break the silence of the alien read more..

  • Page - 237

    Chapter 8 Pump Up the Volume!198and Steve Oldmeadow. The code for Space Viking borrows heavily from the Tom the Turret sample.actionGoTo:15,Importing and Setting actionGoTo:15,Up the Audio FiactionGoTo:15,lenamesBefore you can dive into coding the audio playback in Space Viking, you need to add the audio files to your project. In this section you also set up a series of #define con-stants for the audio filenames, as you have done with other constants in Space Viking.Adding the Audio Files to read more..

  • Page - 238

    Importing and Setting Up the Audio Filenames199Open Constants.h and add the lines in Listing 8.1. The audio filenames are set up as #define statements to make it easy to switch filenames without having to find every reference to them in the code. Do not worry about hand-typing all of these #defines; in the resources folder for this chapter is a file called AddtionsToConstants-HeaderFile.rtf that includes all of them.Listing 8.1 #defines for audio filenames in Constants.h// Audio Items#define read more..

  • Page - 239

    Chapter 8 Pump Up the Volume!200At this point, the #defines and typedef enum declarations should be pretty familiar to you. The GameManagerSoundState type definition makes it easier to track what state the audio engine is in. In this enumeration you also declare the value of each choice. Notice how the states before “initialized” are less than 100 in value. That makes it easier later on to check whether the engine is still initializing or loading audio. The #defines serves as reference for read more..

  • Page - 240

    Synchronous versus Asynchronous Loading of Audio 201WarningBe sure to copy the SoundEffects.plist file into your Xcode project; otherwise, Space Vikingwill not work when you reach the end of this chapter.The code that utilizes the SoundEffects.plist is inside GameManager. Before learning about those methods, it is important to understand the two ways that audio files can be loaded into CocosDenshion.actionGoTo:15,Synchronous versus AsyncactionGoTo:15,hronous Loading actionGoTo:15,of AudioMusic read more..

  • Page - 241

    Chapter 8 Pump Up the Volume!202soundEngine = [SimpleAudioEngine sharedEngine]; // 3 // 4 [soundEngine preloadBackgroundMusic:BACKGROUND_TRACK_OLE_AWAKES]; // 5 [soundEngine playBackgroundMusic:BACKGROUND_TRACK_OLE_AWAKES];}The loadAudio method here is very simple, since it loads the music synchronously and plays it immediately after loading. The method works as follows:1. The audio mixing rate is set up for the CocosDenshion SoundEngine.The iPhone and iPad audio hardware read more..

  • Page - 242

    Synchronous versus Asynchronous Loading of Audio 203Before we get to asynchronous loading, let’s quickly cover how to play sound effects. In the start of the level, let’s have Ole speak a quick curse to show his frustra-tion with his situation. You can imagine how irritated you would be, waking up in an alien world surrounded by robots. Don’t worry—the curse is PG-rated and spoken in words only a Viking would know.Add the lines shown in Listing 8.3 to your loadAudio method in order to read more..

  • Page - 243

    Chapter 8 Pump Up the Volume!204Remember to remove or comment out the code you just added to GameplayLayer.m.You are going to have the audio set up and preloaded in the GameManager, and the individual GameObjects, such as the Viking and EnemyRobot, will take care of calling GameManager to play their audio.Adding Audio to GameManagerFor the next step you need to move the audio initialization and preloading code to GameManager. You will use NSOperationQueue to manage the background threads for read more..

  • Page - 244

    Synchronous versus Asynchronous Loading of Audio 205The first line is the import of the SimpleAudioEngine, which brings the Cocos-Denshion classes into GameManager. In the @interface block add two instance variables, one to keep track of the GameManagerSoundState and another to be a pointer to the soundEngine. Lastly, add two @property statements for the managerSoundState and the soundEngine. Note also the NSMutableDictionaryvariables that keep track of the sound effect filenames and whether or read more..

  • Page - 245

    Chapter 8 Pump Up the Volume!206 [queue addOperation:asyncSetupOperation]; [asyncSetupOperation autorelease]; }}The first part of setupAudioEngine checks to make sure the audio engine has not yet been initialized. If the engine is already initialized, there is no need to do anything else, so the method just returns. If the engine is not initialized, the process to get it set up is started. The next few lines set up NSOperationQueue and NSInvocationOperation to run the contents read more..

  • Page - 246

    Synchronous versus Asynchronous Loading of Audio 207 } else { [audioManager setResignBehavior:kAMRBStopPlay autoHandle:YES];soundEngine = [SimpleAudioEngine sharedEngine];managerSoundState = kAudioManagerReady;CCLOG(@"CocosDenshion is Ready"); }}The first part of the initAudioSync method sets the managerSoundState to initializing and sets the CocosDenshion sample rate. The sample rate should match the sample rate in your audio files. Usually you want this to be set to read more..

  • Page - 247

    Chapter 8 Pump Up the Volume!208Caveat about Multiple ThreadsAlthough asynchronous loading of audio is recommended and encouraged, CocosDenshion is not designed to be thread safe, meaning that you should not attempt to load and play audio at the same time or load audio from a number of separate threads. When loading audio asynchronously, you should always have one worker thread, as shown here. The background music and sound effects engines are separate, though, so it is perfectly safe to play read more..

  • Page - 248

    Synchronous versus Asynchronous Loading of Audio 209case kGameLevel3: result = @"kGameLevel3";break;case kGameLevel4: result = @"kGameLevel4";break;case kGameLevel5: result = @"kGameLevel5";break;case kCutSceneForLevel2: result = @"kCutSceneForLevel2";break;default: [NSException raise:NSGenericException format:@"UnexpectedSceneType."]; }return result;}-(NSDictionary read more..

  • Page - 249

    Chapter 8 Pump Up the Volume!210NSLog(@"Before"); [self setListOfSoundEffectFiles: [[NSMutableDictionary alloc] init]];NSLog(@"after");for (NSString *sceneSoundDictionary in plistDictionary) { [listOfSoundEffectFilesaddEntriesFromDictionary: [plistDictionary objectForKey:sceneSoundDictionary]]; }CCLOG(@"Number of SFX filenames:%d", [listOfSoundEffectFiles count]); }// 5. Load the list of sound effects read more..

  • Page - 250

    Synchronous versus Asynchronous Loading of Audio 211branch to create and return an NSString based on the SceneTypes typedefenum you send it.The getSoundEffectsListForSceneWithID method loads the SoundEffects.plistfile and returns just the NSDictionary for the scene that was requested. This should be familiar to you by now, as this method contains the same logic you used to load the animation plist files.Pay close attention to step 4 in the getSoundEffectsListForSceneWithIDmethod. The read more..

  • Page - 251

    Chapter 8 Pump Up the Volume!212 NSDictionary *soundEffectsToLoad = [self getSoundEffectsListForSceneWithID:sceneID];if (soundEffectsToLoad == nil) { // 2CCLOG(@"Error reading SoundEffects.plist");return; }// Get all of the entries and PreLoad // 3for( NSString *keyString in soundEffectsToLoad ) {CCLOG(@"\nLoading Audio Key:%@ File:%@", keyString,[soundEffectsToLoad objectForKey:keyString]); [soundEngine preloadEffect: read more..

  • Page - 252

    Synchronous versus Asynchronous Loading of Audio 213 [pool release];}The loadAudioForSceneWithID and unloadAudioForSceneWithID methods work in the same way: they both grab an NSDictionary from the SoundEffects.plistfile and call on CocosDenshion to either load or unload the audio files from memory.You are almost there. Next you need to add three more small methods to Game-Manager to finish the setup. The playBackgroundTrack method preloads and starts playing a background music track. The read more..

  • Page - 253

    Chapter 8 Pump Up the Volume!214-(ALuint)playSoundEffect:(NSString*)soundEffectKey {ALuint soundID = 0;if (managerSoundState == kAudioManagerReady) {NSNumber *isSFXLoaded = [soundEffectsState objectForKey:soundEffectKey];if ([isSFXLoaded boolValue] == SFX_LOADED) { soundID = [soundEngine playEffect: [listOfSoundEffectFiles objectForKey:soundEffectKey]]; } else {CCLOG(@"GameMgr: SoundEffect %@ is not loaded.",soundEffectKey); } read more..

  • Page - 254

    Adding the soundEngine to GameObjects215 // Load audio for new scene based on sceneID [self performSelectorInBackground: @selector(loadAudioForSceneWithID:) withObject:[NSNumber numberWithInt: currentScene]];if ([[CCDirector sharedDirector] runningScene] == nil) { [[CCDirector sharedDirector] runWithScene:sceneToRun]; } else { [[CCDirector sharedDirector]replaceScene: [CCTransitionFlipAngular read more..

  • Page - 255

    Chapter 8 Pump Up the Volume!216First, open GameObject.h and add an import for the GameManager.h class.#import "GameManager.h"This is all that is needed to make the GameManager available in the GameObjectand therefore in the Viking, EnemyRobot, and other objects in Space Viking. The GameManager will handle the playing of sound effects and the background music. The next section covers how to play the sound effects in time with the actions and animations.Adding Sounds to RadarDish and read more..

  • Page - 256

    Adding the soundEngine to GameObjects217 [self changeState:kStateDead]; } else { PLAYSOUNDEFFECT(VIKING_HAMMERHIT1); action = [CCAnimate actionWithAnimation:takingAHitAnimrestoreOriginalFrame:NO];}break;case kStateDead:CCLOG(@"RadarDish->Changing State to Dead"); PLAYSOUNDEFFECT(VIKING_HAMMERHIT2);PLAYSOUNDEFFECT(ENEMYROBOT_DYING); action = [CCAnimate read more..

  • Page - 257

    Chapter 8 Pump Up the Volume!218creating this method, open the SpaceCargoShip.h header file and add the following instance variable inside the @interface declaration block.int soundNumberToPlay;This is a number you will increment to indicate which engine sound the Space-CargoShip should play. Open the SpaceCargoShip.m file and add the contents of List-ing 8.15 into the init method.Listing 8.15 SpaceCargoShip.m playSpaceCargoShipSound#pragma mark -#pragma mark read more..

  • Page - 258

    Adding Sounds to EnemyRobot219 [CCScaleTo actionWithDuration:0.01f scale:0.5f], [CCFlipX actionWithFlipX:YES],[CCCallFunc actionWithTarget:self selector:@selector(playSpaceCargoShipSound)], [CCMoveTo actionWithDuration:8.5fposition:ccp(screenSize.width+1000.0f,550.0f)],In the resources folder for this chapter, the changes to the init method in the SpaceCargoShip class are included in the UpdatedSpaceCargoShipInit.rtf file. All of read more..

  • Page - 259

    Chapter 8 Pump Up the Volume!220if (soundToPlay == 0) { PLAYSOUNDEFFECT(ENEMYROBOT_PHASERFIRE_1); } else { PLAYSOUNDEFFECT(ENEMYROBOT_PHASERFIRE_2); }}In the playPhaserFireSound method the modulus (%) operator is used to get the remainder of a random number divided by two. The two possible outcomes are 0 and 1, and they are used to select one of the two enemy phaser sounds to play.Next you need to create a similar method to alternate between the two walking sounds for the read more..

  • Page - 260

    Adding Sounds to EnemyRobot221Listing 8.19 EnemyRobot.m changeState method (partial) [self stopAllActions]; STOPSOUNDEFFECT(walkingSound);id action = nil; characterState = newState;switch (newState) {case kStateSpawning: [soundEngineLink PLAYSOUNDEFFECT(ENEMYROBOT_TELEPORT); [self runAction:[CCFadeOut actionWithDuration:0.0f]]; ...break;...case kStateWalking: CCLOG(@"EnemyRobot->Changing State to Walking");if (isVikingWithinBoundingBox) break;[self read more..

  • Page - 261

    Chapter 8 Pump Up the Volume!222 } else {// Viking does not have weapon, body blowaction = [CCAnimate actionWithAnimation:torsoHitAnim restoreOriginalFrame:YES]; } break;...case kStateDead: CCLOG(@"EnemyRobot -> Going to Dead State");PLAYSOUNDEFFECT(ENEMYROBOT_DYING);...The first addition to the changeState method is the line [soundEngineLink stopEffect:walkingSound], which stops the walking sound if it is read more..

  • Page - 262

    Adding Sound Effects to Ole the Viking223Just as with EnemyRobot, the walkingSound instance variable allows the Viking to stop the walking sound anytime he transitions out of that state.Now move to the Viking.m implementation file to create a set of methods to play the sounds. Be sure to copy the code in Listings 8.20 to 8.22 into Viking.m into the changeState method.Listing 8.20 Viking.m playJumpingSound#pragma mark -#pragma mark SoundEffectsMethods-(void)playJumpingSound {int soundToPlay = read more..

  • Page - 263

    Chapter 8 Pump Up the Volume!224case 4:PLAYSOUNDEFFECT(VIKING_SWINGING_5);break;case 5:PLAYSOUNDEFFECT(VIKING_SWINGING_6);break;case 6:PLAYSOUNDEFFECT(VIKING_SWINGING_7);break;case 7:PLAYSOUNDEFFECT(VIKING_SWINGING_8);break;default: PLAYSOUNDEFFECT(VIKING_SWINGING_9);break; }}-(void)playBreathingSound {int soundToPlay = random() % 4;if (soundToPlay == 0) { PLAYSOUNDEFFECT(VIKING_GRUMBLING_1); } else if (soundToPlay == 1) { PLAYSOUNDEFFECT(VIKING_GRUMBLING_2); } read more..

  • Page - 264

    Adding Sound Effects to Ole the Viking225 } else if (soundToPlay == 1) {PLAYSOUNDEFFECT(VIKING_HIT_2); } else if (soundToPlay == 2) {PLAYSOUNDEFFECT(VIKING_HIT_3); } else if (soundToPlay == 3) { PLAYSOUNDEFFECT(VIKING_HIT_4); } else { PLAYSOUNDEFFECT(VIKING_HIT_5); }}-(void)playDyingSound {int soundToPlay = random() % 5;if (soundToPlay == 0) {PLAYSOUNDEFFECT(VIKING_DYING_1); } else if (soundToPlay == 1) {PLAYSOUNDEFFECT(VIKING_DYING_2); } else if (soundToPlay read more..

  • Page - 265

    Chapter 8 Pump Up the Volume!226Adding the Sound Method Calls in changeState for OleThe last step in making Ole speak is to add the calls to the methods you just created. The calls are inside of the changeState method. Listing 8.23 shows the lines added to the changeState method. Look closely at Listing 8.23 and add these lines in your Viking.m implementation file.Listing 8.23 Viking.m changeState method (partial) STOPSOUNDEFFECT(walkingSound); [self setCharacterState:newState];switch read more..

  • Page - 266

    Adding Sound Effects to Ole the Viking227case kStateTakingDamage:[self playTakingDamageSound];...break;case kStateDead:[self playDyingSound];...break;default:break; }In the changeState method, the first line added is a call to stop playing the walk-ing sound effect. This call does nothing if the walking sound is not currently playing. In the switch block for the states, the following occurs.If the state is switching to:1. kStateWalkingThe walking sound effect is played and the audio layer read more..

  • Page - 267

    Chapter 8 Pump Up the Volume!2287. kStateDeadCalls the playDyingSound to randomly play one of the five sound effects of Ole dying and turning to dust. Let’s hope you don’t hear this sound effect very often.This concludes all the setup you need to give Ole the Viking a voice and a full complement of sound effects. If you click Run, you should be able to hear Ole making the various sound effects as you play Space Viking.actionGoTo:16,Adding Music toactionGoTo:16, the Menu ScreenAll of the read more..

  • Page - 268

    For the More Curious: If You Need More Audio Control229Once more, click Run, and you should now hear music in the Main Menu along with the Gameplay layer. Since the other menus in Space Viking do not have their own music, the main menu background track will continue playing when you transi-tion to them.actionGoTo:16,For the More CuractionGoTo:16,ious: If You Need actionGoTo:16,More Audio actionGoTo:16,ControlSimpleAudioEngine is an excellent interface for getting sounds into your games with a read more..

  • Page - 269

    Chapter 8 Pump Up the Volume!230Covering these two portions of CocosDenshion is beyond the scope of this book, but there are several example projects included with Cocos2D to help you get started with these two APIs.The DrumPad, Fade to Grey, and FancyRat Metering targets included in the Cocos2D Xcode project are a great starting point for delving deeper into the Cocos-Denshion framework.There are also additional examples included with the source files of this book, found at the InformIT website read more..

  • Page - 270

    actionGoTo:16,9actionGoTo:16,When the World GeactionGoTo:16,tsactionGoTo:16, Bigger: actionGoTo:16,AddingactionGoTo:16, ScrollingIn the last chapter you learned how to add sound effects and music to Space Viking, giving Ole a heavy metal soundtrack as inspiration to beat the aliens. In this chapter you learn how to make Ole’s world even larger by adding scrolling and creating a second game level and a cut-scene. Scrolling is an easy and powerful technique that can be used to make your levels read more..

  • Page - 271

    Chapter 9 When the World Gets Bigger: Adding Scrolling232nTileMapA large image made up of tiles of a standard size. The tile images/textures can repeat so that a large TileMap needs only a small amount of unique tiles. TileMaps can contain multiple TileSets and can contain image and other custom data for each tile.nTileSetA set of tiles stored as one image. Consider how texture atlases are used to combine multiple sprites images into a single larger image: the TileSet is the texture atlas of read more..

  • Page - 272

    Adding the Logic for a Larger World233Listing 9.2 GameManager.m getDimensionsOfCurrentScene method-(CGSize)getDimensionsOfCurrentScene {CGSize screenSize = [[CCDirector sharedDirector] winSize];CGSize levelSize;switch (currentScene) {case kMainMenuScene: case kOptionsScene:case kCreditsScene:case kIntroScene:case kLevelCompleteScene:case kGameLevel1: levelSize = screenSize;break;case kGameLevel2: levelSize = CGSizeMake(screenSize.width * 2.0f, read more..

  • Page - 273

    Chapter 9 When the World Gets Bigger: Adding Scrolling234float xOffset;if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {// Clamp for the iPad xOffset = 30.0f; } else {// Clamp for iPhone, iPhone 4, or iPod touch xOffset = 24.0f; }if (currentSpritePosition.x < xOffset) { [self setPosition:ccp(xOffset, currentSpritePosition.y)]; } else if (currentSpritePosition.x > (levelSize.width - xOffset)) { [self setPosition:ccp((levelSize.width - xOffset), read more..

  • Page - 274

    Creating a Larger World235The first game level scene was not set for scrolling, so when Ole moves to the right, the scene does not follow him, and he quickly disappears offscreen. This was an exercise to illustrate how you need to track Ole’s position in order to scroll the entire layer properly to match his position. Keep this in mind as you work through the next section.Make sure to return the kGameLevel1 to just be the width of the screenSizebefore moving on.case kGameLevel1:levelSize = read more..

  • Page - 275

    Chapter 9 When the World Gets Bigger: Adding Scrolling236Next create a new group under Scenes called Scene2, as shown in Figure 9.2. All of the classes for this scene and level will be created under this group to keep your SpaceViking project organized.Figure 9.2 Scene2 group in XcodeCreating the Second Game SceneIn order to keep things simple and compartmentalized, you will create a new scene class instead of adding code to the existing GameScene.Right-click on the Scene2 group in Xcode and read more..

  • Page - 276

    Creating a Larger World237#import "cocos2d.h"#import "Constants.h"#import "GameControlLayer.h"#import "GameplayScrollingLayer.h"#import "StaticBackgroundLayer.h"@interface GameScene2 : CCScene {GameControlLayer *controlLayer;}@endIn the import statements, the GameControlLayer GameplayScrollingLayer,and StaticBackgroundLayer are three classes you have not created yet. Do not worry if Xcode starts displaying warnings for the missing classes; you read more..

  • Page - 277

    Chapter 9 When the World Gets Bigger: Adding Scrolling238 // Initialize the Control LayercontrolLayer = [GameControlLayer node]; [self addChild:controlLayer z:2 tag:2]; // Gameplay LayerGameplayScrollingLayer *scrollingLayer = [GameplayScrollingLayer node];[scrollingLayer connectControlsWithJoystick:[controlLayer leftJoystick] andJumpButton:[controlLayer jumpButton] andAttackButton:[controlLayer read more..

  • Page - 278

    Creating a Larger World239@interface StaticBackgroundLayer : CCLayer {}@endThe header file is as simple as possible, containing just an import for Cocos2D and declaring StaticBackgroundLayer as a subclass to CCLayer. Move to the imple-mentation file and replace the code with the contents of Listing 9.8.Listing 9.8 StaticBackgroundLayer.m implementation file// StaticBackgroundLayer.m// SpaceViking#import "StaticBackgroundLayer.h"@implementation StaticBackgroundLayer-(id)init { self = read more..

  • Page - 279

    Chapter 9 When the World Gets Bigger: Adding Scrolling240Listing 9.9 GameControlLayer.h header file// GameControlLayer.h// SpaceViking//#import <Foundation/Foundation.h>#import "cocos2d.h"#import "SneakyJoystick.h"#import "SneakyJoystickSkinnedBase.h"#import "SneakyButton.h"#import "SneakyButtonSkinnedBase.h"@interface GameControlLayer : CCLayer {SneakyJoystick *leftJoystick;SneakyButton *jumpButton;SneakyButton *attackButton;}@property read more..

  • Page - 280

    Creating a Larger World241CGRect attackButtonDimensions = CGRectMake(0, 0, 64.0f, 64.0f);CGPoint joystickBasePosition;CGPoint jumpButtonPosition;CGPoint attackButtonPosition;if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {// The device is an iPad running iPhone 3.2 or later.CCLOG(@"Positioning Joystick and Buttons for iPad"); joystickBasePosition = ccp(screenSize.width*0.0625f, screenSize.height*0.052f); jumpButtonPosition = read more..

  • Page - 281

    Chapter 9 When the World Gets Bigger: Adding Scrolling242 jumpButtonBase.pressSprite = [CCSprite spriteWithFile:@"jumpDown.png"]; jumpButtonBase.button = [[SneakyButton alloc]initWithRect:jumpButtonDimensions];jumpButton = [jumpButtonBase.button retain];jumpButton.isToggleable = NO; [self addChild:jumpButtonBase];SneakyButtonSkinnedBase *attackButtonBase = [[[SneakyButtonSkinnedBasealloc] init] autorelease]; attackButtonBase.position = attackButtonPosition; read more..

  • Page - 282

    Creating a Larger World243to save on memory while creating much larger levels. Along the way you also learn how to create infinite scrolling for a cut-scene.To start, create the GameplayScrollingLayer class as a subclass of CCLayerinside of the Scene2 group. Open the header file and replace the code with the con-tents of Listing 9.11.Listing 9.11 GameplayScrollingLayer.h// GameplayScrollingLayer.h// SpaceViking//#import <Foundation/Foundation.h>#import "cocos2d.h"#import read more..

  • Page - 283

    Chapter 9 When the World Gets Bigger: Adding Scrolling244Viking *viking = (Viking*)[sceneSpriteBatchNodegetChildByTag:kVikingSpriteTagValue]; [viking setJoystick:leftJoystick]; [viking setJumpButton:jumpButton]; [viking setAttackButton:attackButton];}// Scrolling with just a large width *2 background-(void)addScrollingBackground {CGSize screenSize = [[CCDirector sharedDirector] winSize]; CGSize levelSize = [[GameManager sharedGameManager] read more..

  • Page - 284

    Creating a Larger World245 [self addChild:sceneSpriteBatchNode z:20]; Viking *viking = [[Viking alloc] initWithSpriteFrame: [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"sv_anim_1.png"]]; [viking setJoystick:nil]; [viking setJumpButton:nil]; [viking setAttackButton:nil]; [viking setPosition:ccp(screenSize.width * 0.35f,screenSize.height * 0.14f)]; [viking setCharacterHealth:100]; read more..

  • Page - 285

    Chapter 9 When the World Gets Bigger: Adding Scrolling246float vikingXPosition = viking.position.x;// 2CGSize screenSize = [[CCDirector sharedDirector] winSize];// 3float halfOfTheScreen = screenSize.width/2.0f;// 4CGSize levelSize = [[GameManager sharedGameManager]getDimensionsOfCurrentScene];// 5// 6if ((vikingXPosition > halfOfTheScreen) && (vikingXPosition < (levelSize.width - halfOfTheScreen))) {// Background should scrollfloat newXPosition = halfOfTheScreen - read more..

  • Page - 286

    Creating a Larger World2477. Calculates how much to move the layer. The layer needs to move in relation to the Viking minus the half of the screen in which it will not scroll. If this seems confusing, don’t worry: you will get to see how it works shortly. Since the Viking is already moved to the new position, the layer needs to be moved so that it stays onscreen and has the appearance of scrolling.8. Changes the position of the layer in the x coordinate. The y coordinate remains the same.There read more..

  • Page - 287

    Chapter 9 When the World Gets Bigger: Adding Scrolling248The update method is the same as you have written before except for the call to adjustLayer. The for loop updates all of the GameObjects in the layer, and then the layer is adjusted, followed by a check to see if the Viking or RadarDish are dead. Since the layer is adjusted according to the Viking’s position, it is important to do it after the Viking has had a chance to update inside of the for loop.Two quick steps remain before you can read more..

  • Page - 288

    Creating a Larger World249The kGameLevel2 branch is called for the Dogs of Loki; the others are for later chapters. If you click Run and select the Dogs of Loki level, you should be able to move Ole to the right. Once he crosses over half of the screen, you should start to see the background scrolling. Figure 9.3 shows the level as Ole scrolls from left to right.Figure 9.3 Space Viking level 2 showing scrollingA Note on CCFollowThere is a built-in action in Cocos2D to move a layer or the camera read more..

  • Page - 289

    Chapter 9 When the World Gets Bigger: Adding Scrolling250actionGoTo:16,ScrollingactionGoTo:16, withactionGoTo:16, ParallaxactionGoTo:16, LayersIn the previous section you created a scrolling scene consisting of a background with two layers. One was the static backdrop of the alien desert, the other the ground along with the boulders and mountains in the background that moved with Ole. In order to give your games more depth, it is useful to have multiple background layers all scroll-ing at read more..

  • Page - 290

    Scrolling with Parallax Layers251 BGLayer3 = [CCSprite spriteWithFile:@"chap9_scrolling3iPhone.png"]; }// chap9_scrolling4 is the ground// chap9_scrolling2 are the large mountains// chap9_scrolling3 are the small rocksparallaxNode = [CCParallaxNode node]; [parallaxNode setPosition:ccp(levelSize.width/2.0f,screenSize.height/2.0f)];float xOffset = 0;// Ground moves at ratio 1,1 [parallaxNode addChild:BGLayer1 z:40 read more..

  • Page - 291

    Chapter 9 When the World Gets Bigger: Adding Scrolling252The child layer position is based on the CCParallaxNode position times the ratio plus the offset.In the second layer of this scrolling background, the ratio on the x-axis is 0.7. Since you already set the position of the CCParallaxNode to be 1024 on the x-axis, this means the second layer would be placed at 716.8 pixels (1024 times 0.7). That would skew the position of the layer to the left, so the offset is needed to put in the correct read more..

  • Page - 292

    Scrolling to Infinity253a f loating platform f lying through the alien landscape with clouds zooming by in the background. The clouds keep zooming by until the player touches the screen. In this example the clouds scroll from right to left, but there is nothing mandating that it has to be that way. You can scroll left to right, top to bottom, or bottom to top in your own games.To start, create a new group in Xcode called CutSceneForLevel2 under the Scenes group. You will have the infinite read more..

  • Page - 293

    Chapter 9 When the World Gets Bigger: Adding Scrolling254Creating the Scrolling LayerThe scrolling layer in the cut-scene is a set of clouds that scrolls from right to left at varying speeds. Figure 9.5 shows how the clouds look along with Ole and the platform.Figure 9.5 Cut-scene for level 2 showing Ole on a platform in front of scrolling cloudsTo make this scene as efficient as possible, you use a texture atlas to hold both the cloud images and the Viking and Platform graphics. In the read more..

  • Page - 294

    Scrolling to Infinity255#import <Foundation/Foundation.h>#import "cocos2d.h"#import "Constants.h"@interface PlatformScrollingLayer : CCLayer {CCSpriteBatchNode *scrollingBatchNode;}@endThe PlatformScrollingLayer header file has only imports for Cocos2D and the Constants.h file, along with an instance variable to hold the CCSpriteBatchNode used in this scene.Note on CCSpriteBatchNodeSince the scrolling layer is made up of many clouds using the same six textures, it is read more..

  • Page - 295

    Chapter 9 When the World Gets Bigger: Adding Scrolling256if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {// Indicates game is running on iPad [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"ScrollingCloudsTextureAtlas.plist"]; scrollingBatchNode = [CCSpriteBatchNode batchNodeWithFile:@"ScrollingCloudsTextureAtlas.png"]; } else { [[CCSpriteFrameCache sharedSpriteFrameCache] read more..

  • Page - 296

    Scrolling to Infinity257method. After the for loop, the createVikingAndPlatform method is called to add Ole and the platform, as you probably already guessed, by the method name.Add the code in Listing 9.21 to PlatformScrollingLayer.m in order to create the static background in the scrolling scene.Listing 9.21 createStaticBackground in PlatformScrollingLayer.m (part 2 of 6)-(void)createStaticBackground { CGSize screenSize = [CCDirector sharedDirector].winSize; CCSprite *background;if read more..

  • Page - 297

    Chapter 9 When the World Gets Bigger: Adding Scrolling258The cloud filenames are tiles_cloud0.png through tiles_cloud5.png. A random number between zero and five is used to create a cloud using one of the six images. The cloud PNG files are inside of the texture atlas PNG, and they can be retrieved via the sprite frame with the same name as the original filename. Remember when the texture atlas was created with TexturePacker, how the filenames of the original images were set as the image frame read more..

  • Page - 298

    Scrolling to Infinity259At a high level, the resetCloud method positions the cloud offscreen on the right side and setups a CCMove action to move the cloud at a random speed across the screen from right to left. The z composition ordering of the cloud is based on its speed with the faster clouds closer to the foreground and the slower clouds toward the background. At the end of the move, the resetCloud method is called on the cloud’s behalf to reset it back offscreen to the right at a random read more..

  • Page - 299

    Chapter 9 When the World Gets Bigger: Adding Scrolling2604. Sets the x position variable to offscreen on the right. By adding the screen width to half of the cloud width (xOffSet) and one more pixel, the cloud is placed directly to the right of the visible area of the screen.5. Sets the y position variable to a random value along the screen height. 6. Sets the cloud position to the new x and y values calculated in steps 4 and 5.7. Sets the move duration to a random value between zero and the read more..

  • Page - 300

    Scrolling to Infinity261Tips and TricksI have often heard more experienced game developers say that most of game develop-ment was done with tricks, and the key was learning what tricks to use to get the effect you need. You don’t have to replicate real life in your game in order for scrolling to feel real. One clear example is keeping Ole centered on this screen and how he was moved in the second level you built previously. Playing the game, you feel like Ole is moving through the level when read more..

  • Page - 301

    Chapter 9 When the World Gets Bigger: Adding Scrolling262be composited in front of them. If you knew you were only going to have 50 or 100 clouds, you could always set the z value to a larger amount, such as 101, or even 2000, just as long as it is larger than any of the clouds’ z values.3. Creates a new CCSprite for the platform and sets it on the bottom center of the screen. The screen size is used to determine the bottom center position. The new CCSprite is added to the CCSpriteBatchNode read more..

  • Page - 302

    Scrolling to Infinity263Creating the Platform SceneThe cut-scene will be a new Cocos2D scene with just a single scrolling layer. Create a new Objective-C class inside of the CutSceneForLevel2 group called PlatformScene.m as a subclass of CCScene. Open the PlatformScene.h header file and replace the template contents with Listing 9.27.Listing 9.27 PlatformScene.h header file// PlatformScene.h// SpaceViking//#import <Foundation/Foundation.h>#import "cocos2d.h"#import read more..

  • Page - 303

    Chapter 9 When the World Gets Bigger: Adding Scrolling264The PlatformScene implementation is straightforward, just a simple boilerplate init method that creates the scrolling layer and adds it to the scene. There are two more steps, and then you can run the cut-scene in Space Viking. First, let’s add the necessary code to the MainMenuLayer.m so that it plays the cut-scene when the second level is selected. Open the MainMenuLayer.m and find the playScene method. Modify the if elsebranch for the read more..

  • Page - 304

    Tile Maps265You should now be able to click Run and select the second level from the Main Menu. The scrolling clouds scene should show up, playing in an endless loop. If you touch anywhere, the game should transition to the second level you built earlier in this chapter.Now that you have learned how to add parallax scrolling and infinite scrolling, the next step is to learn about TileMaps. You can use TileMaps to create large scrolling worlds of almost infinite size while keeping your game’s read more..

  • Page - 305

    Chapter 9 When the World Gets Bigger: Adding Scrolling266In Space Viking you are going to use tiles that are 64 × 64 pixels in size. It is impor-tant that your tiles all be the same size, and preferably a size that is a power of two. Most games can get away with 32 × 32 pixel tiles. Looking at Figure 9.7, imagine that you use the four ground tiles to re-create the entire ground layer on the second level you created in this chapter. In other words, by using various combinations of these tiles, read more..

  • Page - 306

    Tile Maps2673. Double-click on the DMG to open it if it is not opened automatically by your browser.4. Drag the Tiled application into your Applications folder.That’s it. Tiled is installed on your system. Figure 9.8 shows the mapeditor.org website and the contents of the Tiled DMG.Figure 9.8 Mapeditor.org website and contents of Tiled DMGNow that you have Tiled installed, the next step is to create the TileMap that you are going to use in Space Viking.Creating the Tile MapYou are going to read more..

  • Page - 307

    Chapter 9 When the World Gets Bigger: Adding Scrolling2684. Click OK to create the empty TileMap.5. From the Map menu, select New Tileset.6. Click Browse and select the TilesTextureAtlas.png file you downloaded previously from the book’s site. Set the tile width and height to 64 and the margins to 1. The Tiled New Tileset window should look like Figure 9.10.Figure 9.9 Tiled showing the new TileMap windowFigure 9.10 Tiled New Tileset window7. Click OK to add the new TileSet to your TileMap.Now read more..

  • Page - 308

    Tile Maps2693. Add two tile layers, one called RockColumnsLayer and one called RockBoulderLayer.4. Rename the first layer to GroundLayer.5. Uncheck both the RockColumnsLayer and the RockBoulderLayer so that only GroundLayer is checked and selected.If you switch over to the Tilesets tab, you can select a tile and place it on the TileMap. Create a ground layer on the bottom row of tiles, similar to the one shown in Figure 9.11.Figure 9.11 GroundLayer populated on TileMapNext, deselect the read more..

  • Page - 309

    Chapter 9 When the World Gets Bigger: Adding Scrolling270There is one more layer to create, the rock boulders, which will scroll the slowest:1. Ensure that both the GroundLayer and the RockColumnsLayers are unchecked.2. Select and check the RockBoulderLayer.3. Create rock boulders randomly across the TileMap, starting with the second tile from the bottom. Your TileMap should look similar to Figure 9.13.Figure 9.13 RockBoulderLayer populated on TileMapThe RockBoulderLayer and the RockColumnsLayer read more..

  • Page - 310

    Tile Maps271Cocos2D Compressed TileMap ClassCocos2D has a built-in class to read TileMap files from Tiled both in a compressed and noncompressed format. Since Tiled exports the TileMaps in a compressed (TMX) format by default, this book covers only this one. If you are using uncompressed tiled maps, the Cocos2D class is different, but the process and code are the same. The class you are going to use is CCTMXTiledMap, and it makes loading and using TileMaps a breeze.You are first going to add a read more..

  • Page - 311

    Chapter 9 When the World Gets Bigger: Adding Scrolling272While you created the Level2TileMap.tmx file in the previous section, you need the Level2TileMapiPhone.tmx and Level2TileMapiPhone-hd.tmx files if you are testing on the iPhone. Take a moment and copy them into Xcode from the resources folder for this chapter.If you click Run and select the second level in Space Viking, you should see the new TileMap background that you created. You should see it scrolling when you move Ole to the right read more..

  • Page - 312

    Tile Maps273Listing 9.33 addScrollingBackgroundWithTileMapInsideParallax// Scrolling with TileMap Layers inside of a Parallax Node-(void)addScrollingBackgroundWithTileMapInsideParallax {CGSize screenSize = [[CCDirector sharedDirector] winSize];CGSize levelSize = [[GameManager sharedGameManager]getDimensionsOfCurrentScene];// 1if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { tileMapNode = [CCTMXTiledMap tiledMapWithTMXFile:@"Level2TileMap.tmx"]; read more..

  • Page - 313

    Chapter 9 When the World Gets Bigger: Adding Scrolling274// 5 xOffset = (levelSize.width/2) * 0.3f; [rockBoulderLayer retain]; [rockBoulderLayer removeFromParentAndCleanup:NO]; [rockBoulderLayer setAnchorPoint:CGPointMake(0.5f, 0.5f)]; [parallaxNode addChild:rockBoulderLayer z:30parallaxRatio:ccp(0.7,1)positionOffset:ccp(xOffset, 0.0f)]; [rockBoulderLayer release];// 6 [self addChild:parallaxNode z:1];}While the method in Listing 9.33 has a long and descriptive name, the read more..

  • Page - 314

    Tile Maps275Add the call to addScrollingBackgroundWithTileMapInsideParallax and comment out the line calling addScrollingBackgroundWithTileMap, as shown in Listing 9.34.Listing 9.34 Changes to init method in GameplayScrollingLayer//[self addScrollingBackgroundWithTileMap];[self addScrollingBackgroundWithTileMapInsideParallax];The last change you need to make is to increase the level size in the GameManager,since the TileMap background is now 4096 pixels wide instead of 2048. Open the read more..

  • Page - 315

    Chapter 9 When the World Gets Bigger: Adding Scrolling276actionGoTo:16,SummaryIn this chapter you learned three different techniques to add scrolling to your games. You learned how to use the CCParallaxNode in Cocos2D, how to move sprites endlessly, and how to use TileMaps to create large levels. Whether you are making a role-playing game (RPG) or the next f lying shooter, you now have the concepts and techniques needed to make it happen.In the next few chapters, you will learn about physics and read more..

  • Page - 316

    actionGoTo:16,PartactionGoTo:16, IVactionGoTo:16,PhysicsactionGoTo:16, EnginesWith the Box2D and Chipmunk physics engines that come with Cocos2D, you can add some amazing effects to your games, such as gravity, real-istic collisions, and even ragdoll effects. In these chapters you get a chance to add some physics-based levels to Space Viking, from simple to advanced.nChapter 10: “Basic Game Physics: Adding Realism with Box2D”nChapter 11: “Intermediate Game Physics: Modeling, Racing, and read more..

  • Page - 317

    This page intentionally left blank read more..

  • Page - 318

    actionGoTo:16,10actionGoTo:16,Basic Game PhysicsactionGoTo:16,: Adding actionGoTo:16,Realism with Box2DSo far Space Viking has been an action-packed game complete with aliens blasting, cargo ships flying, and fists bashing. Up until this point, any time you wanted to move an object in Space Viking, it was up to you. You would use Cocos2D actions or update the positions of objects manually.But what if you wanted to add more realistic physics behavior in your game? Maybe you want more realistic read more..

  • Page - 319

    Chapter 10 Basic Game Physics: Adding Realism with Box2D2803. In your game update loop, you tell Box2D to simulate the world for a certain amount of time. Box2D then calculates the new positions for each object based on forces and collisions.4. Also in your game update loop, you get the new positions of the objects from Box2D and update your sprites to match those positions.In summary, Box2D controls the positions of your objects and where they move, and you just update your sprites to where read more..

  • Page - 320

    Getting Started281nPointersIn the previous example, you see that the variable is prefixed with a star (*). This indicates that the variable is a pointer to an object somewhere in memory. Later, when you want to call a method on a pointer to an object, you use the arrow (->). For example:myClassPointer->doSomething();nFor More InformationFor more information on C++, a great reference is The C++ Programming Lan-guage by Bjarne Stroustrup (Addison-Wesley Professional, 2000).Mad Dreams of the read more..

  • Page - 321

    Chapter 10 Basic Game Physics: Adding Realism with Box2D282Creating a New SceneThe first thing to do is create a new scene for the puzzle level. Open your SpaceVikingproject if you don’t have it open already, expand Classes\Scenes, click New Group,then rename the new folder that was created to Scene3. Then with the Scene3 group selected, go to File > New > New File..., choose iOS > Cocoa Touch > Objective-C class, and click Next. Enter CCLayer as the Subclass of, click Next,name read more..

  • Page - 322

    Getting Started283CGSize winSize = [CCDirector sharedDirector].winSize;CCLabelTTF *label = [CCLabelTTFlabelWithString:@"Hello, Mad Dreams of the Dead!"fontName:@"Helvetica" fontSize:24.0]; label.position = ccp(winSize.width/2, winSize.height/2); [self addChild:label]; }return self;}@endThere should be no surprises here. The init method simply puts a label in the middle of the screen so you can verify it’s working.Finally, you need to modify GameManager.m to read more..

  • Page - 323

    Chapter 10 Basic Game Physics: Adding Realism with Box2D284Adding Box2D Files to Your ProjectNow you have a scene ready to try out Box2D—except you don’t have the required Box2D files in your project! This is because you created the project with the plain Cocos2D Application template (i.e., you didn’t pick the Cocos2D Box2D Applicationtemplate). The plain Cocos2D Application template doesn’t come with the Box2D files included by default.Luckily, this is quite easy to fix. Just perform read more..

  • Page - 324

    Getting Started285Figure 10.4 Where to place the Box2D files in the SpaceViking projectFigure 10.5 Adding the Box2D directory to your Xcode project read more..

  • Page - 325

    Chapter 10 Basic Game Physics: Adding Realism with Box2D286Figure 10.6 Adding libs folder to header search pathsNext you need to set up the project so it knows where the Box2D header files are. Click on your SpaceViking project in the Project Navigator to bring up your project settings, select the Build Settings tab, make sure the All and Combined buttons are selected, and look for the entry for Search Paths > Header Search Paths.Double-click the entry to bring up an editor, click the plus read more..

  • Page - 326

    Getting Started287Now, let’s test if it’s working. In Xcode, expand the Classes\Scenes\Scene3 group, and open PuzzleLayer.h. Import the Box2D header at the top of the file, as shown in List-ing 10.5.Listing 10.5 PuzzleLayer.h (at top of file)#import "Box2D.h"Now try to compile your project. Yowza! You will notice a huge list of errors, as shown in Figure 10.7.Figure 10.7 Errors you’ll see if you don’t use the .mm extension when using C++ codeThis is happening because you are read more..

  • Page - 327

    Chapter 10 Basic Game Physics: Adding Realism with Box2D288to do this for GameManager.m is because GameManager.m imports PuzzleLayer.h, which imports Box2D.h.Ok! Compile and run again, and this time it should compile with no errors. TipAs you’ve seen, if you’re working with Box2D and you see hundreds of strange errors like we demonstrated here, chances are that you’re trying to use C++ code in a file that doesn’t end with .mm. Just remember, when you see a huge list of errors like that, read more..

  • Page - 328

    Hello, Box2D!289In code, the conversion looks something like this:#define PTM_RATIO100.0// When converting from Cocos2D coord to Box2D coord:float x_box2D = x_cocos2D / PTM_RATIO;float y_box2D = y_cocos2D / PTM_RATIO;// When converting from Box2D coord to Cocos2D coord:float x_cocos2D = x_box2D * PTM_RATIO;float y_cocos2D = y_box2D * PTM_RATIO;TipIf you look at Box2D samples, you’ll see that a common value for the PTM_RATIO is 32. Why is this number commonly chosen? Well, the size of the read more..

  • Page - 329

    Chapter 10 Basic Game Physics: Adding Realism with Box2D290Let’s see how to create a Box2D world. First open up PuzzleLayer.h and import the Box2D debug drawing header that you added earlier and the constants file containing the PTM_RATIO, as shown in Listing 10.7.Listing 10.7 PuzzleLayer.h (at the top of the file)#import "GLES-Render.h"#import "Constants.h"Next add a few member variables inside the @interface declaration, as shown in Listing 10.8.Listing 10.8 PuzzleLayer.h read more..

  • Page - 330

    Hello, Box2D!291Whether the vector is used as a position or direction/magnitude depends on the context. In the case of gravity, you know that the vector is being used to indicate a direction and magnitude.Don’t worry if you’re still confused by this. You’ll be using vectors a lot as you go through this chapter, and it will start to make more sense as you proceed!(3, 4)153°5234213Figure 10.9 Diagram of a vector, which can represent either a point or a magnitude/angleIn summary, the first read more..

  • Page - 331

    Chapter 10 Basic Game Physics: Adding Realism with Box2D292That’s it—you have created a Box2D world! However, there’s currently nothing in it. So let’s fix this by adding a simple box into the world.Creating a Box2D ObjectBefore you create a Box2D object, it’s important to understand the terminology that Box2D uses when setting up objects.Each individual object in a Box2D world is called a body. Box2D is a rigid body physics simulation, which just means that when two bodies collide, read more..

  • Page - 332

    Hello, Box2D!293Figure 10.11 illustrates the steps you take to create a body with Box2D. As you can see in the figure, first you create a body definition. A body definition specifies some properties of the body, such as its position and movement type. There are three differ-ent movement types: a dynamic body (Box2D handles the movement), a kinematic body(the game code handles the movement), or a static body (the body doesn’t move at all).WorldBodyBodyDefinitionFigure 10.11 Creating a body with read more..

  • Page - 333

    Chapter 10 Basic Game Physics: Adding Realism with Box2D294body, as Figure 10.12 illustrates. Basically, first you create a shape, which can be a cir-cle, a square, or an arbitrary shape made up of connected vertices. You pass that shape to a fixture definition, where you can set other properties such as bounciness or density. You then pass the fixture definition to the body, which returns to you a fixture object.BodyFixtureFixtureDefinitionShapeFigure 10.12 Creating a fixture with Box2DTo try read more..

  • Page - 334

    Hello, Box2D!295WarningNote that when using the SetAsBox method, it’s easy to forget that you have to pro-vide a half width and half height and to instead pass in the full height and width. If your objects seem to be double the size you expect, double check that you’ve passed in the half width and half height correctly in this method.Note that this function sets the density of the box to 1.0. The higher the fixture’s density, the “heavier” it is, but for now don’t worry too much read more..

  • Page - 335

    Chapter 10 Basic Game Physics: Adding Realism with Box2D296Next you need to make sure that the debug draw class gets a chance to draw. Add a draw method to your layer, as shown in Listing 10.14.Listing 10.14 PuzzleLayer.mm (below init method)-(void) draw {glDisable(GL_TEXTURE_2D);glDisableClientState(GL_COLOR_ARRAY);glDisableClientState(GL_TEXTURE_COORD_ARRAY);world->DrawDebugData();glEnable(GL_TEXTURE_2D);glEnableClientState(GL_COLOR_ARRAY);glEnableClientState(GL_TEXTURE_COORD_ARRAY);}Here read more..

  • Page - 336

    Hello, Box2D!297 [self scheduleUpdate];self.isTouchEnabled = YES; }return self;}- (void)registerWithTouchDispatcher { [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];}The first two lines call the methods you added earlier to set up the world and debug drawing. It then schedules an update method to be called every tick, which you’ll write in a second. It also sets up the layer to accept touches by setting isTouchEnabledto YES read more..

  • Page - 337

    Chapter 10 Basic Game Physics: Adding Realism with Box2D298If you don’t use a fixed timestep, as your simulations get more complicated, you may see some strange behavior, such as joints disconnecting or bodies bouncing strangely. We’ll come back to the game loop in Chapter 11, “Intermediate Game Physics,” with an improved version, but for this level you can get away fine with this simple implementation without any noticeable problems.One last step: you need to add the code to create the read more..

  • Page - 338

    Hello, Box2D!299Creating GroundThe goal here is to create a boundary that lines up with the edges of the screen so that the falling objects don’t fall out of view.NoteYou don’t have to set up the boundaries of the Box2D world to line up exactly to the screen. It’s typical to want to have worlds that extend many screen widths so players can scroll from side to side. If you want to do that, you simply make the ground boundaries wider and move the position of the layer as the user scrolls read more..

  • Page - 339

    Chapter 10 Basic Game Physics: Adding Realism with Box2D300Listing 10.20 PuzzleLayer.mm (above init method)- (void)createGround {CGSize winSize = [[CCDirector sharedDirector] winSize];float32 margin = 10.0f;b2Vec2 lowerLeft = b2Vec2(margin/PTM_RATIO, margin/PTM_RATIO);b2Vec2 lowerRight = b2Vec2((winSize.width-margin)/PTM_RATIO, margin/PTM_RATIO);b2Vec2 upperRight = b2Vec2((winSize.width-margin)/PTM_RATIO, read more..

  • Page - 340

    Hello, Box2D!301However, if the position of the body was at (5, 5) and you specified a vertex for a fixture at (10,10), the world coordinates for the fixture would be at (15,15). This is a handy property of Box2D, since it allows you to create fixtures relative to a body, then easily change where you place a body without having to redo the fixture coordinates. It doesn’t matter very much in this particular example, but it becomes useful when making complicated objects (such as vehicles) that read more..

  • Page - 341

    Chapter 10 Basic Game Physics: Adding Realism with Box2D302actionGoTo:17,Basic Box2D Interaction actionGoTo:17,and DecorationThis scene is starting to be a little bit fun, watching boxes fall off each other and the like, but you know what would make it even more fun? The ability to move your device around and modify your Box2D world’s gravity based on how you hold it!This is ridiculously easy to do, so let’s give it a shot. First enable accelerometer sup-port in your scene by adding a line read more..

  • Page - 342

    Basic Box2D Interaction and Decoration303This simply converts the accelerometer input to a gravity vector. It multiplies the accelerometer result (which typically ranges between −1 and 1) by 15, in order to get a nice feel for gravity in the level. Since Space Viking is set up to run in landscape mode (and accelerometer data is given in portrait orientation), it reverses the x and y coordi-nates and f lips the sign of the y coordinate to get the proper vector.Then it simply calls SetGravity on read more..

  • Page - 343

    Chapter 10 Basic Game Physics: Adding Realism with Box2D304Listing 10.24 PuzzleLayer.mm (in createBoxAtLocation, before call to CreateBody)bodyDef.allowSleep = false;Now compile and run your project again, and note that the bodies no longer go to sleep, so they will no longer get stuck.NoteIf you’re interested in the high-pass filter option, check out Apple’s Event Handling Guide for iOS (inside the Motion Events section), which does a great job explaining the topic in further detail. read more..

  • Page - 344

    Basic Box2D Interaction and Decoration305aabb.lowerBound = locationWorld - delta;aabb.upperBound = locationWorld + delta;SimpleQueryCallback callback(locationWorld);world->QueryAABB(&callback, aabb);To set up a mouse joint, the first thing you need to do is figure out what object the user wants to move. You can do this by asking Box2D what object is at a certain location.To search for an object in the Box2D world, you need to use a method called AABB Testing, which stands for axis-aligned read more..

  • Page - 345

    Chapter 10 Basic Game Physics: Adding Realism with Box2D306choose iOS > C and C++ > Header File, and click Next. Name the file SimpleQueryCallback.h, and click Save.Then replace SimpleQueryCallback.h with the contents of Listing 10.27.Listing 10.27 SimpleQueryCallback.h#import "Box2D.h"class SimpleQueryCallback : public b2QueryCallback{public:b2Vec2 pointToTest;b2Fixture * fixtureFound; SimpleQueryCallback(const b2Vec2& point) { pointToTest = point; read more..

  • Page - 346

    Basic Box2D Interaction and Decoration307Listing 10.28 PuzzleLayer.mm (at the top of the file)#import "SimpleQueryCallback.h"Looking back to your ccTouchBegan method, you see that your last line calls QueryAABB. After this method returns, the world will have called the SimpleQuery-Callback object for each potential intersection, and the class will have figured out if the point actually intersects anything or not. Now it’s time to make use of that infor-mation! Continue your read more..

  • Page - 347

    Chapter 10 Basic Game Physics: Adding Realism with Box2D308maxForce: The maximum amount of force to apply to move the body. In this case, you want to be able to move an object of any mass, so you give it a multiple of the body’s mass. The larger the multiple, the faster objects will move to their target locations.collideConnected: Whether or not bodyA and bodyB should collide. In this case, you still want the chosen body to collide with the ground, so you set it to true.WarningIt’s a common read more..

  • Page - 348

    Basic Box2D Interaction and Decoration309The ccTouchMoved method simply updates the target of the existing mouse joint based on the new touch location, and the ccTouchEnded method destroys the joint, since the movement is complete.That’s it! Compile and run your app, and you should now be able to drag the objects all around the screen and f lick them around in fun and amusing ways!Mass, Density, Friction, and RestitutionSo far, the bodies you’ve added to your Box2D world have used mostly read more..

  • Page - 349

    Chapter 10 Basic Game Physics: Adding Realism with Box2D310friction, and the restitution. If you don’t know what these mean, don’t worry—you’re about to learn what they mean through hands-on experimentation!Next add some calls to the bottom of your init method to add three boxes to your scene when it first loads, as shown in Listing 10.32.Listing 10.32 PuzzleLayer.mm (at the bottom of the init method)CGPoint location1, location2, location3;CGSize smallSize, medSize, largeSize;if read more..

  • Page - 350

    Basic Box2D Interaction and Decoration311when you throw one object into another, and how bouncy it is when it collides on the ground.Next replace the three createBoxAtLocation lines with the contents of Listing 10.34.Listing 10.34 PuzzleLayer.mm (replace createBoxAtLocation lines in init method)[self createBoxAtLocation:location1 withSize:smallSize friction:0.2 restitution:0.0 density:1.0];[self createBoxAtLocation:location2 withSize:medSize friction:0.2 restitution:0.0 density:1.0];[self read more..

  • Page - 351

    Chapter 10 Basic Game Physics: Adding Realism with Box2D312Listing 10.36 PuzzleLayer.mm (replace createBoxAtLocation lines in init method)[self createBoxAtLocation:location1 withSize:medSize friction:0.0 restitution:0.0 density:1.0];[self createBoxAtLocation:location2 withSize:medSize friction:1.0 restitution:0.0 density:1.0];[self createBoxAtLocation:location3 withSize:medSize friction:10.0 restitution:0.0 density:1.0];The boxes are back to being all the same size now, but the first read more..

  • Page - 352

    Basic Box2D Interaction and Decoration313By thinking about the bodies in your game and how heavy/slippery/bouncy they should be, you can tweak these properties and get much nicer (and more realistic, if that’s what you’re aiming for) behavior! Decorating Your Box2D Bodies with SpritesYou’re getting close to being able to have all the tools necessary to make a simple game using Box2D, except you’re missing one major piece: the ability to associate sprites with Box2D bodies! Obviously, read more..

  • Page - 353

    Chapter 10 Basic Game Physics: Adding Realism with Box2D314@interface Box2DSprite : GameCharacter {b2Body *body;}@property (assign) b2Body *body;// Return TRUE to accept the mouse joint// Return FALSE to reject the mouse joint- (BOOL)mouseJointBegan;@endThis class derives from GameCharacter, since subclasses will need the ability to store their current character state. It contains a single instance variable and property for the associated Box2D body. It also defines a method that you will use to read more..

  • Page - 354

    Basic Box2D Interaction and Decoration315Next, switch to PuzzleLayer.mm and import the header for Box2DSprite at the top of the file, as shown in Listing 10.41.Listing 10.41 PuzzleLayer.mm (at top of file)#import "Box2DSprite.h"Then modify your createBoxAtLocation one more time, as shown in Listing 10.42. The bold lines indicate the changes since last time.Listing 10.42 PuzzleLayer.mm (modify createBoxAtLocation to this)- read more..

  • Page - 355

    Chapter 10 Basic Game Physics: Adding Realism with Box2D316There are a few interesting differences this time. First, the routine takes a parameter of a Box2DSprite (our new subclass of GameCharacter), and sets this as the user data of the Box2D body. It also uses the content size of the sprite to figure out the size of the box to create.NoteThe content size of a sprite includes any transparent space that may be in the sprite image. This isn’t a problem for the puzzle level, as the sprites read more..

  • Page - 356

    Basic Box2D Interaction and Decoration317 [self createBodyAtLocation:location forSprite:sprite friction:0.2restitution:0.0 density:1.0 isBox:TRUE]; [sceneSpriteBatchNode addChild:sprite];}- (void)createIceBlockAtLocation:(CGPoint)location {Box2DSprite *sprite = [Box2DSprite spriteWithSpriteFrameName:@"ice_block.png"]; sprite.gameObjectType = kIceType; [self createBodyAtLocation:location forSprite:sprite friction:0.2restitution:0.2 density:1.0 isBox:TRUE]; read more..

  • Page - 357

    Chapter 10 Basic Game Physics: Adding Realism with Box2D318 [self addChild:sceneSpriteBatchNode z:0]; [self createMeteorAtLocation:ccp(200, 600)]; [self createSkullAtLocation:ccp(200, 500)]; [self createRockAtLocation:ccp(400, 100)]; [self createIceBlockAtLocation:ccp(400, 400)]; [self createLongBlockAtLocation:ccp(400, 300)]; [self createFrozenOleAtLocation:ccp(100, 400)]; [self createRockAtLocation:ccp(300, 400)]; [CCTexture2D read more..

  • Page - 358

    Basic Box2D Interaction and Decoration319WarningIf you don’t make wise use of setting pixel formats and load a lot of massive images, eventually you will run out of memory and the OS will shut down your app. To learn more about pixel formats, check out this great post written by Ricardo Quesada on the Cocos2D site:actionURI(http://www.cocos2d-iphone.org/archives/61):http://www.cocos2d-iphone.org/archives/61To review, at this point you’ve created a sprite sheet and then created several Box2D read more..

  • Page - 359

    Chapter 10 Basic Game Physics: Adding Realism with Box2D320Compile and run your code, and you should now see a bunch of Box2D objects decorated with sprites, as shown in Figure 10.17. You can try moving the various objects around and check out their various density/restitution/friction properties!Figure 10.17 Box2D objects decorated with spritesAt this point you’ve learned a ton about Box2D—how to create bodies of square and circle shapes, how to move them around the screen with mouse read more..

  • Page - 360

    Making a Box2D Puzzle Game321But this isn’t ideal, because you might want to detect if Ole hits near, but not exactly on, the bottom right corner. Luckily, Box2D provides a very nice solution to this: sensors!Sensors are just Box2D objects that don’t cause any collision responses. So you can have an “imaginary box” in the lower right corner that Ole and other objects can just pass through as if it weren’t there. However, Box2D will still report when objects col-lide with the imaginary read more..

  • Page - 361

    Chapter 10 Basic Game Physics: Adding Realism with Box2D322b2PolygonShape shape; shape.SetAsBox(sensorSize.width/PTM_RATIO, sensorSize.height/PTM_RATIO); b2FixtureDef fixtureDef; fixtureDef.shape = &shape; fixtureDef.isSensor = true;sensorBody->CreateFixture(&fixtureDef);}This sets up a body and attaches a box-shaped fixture to it in the usual manner. However, there is one difference—it sets isSensor to true on the fixture. This makes the object detect read more..

  • Page - 362

    Making a Box2D Puzzle Game323This code checks if the user has won, and if not, it checks if Ole is colliding with the sensor.How does this work? Well, Box2D maintains a list of all of the contacts that one body makes to other bodies. Each contact contains information on exactly what points are touching as well as references to the fixtures that are touching (from which you can get the bodies). So this simply looks through Ole’s current contacts and checks if any of them are the sensor body. If read more..

  • Page - 363

    Chapter 10 Basic Game Physics: Adding Realism with Box2D324CCLabelTTF *label = [CCLabelTTF labelWithString:@"You Win!"fontName:@"Helvetica" fontSize:48.0]; label.position = ccp(winSize.width/2, winSize.height/2); label.scale = 0.25; [self addChild:label];CCScaleTo *scaleUp = [CCScaleTo actionWithDuration:1.0 scale:1.2];CCScaleTo *scaleBack = [CCScaleTo actionWithDuration:1.0 scale:1.0];CCDelayTime *delay = [CCDelayTime actionWithDuration:2.0];CCCallFuncN *winComplete read more..

  • Page - 364

    Making a Box2D Puzzle Game325To make things more challenging, you’ll set things up so that you can’t move cer-tain objects directly, such as Ole or the long stone block, and you’ll also add a bunch of extra objects to clutter up the space. While you’re at it, you’ll add a little extra interactivity by adding sound effects and making skulls “pop” and disappear when you tap them.Up to this point, you’ve been using the same subclass of CCSprite for all of the sprites (Box2DSprite) read more..

  • Page - 365

    Chapter 10 Basic Game Physics: Adding Realism with Box2D326-(id) init {if((self = [super init])) { [self setDisplayFrame:[ [CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:@"frozen_ole.png"]];gameObjectType = kFrozenVikingType; }return self;}- (BOOL)mouseJointBegan {return FALSE;}@endThis simply sets the display frame to be the frozen Ole image and sets up the game object type appropriately. It’s nice to encapsulate this logic inside the FrozenOle read more..

  • Page - 366

    Making a Box2D Puzzle Game327- (BOOL)mouseJointBegan {return FALSE;}@endThis is very similar in behavior to the FrozenOle class, so there’s not much to dis-cuss here. Next replace IceBlock.mm, as shown in Listing 10.56.Listing 10.56 IceBlock.mm#import "IceBlock.h"@implementation IceBlock-(id) init { if((self = [super init])) { [self setDisplayFrame:[ [CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:@"ice_block.png"]]; gameObjectType = read more..

  • Page - 367

    Chapter 10 Basic Game Physics: Adding Realism with Box2D328- (BOOL)mouseJointBegan { PLAYSOUNDEFFECT(PUZZLE_ROCK1);return TRUE;}@endSimilar implementation, except here we spice things up a bit by playing a sound effect when the user begins to move the rock.Next replace Meteor.mm with the contents of Listing 10.58, which is similar but plays a different sound effect.Listing 10.58 Meteor.mm#import "Meteor.h"#import "SimpleAudioEngine.h"@implementation Meteor-(id) init { if( read more..

  • Page - 368

    Making a Box2D Puzzle Game329gameObjectType = kSkullType; [self setDisplayFrame:[ [CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:@"skull.png"]]; } return self;}- (void)shrinkDone:(id)sender { [self removeFromParentAndCleanup:YES];}-(void)changeState:(CharacterStates)newState { [self setCharacterState:newState];switch (newState) {case kStateDead: { CCLOG(@"Skull->Changing State to Dead"); read more..

  • Page - 369

    Chapter 10 Basic Game Physics: Adding Realism with Box2D330In the case of the skull, when the user begins to tap the skull, it sets the state of the skull to dead and returns false (mouse joint not allowed). When the state is changed to dead, it performs the following steps:1. Destroys the Box2D body by calling DestroyBody(), passing in the saved away Box2D body as a parameter.2. Sets the body pointer to NULL.3. Runs a little animation showing the skull popping away with Cocos2D actions, with a read more..

  • Page - 370

    Making a Box2D Puzzle Game331Listing 10.62 PuzzleLayer.mm (at the bottom of the init method)for(int i = 0; i < 10; ++i) { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [self createSkullAtLocation:ccp(200, 700)]; } else { [self createSkullAtLocation:ccp(100, 250)]; }}for(int i = 0; i < 2; ++i) {if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [self createMeteorAtLocation:ccp(300, 600)]; [self createRockAtLocation:ccp(300, 600)]; read more..

  • Page - 371

    Chapter 10 Basic Game Physics: Adding Realism with Box2D332longer move Ole or the long ice block directly, and there are more objects blocking the way, so you’ll have to use a little physics to win! See Figure 10.19.Figure 10.19 The final puzzle level!actionGoTo:17,SummaryYou have developed a cool mini-puzzle game, using Box2D to handle the game physics automatically. You should now be familiar with the most important concepts in Box2D, such as bodies, fixtures, density, restitution, and read more..

  • Page - 372

    actionGoTo:17,11actionGoTo:17,Intermediate GameactionGoTo:17, Physics: actionGoTo:17,Modeling,actionGoTo:17, Racing,actionGoTo:17, andactionGoTo:17, LeapingIn Chapter 10, “Basic Game Physics: Adding Realism with Box2D,” you learned the basics of using the Box2D physics engine. Specifically, you learned how to create basic shapes, decorate them with sprites, and use gravity. In the process, you made your own simple puzzle game with Box2D physics!Although the level you made is quite cool, it read more..

  • Page - 373

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping334actionGoTo:17,Getting StartedTo get started with this level, you first need to get a basic Box2D scene set up—then you can build from there, adding features bit by bit. In this section you add the required resource files for this chapter to your project and create a basic Box2D scene as a starting point. You should be familiar with how to do the code in this section based on what you learned in Chapter 10, but this will be a read more..

  • Page - 374

    Getting Started335NoteYou do not need to add the contents of the Raw Art—Do Not Add! folder to your project—that folder contains the images inside the sprite sheet in case you want to try making the sprite sheet yourself with TexturePacker or Zwoptex.Now that you have the files you need for Chapter 11 added, it’s time to create a basic Box2D scene for the level.Creating a Basic Box2D SceneYou start simple for the scene for this level and just create a Box2D world and one sprite-decorated read more..

  • Page - 375

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping336and runs a callback upon completion. You use this to display text on the screen, such as when the level begins or when the player wins or loses. Next switch to Scene4UILayer.m and replace it with the contents of Listing 11.2.Listing 11.2 Scene4UILayer.m#import "Scene4UILayer.h"@implementation Scene4UILayer- (id)init {if ((self = [super init])) {CGSize winSize = [CCDirector sharedDirector].winSize; label = read more..

  • Page - 376

    Getting Started337The init method adds a blank label to the middle of the screen and sets it to invis-ible. The displayText method stops any running actions (in case the label is cur-rently animating), sets the string to the value passed in, and resets the label to visible, fully opaque, and very tiny (with a scale of 0.0). Then it scales the label up and slightly back to make it appear to “pop” into view, waits a few seconds, then fades out and rehides the label. It then calls whatever read more..

  • Page - 377

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping338b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);body = world->CreateBody(&bodyDef);body->SetUserData(self); b2FixtureDef fixtureDef;b2PolygonShape shape; shape.SetAsBox(self.contentSize.width/2/PTM_RATIO,self.contentSize.height/2/PTM_RATIO); fixtureDef.shape = &shape; fixtureDef.density = 1.0; fixtureDef.friction = 0.5; fixtureDef.restitution = 0.5;body->CreateFixture(&fixtureDef);}- read more..

  • Page - 378

    Getting Started339Listing 11.5 Scene4ActionLayer.h#import "cocos2d.h"#import "Box2D.h"#import "GLES-Render.h"#import "Constants.h"@class Scene4UILayer;@class Cart;@interface Scene4ActionLayer : CCLayer {b2World * world;GLESDebugDraw * debugDraw;CCSpriteBatchNode * sceneSpriteBatchNode;b2Body * groundBody;b2MouseJoint * mouseJoint;Cart * cart;Scene4UILayer * uiLayer;}- (id)initWithScene4UILayer:(Scene4UILayer *)scene4UILayer;@endThis includes the Cocos2D read more..

  • Page - 379

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping340- (void)setupWorld {b2Vec2 gravity = b2Vec2(0.0f, -10.0f);bool doSleep = true; world = new b2World(gravity, doSleep);}- (void)setupDebugDraw { debugDraw = new GLESDebugDraw(PTM_RATIO* [[CCDirector sharedDirector] contentScaleFactor]); world->SetDebugDraw(debugDraw); debugDraw->SetFlags(b2DebugDraw::e_shapeBit);}- (void)createGround {CGSize winSize = [[CCDirector sharedDirector] winSize];float32 margin read more..

  • Page - 380

    Getting Started341 [sceneSpriteBatchNode addChild:cart z:1 tag:kVikingSpriteTagValue]; }- (void)registerWithTouchDispatcher { [[CCTouchDispatcher sharedDispatcher]addTargetedDelegate:self priority:0 swallowsTouches:YES];}- (id)initWithScene4UILayer:(Scene4UILayer *)scene4UILayer {if ((self = [super init])) {CGSize winSize = [CCDirector sharedDirector].winSize; uiLayer = scene4UILayer; [self setupWorld]; [self setupDebugDraw]; [[GameManager sharedGameManager] read more..

  • Page - 381

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping342 world->Step(dt, velocityIterations, positionIterations);for(b2Body *b=world->GetBodyList(); b!=NULL; b=b->GetNext()) {if (b->GetUserData() != NULL) {Box2DSprite *sprite = (Box2DSprite *) b->GetUserData(); sprite.position = ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO); sprite.rotation = CC_RADIANS_TO_DEGREES(b->GetAngle() * -1); } read more..

  • Page - 382

    Getting Started343if (callback.fixtureFound) {b2Body *body = callback.fixtureFound->GetBody(); b2MouseJointDef mouseJointDef; mouseJointDef.bodyA = groundBody; mouseJointDef.bodyB = body; mouseJointDef.target = locationWorld; mouseJointDef.maxForce = 50 * body->GetMass(); mouseJointDef.collideConnected = true; mouseJoint = (b2MouseJoint *) world->CreateJoint(&mouseJointDef);body->SetAwake(true);return YES; }return read more..

  • Page - 383

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping344setupWorld creates a Box2D world with gravity similar to Earth’s gravity. It stores a pointer to the world object in an instance variable for future reference.setupDebugDraw creates a Box2D debug draw object and tells the world object to use it. The draw method sets up the OpenGL states properly for debug drawing and tells the world to do the debug drawing.createGround creates a static Box2D body (out of four edge fixtures) read more..

  • Page - 384

    Getting Started345@implementation Scene4-(id)init { if ((self = [super init])) {Scene4UILayer * uiLayer = [Scene4UILayer node]; [self addChild:uiLayer z:1];Scene4ActionLayer * actionLayer = [[[Scene4ActionLayer alloc] initWithScene4UILayer:uiLayer] autorelease]; [self addChild:actionLayer z:0]; } return self;}@endThis simply creates both of the layers (passing the UI layer as a parameter to the action layer) and adds both to the scene. Note that the UI layer read more..

  • Page - 385

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping346That’s it! If you compile and run the app and choose Descent Into Hades! from the Main Menu (or have it set up to launch right away), you should see your new scene appear with a ground body around the edges, and Ole’s cart (well at least part of it) will drop into your scene, as shown in Figure 11.3.Figure 11.3 A Basic Box2D scene with a world, ground box, and single body/spriteactionGoTo:17,CreatingactionGoTo:17, read more..

  • Page - 386

    Creating a Cart with Box2D347Let’s explain how Figure 11.4 works. When defining vertices for Box2D shapes, there are four important things to know: vertices are relative to the body’s center, vertices need to be defined in counterclockwise order, there is a maximum count of vertices per shape, and vertices cannot define a concave shape. Let’s go through these one by one.Vertices are relative to the body’s center: As you can see in the code shown in Figure 11.4, when you set vertices, you read more..

  • Page - 387

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping348180 degrees. A good way to think of it is as a shape that has an indentation in it. Figure 11.5 illustrates the difference between convex and concave polygons.ConvexAll internal angles < 180°ConcaveAt least one internal angle > 180°Angle > 180°Figure 11.5 Convex vs. concave polygonsWhen defining vertices in Box2D, you have several options. First, you could guess-timate the pixel offsets for the vertices, compile, read more..

  • Page - 388

    Creating a Cart with Box2D349Figure 11.6 Downloading Vertex HelperFigure 11.7 Main Vertex Helper screen read more..

  • Page - 389

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping350Now click on Edit Mode in the upper right corner, and then click on the upper right corner of the cart, which sets the first vertex at that point. Click on the upper left corner next, then the lower left corner, and lower right corner (counterclockwise order). Do not finish the shape off with a line back to the upper right—Box2D closes the shape automatically.As you click your vertices, Vertex Helper draws a green line read more..

  • Page - 390

    Creating a Cart with Box2D351Listing 11.11 Cart.mm (in createBodyAtLocation method)// Comment out this line//shape.SetAsBox(self.contentSize.width/2/PTM_RATIO,// self.contentSize.height/2/PTM_RATIO);// Add your code from Vertex Helper here, but replace all// instances of PTM_RATIO with 100.0int num = 4;b2Vec2 verts[] = {b2Vec2(77.5f / 100.0, 37.0f / 100.0),b2Vec2(-78.5f / 100.0, 38.0f / 100.0),b2Vec2(-60.5f / 100.0, -37.0f / 100.0),b2Vec2(56.5f / 100.0, -38.0f / 100.0)};// Then call read more..

  • Page - 391

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping352Now you know how to make an arbitrary shape using Box2D and how to use Ver-tex Helper to make your life a lot easier. But right now our cart has a big problem—it doesn’t have wheels. So let’s roll on out of the Stone Age and learn about Box2D revo-lute joints!Adding Wheels with Box2D Revolute JointsTo add wheels to the cart, you need to make two more bodies—one for each wheel. Remember from Chapter 10 that they need to read more..

  • Page - 392

    Creating a Cart with Box2D353Then switch to Cart.mm and synthesize the properties right after the @implemen-tation line, as shown in Listing 11.14.Listing 11.14 Cart.mm (after @implementation)@synthesize wheelL;@synthesize wheelR;@synthesize wheelLBody;@synthesize wheelRBody;Next add a new method to create a wheel before the initWithWorld method, as shown in Listing 11.15.Listing 11.15 Cart.mm (before initWithWorld method)- ( b2Body *)createWheelWithSprite:(Box2DSprite*)sprite read more..

  • Page - 393

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping354Second, the friction for the wheels is quite high (1.0). This is because you will be using the wheels to drive the cart along the ground, so you want a high friction so that moving the wheels causes the cart to move responsively (rather than slipping along the ground too much).Third, the density of the wheel (10.0) is much larger than the density of the cart (1.0). This is because the wheels behave best in Box2D when they have read more..

  • Page - 394

    Creating a Cart with Box2D355NoteThe offsets for the wheels were figured out by using the ruler tool in an image editor to estimate the number of pixels that each wheel should be offset from the center of the cart. Since the HD artwork was used for this, it needs to be converted to HD coordinates by dividing by the HD PTM_RATIO, which is 100.0.Next call this new method in initWithWorld:atLocation, as shown in Listing 11.17.Listing 11.17 Cart.mm (at the bottom of initWithWorld:atLocation)[self read more..

  • Page - 395

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping356actionGoTo:17,Making the CartactionGoTo:17, MoveactionGoTo:17, and JumpOle’s cart is pretty cool so far, and it rolls around adhering to real game physics. How-ever, there’s still a long way to go—the goal is to make this level an action-packed side-scroller, complete with accelerometer-based movement, interesting obstacles and ground terrain to ride over, and the ability to tap to launch the cart into the air so Ole can read more..

  • Page - 396

    Making the Cart Move and Jump357revJointDef.enableMotor = true;revJointDef.maxMotorTorque = 1000;revJointDef.motorSpeed = 0;wheelLJoint = (b2RevoluteJoint *) world->CreateJoint(&revJointDef);revJointDef.Initialize(body, wheelRBody, wheelRBody->GetWorldCenter());wheelRJoint = (b2RevoluteJoint *) world->CreateJoint(&revJointDef);These calls enable the motor for the revolute joint and set the initial speed to 0. Think of a motor as an automatic mechanism that read more..

  • Page - 397

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping358Now that this is set up, open Scene4ActionLayer.mm and add a line in the initmethod to enable accelerometer support, as shown in Listing 11.22.Listing 11.22 Scene4ActionLayer.mm (at the bottom of the initWithScene4UILayer method)self.isAccelerometerEnabled = YES;Next write the actual implementation of the accelerometer callback to set the speed of the wheels based on how much the device is tilted, as shown in Listing read more..

  • Page - 398

    Making the Cart Move and Jump359Making It ScrollableWhile you could probably make an entire game about moving back and forth within this box, in this chapter you’re going to do even better. You’re now going to learn how to make a scrollable level with Box2D—and have the view stay focused on the cart as it moves!Figure 11.11 shows part of Images\groundAtlas-hd.png, which contains the pieces of ground that you’re about to add to the level. You’ll be adding each of these strips to the read more..

  • Page - 399

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping360Remember back to earlier in this chapter—when defining shapes in Box2D, you can only have up to eight vertices (by default), and they can’t be concave (i.e., have an interior angle of greater than 180 degrees). You could split the ground body up into smaller pieces so that both of these rules would be followed, but that would be a big pain.Luckily, there is an easy solution—and you can still use Vertex Helper. The idea read more..

  • Page - 400

    Making the Cart Move and Jump361b2PolygonShape groundShape; b2FixtureDef groundFixtureDef; groundFixtureDef.shape = &groundShape; groundFixtureDef.density = 0.0;for(int i = 0; i < num - 1; ++i) {b2Vec2 offset = b2Vec2(groundMaxX/PTM_RATIO + ground.contentSize.width/2/PTM_RATIO, ground.contentSize.height/2/PTM_RATIO);b2Vec2 left = verts[i] + offset;b2Vec2 right = verts[i+1] + offset; groundShape.SetAsEdge(left, read more..

  • Page - 401

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping362the Vertex Helper window. As usual, type 1 for Rows, 1 for Cols, set the Typeto Box2D, set the Style to Initialization, and click Edit Mode to begin clicking vertices. Add the vertices by clicking from left to right across the ground. Since the ground is quite wide, it will most likely extend beyond the width of your window. To scroll, you need to toggle the Edit Mode checkbox so you can pan the image, toggle it again to read more..

  • Page - 402

    Making the Cart Move and Jump363b2Vec2(-888.8f / 100.0, 1.1f / 100.0),b2Vec2(-804.0f / 100.0, 10.3f / 100.0),b2Vec2(-799.7f / 100.0, 5.3f / 100.0),b2Vec2(-795.5f / 100.0, 8.1f / 100.0),b2Vec2(-755.2f / 100.0, -1.8f / 100.0),b2Vec2(-755.2f / 100.0, -9.5f / 100.0),b2Vec2(-632.2f / 100.0, 5.3f / 100.0),b2Vec2(-603.9f / 100.0, 17.3f / 100.0),b2Vec2(-536.0f / 100.0, 18.0f / 100.0),b2Vec2(-518.3f / 100.0, 28.6f / 100.0),b2Vec2(-282.1f / 100.0, 13.1f / 100.0),b2Vec2(-258.1f / 100.0, 27.2f / read more..

  • Page - 403

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping364b2Vec2(471.0f / 100.0, -7.0f / 100.0),b2Vec2(503.0f / 100.0, 4.0f / 100.0),b2Vec2(614.0f / 100.0, 66.0f / 100.0),b2Vec2(679.0f / 100.0, 59.0f / 100.0),b2Vec2(681.0f / 100.0, 46.0f / 100.0),b2Vec2(735.0f / 100.0, 31.0f / 100.0),b2Vec2(822.0f / 100.0, 24.0f / 100.0),b2Vec2(827.0f / 100.0, 12.0f / 100.0),b2Vec2(934.0f / 100.0, 14.0f / 100.0),b2Vec2(975.0f / 100.0, 1.0f / 100.0),b2Vec2(982.0f / 100.0, -19.0f / read more..

  • Page - 404

    Making the Cart Move and Jump365 background.anchorPoint = ccp(0,0); [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_Default]; [parallax addChild:background z:-10 parallaxRatio:ccp(0.05f, 0.05f)positionOffset:ccp(0,0)]; [self addChild:parallax z:-10];}This creates a parallax node to store the background image so that it slowly scrolls as the player moves through the level. Note that it sets the texture pixel format to RGB565, which is a 16-bit pixel format (saves read more..

  • Page - 405

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping366 [self setPosition:newPos];}This method moves the layer to keep the cart in a fixed position as the cart moves through the level. Figure 11.13 illustrates how this works.Figure 11.13 Moving the layer to keep the cart at a fixed position onscreenAs Figure 11.13 shows, if the layer did not move, the cart would simply move offscreen. However, you can keep the cart centered by figuring out the difference between where you want read more..

  • Page - 406

    Making the Cart Move and Jump367One last step: add the code to set up the ground batch sprite node and call cre-ateLevel at the end of initWithScene4UILayer, as shown in Listing 11.33.Listing 11.33 Scene4ActionLayer.mm (at the end of initWithScene4UILayer)[CCTexture2D setDefaultAlphaPixelFormat: kCCTexture2DPixelFormat_RGB5A1];if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [[CCSpriteFrameCache sharedSpriteFrameCache] read more..

  • Page - 407

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping368Forces and ImpulsesAn impulse is an instantaneous change in momentum (momentum is mass × velocity). Think of it as an instant boost that you can apply to an object to make it jump or f ly through the air.A force is a change in momentum over a period of time. Think of it as a gradual energy that you can use to make objects f loat into the air or be pushed toward a wall.Both impulses and forces affect an object’s velocity read more..

  • Page - 408

    Making the Cart Move and Jump369float32 maxAngle = CC_DEGREES_TO_RADIANS(20);double desiredAngle = self.body->GetAngle();if (self.body->GetAngle() > maxAngle) { desiredAngle = maxAngle; } else if (self.body->GetAngle() < minAngle) { desiredAngle = minAngle; }float32 diff = desiredAngle - self.body->GetAngle();if (diff != 0) { body->SetAngularVelocity(0);float32 diff = desiredAngle - self.body->GetAngle();float angimp = self.body->GetInertia() * read more..

  • Page - 409

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping370This simply predeclares the helper function you’re about to write. Next write the implementation by replacing Box2DHelpers.mm with the contents of Listing 11.36.Listing 11.36 Box2DHelpers.mm#import "Box2DHelpers.h"#import "Box2DSprite.h"bool isBodyCollidingWithObjectType(b2Body *body, GameObjectTypeobjectType) { b2ContactEdge* edge = body->GetContactList();while (edge) {b2Contact* contact = read more..

  • Page - 410

    Making the Cart Move and Jump371Now go to Scene4ActionLayer.mm and import Box2DHelpers.h at the top of the file, as shown in Listing 11.37.Listing 11.37 Scene4ActionLayer.mm (at the top of the file)#import "Box2DHelpers.h"Next delete the ccTouchBegan, ccTouchMoved, and ccTouchEnded methods, since you won’t need the mouse joint for debugging anymore. Then add the contents of Listing 11.38 as your new ccTouchBegan method.Listing 11.38 Scene4ActionLayer.mm (delete ccTouchXX methods and read more..

  • Page - 411

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping372 }}- (float32)fullMass {return body->GetMass() + wheelLBody->GetMass() + wheelRBody->GetMass();}- (void)jump { [self playJumpEffect];b2Vec2 impulse = b2Vec2([self fullMass]*1.0, [self fullMass]*5.0);b2Vec2 impulsePoint = body->GetWorldPoint(b2Vec2(5.0/100.0, -15.0/100.0));body->ApplyLinearImpulse(impulse, impulsePoint);}The code first plays a sound effect, then applies a linear impulse to the cart body to read more..

  • Page - 412

    Making the Cart Move and Jump373More Responsive Direction SwitchingIf you experiment with the level, you’ll see that once the cart gets moving, it takes a bit of time to switch directions. This models what would happen in real life, but in games, players are used to instant gratification! So let’s use impulses again to make the direction switching a bit faster for play-ers. Inside Scene4ActionLayer.mm, add the contents of Listing 11.42 to the bottom of accelerometer:didAccelerate.Listing read more..

  • Page - 413

    Chapter 11 Intermediate Game Physics: Modeling, Racing, and Leaping374Compile and run the code, and now the cart should switch directions more quickly. Finally, you have a cart worthy of Ole to ride in!actionGoTo:17,SummaryAt this point you have created a side-scrolling action level with Box2D, complete with vehicles, motors, joints, impulses, and more! You should now be familiar with how to use Box2D to model arbitrary shapes with Vertex Helper, connect multiple bodies with joints, and use read more..

  • Page - 414

    actionGoTo:18,12actionGoTo:18,Advanced GameactionGoTo:18, Physics:actionGoTo:18, Even actionGoTo:18,BetteractionGoTo:18, thanactionGoTo:18, theactionGoTo:18, RealactionGoTo:18, ThingIn Chapter 11, “Intermediate Game Physics,” you made an action-packed level where you can race a mining cart across interesting terrain and tap to leap through the air. However, there are two major problems. First, the level is far too easy! There are no dangers to avoid, no enemies to fight. Second, our hero Ole read more..

  • Page - 415

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing376actionGoTo:18,Joints and RagdollsactionGoTo:18,: Bringing Ole Back actionGoTo:18,into ActionNow that you have the cart ready for Ole to ride in, let’s add him into the scene!One way you could approach this is to draw Ole in as part of the cart sprite—but where would be the fun in that? In this chapter, you take things to the next level by adding Ole to the cart using ragdoll physics, so he bounces and moves in realistic and read more..

  • Page - 416

    Joints and Ragdolls: Bringing Ole Back into Action 377spinning around and around 360 degrees without any limits, people would think it was time to call an exorcist!Luckily, it is quite easy to restrict revolute joints to a certain angle range with Box2D. When you set up a b2RevoluteJointDef, you just set a few extra proper-ties: enableLimit, lowerAngle, and upperAngle. Listing 12.1 shows an example of connecting an arm to the main body.Listing 12.1 Example of limiting revolute joint read more..

  • Page - 417

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing378Using Prismatic JointsA prismatic joint is a type of joint that restricts two bodies so they can move relative to each other only along a specified axis. For example, you could connect a garage door body with a ground body and set the axis to be the y-axis, so the garage door can only slide up and down. Or you could connect a raft body with a ground body and set the axis to be the x-axis, so the raft can only slide right and read more..

  • Page - 418

    Joints and Ragdolls: Bringing Ole Back into Action 379location? A second method is to measure the distance of each object relative to a main body (such as the cart) and then add the main body’s current position to that point. This is better, but if you try to change the cart’s initial angle, the related bodies will no longer be in the correct location.An approach that works well even if you want to place an object in a different spot or at a different initial angle is to (1) measure the read more..

  • Page - 419

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing380In summary, to place multiple bodies and joints at the right spot, it’s a matter of using GetWorldPoint to convert local offsets from bodies to world coordinates and using an image editing tool to measure the offsets to place each body.In this chapter, you can use the sample code, which has the offsets premeasured, or you can replace the coordinates with your own measurements to make sure you fully understand how it read more..

  • Page - 420

    Joints and Ragdolls: Bringing Ole Back into Action 381Box2DSprite * helm;Box2DSprite * arm;b2Body * legsBody;b2Body * trunkBody;b2Body * headBody;b2Body * helmBody;b2Body * armBody;Then underneath, add properties for the sprites, as shown in Listing 12.5.Listing 12.5 Cart.h (after @interface)@property (readonly) Box2DSprite * legs;@property (readonly) Box2DSprite * trunk;@property (readonly) Box2DSprite * head;@property (readonly) Box2DSprite * helm;@property (readonly) Box2DSprite * arm;At the read more..

  • Page - 421

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing382You can set which categories of objects an object will collide with by setting the maskBits field. This is a 16-bit value, so setting it to 0xFFFF means that it collides with all categories (the same as the default behavior).The final item, groupIndex, is a special field you can use to override the mask bits. When two bodies share the same group index, if the number is negative, they will not collide, and if the number is read more..

  • Page - 422

    Joints and Ragdolls: Bringing Ole Back into Action 383Most of this is standard body creation code that you have seen many times. There are three things in particular to point out though. First, the density is set to very low so Ole’s bouncing around only affects the cart’s movement a little bit. Without this, you might see an effect where the force of Ole bouncing around overwhelms the joint constraints, and Ole could end up under the cart!Second, the category filtering is set up so that Ole read more..

  • Page - 423

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing384This simply uses the above method to create a Box2D body for each piece of Ole. Note that it uses GetWorldPoint to make each piece relative to the piece it’s connect-ing to for maximum code reuse. All of the points listed here were simply measured with a ruler tool in an image-editing program using the HD artwork, so they need to be divided by the HD PTM_RATIO (100.0) to be converted to the proper Box2D coor-dinates as read more..

  • Page - 424

    Joints and Ragdolls: Bringing Ole Back into Action 385revJointDef.enableLimit = true;world->CreateJoint(&revJointDef);prisJointDef.Initialize(headBody, helmBody, helmBody->GetWorldCenter(), axis);prisJointDef.enableLimit = true;prisJointDef.lowerTranslation = 0.0/100.0;prisJointDef.upperTranslation = 5.0/100.0;world->CreateJoint(&prisJointDef);Based on the discussion earlier in this chapter, most of this should be straightfor-ward. It’s simply creating revolute joints and read more..

  • Page - 425

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing386actionGoTo:18,Adding Obstacles and actionGoTo:18,BridgesSo far the level is kind of fun, with a cart that you can move around and jump—but there’s absolutely no challenge! So let’s spice things up a bit by adding some simple spikes along the ground that you have to jump and a neat swaying bridge you can cross.Adding a BridgeYou start with adding the bridge, since it’s simpler and will reinforce what you just learned read more..

  • Page - 426

    Adding Obstacles and Bridges387These just hold a reference to the first and last joints in the bridge added to the scene. They come in handy later in this chapter.Next add a new method to Scene4ActionLayer.mm to create the bridge, as shown in Listing 12.14.Listing 12.14 Scene4ActionLayer.mm (before createLevel)- (void)createBridge {Box2DSprite *lastObject;b2Body *lastBody = groundBody;for(int i = 0; i < 15;i++) {Box2DSprite *plank = [Box2DSprite read more..

  • Page - 427

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing388 shape.SetAsBox( plank.contentSize.width/2/PTM_RATIO, 40.0/100.0,b2Vec2(0, -plank.contentSize.height/2/PTM_RATIO-diff/PTM_RATIO), 0); b2FixtureDef fixtureDef; fixtureDef.shape = &shape; fixtureDef.density = 2.0; plankBody->CreateFixture(&fixtureDef);b2RevoluteJointDef jd; jd.Initialize(lastBody, plankBody, read more..

  • Page - 428

    Adding Obstacles and Bridges389Next, just modify your createLevel method to call the new createBridgemethod between the calls to create the ground, as shown in Listing 12.15. Listing 12.15 Scene4ActionLayer.mm (replace createLevel with this)- (void)createLevel { [self createBackground]; [self createGround3]; [self createBridge]; [self createGround1]; [self createBridge]; [self createGround3]; [self createBridge]; [self createGround2]; [self createGround3]; [self read more..

  • Page - 429

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing390Adding SpikesNow that you have bridges, let’s increase the challenge for the player by scattering some spikes across the level for the player to avoid.To start, you create a new subclass of Box2DSprite for the spikes. Select the Classes\Game Objects\Box2D group, go to File > New > New File..., choose iOS > Cocoa Touch > Objective-C class, and click Next. Enter Box2DSprite as the Sub-class of, click Next, name the read more..

  • Page - 430

    Adding Obstacles and Bridges391 b2FixtureDef fixtureDef; fixtureDef.shape = &shape; fixtureDef.density = 1000.0;body->CreateFixture(&fixtureDef);}- (id)initWithWorld:(b2World *)theWorld atLocation:(CGPoint)location {if ((self = [super init])) { world = theWorld; [self setDisplayFrame:[[CCSpriteFrameCachesharedSpriteFrameCache] spriteFrameByName:@"spikes.png"]]; gameObjectType = kSpikesType; [self createBodyAtLocation:location]; }return read more..

  • Page - 431

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing392 } else if (soundToPlay == 3) { PLAYSOUNDEFFECT(VIKING_HIT_4); } else { PLAYSOUNDEFFECT(VIKING_HIT_5); }}-(void)changeState:(CharacterStates)newState {if (characterState == newState) return; [self stopAllActions]; [self setCharacterState:newState];switch (newState) {case kStateTakingDamage: { [self playHitEffect];characterHealth = characterHealth - 10;CCAction *blink = [CCBlink read more..

  • Page - 432

    Adding Obstacles and Bridges393if ((characterState == kStateTakingDamage) && ([self numberOfRunningActions] > 0))return; // Currently playing the taking damage animationif ([self numberOfRunningActions] == 0) {// Not playing an animationif (characterHealth <= 0) { [self changeState:kStateDead]; } else { [self changeState:kStateIdle]; }}if (isBodyCollidingWithObjectType(wheelLBody, kSpikesType)) { [self changeState:kStateTakingDamage];} else if read more..

  • Page - 433

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing394Note that the coordinates are divided by two if it’s not the iPad—this way we can specify the coordinates once (for the HD artwork) and convert to the other device.One last step! Modify your createLevel method to call this new method a couple times, as shown in Listing 12.23.Listing 12.23 Scene4ActionLayer.mm (replace createLevel with this)- (void)createLevel { [self createBackground]; [self createGround3]; [self read more..

  • Page - 434

    Adding Obstacles and Bridges395Listing 12.24 Current main loop for Box2D—a variable rate timestepint32 velocityIterations = 3;int32 positionIterations = 2;world->Step(dt, velocityIterations, positionIterations);As you can see in Listing 12.24, each time the update method is called, the Stepmethod is called in the world with a different amount of time—whatever the variable dt happens to be.As mentioned in Chapter 10, “Basic Game Physics,” Box2D doesn’t work well with a variable rate read more..

  • Page - 435

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing396timeAccumulator += dt;if (timeAccumulator > (MAX_CYCLES_PER_FRAME * UPDATE_INTERVAL)) { timeAccumulator = UPDATE_INTERVAL;}int32 velocityIterations = 3;int32 positionIterations = 2;while (timeAccumulator >= UPDATE_INTERVAL) { timeAccumulator -= UPDATE_INTERVAL;world->Step(UPDATE_INTERVAL, velocityIterations, positionIterations);}Every time the Step method is called on the world, it’s always called with read more..

  • Page - 436

    The Boss Fight!397To make the Digger Robot, the first thing you need to do is create a new subclass of Box2DSprite for the Digger. Select the Classes\Game Objects\Box2D group, go to File > New > New File..., choose iOS > Cocoa Touch > Objective-C class,and click Next. Enter Box2DSprite as the Subclass of, click Next, name the file Digger.mm (note the .mm extension, since this will be importing Box2D), and click Save.Replace the contents of Digger.h, as shown in Listing 12.26.Listing read more..

  • Page - 437

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing398Here you make a subclass of Box2DSprite for the Digger Robot and declare refer-ences to a few variables you’ll need to keep track of. Specifically, these variables keep track of the Box2D bodies and joints for the Digger’s wheels and the body and fixture for the two drill sensor bodies.Next, switch to Digger.mm and add the method to create a body for the Digger Robot, as shown in Listing 12.27.Listing 12.27 Digger.mm (inside read more..

  • Page - 438

    The Boss Fight!399for the shape were created with Vertex Helper; you can trace the shape to define your own vertices if you wish.As far as the settings go, the robot is set up to have a low density (so that when Ole collides with it, he gives it a good thwack). It’s also set up to use angular damping. Angular damping is a value that affects the body’s resistance to rotation, so you set this to a high value here to prevent the Digger from f lipping when Ole collides with it.Next add a method read more..

  • Page - 439

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing400wheelLSprite.body = wheelLBody;wheelLBody->SetUserData(wheelLSprite);wheelRSprite = [Box2DSprite spriteWithSpriteFrameName:@"digger_wheel.png"];wheelRSprite.body = wheelRBody;wheelRBody->SetUserData(wheelRSprite);}This method creates two wheels for the Digger. Even though the Digger doesn’t appear to have wheels, you still want it to slide around the ground as if it has wheels. This is a good example of read more..

  • Page - 440

    The Boss Fight!401 fixtureDef.shape = &shape; fixtureDef.isSensor = true;drillLFixture = drillLBody->CreateFixture(&fixtureDef);int num2 = 3;b2Vec2 verts2[] = {b2Vec2(85.0f / 100.0, -72.0f / 100.0),b2Vec2(189.0f / 100.0, -2.0f / 100.0),b2Vec2(65.0f / 100.0, 31.0f / 100.0), }; shape.Set(verts2, num2);drillRFixture = drillRBody->CreateFixture(&fixtureDef);b2WeldJointDef weldJointDef; weldJointDef.Initialize(body, drillLBody, body->GetWorldCenter()); read more..

  • Page - 441

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing402Next add the init method to create a new Digger, as shown in Listing 12.30.Listing 12.30 Digger.mm (after createDrillWithWorld)- (id)initWithWorld:(b2World *)world atLocation:(CGPoint)location {if ((self = [super init])) { [self setDisplayFrame: [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:@"digger_anim5.png"]]; gameObjectType = kDiggerType; characterHealth = 100.0f; read more..

  • Page - 442

    The Boss Fight!403Listing 12.34 Scene4ActionLayer.mm (before createLevel)- (void)createDigger {CGSize winSize = [CCDirector sharedDirector].winSize;digger = [[[Digger alloc] initWithWorld:world atLocation:ccp(groundMaxX - winSize.width * 0.8, winSize.height/2)] autorelease]; [sceneSpriteBatchNode addChild:digger]; [sceneSpriteBatchNode addChild:digger.wheelLSprite]; [sceneSpriteBatchNode addChild:digger.wheelRSprite];}This method places the Digger 80 percent read more..

  • Page - 443

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing404Next, add some code to the bottom of your update method to check for the win and lose conditions, as shown in Listing 12.36.Listing 12.36 Scene4ActionLayer.mm (at the bottom of the update method)if (!gameOver) {if (isBodyCollidingWithObjectType(offscreenSensorBody, kCartType)) { gameOver = true; [uiLayer displayText:@"You Lose"andOnCompleteCallTarget:self selector:@selector(gameOver:)]; } else if read more..

  • Page - 444

    The Boss Fight!405A Dangerous DiggerThe Digger will move back and forth along the platform, switching directions every so often, while Ole tries to slam into the Digger from behind. If Ole is successful, he’ll bump the Digger a bit toward the edge, but if he fails and collides with the drill, Ole takes some damage.To implement this action, you add a new updateStateWithDeltaTime method inside the Digger class to check for collisions and implement game logic and a changeState method to switch read more..

  • Page - 445

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing406Listing 12.40 Digger.mm (at the top of the file)#import "Cart.h"#import "Box2DHelpers.h"Then add the first part of the updateStateWithDeltaTime method, which con-tains most of the game logic for the Digger, as shown in Listing 12.41.Listing 12.41 Digger.mm (anywhere in class)- (void) updateStateWithDeltaTime:(ccTime)deltaTime andListOfGameObjects:(CCArray *)listOfGameObjects {// 1if ((characterState == read more..

  • Page - 446

    The Boss Fight!4072. Check to see if the Digger is in the drilling state and has no actions running (which would mean the drilling animation has finished). If this is the case, it immediately rotates the Digger (so Ole has a chance to retaliate).3. Check to see if the Digger is in the taking-damage state and has no actions run-ning (which would mean the blinking action has finished). If this is the case, it stops the wheel motors to pause the Digger and switches the state to rotating (to give read more..

  • Page - 447

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing408 // 9else if (isBodyCollidingWithObjectType(cartBody, kDiggerType)) { [[SimpleAudioEngine sharedEngine] playEffect:@"collision.caf"]; [self changeState:kStateTakingDamage]; cartBody->ApplyLinearImpulse(b2Vec2(-direction * cart.fullMass * 8, -1.0 * cart.fullMass), cartBody->GetWorldPoint(b2Vec2(0, -15.0/100.0)));body->ApplyLinearImpulse(b2Vec2(direction * read more..

  • Page - 448

    The Boss Fight!40910. Check to see if the cart has moved in the current direction for a preset period of time, and if so, switch directions by switching to the rotating state.11. If none of the above conditions are met, set the wheels of the Digger to move in the current direction as the default action.Phew! You’ve made a lot of progress so far and are well on your way to having a cool boss fight! Just a few more steps to go.The next thing you need is a method to change states and supporting read more..

  • Page - 449

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing410CCCallFunc *disableDrills = [CCCallFunc actionWithTarget:selfselector:@selector(disableDrills)];CCAnimate *rotToCenter = [CCAnimate actionWithAnimation:rotateAnimrestoreOriginalFrame:NO];CCFlipX *flip = [CCFlipX actionWithFlipX:!self.flipX];CCAnimate *rotToSide = (CCAnimate *) [rotToCenter reverse];CCCallFunc *enableDrills = [CCCallFunc read more..

  • Page - 450

    The Boss Fight!411This uses the same helper methods you’ve used before to create animations based on a property list. If you would like, you can look at the property list and compare it to the images in the sprite sheet to see how each animation is put together.NoteThe animations are added to the CCAnimationCache so that they are retained some-where for future use. Alternatively, you could just retain these variables and release them in dealloc.One final step! Just add the following call to read more..

  • Page - 451

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing412The idea is that when Ole approaches the final boss, action pauses for a moment, and the camera pans to the left to show the bridge that Ole just crossed go up in f lames and drop to the ground! The camera then pans to reveal the boss menacingly approach Ole with the drill, and then again to the far side of the screen to reveal the pit where you can push the Digger off.Not only does this make the level cooler, but it also read more..

  • Page - 452

    The Boss Fight!413 sensorHeight/2/PTM_RATIO);finalBattleSensorBody = world->CreateBody(&bodyDef);b2PolygonShape shape; shape.SetAsBox(sensorWidth/2/PTM_RATIO, sensorHeight/2/PTM_RATIO); b2FixtureDef fixtureDef; fixtureDef.shape = &shape; fixtureDef.isSensor = true; fixtureDef.density = 0.0;finalBattleSensorBody->CreateFixture(&fixtureDef);}This is just a tall thin box that is placed right after the final bridge leading to the boss. When the player collides read more..

  • Page - 453

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing414Listing 12.49 Scene4ActionLayer.mm (at the end of the update method)CGSize winSize = [CCDirector sharedDirector].winSize;if (!inFinalBattle && isBodyCollidingWithObjectType(finalBattleSensorBody, kCartType)) { inFinalBattle = true; actionStopped = true; [cart setMotorSpeed:0]; cart.body->SetLinearVelocity(b2Vec2(0, 0)); [self runAction: [CCSequence actions: [CCDelayTime read more..

  • Page - 454

    The Boss Fight!415NoteSetLinearVelocity is a function that immediately sets the velocity of a Box2D body to a specified value. Usually, it is better to use impulses or forces to indirectly influ-ence the velocity of an object rather than using SetLinearVelocity, because Set-LinearVelocity can cause strange behavior with the physics engine. However, it’s okay in cases in which you just want to immediately stop a body.Once everything is stopped, it runs a sequence of actions. Specifically, the read more..

  • Page - 455

    Chapter 12 Advanced Game Physics: Even Better than the Real Thing416Next, you need to add some code to check for the actionStopped variable. If the variable is set, the layer shouldn’t follow the cart and the cart shouldn’t be able to move. So add a check to the top of both the accelerometer:didAccelerate and followCart methods, as shown in Listing 12.51.Listing 12.51 Scene4ActionLayer.mm (at the top of both accelerometer:didAccelerate and followCart)if (actionStopped) return;One last step. read more..

  • Page - 456

    Challenges417actionGoTo:18,SummaryAt this point you have created a side-scrolling action level with Box2D, complete with vehicles, motors, joints, collisions, enemy logic, cinematic effects, and more! You should now be familiar with how to use Box2D in real games and how to use the most important capabilities of the engine.To learn more about Box2D, check out the Box2D manual available on the offi-cial Box2D site actionURI(http://www.box2d.org):(http://www.box2d.org). It contains a full read more..

  • Page - 457

    This page intentionally left blank read more..

  • Page - 458

    actionGoTo:18,13actionGoTo:18,The ChipmunkactionGoTo:18, Physics EngiactionGoTo:18,neactionGoTo:18, actionGoTo:18,(No Alvin RequiractionGoTo:18,ed)Now that you have experienced using Box2D to make a cart-racing-and-jumping level, you can see how using a game physics library allows you to add some amazing effects to your game.One of the nice things about Cocos2D is that it comes with not one but two different 2D game physics libraries. You’ve tried Box2D already in Chapters 10, 11, and 12, so read more..

  • Page - 459

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)420actionGoTo:18,What Is Chipmunk?Chipmunk is an open source 2D game physics library originally written by Scott Lembcke. Like Box2D, Chipmunk comes integrated with Cocos2D by default, so it is quite easy to use in your Cocos2D games. Its feature set is very similar to Box2D, and even works in the same way but has slightly different terminology:nYou start by creating a physics world (but it’s called a “space” in Chipmunk) to place read more..

  • Page - 460

    Getting Started with Chipmunk421coordinates in Chipmunk, which can make your code less error prone and easier to read.nChipmunk code is often more terse. The code to create the same effect in Chip-munk is often fewer lines of boilerplate than it is in Box2D, which can be nice when you want to quickly prototype your game.nBox2D joints and Chipmunk constraints have some differences. For example, when you create a revolute joint in Box2D, you can also set limits on how much the joint can move and read more..

  • Page - 461

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)422Replace Scene5UILayer.h with contents of Listing 13.1.Listing 13.1 Scene5UILayer.h#import "cocos2d.h"@interface Scene5UILayer : CCLayer {CCLabelTTF *label;}- (void)displaySecs:(double)secs;@endNote that the UI layer contains a single label used for the countdown timer, and a method that the action layer uses to display the number of seconds remaining.Next switch to Scene5UILayer.m and replace it with the contents of Listing read more..

  • Page - 462

    Getting Started with Chipmunk423label = [CCLabelTTF labelWithString:@""fontName:@"AmericanTypewriter-Bold" fontSize:fontSize]; label.anchorPoint = ccp(1, 1); label.position = ccp(winSize.width - 20, winSize.height - 20); [self addChild:label]; }return self;}@endLet’s go through this section by section.1. This makes the minimum number of seconds zero, because it wouldn’t make sense to display a negative number of seconds in this scene. After all, read more..

  • Page - 463

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)424This layer contains a reference to the UI layer and the time the layer started. It also contains an initializer that takes the UI layer as a parameter.Now switch to Scene5ActionLayer.m and replace it with the contents of Listing 13.4.Listing 13.4 Scene5ActionLayer.m#import "Scene5ActionLayer.h"#import "Scene5UILayer.h"@implementation Scene5ActionLayer- (id)initWithScene5UILayer:(Scene5UILayer *)scene5UILayer {if read more..

  • Page - 464

    Getting Started with Chipmunk425So far this is nothing but a subclass of CCScene. Now switch to Scene5.m and replace it with the contents of Listing 13.6.Listing 13.6 Scene5.m#import "Scene5.h"#import "Scene5UILayer.h"#import "Scene5ActionLayer.h"@implementation Scene5-(id)init {if ((self = [super init])) {Scene5UILayer * uiLayer = [Scene5UILayer node]; [self addChild:uiLayer z:1];Scene5ActionLayer * actionLayer = [[[Scene5ActionLayer alloc] read more..

  • Page - 465

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)426TipAs mentioned in the previous chapters, you may wish to set up your app to run this new scene right away, since you’ll be working with it a lot in this chapter. Again, to do this simply open Classes\Singletons\SpaceVikingAppDelegate.m, navigate to the bottom of applicationDidFinishLaunching, and replace the CCDirector:runScene-WithID call at the bottom to:[[GameManager sharedGameManager] runSceneWithID:kGameLevel5];That’s it. read more..

  • Page - 466

    Getting Started with Chipmunk427The next step is adding these files to your Xcode project. Expand the cocos2d Sourcesgroup, then drag the Chipmunk folder from your SpaceViking\ libs directory to the group. When the dialog appears, make sure Copy items into destination group’s folder (if needed) is not checked, Create groups for any added folders is selected, and click Finish, as shown in Figure 13.4.Figure 13.3 Copying the Chipmunk files to your project directoryFigure 13.4 Adding the Chipmunk read more..

  • Page - 467

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)428Although you just added the entire Chipmunk directory, you actually only need the include and src subdirectories, so let’s remove the references for the rest. To do this, expand your new Chipmunk group in Xcode and select all of the subfolders and files except for include and src. Control-click and choose delete, then choose Remove References Only, as shown in Figure 13.5.Figure 13.5 Removing all subfolders except for include and read more..

  • Page - 468

    Getting Started with Chipmunk429One last step. Click on your Space Viking project in the Project Navigator to bring up your project settings, select the Build Settings tab, make sure the All and Combined buttons are selected, and look for the entry for Search Paths > Header Search Paths. Double-click the entry to bring up an editor, click the Plus button to add a new entry, double-click the entry for path, set it to libs/Chipmunk/include/ chipmunk if you are using Xcode 3 or read more..

  • Page - 469

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)430Switch to GameManager.mm and import chipmunk.h at the top of the file, as shown in Listing 13.9.Listing 13.9 GameManager.mm (at top of file)#import "chipmunk.h"Then call cpInitChipmunk inside the init method, as shown in Listing 13.10.Listing 13.10 GameManager.mm (inside init method)cpInitChipmunk();NotecpInitChipmunk allocates some global data necessary for Chipmunk to run properly. If you forget to call cpInitChipmunk, your read more..

  • Page - 470

    Getting Started with Chipmunk431if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { space->gravity = ccp(0, -1500);// 2 } else {space->gravity = ccp(0, -750); }cpSpaceResizeStaticHash(space, 400, 200);// 3cpSpaceResizeActiveHash(space, 200, 200);}It’s important to understand everything that’s going on here, so let’s review it line by line:1. This creates a new Chipmunk space by calling cpSpaceNew and stores the result in the space instance variable that you’ll read more..

  • Page - 471

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)432cpSpaceAddBody(space, body);// 3cpShape *shape = cpBoxShapeNew(body, boxSize, boxSize);// 4 shape->e = 0.0;// 5 shape->u = 0.5;// 6cpSpaceAddShape(space, shape);// 7}Again, this is foundational knowledge that is important to understand, so let’s step through this line by line:1. Creates a new Chipmunk body for the box. It sets the mass of the box (how hard the box is to move) to 1.0 and uses a helper function to compute read more..

  • Page - 472

    Getting Started with Chipmunk433Listing 13.14 Scene5ActionLayer.m (after createLevel)- (void)createGround {// 1CGSize winSize = [CCDirector sharedDirector].winSize;CGPoint lowerLeft = ccp(0, 0);CGPoint lowerRight = ccp(winSize.width, 0); groundBody = cpBodyNewStatic();// 2float radius = 10.0f;cpShape * shape = cpSegmentShapeNew(groundBody, lowerLeft, lowerRight, radius);// 3 shape->e = 1.0f;// 4 shape->u = 1.0f;// 5 shape->layers ^= GRABABLE_MASK_BIT;// read more..

  • Page - 473

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)434Listing 13.15 Scene5ActionLayer.m (at end of the update method)static double UPDATE_INTERVAL = 1.0f/60.0f;static double MAX_CYCLES_PER_FRAME = 5;static double timeAccumulator = 0;timeAccumulator += dt;if (timeAccumulator > (MAX_CYCLES_PER_FRAME * UPDATE_INTERVAL)) { timeAccumulator = UPDATE_INTERVAL;}while (timeAccumulator >= UPDATE_INTERVAL) { timeAccumulator -= UPDATE_INTERVAL;cpSpaceStep(space, UPDATE_INTERVAL);}This read more..

  • Page - 474

    Getting Started with Chipmunk435After you add the files, there’s an important step to take to make sure they compile correctly. In Xcode, select cpMouse.c, and go to View > Utilities > File Inspector.Click on the File Type dropdown, and set it to Objective-C source, as you can see in Figure 13.9. Repeat the process with drawSpace.c.Figure 13.9 Setting file type of cpMouse.c and drawSpace.c to Objective-C sourceSwitch to Scene5ActionLayer.h and import chipmunk.h, cpMouse.h, and read more..

  • Page - 475

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)436Switch back to Scene5ActionLayer.m and implement your draw method to call Chip-munk’s debug draw code in drawSpace.c/h, as shown in Listing 13.18.Listing 13.18 Scene5ActionLayer.m (after update method)- (void)draw {drawSpaceOptions options = {0,// drawHash0,// drawBBs1,// drawShapes4.0f,// collisionPointSize0.0f,// bodyPointSize1.5f,// lineThickness };drawSpace(space, &options);}This method calls the helper code contained in read more..

  • Page - 476

    Getting Started with Chipmunk437This registers the node with the touch dispatcher to receive the callbacks, then for each callback, it calls the appropriate helper routine in cpMouse.c/h to enable mouse movement for this scene. Note how you have to convert the touches to node coordi-nates as usual before passing them on to the helper routines.You’re almost done! To wrap things up, add the code to call the new methods you wrote at the end of initWithScene5UILayer, as shown in Listing read more..

  • Page - 477

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)438nHow to enable debug drawingnHow to use mouse joint supportBased on this knowledge, you could use Chipmunk to make the puzzle level you created with Box2D in Chapter 10, “Basic Game Physics,” except for one piece: how to map a sprite to the Chipmunk body. So let’s learn this by bringing our hero back into action and enabling him to run and leap to safety.actionGoTo:18,Adding Sprites and actionGoTo:18,Making Them MoveIt’s time read more..

  • Page - 478

    Adding Sprites and Making Them Move439- (void)addBoxBodyAndShapeWithLocation:(CGPoint)location size:(CGSize)size space:(cpSpace *)theSpace mass:(cpFloat)mass e:(cpFloat)e u:(cpFloat)u collisionType:(cpCollisionType)collisionType canRotate:(BOOL)canRotate;@endNote the base class defines a single body and shape for the sprite and keeps a refer-ence to the Chipmunk space. It also has a superlong helper method to create a box body and shape based on several passed in read more..

  • Page - 479

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)440cpSpaceAddBody(space, body); shape = cpBoxShapeNew(body, size.width, size.height); shape->e = e; shape->u = u; shape->collision_type = collisionType; shape->data = self;cpSpaceAddShape(space, shape);}@endThis first implements updateStateWithDeltaTime to update the position of the sprite based on the position of the Chipmunk body.Then addBoxBodyAndShapeWithLocation creates a Chipmunk body and shape based on read more..

  • Page - 480

    Adding Sprites and Making Them Move441Listing 13.24 CPViking.m#import "CPViking.h"@implementation CPViking- (id)initWithLocation:(CGPoint)location space:(cpSpace *)theSpace groundBody:(cpBody *)groundBody {if ((self = [super initWithSpriteFrameName:@"sv_anim_1.png"])) { CGSize size; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { size = CGSizeMake(60, 60);self.anchorPoint = ccp(0.5, 30/self.contentSize.height);} else { size = CGSizeMake(30, read more..

  • Page - 481

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)442NoteIf you’re still confused about why the anchor point was set, remember that the anchor point is the offset within the sprite that represents its position. For this sprite, you are creating a 60 × 60 box toward the bottom of the sprite, so you want the sprite’s position to match up with the center of the box (i.e., the Chipmunk body’s position). Since anchor point’s values range from 0 to 1 (a percentage of the sprite’s read more..

  • Page - 482

    Adding Sprites and Making Them Move443 viking = [[[CPViking alloc] initWithLocation:ccp(200,200) space:space groundBody:groundBody] autorelease];} else { [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"scene5atlas.plist"]; sceneSpriteBatchNode = [CCSpriteBatchNode batchNodeWithFile:@"scene5atlas.png"]; viking = [[[CPViking alloc] initWithLocation:ccp(100,100) space:space groundBody:groundBody] read more..

  • Page - 483

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)444Jumping by Directly Setting VelocityIn the mine cart level you made in Chapters 11 and 12, you implemented jumping by applying an impulse to the Box2D body. You can apply forces and impulses in Chip-munk as well, but for this level you take a different approach: you implement jumping by setting the velocity of the sprite directly.One of the nice things about Chipmunk is that it works well with directly setting the velocity of bodies, read more..

  • Page - 484

    Adding Sprites and Making Them Move445Ground Movement by Setting Surface VelocityChipmunk has a neat property you can set on objects called surface velocity that works nicely for conveyor belt effects or for character controls such as this.Basically, the surface velocity for an object represents the speed at which the surface of the object itself is moving. You can set it to make an object slide along the ground or move across a conveyor belt.For this level, when Ole is on the ground, you will read more..

  • Page - 485

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)446In this level, you use collision detection callbacks for two reasons: (1) to detect if the player is currently on the ground, by implementing the Begin and Separatecallbacks, and (2) to allow the player to jump through the bottom of a one-way plat-form, by implementing the PreSolve callback.NoteThe callback functions you write are C functions, so you can’t access member variables from your class in these functions. A common read more..

  • Page - 486

    Adding Sprites and Making Them Move447Listing 13.33 CPViking.m (modify call to addBoxBodyAndShapeWithLocation in initWithLocation)[self addBoxBodyAndShapeWithLocation:location size:size space:theSpace mass:1.0 e:0.0 u:1.0 collisionType:kCollisionTypeViking canRotate:TRUE];Similarly, switch to Scene5ActionLayer.m and set the collision type for the ground shape created in createGround, as shown in Listing 13.34.Listing 13.34 Scene5ActionLayer.m (before calling cpSpaceAddShape in read more..

  • Page - 487

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)448NoteThis method is a good example of how to create shapes with arbitrary vertices by using cpPolyShapeNew, passing in an array of vertices. If you wanted to, you could use Ver-tex Helper to trace exact shapes and create bodies based on those shapes, just as you did in Chapter 11. However, note that for Chipmunk, vertices must be defined in clockwise order (rather than counterclockwise as with Box2D).Now that each of the shapes in the read more..

  • Page - 488

    Adding Sprites and Making Them Move449Listing 13.40 CPViking.m (before initWithLocation)static cpBool begin(cpArbiter *arb, cpSpace *space, void *ignore) {CP_ARBITER_GET_SHAPES(arb, vikingShape, groundShape);// 1CPViking *viking = (CPViking *)vikingShape->data;// 2cpVect n = cpArbiterGetNormal(arb, 0);// 3if (n.y < 0.0f) {// 4cpArray *groundShapes = viking.groundShapes;// 5cpArrayPush(groundShapes, groundShape); }return cpTrue;}static cpBool preSolve(cpArbiter *arb, cpSpace *space, void read more..

  • Page - 489

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)4505. Any time Ole is colliding with the top of the platform, this adds it to the list of shapes Ole is currently colliding with.6. This tests to see if Ole is jumping through the bottom of the platform and, if so, cancels the collision response by returning false. Otherwise it returns true to have Chipmunk continue to process the collision response.7. The separate method removes the ground shape from the array of shapes cur-rently in read more..

  • Page - 490

    Adding Sprites and Making Them Move451Note that these are the methods that accept accelerometer and touch input; you need to forward the accelerometer and touch input from the action layer straight to the CPViking class for processing. Now switch to CPViking.m and implement those meth-ods, as shown in Listing 13.43.Listing 13.43 CPViking.m (after initWithLocation)- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { if (groundShapes->num > 0) { jumpStartTime = read more..

  • Page - 491

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)452Next override the updateStateWithDeltaTime method to add the jumping code, as shown in Listing 13.44.Listing 13.44 CPViking.m (before initWithLocation)-(void)updateStateWithDeltaTime:(ccTime)dt andListOfGameObjects:(CCArray*)listOfGameObjects { [super updateStateWithDeltaTime:dtandListOfGameObjects:listOfGameObjects];// 1 float jumpFactor;if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { jumpFactor = 300.0; read more..

  • Page - 492

    Adding Sprites and Making Them Move4536. If the jump start time isn’t 0 (i.e., Ole is currently trying to jump) and Ole hasn’t been jumping for more than a quarter second, it sets the y component of the velocity to a straight 600.0 to make Ole leap into the air. After a quarter second, gravity starts to gradually lower the y component so Ole returns to earth.7. Sets the velocity of the Chipmunk body to the newly calculated velocity. That covers the movement of Ole while he’s in the air, read more..

  • Page - 493

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)454Listing 13.46 CPViking.m (at bottom of updateStateWithDeltaTime)float margin = 70;CGSize winSize = [CCDirector sharedDirector].winSize;if (body->p.x < margin) {cpBodySetPos(body, ccp(margin, body->p.y));}if (body->p.x > winSize.width - margin) {cpBodySetPos(body, ccp(winSize.width - margin, body->p.y));}This code prevents Ole from going off the sides of the screen by clamping the xcoordinate to min/max values.You’re read more..

  • Page - 494

    Chipmunk and Constraints455That’s it. Compile and run, and now you should be able to use the accelerometer to move Ole back and forth, tap to jump in the air, and land on top of the platform (but still be able to jump through the bottom of the platform). See Figure 13.12.Figure 13.12 A moving and jumping Viking with a platformABABFigure 13.13 Pivot joint: Rotate around a pointIt’s starting to work nicely, except you may notice that Ole sometimes gets f lipped over, landing unheroically on read more..

  • Page - 495

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)456Rotary limit joint: Unlike in Box2D, when you make pivot joints you cannot restrict the rotation to a certain degree range. Instead, you need to create a second constraint: a rotary limit joint. With this, you can specify the minimum and maxi-mum rotation range for two objects (Figure 13.14).ABBA+15° maximumrotationInitialangleFigure 13.14 Rotary limit joint: Restrict rotationSimple motor: Unlike Box2D, Chipmunk does not allow you to read more..

  • Page - 496

    Chipmunk and Constraints457Damped spring: Creates a “spring effect” between two objects that should be a specified distance apart. If you push the objects together, the constraint pushes them apart. If you pull them too far apart, the constraint pulls them together. This is similar to a soft distance joint in Box2D (with frequencyHz and dampingRatioset) (Figure 13.18).Figure 13.18 Damped spring: Creates a spring effect for the distance between objectsDamped rotary spring: This works read more..

  • Page - 497

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)458So let’s see this in code. Switch to CPViking.m and add two lines of code to the bottom of your initWithLocation method, as shown in Listing 13.49.Listing 13.49 CPViking.m (at bottom of initWithLocation)cpConstraint *constraint = cpRotaryLimitJointNew(groundBody, body, CC_DEGREES_TO_RADIANS(-30), CC_DEGREES_TO_RADIANS(30));cpSpaceAddConstraint(space, constraint);That’s how easy constraints are to use! Compile and run your code, read more..

  • Page - 498

    Chipmunk and Constraints459- (id)initWithLocation:(CGPoint)location space:(cpSpace *)theSpace groundBody:(cpBody *)groundBody {if ((self = [superinitWithSpriteFrameName:@"platform_revolve.png"])) { [self addBoxBodyAndShapeWithLocation:locationsize:self.contentSize space:theSpace mass:1.0 e:0.2 u:1.0collisionType:kCollisionTypeGround canRotate:TRUE];// 1cpConstraint *c1 = cpPivotJointNew(groundBody, body, body->p);cpSpaceAddConstraint(space, c1);// 2cpConstraint *c2 = read more..

  • Page - 499

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)460Finally, inside your createLevel method, comment out the call to createBox-AtLocation and call your new method, as shown in Listing 13.54.Listing 13.54 Scene5ActionLayer.m (replace createBoxAtLocation inside createLevel with this)[self createRevolvePlatformAtLocation: ccp(winSize.width * 0.5, winSize.height * 0.25)];Compile and run your code, and you should now be able to jump on top of a revolving platform (Figure 13.20)!Figure read more..

  • Page - 500

    Chipmunk and Constraints461Listing 13.55 CPPivotPlatform.h#import "CPSprite.h"@interface CPPivotPlatform : CPSprite {}@endThis is just a subclass of CPSprite, with nothing extra added. Next replace CPPivotPlatform.m with the contents of Listing 13.56.Listing 13.56 CPPivotPlatform.m#import "CPPivotPlatform.h"@implementation CPPivotPlatform- (id)initWithLocation:(CGPoint)location space:(cpSpace *)theSpace groundBody:(cpBody *)groundBody {if ((self = read more..

  • Page - 501

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)462This creates a body for the pivot platform using the helper method you wrote ear-lier (but notice how it uses a large mass for this body to make it a bit harder to move). It then sets up three constraints:1. Creates a pivot joint connecting the platform body with the ground body so that the platform body can rotate around its center point (its position).2. Creates a damped rotary spring between the platform body and the ground body. read more..

  • Page - 502

    Chipmunk and Constraints463size:self.contentSize space:theSpace mass:1.0 e:0.2 u:1.0collisionType:kCollisionTypeGround canRotate:FALSE];// 1float springLength = 200; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { springLength /= 2; }cpConstraint * constraint = cpDampedSpringNew(groundBody, body,ccp(body->p.x, body->p.y-springLength), ccp(0,0), springLength, 25.0, 0.5);cpSpaceAddConstraint(space, constraint);// 2cpConstraint * c2 = read more..

  • Page - 503

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)464little bit above and below the platform body’s current position. The fifth param-eter is the platform body-local coordinate that slides up and down the groove—set here to be the center position of the platform body.Just one more platform type to add, and then you’ll get to test them out. This time you add a normal platform. This platform is a special case because it doesn’t move at all, so you can add it as a static shape read more..

  • Page - 504

    Chipmunk and Constraints465 shape = cpPolyShapeNew(groundBody, 4, verts, location); shape->e = 1.0f; shape->u = 1.0f; shape->collision_type = kCollisionTypeGround;cpSpaceAddStaticShape(space, shape); }return self;}@endThis first overrides updateStateWithDeltaTime to do nothing, since there is no need to update the position of the sprite based on the body, since the body never moves!It then creates a new static shape for the sprite based on the size of the read more..

  • Page - 505

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)466- (void)createNormalPlatformAtLocation:(CGPoint)location {CPNormalPlatform *normPlatform = [[[CPNormalPlatform alloc]initWithLocation:location space:space groundBody:groundBody]autorelease]; [sceneSpriteBatchNode addChild:normPlatform];}Finally, comment out the call to createRevolvePlatformAtLocation in your createLevel method and replace it with the contents of Listing 13.63.Listing 13.63 Scene5ActionLayer.m (replace contents of read more..

  • Page - 506

    The Great Escape!467actionGoTo:19,The Great EscapeactionGoTo:19,!At this point, you have enough building blocks to make this into a complete level, so let’s put things together and add in a bit of polish and excitement along the way.Following OleSince Ole will be moving vertically up this level, you need to set the layer to follow Ole as he moves up and down the scene. While you’re at it, you’ll apply a neat “screen shake” effect to the layer to make it seem like the planet is about to read more..

  • Page - 507

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)4682. To shake the screen, you need to move the layer a little bit to the right for a short period of time, then a little bit to the left, then repeat. Whenever you find yourself needing to do something on a periodic basis like this, a good trick is to use the sin function. The sin function gives a periodic wave that cycles between −1 and 1 every 2*M_PI (6.28), so if you pass in seconds, it cycles between −1 and 1 every 6.28 seconds. read more..

  • Page - 508

    The Great Escape!469 [self createPivotPlatformAtLocation:ccp(winSize.width * 0.4, winSize.height * 1.60)]; [self createNormalPlatformAtLocation:ccp(winSize.width * 0.7, winSize.height * 1.90)]; [self createNormalPlatformAtLocation:ccp(winSize.width * 0.4, winSize.height * 2.15)]; [self createSpringPlatformAtLocation:ccp(winSize.width * 0.45, winSize.height * 2.60)]; [self createSpringPlatformAtLocation:ccp(winSize.width * 0.75, winSize.height * 2.80)]; [self read more..

  • Page - 509

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)470Now switch to CPViking.m and add a method to load the animations from the property list, as shown in Listing 13.68.Listing 13.68 CPViking.m (before initWithLocation)-(void)initAnimations { walkingAnim = [self loadPlistForAnimationWithName:@"walkingAnim"andClassName:NSStringFromClass([self class])]; [[CCAnimationCache sharedAnimationCache]addAnimation:walkingAnim name:@"walkingAnim"]; jumpingAnim = [self read more..

  • Page - 510

    The Great Escape!471case kStateJumping: action = [CCAnimate actionWithAnimation:jumpingAnimrestoreOriginalFrame:NO];break;case kStateAfterJumping: action = [CCAnimate actionWithAnimation:afterJumpingAnimrestoreOriginalFrame:NO];break;default:break; }if (action != nil) { [self runAction:action]; }}You should be familiar with how this works by now, based on what you learned starting back in Chapter 4, “Simple Collision Detection and the First Enemy.”You’re read more..

  • Page - 511

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)472// 2if (characterState != kStateJumping && jumpStartTime != 0) { [self changeState:kStateJumping];}// 3if (characterState == kStateIdle && accelerationFraction != 0) { [self changeState:kStateWalking];}// 3if ([self numberOfRunningActions] == 0) {if (characterState == kStateJumping) {if (groundShapes->num > 0) { [self changeState:kStateAfterJumping]; } } else if (characterState != read more..

  • Page - 512

    The Great Escape!473Music and Sound EffectsNow let’s add some music and sound effects to make it even cooler. Add the line to start the background music playing in initWithScene5UILayer, as shown in Listing 13.73.Listing 13.73 Scene5ActionLayer.m (at bottom of initWithScene5UILayer)[[GameManager sharedGameManager] playBackgroundTrack:BACKGROUND_TRACK_ESCAPE];Similarly, switch to CPViking.m and add a method to play a random jump sound effect, as shown in Listing 13.74.Listing 13.74 read more..

  • Page - 513

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)474 } else { PLAYSOUNDEFFECT(VIKING_JUMPING_4); }}Finally, inside the changeState method in the case for kStateJumping, call the playJumpEffect method, as shown in Listing 13.75.Listing 13.75 CPViking.m (inside changeState method’s kStateJumping case)[self playJumpEffect];Compile and run your code, and enjoy the grooves and grunts!Adding the BackgroundThe black background is getting kind of boring, so let’s add a real read more..

  • Page - 514

    The Great Escape!475// 2 CCSprite *groundSprite;if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { groundSprite = [CCSprite spriteWithFile:@"chipmunk_ground-hd.png"]; } else { groundSprite = [CCSprite spriteWithFile:@"chipmunk_ground.png"]; } groundSprite.anchorPoint = ccp(0,0); groundSprite.position = ccp(0,0); [self addChild:groundSprite z:-10];// 3 [background runAction: [CCRepeatForever read more..

  • Page - 515

    Chapter 13 The Chipmunk Physics Engine (No Alvin Required)476Adding Win/Lose ConditionsOne last thing to add: a check to see if Ole has escaped the planet or if he’s run out of time. You’re going to do a real simple check for this here, and just check if the y posi-tion of Ole is greater than a certain amount.You’ll need to use GameManager to switch to the win/lose scene, so import that at the top of the file, as you can see in Listing 13.78.Listing 13.78 Scene5ActionLayer.m (at top of read more..

  • Page - 516

    Challenges477Compile and run your level—see if you can help Ole escape from the planet before it’s too late!actionGoTo:19,SummaryAt this point, you have created a complete Metroid-style platformer escape level with Chipmunk. In the process, you gained hands-on experience using the most important aspects of Chipmunk: creating a space, adding bodies and shapes, moving the bodies, and restricting their movement with constraints.Now that you know the basics of using Chipmunk, you should check read more..

  • Page - 517

    This page intentionally left blank read more..

  • Page - 518

    actionGoTo:19,PartactionGoTo:19, VactionGoTo:19,ParticleactionGoTo:19, Systems,actionGoTo:19, actionGoTo:19,Game Center, and actionGoTo:19,PerformanceLearn how to quickly create and add particle systems to your games, how to integrate with Apple’s Game Center for online leaderboards and achievements, and some performance tips and tricks to keep your game running fast.nChapter 14: “Particle Systems: Creating Fire, Snow, Ice, and More”nChapter 15: “Achievements and Leaderboards with Game read more..

  • Page - 519

    This page intentionally left blank read more..

  • Page - 520

    actionGoTo:19,14actionGoTo:19,ParticleactionGoTo:19, Systems:actionGoTo:19, CreatingactionGoTo:19, Fire,actionGoTo:19, actionGoTo:19,Snow, Ice,actionGoTo:19, and MoreIn the previous chapters you learned about the Box2D and Chipmunk physics engines and how to incorporate them into Space Viking and your games. In this chapter you will learn about par-ticle systems and how easily you can add realistic fire, smoke, snow, rain, and other effects to your games. Particle system is just a name for a read more..

  • Page - 521

    Chapter 14 Particle Systems: Creating Fire, Snow, Ice, and More482nCCParticleSystemQuadCocos2D particle system that renders the particles using quads (two triangles). The CCParticleSystemQuad can have particle images of any size, and it allows for rotating and scaling of the entire particle system as a whole.Do not worry if it is not clear to you how the emitter works or is configured. This chap-ter guides you through several examples of setting up and adding particle systems to Space read more..

  • Page - 522

    Built-In Particle Systems483Figure 14.1 ParticleTest in the Scheme dropdown menu in XcodePay close attention to the ParticleSmoke and ParticleSnow examples, as you will be incorporating those into Space Viking.To see how the example particle systems are added to the scene, open the ParticleTest.m class in the cocos2d-ios Xcode project, located inside the Tests group. Move to the DemoSnow implementation and observe the lines shown on Listing 14.1.Listing 14.1 ParticleSnow being created in the read more..

  • Page - 523

    Chapter 14 Particle Systems: Creating Fire, Snow, Ice, and More484If you are using the built-in particle systems, it just takes these two lines of code to get it into your game. If you click Run and select the Ole Awakes level, you will see Ole the Viking on the familiar alien desert, this time with snow. Figure 14.3 shows the Space Viking first level with the snow particle system.Figure 14.2 Particles image folder added to SpaceViking Xcode projectFigure 14.3 Space Viking with the snow particle read more..

  • Page - 524

    Getting Started with Particle Designer485Mike Daley and Tom Bradley provides a great way to create and see your particle sys-tems in real time. It also exports any particle systems you create in a plist format that Cocos2D can read and use natively.The next section takes you through installing Particle Designer and creating the engine exhaust for the space cargo ship.actionGoTo:19,Getting Started with PactionGoTo:19,article DesignerAlthough Particle Designer is a tool you must pay for, you can read more..

  • Page - 525

    Chapter 14 Particle Systems: Creating Fire, Snow, Ice, and More486The iPhone and iPad simulators in Particle Designer are not the Xcode iPhone/iPad simulator but a window running the OpenGL code to render the particle system. The next version of Particle Designer includes a live export to iOS devices, so you can see your particle systems directly on your iPhone or iPad. Keep in mind that just because a particle system runs fast on your Mac does not mean it will run as fast on your iOS device. read more..

  • Page - 526

    Getting Started with Particle Designer487Particle Designer ControlsAs you can see from Figure 14.6, there are quite a lot of options behind creating a particle system. Don’t be overwhelmed if this looks like the control panel for a nuclear reactor: it is much simpler than it looks at first glance. Here is what each section sets up in the particle system:nBackground Color SectionThe background color is not exported to Cocos2D plist files. It is only used so that you can better see your particle read more..

  • Page - 527

    Chapter 14 Particle Systems: Creating Fire, Snow, Ice, and More488nThe variance determines how much each of the settings will vary from particle to particle. Having a good amount of variance in your particle system can make it seem more realistic. Having no variance will have each of the particles act exactly as the previous ones.nEmitter Type SectionThe emitter type section lets you choose between a gravity or radial style par-ticle system. Gravity has the particles flowing in one direction read more..

  • Page - 528

    Creating and Adding a Particle System to Space Viking 489actionGoTo:19,Creating and Adding a PactionGoTo:19,article System toactionGoTo:19, actionGoTo:19,Space VikingTo create the space cargo ship exhaust plume, you take one of the existing Particle Designer systems and modify it. To start:1. Open Particle Designer and look at the Shared Emitters Gallery.2. Select the Plasma Exhaust Particle System.In the Particle Configuration section:1. Change the Max Particles to 100 (from 1000).2. Change the read more..

  • Page - 529

    Chapter 14 Particle Systems: Creating Fire, Snow, Ice, and More490Adding the Engine Exhaust to Space VikingWhat could be cooler than a fire and smoke exhaust trail on the space cargo ship? In this section you add the fire plume particle system (EngineExhaust.plist) you created as well as a smoke particle system.To start, open the GameplayLayer.h header file and add the lines shown in Listing 14.3 inside the @interface declaration.Listing 14.3 Engine exhaust particle systems in GameplayLayer.h read more..

  • Page - 530

    Creating and Adding a Particle System to Space Viking 491Listing 14.4 creatObjectofType method in GameplayLayer.m implementation file} else if (kEnemyTypeSpaceCargoShip == objectType) {CCLOG(@"Creating the Cargo Ship Enemy");SpaceCargoShip *spaceCargoShip = [[SpaceCargoShip alloc]initWithSpriteFrameName:@"ship_2.png"]; [spaceCargoShip setDelegate:self]; [spaceCargoShip setPosition:spawnLocation]; [sceneSpriteBatchNode addChild:spaceCargoShip read more..

  • Page - 531

    Chapter 14 Particle Systems: Creating Fire, Snow, Ice, and More492Now that the particle systems are added to the Gameplay layer, the last step is to position both particle systems behind the SpaceCargoShip so that they follow it left and right.Move to the update method inside GameplayLayer.m and add the lines shown in bold in Listing 14.5.Listing 14.5 update method in GameplayLayer.m implementation file#pragma mark Update Method-(void) update:(ccTime)deltaTime {CCArray *listOfGameObjects = read more..

  • Page - 532

    Creating and Adding a Particle System to Space Viking 493 if ([spaceCargoShip flipX] == NO) { // Ship facing to the left xOffset = cargoShipBoundingBox.size.width; } CGPoint newPosition = ccp(cargoShipBoundingBox.origin.x + xOffset, cargoShipBoundingBox.origin.y + (cargoShipBoundingBox.size.height*0.6f)); [emitter setPosition:newPosition]; [smokeEmitter setPosition:newPosition]; }}After the for loop has read more..

  • Page - 533

    Chapter 14 Particle Systems: Creating Fire, Snow, Ice, and More494actionGoTo:19,SummaryParticle systems can add a great deal of realism to your games and help pull the player into the game world. In this chapter you learned about particle systems and how to easily add them to your own Cocos2D games. You also learned about the Particle Designer tool and how to experiment with the various settings for particle systems quickly and easily from your Mac. In the next chapter you learn about Apple’s read more..

  • Page - 534

    actionGoTo:19,15actionGoTo:19,AchievementsactionGoTo:19, andactionGoTo:19, LeaderboardsactionGoTo:19, actionGoTo:19,withactionGoTo:19, GameactionGoTo:19, CenterSpace Viking is quickly becoming a pretty cool game. It uses a lot of different aspects of Cocos2D, including actions, animation, scrolling, sound, and game physics. It has multiple levels with different styles and has a kick-butt main character.But when you make a game like this, you want to keep your players coming back for more. One read more..

  • Page - 535

    Chapter 15 Achievements and Leaderboards with Game Center496Figure 15.1 Friends list in Game Center and viewing friend’s gamesFigure 15.2 Viewing your progress in a game in Game Center read more..

  • Page - 536

    Enabling Game Center for Your App497In this chapter, you get some hands-on experience using Game Center, by adding leaderboards and achievements into Space Viking. But before we get started, let’s talk about why you’d want to use Game Center in the first place.Why Use Game Center?Using Game Center is a great idea for many reasons:First, it’s easy to do. Adding networked leaderboards or achievements to your game used to be a difficult task involving writing networking code and a server-side read more..

  • Page - 537

    Chapter 15 Achievements and Leaderboards with Game Center498In order to complete this chapter and try out Game Center, you need to sign up for this program first and pay your $99 if you haven’t already. At the time of writing this book, you can sign up at actionURI(http://developer.apple.com/programs/ios/):http://developer.apple.com/programs/ios/.Note that it usually takes a couple weeks for the application to go through, so it’s a good idea to register as soon as you can!Create an App ID read more..

  • Page - 538

    Enabling Game Center for Your App4992. Click the link for iOS Provisioning Portal on the right-hand side, as shown in Figure 15.5. The iOS Provisioning Portal is a service that helps you set up your devices, App IDs, and provisioning/distribution/ad-hoc profiles.Figure 15.4 Click Log inFigure 15.5 Click iOS Provisioning Portal3. Right now, you just need an App ID, so click the link for App IDs on the left-hand side, then click the New App ID button in the upper right. Create a new App ID for read more..

  • Page - 539

    Chapter 15 Achievements and Leaderboards with Game Center500nFor the Bundle Seed ID, choose the same Bundle ID as your other apps if you want to share keychain access; otherwise choose Generate New.nFor the Bundle Identif ier, enter in a unique name based on a DNS name you own, such as com.prop-group.spaceviking. If you do not own a domain name, you can make one up based on your full name or something else unique.When you’re done, click Submit, as shown in Figure 15.6.Figure 15.6 Create new read more..

  • Page - 540

    Enabling Game Center for Your App501Congratulations! You’ve successfully set up your app with a unique identifier, which is the first step toward enabling Game Center in your app. The next thing you need to do is register your app in iTunes Connect.Register Your App in iTunes ConnectIf you’ve developed other apps on the App Store before, you may be used to writing the app first, then registering the app in iTunes Connect and uploading it. If you want to use Game Center, however, you have to read more..

  • Page - 541

    Chapter 15 Achievements and Leaderboards with Game Center5023. From your list of apps, click Add New App to register a new app, and choose iOS App for the App type, as shown in Figure 15.10. Note that this screen may not appear if you are an iOS-only developer (if so, just continue to the next step). Also note that you may get a screen that asks you for your company name and language.Figure 15.9 Click Manage Your ApplicationsFigure 15.10 Click Add New App, then select iOS App as the App Type read more..

  • Page - 542

    Enabling Game Center for Your App5034. Next you enter in the basic information for your app, according to the following instructions:nFor the App Name, choose a unique app name. We chose Space Viking here, but you must choose a different name, as this name is already taken. nFor SKU Number, you can put in some kind of abbreviation to keep track of your app; we just use SPACEVIKING001. nFor Bundle ID, choose the Bundle Identifier you just made as part of your App ID; ours is read more..

  • Page - 543

    Chapter 15 Achievements and Leaderboards with Game Center504Figure 15.12 Entering rights and pricingFigure 15.13 Enter placeholder information in Version Information screen read more..

  • Page - 544

    Enabling Game Center for Your App505At this point you should see a page for your app in the Prepare for Upload state, as shown in Figure 15.14. You won’t be uploading the app yet (since you’re still working on it), but at this point it’s ready for you to enable Game Center support!Figure 15.14 Your placeholder app entry in iTunes ConnectEnable Game Center SupportNow that you’ve gotten this far, enabling Game Center in your app is really easy. Just click on the Manage Game Center button, read more..

  • Page - 545

    Chapter 15 Achievements and Leaderboards with Game Center506actionGoTo:19,Game Center AuthenticationBefore you can do anything with Game Center, you must take three steps:1. Make sure Game Center is available on the current device.2. Try to authenticate the player with Game Center.3. Keep informed if authentication status ever changes.You’ll start by learning what all of this means and how to implement it, then you’ll try it out yourself by adding the code into Space Viking. So let’s get read more..

  • Page - 546

    Game Center Authentication507// Check if the device is running iOS 4.1 or later NSString *reqSysVer = @"4.1"; NSString *currSysVer = [[UIDevice currentDevice] systemVersion];BOOL osVersionSupported = ([currSysVer compare:reqSysVeroptions:NSNumericSearch] != NSOrderedAscending);return (gcClass && osVersionSupported);}The method in Listing 15.1 checks if the GKLocalPlayer class exists (one of the Game Center API classes), and then checks that the OS is 4.1 or later (since read more..

  • Page - 547

    Chapter 15 Achievements and Leaderboards with Game Center508nIf the user isn’t logged in (and has opted out by pressing cancel three times in a row), no dialog will be presented to the user—ever! The user will have to go to Game Center to log in again. This behavior is by design, as Game Center should be treated as systemwide login behavior.NoteNote that you shouldn’t try to add a Game Center button that calls authenticate-WithCompletionHandler again. If the user wants to log in to Game read more..

  • Page - 548

    Game Center Authentication509Now it’s time to add some code. You’ll be putting all of the Game Center–related code in a helper class to keep your code clean and reusable in future projects.To add the helper class, select the Singletons group in Xcode, go to File > New > New File..., choose iOS > Cocoa Touch > Objective-C class, and click Next.Enter NSObject as the Subclass of, click Next, name the file GCHelper.m, and click Save.Once you’ve created the class, replace read more..

  • Page - 549

    Chapter 15 Achievements and Leaderboards with Game Center510device and one to keep track if the user is currently authenticated. It also defines a static method to get the single instance of the GCHelper for the application, prede-clares the callback for authentication status changes, and defines a method that will authenticate the local user.Next, switch to GCHelper.m and replace it with the contents of Listing 15.5.Listing 15.5 GCHelper.m#import "GCHelper.h"@implementation read more..

  • Page - 550

    Game Center Authentication511Now that you’ve added the code to create a singleton instance of GCHelper, add the code to initialize the object and keep track of authentication status changes, as shown in Listing 15.6.Listing 15.6 GCHelper.m (after alloc method)- (BOOL)isGameCenterAvailable {// check for presence of GKLocalPlayer APIClass gcClass = (NSClassFromString(@"GKLocalPlayer"));// check if the device is running iOS 4.1 or laterNSString *reqSysVer = @"4.1";NSString read more..

  • Page - 551

    Chapter 15 Achievements and Leaderboards with Game Center512isGameCenterAvailable is the same code shown earlier in this chapter that checks to see if this version of the OS has the Game Center code on it.init first checks to see if Game Center is available. If it is, it registers authentication Changed to be called whenever the authentication status changes.authenticationChanged keeps a f lag of whether or not the user is currently authenticated and logs when there is a change in status. read more..

  • Page - 552

    Game Center Authentication513Now that you’re done with the implementation, it’s time to try it out! Switch to SpaceVikingAppDelegate.m and import the GCHelper class at the top of your file, as shown in Listing 15.8.Listing 15.8 SpaceVikingAppDelegate.m (at top of file)#import "GCHelper.h"Then at the beginning of applicationDidFinishLaunching, add a call to authenticate the user, as shown in Listing 15.9.Listing 15.9 SpaceVikingAppDelegate.m (at beginning of read more..

  • Page - 553

    Chapter 15 Achievements and Leaderboards with Game Center514NoteNote that the dialog has the label “Sandbox” on it. This is because there are two differ-ent Game Center environments: a development “sandbox” environment for testing and a production environment that is used when your app has launched. You can tell which one you’re on because the dialog boxes and Game Center app itself make it clear by contain-ing Sandbox labels if you’re on the sandbox.Each environment has its own set read more..

  • Page - 554

    Setting Up Achievements515actionGoTo:20,Setting Up AchievementactionGoTo:20,sAchievements are a way that you can set a challenge for users (such as “Get 1000 coins,” “Kill 20 monsters,” or “Beat this level”) and then reward users for reaching that goal by keeping track of their achievements and giving them points. Users can see at a quick glance what achievements they’ve fulfilled and which are yet to be done.In this section, you add achievements to Space Viking. To keep things read more..

  • Page - 555

    Chapter 15 Achievements and Leaderboards with Game Center516NoteBe careful with how you allocate points, because if you start out with achievements sum-ming to 1000 points and you want to add another achievement later, there will be no more points left to give out. Therefore, it’s a good idea to start with giving out a smaller number of points if you aren’t sure how many you might add later.3. Click Add New Achievement to bring up the Add Achievement screen, as shown in Figure 15.20. Figure read more..

  • Page - 556

    Setting Up Achievements517There are several more values that are set on a per-language basis; you can see them by clicking Add Language. They are self-explanatory: the title of the achievement, the descriptions for before and after the user accomplishes the achievement, and a 512 × 512 image for the achievement.NoteNote that achievement images in Game Center are circular to look a bit like coins. You can either make your icons circular as well or just upload a square image with transpar-ency read more..

  • Page - 557

    Chapter 15 Achievements and Leaderboards with Game Center518[achievement reportAchievementWithCompletionHandler:^(NSError *error) {// Do something...}];Pretty simple, eh? But there’s one big problem: there is a chance that report-AchievementWithCompletionHandler could fail, such as if the Internet connec-tion goes down or if Game Center itself is having troubles. If that happens, you don’t want the player to lose the achievement, especially since some achievements entail a lot of work and read more..

  • Page - 558

    Implementing Achievements519Creating a Game State ClassFirst, you create a new object called GameState, which the game will use to keep track of the user’s progress. Select the Singletons group in Xcode, go to go to File > New > New File..., choose iOS > Cocoa Touch > Objective-C class, and click Next. Enter NSObject as the Subclass of, click Next, name the file GameState.m, and click Save.Once you’ve created the class, replace GameState.h with the contents of Listing read more..

  • Page - 559

    Chapter 15 Achievements and Leaderboards with Game Center520Listing 15.12 GameState.m#import "GameState.h"#import "GCDatabase.h"@implementation GameState@synthesize completedLevel1;@synthesize completedLevel2;@synthesize completedLevel3;@synthesize completedLevel4;@synthesize completedLevel5;@synthesize timesFell;static GameState *sharedInstance = nil;+(GameState*)sharedInstance {@synchronized([GameState class]) {if(!sharedInstance) {sharedInstance = read more..

  • Page - 560

    Implementing Achievements521 [encoder encodeBool:completedLevel2 forKey:@"CompletedLevel2"]; [encoder encodeBool:completedLevel3 forKey:@"CompletedLevel3"]; [encoder encodeBool:completedLevel4 forKey:@"CompletedLevel4"]; [encoder encodeBool:completedLevel5 forKey:@"CompletedLevel5"]; [encoder encodeInt:timesFell forKey:@"TimesFell"];}- (id)initWithCoder:(NSCoder *)decoder {if ((self = [super init])) {completedLevel1 = [decoder read more..

  • Page - 561

    Chapter 15 Achievements and Leaderboards with Game Center522Creating Helper Functions to Load and Save DataNow you implement the loadData() and saveData() methods referenced above in a new file: GCDatabase. Select the Singletons group in Xcode, go to go to File > New > New File..., choose iOS > Cocoa Touch > Objective-C class, and click Next. Enter NSObject as the Subclass of, click Next, name the file GCDatabase.m, and click Save.Replace GCDatabase.h with the contents of Listing read more..

  • Page - 562

    Implementing Achievements523// 6NSData *data = [[[NSData alloc]initWithContentsOfFile:filePath] autorelease];// 7NSKeyedUnarchiver *unarchiver = [[[NSKeyedUnarchiver alloc]initForReadingWithData:data] autorelease];// 8id retval = [unarchiver decodeObjectForKey:@"Data"]; [unarchiver finishDecoding];return retval; }return nil;}void saveData(id theData, NSString *filename) {// 9NSMutableData *data = [[[NSMutableData alloc] init] autorelease];// 10NSKeyedArchiver *archiver = read more..

  • Page - 563

    Chapter 15 Achievements and Leaderboards with Game Center5245. To check if a file exists on the disk, it uses the NSFileManager singleton’s fileExistsAtPath method. NSFileManager is a useful class that can check if files exist, delete files, enumerate directories, and more.6. To read an entire file off the disk and put it into a data buffer, there is a handy helper method on NSData called initWithContentsOfFile. This returns an NSData, which is a helper class that represents a buffer of bytes read more..

  • Page - 564

    Implementing Achievements525#define kAchievementLevel2 @"com.prop-group.spaceviking.achievement.level2"#define kAchievementLevel3 @"com.prop-group.spaceviking.achievement.level3"#define kAchievementLevel4 @"com.prop-group.spaceviking.achievement.level4"#define kAchievementLevel5 @"com.prop-group.spaceviking.achievement.level5"#define kAchievementBadDream @"com.prop-group.spaceviking.achievement.baddream"#define kLeaderboardEscape read more..

  • Page - 565

    Chapter 15 Achievements and Leaderboards with Game Center526The third change is to add new arrays to store the scores and achievements that still need to be sent to Game Center. Note that you’re adding the scores array now (even though you won’t use it until later) just to avoid backtracking here later.The final change is to add several new methods: one to save the GCHelper class to disk, an updated initializer, and methods to report achievements and scores (although right now, only the read more..

  • Page - 566

    Implementing Achievements527Listing 15.19 GCHelper.m (below alloc method)- (void)save {saveData(self, @"GameCenterData");}Then modify the init method to take arrays as parameters, as shown in Listing 15.20.Listing 15.20 GCHelper.m (modify init method)- (id)initWithScoresToReport:(NSMutableArray *)theScoresToReport achievementsToReport:(NSMutableArray *)theAchievementsToReport {if ((self = [super init])) {self.scoresToReport = theScoresToReport; self.achievementsToReport = read more..

  • Page - 567

    Chapter 15 Achievements and Leaderboards with Game Center528 } else {NSLog(@"Achievement failed to send... will try again \ later. Reason: %@", error.localizedDescription); } }); }];}This uses the reportAchievementWithCompletionHandler method to attempt to send an achievement to Game Center. Note that the handler isn’t guaranteed to run on the main thread, so this uses dispatch_async to run the inner code on the main thread. If the read more..

  • Page - 568

    Implementing Achievements529- (void)reportAchievement:(NSString *)identifier percentComplete:(double)percentComplete {GKAchievement* achievement = [[[GKAchievement alloc]initWithIdentifier:identifier] autorelease]; achievement.percentComplete = percentComplete; [achievementsToReport addObject:achievement]; [self save];if (!gameCenterAvailable || !userAuthenticated) return; [self sendAchievement:achievement];}The reportScore method is just a stub to be filled in later. The read more..

  • Page - 569

    Chapter 15 Achievements and Leaderboards with Game Center530This encodes the two arrays of scores and achievements to report to disk in encodeWithDecoder, decodes them in initWithCoder, and calls the initializer.Phew! That was a lot of code, but the good news is most of it is reusable for future projects and for the leaderboard implementation as well. There’s only one part left: to make use of these new classes in Space Viking.Using GameState and GCHelper in SpaceVikingNow you’re ready to read more..

  • Page - 570

    Implementing Achievements531 [[GameState sharedInstance] save]; [[GCHelper sharedInstance] reportAchievement:kAchievementLevel2percentComplete:100.0]; achievementLabelText.string = @"Achievement Unlocked: Side Scroller!"; }} else if ([GameManager sharedGameManager].lastLevel == kGameLevel3 && ![GameManager sharedGameManager].hasPlayerDied) {CCLOG(@"Finished level 3");if (![GameState sharedInstance].completedLevel3) { [GameState read more..

  • Page - 571

    Chapter 15 Achievements and Leaderboards with Game Center532double pctComplete = ((double) [GameState sharedInstance].timesFell / (int)maxTimesToFall) * 100.0; [[GCHelper sharedInstance]reportAchievement:kAchievementBadDreampercentComplete:pctComplete];if ([GameState sharedInstance].timesFell >= maxTimesToFall) { achievementLabelText.string = @"Achievement Unlocked: Bad Dream!"; } }}There’s a lot of code here, but it’s read more..

  • Page - 572

    Implementing Achievements533Listing 15.30 GameManager.m (after @implementation)@synthesize curLevel;@synthesize lastLevel;Finally, add the contents of Listing 15.31 to the beginning of runSceneWithID.Listing 15.31 GameManager.m (at top of runSceneWithID)lastLevel = curLevel;curLevel = sceneID;Now GameManager keeps track of the last level played, so the LevelComplete-Layer code can work properly.That’s it! Compile and run your code, and beat a level in the game. Then exit out of the app, go to read more..

  • Page - 573

    Chapter 15 Achievements and Leaderboards with Game Center534should resend your achievement data to Game Center, and you won’t have lost your progress!Displaying Achievements within the AppIt’s extremely easy to display achievements within your game by using a built-in view controller provided by Apple. Let’s try it out!In Space Viking, you display the achievements when the user selects the option in the Options menu. There’s already an entry there: you just have to implement it! Switch read more..

  • Page - 574

    Implementing Achievements535You also need to modify init to add new menu options for achievements, as shown in Listing 15.34.Listing 15.34 OptionsLayer.m (in init, replace CCMenu * optionsMenu… and [optionsMenu alignItems… lines with the following)CCLabelBMFont *achievementsButtonLabel = [CCLabelBMFontlabelWithString:@"Achievements" fntFile:@"VikingSpeechFont64.fnt"];CCMenuItemLabel *achievementsButton = [CCMenuItemLabelitemWithLabel:achievementsButtonLabel read more..

  • Page - 575

    Chapter 15 Achievements and Leaderboards with Game Center536NoteDisplaying achievements with the built-in view controller like this is definitely the easiest way and will suffice for many apps, but you may want to make the achievement display look different (and more like the rest of your app). This is possible with Game Center: you just need to load the achievements and descriptions yourself and create a custom view. For more information, check the Creating a Custom Achievement User Interface read more..

  • Page - 576

    Setting Up and Implementing Leaderboards5371. Log on to iTunes Connect at actionURI(https://itunesconnect.apple.com):https://itunesconnect.apple.com.2. Click Manage Your Applications, select your application, click Manage Game Center, and then click Set up under Leaderboards. At this point, you should see a window similar to Figure 15.24.Figure 15.24 Empty leaderboards screen3. Click Add Leaderboard to add a new leaderboard. It gives you a choice between a Single Leaderboard or Combined read more..

  • Page - 577

    Chapter 15 Achievements and Leaderboards with Game Center538How Leaderboards WorkA leaderboard is simply an ordered collection of best scores. When the user has reached a score, you create a GKScore object and call a method to send the score to Game Center. Game Center keeps track of the max score for each user, and it is okay if you submit a lower score or send a score more than once; it silently discards it. The process looks similar to Listing 15.38.Listing 15.38 Example of sending a score to read more..

  • Page - 578

    Setting Up and Implementing Leaderboards539Implementing LeaderboardsSince you’ve already added the code to persist an array of scores to disk in GCHelperand added a placeholder method, implementing leaderboards will be easy. Start by adding a new method called sendScore right above sendAchievementin GCHelper.m, as shown in Listing 15.39.Listing 15.39 GCHelper.m (above sendAchievement)- (void)sendScore:(GKScore *)score { [score reportScoreWithCompletionHandler:^(NSError *error) { read more..

  • Page - 579

    Chapter 15 Achievements and Leaderboards with Game Center540 score.value = rawScore; [scoresToReport addObject:score]; [self save];if (!gameCenterAvailable || !userAuthenticated) return; [self sendScore:score];}This is similar to the reportAchievement method. It sets up the GKScore object, adds it to the array of scores to report, and saves the array. It bails if game center isn’t available or the user isn’t authenticated; otherwise, it calls the sendScore method to attempt to read more..

  • Page - 580

    Setting Up and Implementing Leaderboards541Then replace ccTouchesBegan with some new code to display a view controller, and add a method underneath, as shown in Listing 15.45.Listing 15.45 LevelCompleteLayer.m (replace ccTouchesBegan and add new method)-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {if ([GameManager sharedGameManager].lastLevel == kGameLevel5) {GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];if read more..

  • Page - 581

    Chapter 15 Achievements and Leaderboards with Game Center542runSceneWithID:kMainMenuScene]; }}- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController{SpaceVikingAppDelegate *delegate = [UIApplication sharedApplication].delegate; [delegate.viewController dismissModalViewControllerAnimated: YES]; [viewController release]; [[GameManager sharedGameManager] setHasPlayerDied:NO]; [[GameManager sharedGameManager] read more..

  • Page - 582

    Challenges543actionGoTo:20,SummaryAt this point you have had hands-on experience integrating Game Center player authentication, achievements, and leaderboards into a Cocos2D game. And you’ve learned how to send achievements and leaderboards in a safe way, so that the player’s hard-earned achievements get sent even if the network connection is temporarily down.Now that you know how to implement Game Center in your games, you can enjoy the many benefits, including making your game easier to read more..

  • Page - 583

    This page intentionally left blank read more..

  • Page - 584

    actionGoTo:20,16actionGoTo:20,PerformanceactionGoTo:20, OptimizationactionGoTo:20,sThroughout this book, you learned how to create a game using Cocos2D, Box2D, and Chip-munk. You learned the basics of Cocos2D and advanced concepts from scrolling to physics engines to particle systems. This chapter takes you through some of the optimizations tips and tricks you may need in bringing that last bit of polish to your game now that you have a foundation of knowledge in Cocos2D game development.In this read more..

  • Page - 585

    Chapter 16 Performance Optimizations546Run this game on your actual iPad device. Right away you should notice that the performance is not very good: the frame rate is around 30 to 40 frames per second (fps), with occasional drops to 22 fps.From the PerformanceTestGame project and the GameplayLayer class. Take a close look at the top of the implementation file and the #define shown in Listing 16.1.Listing 16.1 #define in GameplayLayer.m in the PerformanceTestGame#import read more..

  • Page - 586

    CCSprite versus CCSpriteBatchNode547Listing 16.2 Init method in GameplayLayer.m in the PerformanceTestGame-(id)init {self = [super init];if (self != nil) {srandom(time(NULL));CGSize screenSize = [CCDirector sharedDirector].winSize;// 1CCSprite *background;if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { background = [CCSprite spriteWithFile:@"background.png"]; } else { background = [CCSprite read more..

  • Page - 587

    Chapter 16 Performance Optimizations548// 5dropElementsArray = [CCArray arrayWithCapacity:NUMBER_OF_ITEMS]; [dropElementsArray retain];// 6for (int x =0; x < NUMBER_OF_ITEMS; x++) {CCSprite *dropSprite = [self createItem]; [dropElementsArray insertObject:dropSprite atIndex:x];// 7#if (USE_CCSPRITEBATCHNODE == 1) [sceneSpriteBatchNode addChild:dropSprite z:currentItemTag tag:currentItemTag];#else [self read more..

  • Page - 588

    CCSprite versus CCSpriteBatchNode5495. Initializes and retains a CCArray to hold all of the falling items. The CCArrayis used for another optimization in this game, reusing the CCSprites (fall-ing items) instead of creating new ones. CCArray is a Cocos2D fast array implementation.Memory allocation and deallocation is an expensive operation that you want to avoid and minimize if you can. By storing the CCSprites inside of a CCArray,they can be reused by simply moving them back to the top of the read more..

  • Page - 589

    Chapter 16 Performance Optimizations550The update method cycles through each of the falling items stored in the CCAr-ray, checking to see if their position is less than 10 on the y-axis. If so, they are reset. The dropWith methods work as follows:dropWithLowPerformanceItemWithID: Method removes the CCSprite item from the layer or CCSpriteBatchNode, creates a new CCSprite, and adds it back in the old one’s place. dropWithHighPerformanceItemWithID: Method simply moves the CCSpriteback to the read more..

  • Page - 590

    CCSprite versus CCSpriteBatchNode551Tips for Textures and Texture AtlasesIn order to get the most performance out of using textures, texture atlases, and the CCSpriteBatchNode class, you should follow these simple rules.Minimize the Empty Space in the Texture AtlasHaving a large, empty texture atlas is just as wasteful as having individual sprites. You want the smallest-sized texture atlas that you can use for your images with the least amount of empty space.Use the Smallest Bit Depth Possible read more..

  • Page - 591

    Chapter 16 Performance Optimizations552Use the FlipX and FlipY for Reverse ImagesIf you need the reverse of an image either horizontally or vertically, use the FlipX or FlipY parameter instead of storing two images of your character facing left and right. You used the FlipX setting in Space Viking to make Ole face left or right depending on his direction of movement.[sprite setFlipX:YES]; // Flip the image Horizontally[sprite setFlipY:YES]; // Flip the image VerticallyAllocate your CCSprites read more..

  • Page - 592

    Reusing CCSprites553Listing 16.4 What not to do: dropWithLowPerformanceItemWithID method-(void)dropWithLowPerformanceItemWithID:(int)arrayID {CGSize screenSize = [CCDirector sharedDirector].winSize;CCSprite *item = [dropElementsArray objectAtIndex:arrayID]; [dropElementsArray removeObjectAtIndex:arrayID]; [item stopAllActions]; [item removeFromParentAndCleanup:YES]; item = nil; item = [CCSprite spriteWithFile:[self getNextItemFileName]];#if (USE_CCSPRITEBATCHNODE == 1) item read more..

  • Page - 593

    Chapter 16 Performance Optimizations554int randomX = random() % 1024; [item setPosition:ccp(randomX,screenSize.height)];float randomDuration = CCRANDOM_0_1() * 5.0f;id moveAction = [CCMoveTo actionWithDuration:randomDurationposition:ccp(randomX,0)]; [item runAction:moveAction];}The dropWithHighPerformance method shows the correct way to reuse a CCSprite. In this case the CCSprite is just moved back to the top of the screen and the CCMove action is added to it once more. In your game you read more..

  • Page - 594

    Profiling within Cocos2D555Listing 16.6 Profiling variables in GameplayLayer.h header file // GameplayLayer.h// PerformanceTestGame//#import <Foundation/Foundation.h>#import "cocos2d.h"@interface GameplayLayer : CCLayer {CCSprite *Viking;int currentItemTag;CCArray *dropElementsArray;CCSpriteBatchNode *sceneSpriteBatchNode; #if CC_ENABLE_PROFILERS CCProfilingTimer *resetSpriteProfiler; CCProfilingTimer *updateLoopProfiler; #endif}@endAll of the profiling code you read more..

  • Page - 595

    Chapter 16 Performance Optimizations556In the GameplayLayer.m class, locate the dropWithLowPerformanceItemWithIDand dropWithHighPerformanceItemWithID methods. In the beginning of these two methods, add the lines shown in Listing 16.8. Then, at the end of both methods, add the lines shown in Listing 16.9.Listing 16.8 Profiler BeginTiming bracket in GameplayLayer.m#if CC_ENABLE_PROFILERS CCProfilingBeginTimingBlock(resetSpriteProfiler);#endifListing 16.9 Profiler EndTiming bracket in read more..

  • Page - 596

    Using Instruments to Find Performance Bottlenecks557If you click Run, you will see timing results on the Xcode console. Figure 16.3 shows the PerformanceTestGame console messages for the updateLoop and resetSpriteprofilers.Figure 16.3 Console showing output from updateLoop and resetSprite profilersYou can use the built-in Cocos2D profilers to quickly see how long sections of your game are taking to execute without having to write the timing code yourself. If you use the #if brackets shown in read more..

  • Page - 597

    Chapter 16 Performance Optimizations558It is important that you run any performance metrics on the actual iPhone, iPad, or iPod touch you are targeting. Performance measurements on your Mac are mean-ingless, as the architecture and underlying hardware are vastly different from the iOS devices. Running the Leaks instrument to catch memory leaks is useful on the iPhone simulator; for everything else, run Instruments against a build on the device.WarningWhen profiling your code, make sure you are read more..

  • Page - 598

    Using Instruments to Find Performance Bottlenecks559Figure 16.4 Time Profiler on PerformanceTestGame running at 40 fpsFigure 16.5 Time Profiler on PerformanceTestGame running at 60 fps read more..

  • Page - 599

    Chapter 16 Performance Optimizations560As you can see, by using the CCSpriteBatchNode, you are utilizing the GPU on the device much more efficiently, the CPU utilization is down, and the frames per seconds are up.OpenGL Driver InstrumentTo get a better feel for what the GPU is doing, there is an excellent OpenGL Instru-ment that can record what the utilization is on the renderer and tiler units in the GPU.The OpenGL Driver Instrument is easily available from within Instruments. To use it:1. read more..

  • Page - 600

    Using Instruments to Find Performance Bottlenecks561If PerformanceTestGame is not already running, click the Record button and cap-ture about a minute or so of the PerformanceTestGame running without CCSprite-BatchNode on your iOS device. Figure 16.7 shows what the instruments trace for the OpenGL ES Driver looks like for the iPad.Figure 16.7 OpenGL ES Instrument on PerformanceTestGame with CCSpriteBatchNode turned offYou can see Device Utilization is around 72 percent, but Renderer Utilization read more..

  • Page - 601

    Chapter 16 Performance Optimizations562Change the PerformanceTestGame to use the CCSpriteBatchNode and select Prof ile once more in Xcode under the Product menu. Xcode automatically builds the PerformanceTestProject and starts another OpenGL ES Driver Instrument cap-ture inside of the Instruments tool. Record for about a minute to see the changes. Fig-ure 16.8 shows what the OpenGL ES Driver Instrument result looks like on the iPad.Figure 16.8 OpenGL ES Instrument on PerformanceTestGame with read more..

  • Page - 602

    Challenges563If you need even more detailed data than Instruments can provide, there is another tool included with Xcode called Shark. Apple has a User’s Guide to Shark at read more..

  • Page - 603

    This page intentionally left blank read more..

  • Page - 604

    actionGoTo:21,17actionGoTo:21,ConclusionThroughout this book you have learned how to create a full game using Cocos2D, Box2D, and Chipmunk. You started out by learning the basics of the Cocos2D frame-work, and about scenes, layers, sprites, and sprite sheets. You then moved on to putting Space Viking together, getting Ole the Viking on the screen, and adding a set of joy-stick controls.From this humble beginning, you learned how to add animations and enemies to Space Viking. You dived into a read more..

  • Page - 605

    Chapter 17 Conclusion566After learning about actions and animations, you worked on building some of the non-gameplay elements, by creating the menus used in Space Viking and a live text debug system. Along the way you discovered how Cocos2D renders fonts and how to use Font texture atlases for lightning-fast text labels.Beyond the menus and labels, you moved on to CocosDenshion, the full-featured sound engine included with Cocos2D. You added a set of background music tracks to Space Viking and read more..

  • Page - 606

    Android and Beyond567actionGoTo:21,Where to Go from HereCocos2D is a 2D game engine even though the OpenGL and OpenGL ES API it relies on to render the graphics supports 3D. If you want to take your games into the third dimension, you have at least three options: using the Cocos3D extension, learning OpenGL, or using a middleware tool such as Unity3D.The Cocos3D extension allows you load and use 3D models in a special layer within Cocos2D. You can mix and match 2D and 3D objects and connect them read more..

  • Page - 607

    Chapter 17 Conclusion568bring it to Android. Many other portable game consoles, such as the Sony PlaySta-tion Portable (PSP) and Nintendo DS, have compilers for C++, so it is not too far off to think that this port could be used there. In other areas of game development, C++ is a much more common language then Objective-C. More information can be found aactionURI(www.cocos2d-x.org/):t www.cocos2d-x.org/.Cocos2D-JavaScriptIf you are interested in building web-based games, there is a port of read more..

  • Page - 608

    actionGoTo:21,AppendixactionGoTo:21,Principal Classes of CactionGoTo:21,ocos2DIn order to use Cocos2D, it is important to understand a few key classes in the Cocos2D framework. To avoid conf licts with your classes or other libraries and frame-works, all of the Cocos2D classes start with CC. When you see Director, Scene,Layer, Sprite, and other Cocos2D classes in this book, they are referred to by their class name, such as CCDirector, CCScene, CCLayer, and so forth. Knowing these classes wilsl read more..

  • Page - 609

    Appendix Principal Classes of Cocos2D570nCCDirectorTypeDisplayLinkThis director utilizes CADisplayLink to synchronize the run loop timer and drawing with the refresh of the screen. It is available only on iOS 3.1 and higher. It integrates well with UIKit objects, and the update interval can be set to 60, 30, or 15 frames per second.nCCNodeThe Cocos2D node is the main class used in Cocos2D. CCNode contains all of the necessary code to render itself using OpenGL ES. CCNode also contains the logic read more..

  • Page - 610

    actionGoTo:21,IndexSymbols and Numbers? (Ternary operator),actionGoTo:173, 134–actionGoTo:174,1353D2D vs.,actionGoTo:26, xxvextensions to Cocos2D,actionGoTo:606, 567z values inactionGoTo:72,, 33AAABB (axis-aligned bounding boxes)avoiding object overlap,actionGoTo:116, 77searching for objects in Box2D world, actionGoTo:344,305–actionGoTo:346,307Accelerometercart movement example,actionGoTo:394, 355–actionGoTo:397,358commenting out,actionGoTo:358, 319enabling support for,actionGoTo:341, read more..

  • Page - 611

    Index572Animation (CCAnimation)actions and,actionGoTo:105, 66–actionGoTo:106,67animating sprites generally,actionGoTo:96, 57–actionGoTo:99,60animating sprites rendered by CCSpriteBatchNodeactionGoTo:99,, 60–actionGoTo:100,61caching,actionGoTo:101, 62delays between frames and frame listactionGoTo:100,, 61frame rate inactionGoTo:100,, 61overview of,actionGoTo:96, 57storing animation data in plist files,actionGoTo:100, 61, actionGoTo:106,67–actionGoTo:108,69Animation, generallyadding read more..

  • Page - 612

    Index573AVAudioPlay, audio framework for iOS devices,actionGoTo:236, 197Axis-aligned bounding boxes (AABB)avoiding object overlap,actionGoTo:116, 77searching for objects in Box2D world, actionGoTo:344,305–actionGoTo:346,307BBackground color, Particle Designer controls, actionGoTo:526,487Background layeradding background music in Chipmunk, actionGoTo:512,473–actionGoTo:513,474adding in Chipmunk,actionGoTo:513, 474–actionGoTo:515,476addScrollingBackground method, actionGoTo:284,245connecting read more..

  • Page - 613

    Index574Box2D, basic physics (continued )puzzle game example,actionGoTo:359, 320–actionGoTo:363,324ramping up puzzle gameactionGoTo:363,, 324–actionGoTo:371,332units inactionGoTo:327,, 288–actionGoTo:328,289viewing PuzzleLayer,actionGoTo:335, 296–actionGoTo:337,298Box2D, intermediate physicsadding resource files,actionGoTo:373, 334–actionGoTo:374,335adding wheels to cart using revolute jointsactionGoTo:391,, 352–actionGoTo:394,355controlling f lipping of cartactionGoTo:407,, read more..

  • Page - 614

    Index575CCSequenceactionGoTo:106,, 67CCSpawnactionGoTo:106,, 67CCSprite (Sprites). See Sprites (CCSprite)CCSpriteBatchNodeanimating sprites rendered byactionGoTo:99,, 60–actionGoTo:100,61GameplayLayer class and,actionGoTo:150, 111performance benefits ofactionGoTo:294,, 255, actionGoTo:584,545–actionGoTo:589,550testing use in game layer,actionGoTo:91, 52–actionGoTo:92,53using texture atlases andactionGoTo:83,, 44–actionGoTo:84,45CCSpriteFrameactionGoTo:99,, 60CCSpriteSheet,actionGoTo:173, read more..

  • Page - 615

    Index576Collisions (continued )detecting in ChipmunkactionGoTo:484,, 445–actionGoTo:489,450Digger Robot andactionGoTo:447,, 408optimizing collision detection in Chip-munkactionGoTo:470,, 431Common protocols. See ProtocolsCompression formats,actionGoTo:82, 43Constantsaudio,actionGoTo:237, 198–actionGoTo:240,201for static values used in more than one class,actionGoTo:110, 71–actionGoTo:111,72Constraints, in Chipmunkcompared with jointsactionGoTo:459,, 420–actionGoTo:460,421creating pivot read more..

  • Page - 616

    Index577classes of game objects,actionGoTo:103, 64–actionGoTo:104,65object-orientation in,actionGoTo:102, 63overview ofactionGoTo:101,, 62–actionGoTo:102,63Devices, olderfixing slow performance,actionGoTo:92, 53–actionGoTo:93,54power-of-two support,actionGoTo:85, 46Digger robotadding dangerous methods toactionGoTo:444,, 405–actionGoTo:450,411creating cinematic fight sequence, actionGoTo:450,411–actionGoTo:455,416pitting Ole againstactionGoTo:435,, 396–actionGoTo:444,405Direction read more..

  • Page - 617

    Index578FilesAdd New File dialogactionGoTo:65,, 26adding Box2D files to project,actionGoTo:373, 334–actionGoTo:374,335adding Chipmunk files to project, actionGoTo:465,426–actionGoTo:468,429audio files,actionGoTo:237, 198,actionGoTo:253, 214–actionGoTo:254,215constants file for static values used in more than one class,actionGoTo:110, 71–actionGoTo:111,72format for fonts,actionGoTo:194, 155formats for imagesactionGoTo:82,, 43GLES-Render files,actionGoTo:334, read more..

  • Page - 618

    Index579initializing audio manager (CDAudio-Manager),actionGoTo:246, 207–actionGoTo:247,208IntroLayer class andactionGoTo:232,, 193LevelCompleteLayer class and,actionGoTo:233, 194–actionGoTo:234,195loading audio asynchronouslyactionGoTo:242,, 203–actionGoTo:243,204loading sound effectsactionGoTo:250,, 211–actionGoTo:252,213loading/unloading audio files,actionGoTo:253, 214–actionGoTo:254,215overview of,actionGoTo:209, 170–actionGoTo:211,172playbackgroundTrack, stopSound-Effect, and read more..

  • Page - 619

    Index580Header files (continued )game manager,actionGoTo:211, 172–actionGoTo:212,173GameplayLayer class,actionGoTo:144, 105–10actionGoTo:145,6healthactionGoTo:160,, 121Main Menu,actionGoTo:221, 182–actionGoTo:222,183malletactionGoTo:157,, 118Ole the VikingactionGoTo:129,, 90–actionGoTo:131,92phaseractionGoTo:177,, 138PlatformScene,actionGoTo:302, 263–actionGoTo:303,264PlatformScrollingLayer,actionGoTo:293, 254–actionGoTo:294,255radar dishactionGoTo:123,, 84space cargo read more..

  • Page - 620

    Index581Inheritance, class hierarchy and,actionGoTo:103, 64–actionGoTo:104,65init methodfor ChipmunkactionGoTo:468,, 429–actionGoTo:469,430in game layer of Space VikingactionGoTo:80,, 41–actionGoTo:81,42for HelloWorld app,actionGoTo:52, 13for PerformanceTestGame,actionGoTo:585, 546–actionGoTo:588,549of platformScrollingLayer,actionGoTo:294, 255–actionGoTo:295,256initAnimations methodMallet class,actionGoTo:159, 120RadarDish class,actionGoTo:127, 88–actionGoTo:128,89Viking read more..

  • Page - 621

    Index582KKinematic bodies, Box2D,actionGoTo:332, 293kStateDead. See Dead state (kStateDead)kStateIdle (idle state)for enemy robot,actionGoTo:171, 132for radar dishactionGoTo:126,, 87kStateSpawning (Spawning state)for enemy robot,actionGoTo:171, 132for radar dishactionGoTo:126,, 87kStateTaking Damage (Taking damage state)actionGoTo:126,, 87kStateTakingDamage. See Damage taking state (kStateTakingDamage)LLabels (CCLabel)adding to scenesactionGoTo:52,, 13–actionGoTo:53,14CCLabelIBMFont read more..

  • Page - 622

    Index583Mekanimo tool, for working with bodiesactionGoTo:419,, 380Member variables, for body part sprites, actionGoTo:419,380–actionGoTo:420,381Memorybenefits of texture atlases,actionGoTo:87, 48managing memory footprint,actionGoTo:56, 17textures and,actionGoTo:84, 45–actionGoTo:86,47Menusadding images and fonts for,actionGoTo:220, 181–actionGoTo:221,182in addition to Main Menu,actionGoTo:229, 190classes inactionGoTo:218,, 179–actionGoTo:219,180Main Menu. See Main Menu (MainMenu)Options read more..

  • Page - 623

    Index584Ole the Viking (continued )connecting button controls to,actionGoTo:284, 245creating cinematic fight sequenceactionGoTo:450,, 411–actionGoTo:455,416following in ChipmunkactionGoTo:506,, 467–actionGoTo:507,468Header files,actionGoTo:129, 90–actionGoTo:131,92leaping with ragdoll effectactionGoTo:420,, 381–actionGoTo:425,386pitting against Digger in fightactionGoTo:435,, 396–actionGoTo:444,405restoring health ofactionGoTo:141,, 102OpenAL audio framework, for iOS devices, read more..

  • Page - 624

    Index585shootPhaser method,actionGoTo:168, 129,actionGoTo:171, 132–actionGoTo:172,133taking damage from,actionGoTo:141, 102Physics EditoractionGoTo:419,, 380Physics enginesadvanced. See Box2D, advanced physicsbasic. See Box2D, basic physicsbundled with Cocos2D, actionGoTo:25,xxivChipmunk. See Chipmunkintermediate. See Box2D, intermediate physicsPin joint, constraints in ChipmunkactionGoTo:495,, 456Pivot jointconstraints in ChipmunkactionGoTo:494,, 455creating pivot platformactionGoTo:501,, read more..

  • Page - 625

    Index586Protocols (continued )in Objective-C,actionGoTo:156, 117use with enemy robot,actionGoTo:166, 127PTM (point-to-meter) ratiactionGoTo:459,o, 420–actionGoTo:460,421,actionGoTo:469, 430Puzzle game example, in Box2D,actionGoTo:359, 320–actionGoTo:363,324PuzzleLayerbox created for,actionGoTo:332, 293createBoxAtLocation method, actionGoTo:333,294–actionGoTo:334,295debug drawing,actionGoTo:334, 295–actionGoTo:335,296decorating bodies using sprites,actionGoTo:352, read more..

  • Page - 626

    Index587classes in menu systemactionGoTo:218,, 179–actionGoTo:219,180creating for Space VikingactionGoTo:71,, 32–actionGoTo:72,33creating new Chipmunk scene,actionGoTo:460, 421–actionGoTo:464,425creating new scene (PuzzleLayer), actionGoTo:321,282–actionGoTo:323,284creating second game scene,actionGoTo:275, 236–actionGoTo:281,242director running game scene,actionGoTo:73, 34–actionGoTo:74,35game manager connected to Chipmunk scene,actionGoTo:464, 425–actionGoTo:465,426game manager read more..

  • Page - 627

    Index588SpaceVikingAppDelegate,actionGoTo:231, 192–actionGoTo:232,193Spawning state (kStateSpawning)for enemy robot,actionGoTo:171, 132for radar dishactionGoTo:126,, 87Spikes, creating obstacles in Box2DactionGoTo:429,, 390–actionGoTo:433,394Spring platform, creating in Chipmunk, actionGoTo:501,462–actionGoTo:502,463Sprite Frame Cache,actionGoTo:150, 111SpriteBatchNodeactionGoTo:127,, 88Sprites (CCSprite)allocating during layer initializationactionGoTo:591,, 552animating sprites rendered read more..

  • Page - 628

    Index589texture atlas softwareactionGoTo:86,, 47trial versionactionGoTo:419,, 380Texturescaching,actionGoTo:56, 17combining into texture atlases,actionGoTo:82, 43f lushing unused,actionGoTo:591, 552loading images into RAM and,actionGoTo:82, 43performance optimization and,actionGoTo:590, 551–actionGoTo:591,552Tile maps. See also Scrollingadding to ParalaxNode,actionGoTo:311, 272–actionGoTo:314,275built-in support for,actionGoTo:25, xxivcompressed TiledMap class,actionGoTo:310, read more..

  • Page - 629

    Index590Viking class. See also Ole the Vikingadding sounds to,actionGoTo:261, 222–actionGoTo:267,228applying joystick movement to,actionGoTo:79, 40–actionGoTo:83,44changeState method for animations in, actionGoTo:134,95–actionGoTo:137,98checking to see if attacking enemy robot, actionGoTo:174,135in class hierarchy,actionGoTo:103, 64dealloc method,actionGoTo:133, 94effect of pragma mark statements in Xcode pulldown menus,actionGoTo:138, 99flipping graphic views,actionGoTo:134, read more..

  • Page - 630

    This page intentionally left blank read more..

  • Page - 631

    Register the Addison-Wesley, Exam Cram, Prentice Hall, Que, and Sams products you own to unlock great benefi ts. To begin the registration process, simply go to informit.com /register to sign in or create an account. You will then be prompted to enter the 10- or 13-digit ISBN that appears on the back cover of your product.informIT.com THE TRUSTED TECHNOLOGY LEARNING SOURCEAddison-Wesley | Cisco Press | Exam Cram IBM Press | Que | Prentice Hall | Sams SAFARI BOOKS ONLINEAbout read more..

  • Page - 632

    InformIT is a brand of Pearson and the online presence for the world’s leading technology publishers. It’s your source for reliable and qualified content and knowledge, providing access to the top brands, authors, and contributors from the tech community.informIT.comTHE TRUSTED TECHNOLOGY LEARNING SOURCELearnIT at InformITLooking for a book, eBook, or training video on a new technology? Seek-ing timely and relevant information and tutorials? Looking for expert opin-ions, advice, and tips? read more..

  • Page - 633

    Try Safari Books Online FREEGet online access to 5,000+ Books and VideosFind trusted answers, fastOnly Safari lets you search across thousands of best-selling books from the top technology publishers, including Addison-Wesley Professional, Cisco Press, O’Reilly, Prentice Hall, Que, and Sams.Master the latest tools and techniquesIn addition to gaining access to an incredible inventory of technical books, Safari’s extensive collection of video tutorials lets you learn from the leading video read more..

  • Page - 634

    Your purchase of Learning Cocos2D includes access to a free online edition for 45 days through the Safari Books Online subscription service. Nearly every Addison-Wesley Professional book is available online through Safari Books Online, along with more than 5,000 other technical books and videos from publishers such as Cisco Press, Exam Cram, IBM Press, O’Reilly, Prentice Hall, Que, and Sams. SAFARI BOOKS ONLINE allows you to search for a specifi c answer, cut and paste code, download read more..

Write Your Review