game development with cocos2d
TRANSCRIPT
iOS Game Developmentwith Cocos2D
Part 1: Why Cocos2D?
Part 2: Cocos2D Basics
Part 3: Let’s build a Cocos2D game
Part 1:Why Cocos2D?
Anatomy of a simple gameCPU & GPU
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
The Cocos2D Family
Cocos3D
(Obj-C)
Cocos2d-Android
(Java)
Cocos2d-Mac
Cocos2d-XNA
Windows Phone 7 (C#)
Cocos2d-X
iPhone/Android (C++)
(Obj-C)
Cocos2d-HTML5
Web (Javascript)
Proven Success
Great Effort-Flexibility Balance
Direct OpenGL/
100
Unity/Corona
0
CoreGraphics
Cocos2D/Sparrow
Flexibility
Cross Device, Cross Resolution
Active Ecosystem
And most importantly..
Tons of great features for games
Sprite Sheets
Effects:
Lense, Ripple, Wave..
Particle Systems
Ribbons
Scene Transitions
Tile Map Support
Integrated Physics Engines
Shaders (v2.0)
Parallax Scrolling
Actions:
Move, Rotate, Scale..
Text Rendering
Sound Support
Part 2:Cocos2D Basics
Basic Cocos2D Concepts
DirectorClass that creates and handle the main Windowand manages how and when to execute the Scenes.
Basic Cocos2D Concepts
Director
Scenes
Creates and handle the main Windowand manages how and when to execute the Scenes.
A scene (implemented with the CCScene object) is moreor less an independent piece of the app workflow. .
Basic Cocos2D Concepts
Director
Scenes
Layers
Creates and handle the main Windowand manages how and when to execute the Scenes.
A scene (implemented with the CCScene object) is moreor less an independent piece of the app workflow. .
A CCLayer has a size of the whole drawablearea, and knows how to draw itself.
Basic Cocos2D Concepts
Director
Scenes
Layers
Sprites
A layer has a size of the whole drawablearea, and knows how to draw itself.
Creates and handle the main Windowand manages how and when to execute the Scenes.
A scene (implemented with the CCScene object) is moreor less an independent piece of the app workflow. .
It is a 2D image that can be moved, rotated, scaled, animated, etc.
Director & Scenes
Director Loss
Intro Main Menu Level I Level 2 Victory
Options
High Scores
Game made up of “game screens” called Scenes
Each Scene can be considered a separate app
Director handles main window and executes Scenes
Layers
Each Scene contains several full screen Layers
Layers contain Sprites which are the game elements
Layers useful for Controls, Background, Labels, Menus.
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
Sprites in Action
Create
CCSpriteFrame* spriteFrame = [[CCSpriteFrameCachesharedSpriteFrameCache]
spriteFrameByName:@"sprite.png”];
CCSprite* sprite = [CCSpritespriteWithSpriteFrame:spriteFrame];
Sprites in ActionwinSize.height
Add to Layer
(x,y) at anchor point
winSize.width(0,0)
sprite.position = ccp(x, y);
[layer addChild:sprite z:5 tag:666];
Sprites in Action
Move
CCMoveTo *moveToAction = [CCMoveToactionWithDuration:duration
position:newPosition];
[sprite runAction:moveToAction];
Properties can be transformed directly or through actions
Sprites in Action
Scale/Rotate
CCScaleTo *scaleToAction = [CCScaleToactionWithDuration:durationscale:scale];
CCRotateBy *rotateByAction = [CCRotateByactionWithDuration:durationangle:angle];
CCSequence *sequence = [CCSequenceactions:scaleToAction, rotateByAction, nil];
[sprite runAction:sequence];
Sprites in Action
Animate
CCAnimation* animation = [[CCAnimationCachesharedAnimationCache]
animationByName:@"animation"];
CCAnimate* animateAction = [CCAnimateactionWithAnimation:animation];
[sprite runAction:animateAction];
Sprites in Action
Schedule Updates
[scene schedule:@selector(updateSprite:) interval:interval];
ActionsCan 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..
Spritesheets
Added as a child to the layer
Created with TexturePacker or Zwoptex
Memory considerations, 16bit images, .pvr.ccz
Controls
- (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;
Implement directly based on CCStandardTouchDelegate
Can use UIGestureRecognizer classes
Open source implementations of joypad/buttons available
Part 3:
Let’s Make a Game!
Part 3:
Let’s Make a Game!..but first we need a story, graphics, music and sfx :)
KillTime
Because he likes to kill paratroopers
Graphics
http://www.freewebs.com/teh_pro/sprites.htm
Music & SFX
Background music, shoot sound, death sound
Steps for making KillTimeApplication 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
New Cocos2D Project
HelloWorldScene.h
@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.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;
}
Hello World
Step 1: Adding Background
(In init)
// Get the window size to place elements
CGSizewinSize = [[CCDirectorsharedDirector] winSize];
// Add the background imageCCSprite *background = [CCSpritespriteWithFile:@"background.png"];
background.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:background z:0];
self.isTouchEnabled = YES; _bullets = [[NSMutableArrayalloc]init];
_targets = [[NSMutableArrayalloc]init];
Step 1: Adding Background
Step 2: Adding Our HeroPreload the spritesheet
(In init)
// Load the sprite sheet
CCSpriteBatchNode *batchNode = [CCSpriteBatchNode
batchNodeWithFile:@”spritesheet.pvr.ccz"];
[self addChild:batchNode];
// Load the sprites into the shareSpriteFrameCache
[[CCSpriteFrameCachesharedSpriteFrameCache]
addSpriteFramesWithFile:@”spritesheet.plist"];
Step 2: Adding Our HeroAdd the hero sprite
// Add the player sprite
CCSpriteFrame* playerFrame = [[CCSpriteFrameCachesharedSpriteFrameCache]
spriteFrameByName:@"player1.png"];
_player = [CCSpritespriteWithSpriteFrame:playerFrame];
_player.position = ccp(_player.contentSize.width/2 + 10, winSize.height/2);
[self addChild:_player z:1];
Step 2: Adding Our Hero
Step 3: Adding Bad Guys (Game Logic)Schedule a new target every second
(in init)
[self schedule:@selector(addTarget:) interval:1.0f];
Step 3: Adding Bad Guys (Game Logic)Create a sprite for the target
// Create a new enemy
-(void)addTarget:(ccTime)dt {
// Create the target sprite
CCSpriteFrame *targetFrame = [[CCSpriteFrameCachesharedSpriteFrameCache]
spriteFrameByName:@"target.png”];
CCSprite *target = [CCSpritespriteWithSpriteFrame:targetFrame];
// Add the target to the layer and the array
! [self addChild:target];
! [_targets addObject:target];}
Step 3: Adding Bad Guys (Game Logic)Generate a random x position for the target
// Determine where to spawn the target along the X axis
CGSizewinSize = [[CCDirectorsharedDirector] winSize];
// Find a random X for the target in the right half of the screen
intminX = winSize.width/2;
intmaxX = winSize.width - target.contentSize.width;
intrangeX = maxX - minX;
intactualX = (arc4random() % rangeX) + minX;
target. position = ccp (actualX, 320 );
target.anchorPoint = ccp(0, 0);
// Determine speed of the target
intminDuration = 2.0;
intmaxDuration = 4.0;
intrangeDuration = maxDuration - minDuration;
intactualDuration = (arc4random() % rangeDuration) + minDuration;
Step 3: Adding Bad Guys (Game Logic)Create a move action for the target with a
callback when reaching the bottom
// Create and run the actions
CCMoveTo* moveTarget = [CCMoveToactionWithDuration:actualDuration
Position:ccp(actualX,-target.contentSize.height/2)];
CCCallFuncN* actionForTargetMoveDidFinish = [CCCallFuncN
actionWithTarget:selfselector:@selector(targetMoveFinished:)];
[target runAction:[CCSequenceactions:moveTarget, actionForTargetMoveDidFinish, nil]];
Step 3: Adding Bad Guys (Game Logic)Add the callback method for a target that
dies or reaches the bottom
// 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];
}
Step 3: Adding Bad Guys (Game Logic)
Step 4: Killing Bad Guys (Adding UI)Detect the touch
- (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 = [[CCDirectorsharedDirector] convertToGL:location];
if (!_isShooting) {
_isShooting = YES;
Step 4: Killing Bad Guys (Adding UI)Create the bullet
// Create the bullet
CCSpriteFrame* bulletFrame = [[CCSpriteFrameCachesharedSpriteFrameCache]
spriteFrameByName: @"bullet.png" ];
CCSprite* bulletSprite = [CCSpritespriteWithSpriteFrame:bulletFrame];
bulletSprite.position = _player.position;
// Bullet actions
CCCallFuncN* actionForRemoveBullet = [CCCallFuncNactionWithTarget:self
selector:@selector(removeBullet:)];
CCMoveBy* bulletMoveBy = [CCMoveBy actionWithDuration:1.0f
position:ccp(winSize.width, 0)];
[bulletSpriterunAction:[CCSequenceactionOne:bulletMoveBy
two:actionForRemoveBullet]];
// Add bullet to layer and array
[self addChild:bulletSprite];
[_bullets addObject:bulletSprite];
_isShooting = NO;
Step 4: Killing Bad Guys (Adding UI)
Step 5: Check for Bad Guy Death
-(void)update:(ccTime)dt {
CCSprite* bulletToRemove = nil;
for (CCSprite *bullet in _bullets) {
for (CCSprite* target in _targets) {
CGRecttargetBox = 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:bulletToRemovecleanup:YES];
[ _bullets removeObject :bulletToRemove];
}
}
Step 5: Check for Bad Guy Death
Step 6: Animating Our HeroPreload the animation from the spritesheet
(In init)
// Load the animation for player
NSMutableArray *animFrames1 = [NSMutableArray array];
for (inti = 1; i< 11; i++) {
CCSpriteFrame *frame = [[CCSpriteFrameCachesharedSpriteFrameCache] spriteFrameByName:
[NSStringstringWithFormat:@"player%d.png”,i]];
[animFrames1 addObject:frame];
}
[[CCAnimationCachesharedAnimationCache] addAnimation:[CCAnimation
animationWithFrames:animFrames1 delay:FRAME_DELAY] name:@"player"];!
Adding Player animation in init
Step 6: Animating Our HeroPreload the animation from the spritesheet
(In init)
//// Load the animation for villain kill
NSMutableArray *animFrames2 = [NSMutableArray array];
for (inti = 1; i< 8; i++) {
CCSpriteFrame *frame2 = [[CCSpriteFrameCachesharedSpriteFrameCache] spriteFrameByName:
[NSStringstringWithFormat:@"kill%d.png",i]];
[animFrames2 addObject:frame2];
}
[[CCAnimationCachesharedAnimationCache] addAnimation:[CCAnimation
animationWithFrames:animFrames2 delay:FRAME_DELAY*5] name:@"kill"];
Adding Kill animation in init
Step 6: Animating Our HeroAnimate the hero when shooting
(In ccTouchesEnded)
// Actions for shooting animation
CCCallFunc* actionForShootDidEnd = [CCCallFuncactionWithTarget:self
selector:@selector(shootDidEnd)];
CCAnimation* playerShootAnimation = [[CCAnimationCachesharedAnimationCache]
animationByName:@"player"];
CCAnimate* shootAnimate = [CCAnimateactionWithAnimation:playerShootAnimation];
[_player runAction:[CCSequenceactionOne:shootAnimatetwo:actionForShootDidEnd]];
Step 6: Animating Our Hero
Step 7: Animating Bad Guys Dying
(in update)
// Set up actions for animation and target removal
CCCallFuncN* actionForDeathDidFinish = [CCCallFuncNactionWithTarget:self
selector:@selector(targetMoveFinished:)];
CCAnimate* deathAnimation = [CCAnimateactionWithAnimation:[[CCAnimationCache
sharedAnimationCache] animationByName:@”kill"] restoreOriginalFrame:NO];
[target runAction:[CCSequenceactionOne:deathAnimationtwo:actionForDeathDidFinish]];
Step 7: Animating Bad Guys Dying
Step 8: Adding Body Count
(In init)
NSString* bodyCountString = [NSStringstringWithFormat:@"%d", _bodyCount];
_labelCount = [CCLabelTTFlabelWithString:bodyCountStringfontName:@"Arial"
fontSize : 16 ];
_labelCount.color = ccc3(0,0,0);
_labelCount.position = ccp(110, winSize.height - 16);
[self addChild:_labelCount z:2];
(In update:)
_bodyCount++;
NSString* bodyCountString = [NSStringstringWithFormat:@"%d", _bodyCount];![_labelCountsetString:bodyCountString];
Step 8: Adding Body Count
Step 9: Adding Sound & Music
(In init)
! // Start background music, set lower volume
SimpleAudioEngine.sharedEngine.backgroundMusicVolume = 0.4f;
! [[SimpleAudioEnginesharedEngine] playBackgroundMusic:@"explosive_attack.mp3"];
(In ccTouchesEnded)
!// Play sound effect on every shot and on death
!
[[SimpleAudioEnginesharedEngine] playEffect:@"shot.mp3"];
! [[SimpleAudioEnginesharedEngine] playEffect:@"death.mp3"];
(In update: where the target is killed)
Let’s Play!
KillTime 2.0
Enemies can move and attack
Joypad
Move our hero
Different weapons, power ups and health
Game menu and high scores
Levels
Save/Load Game
Refactor code (More scenes and layers)
More stuff to explore
Physics Engines - Chipmunk and Box2D
Particle System
Tilemaps
Menu Interface
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
Thank You!SAALIS UMER