Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOS Game Development with Cocos2D

hjue
October 19, 2012

iOS Game Development with Cocos2D

Cocos2D is an extensive and popular framework for developing games for iOS devices. In this talk we'll explore iOS app development and Cocos2D, and build a game using the framework.

hjue

October 19, 2012
Tweet

More Decks by hjue

Other Decks in Programming

Transcript

  1. iOS Game Development with Cocos2D Part 1: Why Cocos2D? Part

    2: Cocos2D Basics Part 3: Let’s build a Cocos2D game Thursday, June 21, 12
  2. Meet Cocos2D for iPhone ★ Open source iOS game development

    framework ★ Developed by Ricardo Quesada, acqui-hired by Zynga (2011) ★ Stable v1.1 Based on OpenGL ES 1.1 ★ Beta v2.0 Based on OpenGL ES 2.0 ★ 3,500+ iOS games shipped Thursday, June 21, 12
  3. The Cocos2D Family Cocos2d-Android (Java) Cocos2d-X iPhone/Android (C++) Cocos2d-Mac (Obj-C)

    Cocos2d-XNA Windows Phone 7 (C#) Cocos2d-HTML5 Web (Javascript) Cocos3D (Obj-C) Thursday, June 21, 12
  4. And most importantly.. Tons of great features for games Scene

    Transitions Sprite Sheets Effects: Lense, Ripple, Wave.. Actions: Move, Rotate, Scale.. Integrated Physics Engines Sound Support Tile Map Support Text Rendering Particle Systems Parallax Scrolling Shaders (v2.0) Ribbons Thursday, June 21, 12
  5. Director & Scenes Intro Main Menu Level I Level 2

    Victory Options High Scores Loss Director ★ Game made up of “game screens” called Scenes ★ Each Scene can be considered a separate app ★ Director handles main window and executes Scenes Thursday, June 21, 12
  6. Layers ★ Each Scene contains several full screen Layers ★

    Layers contain Sprites which are the game elements ★ Layers useful for Controls, Background, Labels, Menus. Thursday, June 21, 12
  7. Nodes Nodes are anything that gets drawn or contains things

    that get drawn (= Scene, Layer, Sprite) Can: ★ Contain other Nodes ★ Schedule periodic callbacks ★ Execute Actions Thursday, June 21, 12
  8. Sprites in Action Create CCSpriteFrame* spriteFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"sprite.png"];

    CCSprite* sprite = [CCSprite spriteWithSpriteFrame:spriteFrame]; Thursday, June 21, 12
  9. Sprites in Action Add to Layer sprite.position = ccp(x, y);

    [layer addChild:sprite z:5 tag:666]; (0,0) winSize.height winSize.width (x,y) at anchor point Thursday, June 21, 12
  10. Sprites in Action Move CCMoveTo *moveToAction = [CCMoveTo actionWithDuration:duration position:newPosition];

    [sprite runAction:moveToAction]; Properties can be transformed directly or through actions Thursday, June 21, 12
  11. Sprites in Action Scale/Rotate CCScaleTo *scaleToAction = [CCScaleTo actionWithDuration:duration scale:scale];

    CCRotateBy *rotateByAction = [CCRotateBy actionWithDuration:duration angle:angle]; CCSequence *sequence = [CCSequence actions:scaleToAction, rotateByAction, nil]; [sprite runAction:sequence]; Thursday, June 21, 12
  12. Sprites in Action Animate CCAnimation* animation = [[CCAnimationCache sharedAnimationCache] animationByName:@"animation"];

    CCAnimate* animateAction = [CCAnimate actionWithAnimation:animation]; [sprite runAction:animateAction]; Thursday, June 21, 12
  13. Actions Can be performed on Sprites or any Node Basic

    Move, Scale, Rotate, Bezier, Hide, Fade, Tint.. Composition Sequence, Repeat, Spawn, RepeatForever.. Ease Ease, EaseExponential, EaseBounce.. Effects Lens, Liquid, Ripple, Shaky, Twirl, Waves.. Special CallFunc, Follow.. Thursday, June 21, 12
  14. Spritesheets ★ Added as a child to the layer ★

    Created with TexturePacker or Zwoptex ★ Memory considerations, 16bit images, .pvr.ccz Thursday, June 21, 12
  15. Controls ★ Implement directly based on CCStandardTouchDelegate ★ Can use

    UIGestureRecognizer classes ★ Open source implementations of joypad/buttons available - (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; - (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; - (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; - (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; Thursday, June 21, 12
  16. Let’s Make a Game! ..but first we need a story,

    graphics, music and sfx :) Part 3: Thursday, June 21, 12
  17. Music & SFX Explosive Attack by McTricky @ Sakari Infinity

    http://www.sakari-infinity.net/author/McTricky Background music, shoot sound, death sound Thursday, June 21, 12
  18. Music & SFX Explosive Attack by McTricky @ Sakari Infinity

    http://www.sakari-infinity.net/author/McTricky Background music, shoot sound, death sound Thursday, June 21, 12
  19. Steps for making Para-Shoot Application Setup Step 1: Adding Background

    Step 2: Adding Our Hero Step 3: Adding Bad Guys (Game Logic) Step 4: Killing Bad Guys (Adding UI) Step 5: Check for Bad Guy Death Step 6: Animating Our Hero Step 7: Animating Bad Guys Dying Step 8: Adding Body Count Step 9: Adding Sound & Music Thursday, June 21, 12
  20. @interface HelloWorldLayer : CCLayer { ! // Player sprite !

    CCSprite *_player; // Target and bullet sprite arrays ! NSMutableArray *_targets; NSMutableArray *_bullets; ! // Body count counter and isShooting flag int _bodyCount; BOOL _isShooting; ! ! // For body count label ! CCLabelTTF *_labelTitle; ! CCLabelTTF *_labelCount; } HelloWorldScene.h Thursday, June 21, 12
  21. HelloWorldScene.m // Create the new scene including this layer +(id)

    scene { ! // Create the scene ! CCScene *scene = [CCScene node]; ! ! // Create the layer ! HelloWorldLayer *layer = [HelloWorldLayer node]; ! ! // add layer as a child to scene ! [scene addChild: layer]; ! ! // return the scene ! return scene; } Thursday, June 21, 12
  22. Step 1: Adding Background (In init) // Get the window

    size to place elements CGSize winSize = [[CCDirector sharedDirector] winSize]; // Add the background image CCSprite *background = [CCSprite spriteWithFile:@"background.png"]; background.position = ccp(winSize.width/2, winSize.height/2); [self addChild:background z:0]; Thursday, June 21, 12
  23. Step 2: Adding Our Hero (In init) // Load the

    sprite sheet CCSpriteBatchNode *batchNode = [CCSpriteBatchNode batchNodeWithFile:@"parashoot.pvr.ccz"]; [self addChild:batchNode]; // Load the sprites into the shareSpriteFrameCache [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"parashoot.plist"]; Preload the spritesheet Thursday, June 21, 12
  24. Step 2: Adding Our Hero // Add the player sprite

    CCSpriteFrame* playerFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"player_01.png"]; _player = [CCSprite spriteWithSpriteFrame:playerFrame]; _player.position = ccp(_player.contentSize.width/2 + 10, winSize.height/2); [self addChild:_player z:1]; Add the hero sprite Thursday, June 21, 12
  25. Step 3: Adding Bad Guys (Game Logic) (in init) [self

    schedule:@selector(addTarget:) interval:1.0f]; Schedule a new target every second Thursday, June 21, 12
  26. // Create a new enemy -(void)addTarget:(ccTime)dt { // Create the

    target sprite CCSpriteFrame *targetFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"target.png"]; ! CCSprite *target = [CCSprite spriteWithSpriteFrame:targetFrame]; // Add the target to the layer and the array ! [self addChild:target]; ! [_targets addObject:target]; Step 3: Adding Bad Guys (Game Logic) Create a sprite for the target Thursday, June 21, 12
  27. Step 3: Adding Bad Guys (Game Logic) ! // Determine

    where to spawn the target along the X axis ! CGSize winSize = [[CCDirector sharedDirector] winSize]; // Find a random X for the target in the right half of the screen ! int minX = winSize.width/2; ! int maxX = winSize.width - target.contentSize.width; ! int rangeX = maxX - minX; ! int actualX = (arc4random() % rangeX) + minX; target.position = ccp(actualX, 320); target.anchorPoint = ccp(0, 0); ! // Determine speed of the target ! int minDuration = 2.0; ! int maxDuration = 4.0; ! int rangeDuration = maxDuration - minDuration; ! int actualDuration = (arc4random() % rangeDuration) + minDuration; Generate a random x position for the target Thursday, June 21, 12
  28. Step 3: Adding Bad Guys (Game Logic) // Create and

    run the actions CCMoveTo* moveTarget = [CCMoveTo actionWithDuration:actualDuration ! ! ! position:ccp(actualX, -target.contentSize.height/2)]; CCCallFuncN* actionForTargetMoveDidFinish = [CCCallFuncN actionWithTarget:self selector:@selector(targetMoveFinished:)]; [target runAction:[CCSequence actions:moveTarget, actionForTargetMoveDidFinish, nil]]; Create a move action for the target with a callback when reaching the bottom Thursday, June 21, 12
  29. Step 3: Adding Bad Guys (Game Logic) // Method for

    removing a target that has died or reached the bottom -(void)targetMoveFinished:(id)sender { ! CCSprite *target = (CCSprite *)sender; [self removeChild:target cleanup:YES]; ! [_targets removeObject:target]; } Add the callback method for a target that dies or reaches the bottom Thursday, June 21, 12
  30. Step 4: Killing Bad Guys (Adding UI) - (void)ccTouchesEnded:(NSSet *)touches

    withEvent:(UIEvent *)event { ! // Choose one of the touches to work with ! UITouch *touch = [touches anyObject]; ! CGPoint location = [touch locationInView:[touch view]]; ! location = [[CCDirector sharedDirector] convertToGL:location]; ! if (!_isShooting) { _isShooting = YES; Detect the touch Thursday, June 21, 12
  31. Step 4: Killing Bad Guys (Adding UI) // Create the

    bullet CCSpriteFrame* bulletFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"bullet.png"]; CCSprite* bulletSprite = [CCSprite spriteWithSpriteFrame:bulletFrame]; bulletSprite.position = _player.position; // Bullet actions CCCallFuncN* actionForRemoveBullet = [CCCallFuncN actionWithTarget:self selector:@selector(removeBullet:)]; CCMoveBy* bulletMoveBy = [CCMoveBy actionWithDuration:1.0f position:ccp(winSize.width, 0)]; [bulletSprite runAction:[CCSequence actionOne:bulletMoveBy two:actionForRemoveBullet]]; // Add bullet to layer and array [self addChild:bulletSprite]; [_bullets addObject:bulletSprite]; Create the bullet Thursday, June 21, 12
  32. Step 5: Check for Bad Guy Death -(void)update:(ccTime)dt { CCSprite*

    bulletToRemove = nil; for (CCSprite *bullet in _bullets) { for (CCSprite* target in _targets) { CGRect targetBox = CGRectMake(target.position.x, target.position.y, [target boundingBox].size.width, [target boundingBox].size.height); // Check if bullet is in the target's bounding box if (CGRectContainsPoint(targetBox, bullet.position)) { // Animate target death and remove target bulletToRemove = bullet; } } } // Remove bullet if target was hit if (bulletToRemove != nil) { [self removeChild:bulletToRemove cleanup:YES]; [_bullets removeObject:bulletToRemove]; } } Thursday, June 21, 12
  33. Step 6: Animating Our Hero (In init) // Load the

    animation for player NSMutableArray *animFrames1 = [NSMutableArray array]; for (int i = 1; i < 12; i++) { CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:@"player_%02d.png",i]]; ! [animFrames1 addObject:frame]; } [[CCAnimationCache sharedAnimationCache] addAnimation:[CCAnimation animationWithFrames:animFrames1 delay:FRAME_DELAY] name:@"player"];! Preload the animation from the spritesheet Thursday, June 21, 12
  34. Step 6: Animating Our Hero (In ccTouchesEnded) // Actions for

    shooting animation CCCallFunc* actionForShootDidEnd = [CCCallFunc actionWithTarget:self selector:@selector(shootDidEnd)]; CCAnimation* playerShootAnimation = [[CCAnimationCache sharedAnimationCache] animationByName:@"player"]; CCAnimate* shootAnimate = [CCAnimate actionWithAnimation:playerShootAnimation]; [_player runAction:[CCSequence actionOne:shootAnimate two:actionForShootDidEnd]]; Animate the hero when shooting Thursday, June 21, 12
  35. Step 7: Animating Bad Guys Dying (in update) // Set

    up actions for animation and target removal CCCallFuncN* actionForDeathDidFinish = [CCCallFuncN actionWithTarget:self selector:@selector(targetMoveFinished:)]; CCAnimate* deathAnimation = [CCAnimate actionWithAnimation:[[CCAnimationCache sharedAnimationCache] animationByName:@"death"] restoreOriginalFrame:NO]; [target runAction:[CCSequence actionOne:deathAnimation two:actionForDeathDidFinish]]; Thursday, June 21, 12
  36. Step 8: Adding Body Count (In init) NSString* bodyCountString =

    [NSString stringWithFormat:@"%d", _bodyCount]; _labelCount = [CCLabelTTF labelWithString:bodyCountString fontName:@"Arial" fontSize:16]; _labelCount.color = ccc3(0,0,0); _labelCount.position = ccp(110, winSize.height - 16); [self addChild:_labelCount z:2]; (In ccTouchesEnded) _bodyCount++; NSString* bodyCountString = [NSString stringWithFormat:@"%d", _bodyCount];! [_labelCount setString:bodyCountString]; Thursday, June 21, 12
  37. Step 9: Adding Sound & Music (In init) ! //

    Start background music, set lower volume ! SimpleAudioEngine.sharedEngine.backgroundMusicVolume = 0.4f; ! [[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"explosive_attack.mp3"]; (In ccTouchesEnded) ! // Play sound effect on every shot and on death ! [[SimpleAudioEngine sharedEngine] playEffect:@"shot.wav"]; ! [[SimpleAudioEngine sharedEngine] playEffect:@"death.wav"]; Thursday, June 21, 12
  38. Para-Shoot 2.0 Enemies can move and attack Joypad + HUD

    Move our hero Different weapons, power ups and health Game menu and high scores Levels Save/Load Game Refactor code (More scenes and layers) Thursday, June 21, 12
  39. Refactoring Para-Shoot Intro Main Menu Level X Victory Options High

    Score Loss Level X Background Player Bad Guys Joypad/HUD Scenes: Layers: Thursday, June 21, 12
  40. More stuff to explore ★ Physics Engines - Chipmunk and

    Box2D ★ Particle System ★ Tilemaps ★ Menu Interface Thursday, June 21, 12
  41. Where can you learn more Cocos2D Demo Library (Comes with

    Cocos) Wiki: http://cocos2d-iphone.org/wiki Ray Wenderlich: http://www.raywenderlich.com Steffen Itterheim: http://learn-cocos2d.com Sapus Tongue Source Code: http://www.sapusmedia.com/sources Thursday, June 21, 12