58
iOS DevCamp Produced by CSDN Website: http://devcamp.csdn.net Weibo: http://weibo.com/cmdnclub Thursday, August 2, 12

在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Embed Size (px)

DESCRIPTION

游戏引擎移植者现身讲解:《在iOS平台上用Cocos2D做开发》 | iOS独立开发者 秦春林 | iOS DevCamp 议题简介:Cocos2d是iOS平台上著名的游戏引擎,它开源,结构简单清晰,功能强大,是个人或者中小型团队开发的首选方案。本议题将以引擎移植者的身份清晰的讲解Cocos2D的结构,除此之外,还会分享App开发中的实际问题,例如灵活使用层,管理好触摸,整合使用Box2d物理引擎,Cocos2D与UIKit的整合等等开发中遇到的常见问题。 讲师简介:秦春林:独立开发者,曾就职于K2,金和,从事企业方面的开发,之后加入北京友录,OpenXLive从事Windows phone产品开发。2011年参与Cocos2d-x到Windows phone平台的移植,贡献了大部分核心功能,对Coco2D游戏引擎有深刻的了解,现从事iOS开发。热爱开源,喜欢交流。

Citation preview

Page 1: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

iOS DevCampProduced by CSDN

Website: http://devcamp.csdn.netWeibo: http://weibo.com/cmdnclub

Thursday, August 2, 12

Page 2: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

怎样灵活使用Cocos2D

秦春林

Thursday, August 2, 12

Page 3: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Don’t reinvent the wheel

Thursday, August 2, 12

Page 4: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

“In the summer of 2008, several "pythoneros" went to a camp program called PyCamp: Python outdoors. This campheld in Cordoba, in the town of Los Cocos. We were about50 people. It covered different topics, one of which was seeking way of not having to "reinvent the wheel" in each jurisdiction Pyweek.In this way a group of friends and I decided to put together a framework to make games. We call cocos2d, since the framework is designed to make 2D games, and the word "coconut" emulates the place where the camp took place.”

Ricardo Quesada

Thursday, August 2, 12

Page 5: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

4,000+ games

Thursday, August 2, 12

Page 6: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

It is Simple

Why Cocos2d?

It is free!

Without having to learn OpenGL ES to getstarted

Active community & tests

Lots of tools

Thursday, August 2, 12

Page 7: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

How simple?

Thursday, August 2, 12

Page 8: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

layer: GameLayer

scene: GameScene

Action: CCMoveTo

UIView:EAGLView

sprite: player

Thursday, August 2, 12

Page 9: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Cocos2d Basics

Game has Scenes

Each Scene has some number of Layers

Layers capture user interaction and contain sprites

Director manages the scenes

Thursday, August 2, 12

Page 10: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Anything thats gets drawn or contains things that get drawn is a CCNode

Thursday, August 2, 12

Page 11: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCSprite

CCParticleSystem

CCMenuItem

CCMenuItemLabel

CCSpriteBatchNode

CCScene

CCLayer

CCNode

CCMenu

CCMenuItemSprite

CCMenuItemToggle

CCTransitionScene

CCLabelTTF

CCTMXLayer

CCLabelBMFont

Thursday, August 2, 12

Page 12: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Just like UIView

Thursday, August 2, 12

Page 13: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

They can contain other CCNode nodes (addChild, getChildByTag, removeChild, etc)

They can schedule periodic callback (schedule, unschedule, etc)

They can execute actions (runAction, stopAction, etc)

main features

Thursday, August 2, 12

Page 14: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Features of CCNode:

- position - scale (x, y) - rotation (in degrees, clockwise) - CCCamera (an interface to gluLookAt ) - CCGridBase (to do mesh transformations) - anchor point - size - visible - z-order - openGL z position

Thursday, August 2, 12

Page 15: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

- (CGAffineTransform)nodeToParentTransform;- (CGAffineTransform)parentToNodeTransform;

- (CGAffineTransform)nodeToWorldTransform;- (CGAffineTransform)worldToNodeTransform;

- (CGPoint)convertToNodeSpace:(CGPoint)worldPoint;- (CGPoint)convertToWorldSpace:(CGPoint)nodePoint;

- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch;

transformation

Thursday, August 2, 12

Page 16: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCScene

GamePlaySceneCCLayer

Background

CCLayer

GamePlay

Thursday, August 2, 12

Page 17: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCLayer is a subclass of CCNode that implements:

- UIAccelerometerDelegate- CCStandardTouchDelegate- CCTargetedTouchDelegate

Thursday, August 2, 12

Page 18: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Thursday, August 2, 12

Page 19: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

targetedHandlersCount>o

foreach...in handlers

ccTouchBegan

ccTouchMove/End

swallowsTouches

remove from mutableTouches

standardHandlersCount>o

foreach...in mutablesTouches

NO

YES

NO

YES

NO

YES

ccTouchesBegan/Move/End

End

(NSSet*)touches

foreach...in touches

YES

NO

Thursday, August 2, 12

Page 20: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

! //! // process the target handlers 1st! //! if( targetedHandlersCount > 0 ) {! ! for( UITouch *touch in touches ) {! ! ! for(CCTargetedTouchHandler *handler in targetedHandlers) {

! ! ! ! BOOL claimed = NO;! ! ! ! if( idx == kCCTouchBegan ) {! ! ! ! ! claimed = [handler.delegate ccTouchBegan:touch withEvent:event];! ! ! ! ! if( claimed )! ! ! ! ! ! [handler.claimedTouches addObject:touch];! ! ! ! }

! ! ! ! // else (moved, ended, cancelled)! ! ! ! else if( [handler.claimedTouches containsObject:touch] ) {! ! ! ! ! claimed = YES;! ! ! ! ! if( handler.enabledSelectors & helper.type )! ! ! ! ! ! [handler.delegate performSelector:helper.touchSel withObject:touch withObject:event];

! ! ! ! ! if( helper.type & (kCCTouchSelectorCancelledBit | kCCTouchSelectorEndedBit) )! ! ! ! ! ! [handler.claimedTouches removeObject:touch];! ! ! ! }

! ! ! ! if( claimed && handler.swallowsTouches ) {! ! ! ! ! if( needsMutableSet )! ! ! ! ! ! [mutableTouches removeObject:touch];! ! ! ! ! break;! ! ! ! }! ! ! }! ! }! }

Thursday, August 2, 12

Page 21: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Targeted Touch Delegate

ccTouchBegan be invoked separately for each of the available touches

The ccTouchBegan method return YES to indicate a touch you care about

You must register as a targeted touch delegate

The swallowsTouches property return YES to indicate only this layer handle the touch

Thursday, August 2, 12

Page 22: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

A sample:How dose CCMenu work?

Thursday, August 2, 12

Page 23: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{ ......! selectedItem_ = [self itemForTouch:touch];! [selectedItem_ selected];

! if( selectedItem_ ) {! ! state_ = kCCMenuStateTrackingTouch;! ! return YES;! }! return NO;}

-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{! [selectedItem_ unselected];! [selectedItem_ activate];}

-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event{! CCMenuItem *currentItem = [self itemForTouch:touch];

! if (currentItem != selectedItem_) {! ! [selectedItem_ unselected];! ! selectedItem_ = currentItem;! ! [selectedItem_ selected];! }}

CCMenu : CCLayerThursday, August 2, 12

Page 24: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Which item is clicked?

Thursday, August 2, 12

Page 25: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

-(CCMenuItem *) itemForTouch: (UITouch *) touch{! CGPoint touchLocation = [touch locationInView: [touch view]];! touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];

! CCMenuItem* item;! CCARRAY_FOREACH(children_, item){! ! // ignore invisible and disabled items: issue #779, #866! ! if ( [item visible] && [item isEnabled] ) {

! ! ! CGPoint local = [item convertToNodeSpace:touchLocation];! ! ! CGRect r = [item rect];! ! ! r.origin = CGPointZero;

! ! ! if( CGRectContainsPoint( r, local ) )! ! ! ! return item;! ! }! }! return nil;}

You will like this methodThursday, August 2, 12

Page 26: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

GameLayer

Which Layer handle touch events?

Priority = 0

Priority = 2

Priority = 1

Thursday, August 2, 12

Page 27: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Return YES to claim the touch.-(BOOL)ccTouchBegan

! //* priority used by the menu for the event handler! kCCMenuHandlerPriority = -128,

Thursday, August 2, 12

Page 28: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Thursday, August 2, 12

Page 29: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCSprite is a 2d image

Thursday, August 2, 12

Page 30: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

+(id) spriteWithTexture:(CCTexture2D*)texture;

+(id) spriteWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;

+(id) spriteWithSpriteFrame:(CCSpriteFrame*)spriteFrame;

+(id) spriteWithSpriteFrameName:(NSString*)spriteFrameName;

+(id) spriteWithFile:(NSString*)filename;

+(id) spriteWithFile:(NSString*)filename rect:(CGRect)rect;

+(id) spriteWithCGImage: (CGImageRef)image key:(NSString*)key;

Thursday, August 2, 12

Page 31: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCSprite CCSpriteFrame CCSpriteFrameCache

frame

CCTexture

0

32

1

(setDisplayFrame)

Thursday, August 2, 12

Page 32: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCSpriteSheetThursday, August 2, 12

Page 33: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCSpriteBatchNode

All CCSprites added to a CCSpriteBatchNode are drawn in one OpenGL ES draw call.

CCTMXLayer

CCLabelBMFont

Thursday, August 2, 12

Page 34: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCDirector

CCScene

LevelCompletedScene

CCScene

GamePlayScene

CCLayer

CCLayer

CCLayer

CCLayer

CCLayer

CCLayer

startScene

GameOlayScene

CompleteScene

.....

.....

Thursday, August 2, 12

Page 35: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

-(CGSize) winSize;

-(CGPoint) convertToGL: (CGPoint) p;-(CGPoint) convertToUI:(CGPoint)p;

-(void) runWithScene:(CCScene*) scene;

-(void) pushScene:(CCScene*) scene;-(void) popScene;

-(void) popToRootScene;

-(void) replaceScene: (CCScene*) scene;

-(void) pause;-(void) resume; CCDirector

200

200

220

200

100

Thursday, August 2, 12

Page 36: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

How does CCAction work?

Thursday, August 2, 12

Page 37: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

@property (nonatomic,readonly,assign) id target;

+(id) action;

-(BOOL) isDone;

-(void) startWithTarget:(id)target;

-(void) stop;

-(void) step: (ccTime) dt;

-(void) update: (ccTime) time;

Thursday, August 2, 12

Page 38: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCNode CCAction

+(id)actionWithDuration:(ccTime)d

-(CCAction*)runAction:(CCAction*)action

-(void) update: (ccTime) t

[target_ setPosition: ccp(

-(void) stopAction: (CCAction*) action;

CCActionManager

addAction:action target:self

-(void) update: (ccTime) dt

#pragma mark CCNode - Init & cleanup-(id) init{ if ((self=[super init]) ) { self.actionManager = [director actionManager]; } return self;}

Thursday, August 2, 12

Page 39: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Simple,but powerful

Thursday, August 2, 12

Page 40: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Position/rotation/scale/visible/z-order/opacity/flip/color

CCActionInterval && CCActionInstant

CCSequence && CCSpawn && CCRepeat

CCDelayTime

CCAnimate

CCCallFun && CCPropertyAction

Camera

CCActionEase

CCActionProgressTimer

effect && 3D Action

Thursday, August 2, 12

Page 41: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Thursday, August 2, 12

Page 42: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

COCOS2D+BOX2D

Box2D is C++

2D rigid physics simulation engine with continuous collision detection

All you files thats touch C++ or include it must be Objective-C++(.mm)

Tuned for 1 meter sized objects

Box2D v2.2.0 User Manual

Thursday, August 2, 12

Page 43: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

A game in 6 steps

Thursday, August 2, 12

Page 44: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

setp 1

Thursday, August 2, 12

Page 45: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

what have the template done for us?

initPhysics

createMenu

draw

addNewSpriteAtPosition

update

ccTouchesEnded

Thursday, August 2, 12

Page 46: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

! b2Vec2 gravity;! gravity.Set(0.0f, -10.0f);! world = new b2World(gravity);!! // Do we want to let bodies sleep?! world->SetAllowSleeping(true);!! world->SetContinuousPhysics(true);!! m_debugDraw = new GLESDebugDraw( PTM_RATIO );! world->SetDebugDraw(m_debugDraw);!! uint32 flags = 0;! flags += b2Draw::e_shapeBit;! m_debugDraw->SetFlags(flags);! !!! // Define the ground body.! b2BodyDef groundBodyDef;! groundBodyDef.position.Set(0, 0); // bottom-left corner!! // Call the body factory which allocates memory for the ground body! // from a pool and creates the ground box shape (also from a pool).! // The body is also added to the world.! b2Body* groundBody = world->CreateBody(&groundBodyDef);!! // Define the ground box shape.! b2EdgeShape groundBox;! !!! // bottom! groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));! groundBody->CreateFixture(&groundBox,0);

Thursday, August 2, 12

Page 47: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

setp 2

Create the dynamic blocks

Thursday, August 2, 12

Page 48: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

sprite = [CCSprite spriteWithFile:spriteFileName]; [sprite setPosition:ccp(p.x,p.y)]; // Remember ccp() is macro for CGPointMake() [self addChild:sprite]; }! }!! // Define the dynamic body.! b2BodyDef bodyDef;! bodyDef.type = b2_dynamicBody; ! bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);! bodyDef.userData = sprite;!! // Tell the physics world to create the body! b2Body *body = world->CreateBody(&bodyDef);!! // Define another box shape for our dynamic body.! b2PolygonShape dynamicBox; ! dynamicBox.SetAsBox(boxDimensions.x, boxDimensions.y);! // Define the dynamic body fixture.! b2FixtureDef fixtureDef;! fixtureDef.shape = &dynamicBox;!! fixtureDef.density = boxDensity;! fixtureDef.friction = 0.3f;! fixtureDef.restitution = 0.5f; // 0 is a lead ball, 1 is a super bouncy ball! body->CreateFixture(&fixtureDef);

Thursday, August 2, 12

Page 49: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

-(void) update: (ccTime) dt{! //It is recommended that a fixed time step is used with Box2D for stability! //of the simulation, however, we are using a variable time step here.! //You need to make an informed choice, the following URL is useful! //http://gafferongames.com/game-physics/fix-your-timestep/!! int32 velocityIterations = 8;! int32 positionIterations = 1;!! // Instruct the world to perform a single step of simulation. It is! // generally best to keep the time step and iterations fixed.! world->Step(1.0f/60.0f, velocityIterations, positionIterations); ! //Iterate over the bodies in the physics world! for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())! {! ! if (b->GetUserData() != NULL) {! ! ! //Synchronize the AtlasSprites position and rotation with the corresponding body! ! ! CCSprite *myActor = (CCSprite*)b->GetUserData();! ! ! myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);! ! ! myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());! ! }!! }!}

Simulating the world(of Box2D)

Thursday, August 2, 12

Page 50: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

setp 3

Touch events

Thursday, August 2, 12

Page 51: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{! for( UITouch *touch in touches ) {! ! if (dist > 10.0f) {! ! ! // Create the object and add impulse! ! ! CCSprite *sprite = [CCSprite spriteWithFile:SNOWBALL_FILENAME];!! ! ! b2CircleShape circleShape;! ! ! b2FixtureDef fd;! ! ! b2Vec2 initVel;! ! ! b2BodyDef circleBodyDefinition;! ! ! circleBodyDefinition.type = b2_dynamicBody;! ! ! circleBodyDefinition.position.Set(startPoint.x/PTM_RATIO, startPoint.y/PTM_RATIO);! ! ! circleBodyDefinition.angle = 0.000000f;! ! ! circleBodyDefinition.userData = sprite;! ! ! b2Body *body = world->CreateBody(&circleBodyDefinition);! ! ! initVel.Set(0.000000f, 0.000000f);! ! ! body->SetLinearVelocity(initVel);! ! !! ! ! circleShape.m_radius = 0.5f;! ! ! fd.shape = &circleShape;! ! ! fd.userData = sprite;! ! ! body->CreateFixture(&fd);! ! !! ! ! // 2. Add an impulse on the direction of the flick and with the flick force! ! ! CGPoint forceVector = CGPointMake((endPoint.x-startPoint.x)/PTM_RATIO,(endPoint.y-startPoint.y)/PTM_RATIO);! ! ! forceVector = CGPointMake(forceVector.x*2, forceVector.y*2);! ! !! ! ! b2Vec2 blockImpulse = b2Vec2(forceVector.x,forceVector.y);! ! ! body->ApplyLinearImpulse(blockImpulse, body->GetPosition());! ! } else {! ! ! //NSLog(@"No Flick occured");! ! }! }}

1

2

34

5

6

Thursday, August 2, 12

Page 52: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

setp 4

Penguin animation

Thursday, August 2, 12

Page 53: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

CCSpriteFrame *frame0 = [CCSpriteFrame frameWithTextureFilename:@"penguino1.png" rect:CGRectMake(0, 0, 64, 64)];CCSpriteFrame *frame1 = [CCSpriteFrame frameWithTextureFilename:@"penguino2.png" rect:CGRectMake(0, 0, 64, 64)]; CCSpriteFrame *frame2 = [CCSpriteFrame frameWithTextureFilename:@"penguino3.png" rect:CGRectMake(0, 0, 64, 64)]; CCSpriteFrame *frame3 = [CCSpriteFrame frameWithTextureFilename:@"penguino4.png" rect:CGRectMake(0, 0, 64, 64)]; sprite = [CCSprite spriteWithSpriteFrame:frame1];[sprite setPosition:ccp(p.x,p.y)]; // Remember ccp() is macro for CGPointMake()[self addChild:sprite]; NSMutableArray *animFrames = [NSMutableArray array];[animFrames addObject:frame0];[animFrames addObject:frame1];[animFrames addObject:frame2];[animFrames addObject:frame3]; CCAnimation *animation = [CCAnimation animationWithSpriteFrames:animFrames delay:0.2f];CCAnimate *animate = [CCAnimate actionWithAnimation:animation];CCCallFunc *actionCall = [CCCallFunc actionWithTarget:self selector:@selector(playRandomArcticSqueakSound:)];CCSequence *seq = [CCSequence actions: animate,actionCall,nil];

[sprite stopAllActions];[sprite runAction:[CCRepeatForever actionWithAction:seq]];

Thursday, August 2, 12

Page 54: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

setp 5

Fun with Particle Systems

Thursday, August 2, 12

Page 55: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

setp 6

music & effect

[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"Penguino.mp3"];

[[SimpleAudioEngine sharedEngine] playEffect:@"PenguinSqueak3.mp3"];

Thursday, August 2, 12

Page 56: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

more features

Labels and FontsParticle systemTiled mapsDraw & updateEffects & Grid & CameraTransitionsDrawingPrimitivesRenderTexture

......Shader (2.0)

Thursday, August 2, 12

Page 57: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

Thursday, August 2, 12

Page 58: 在iOS平台上用Cocos2D做开发 | iOS独立开发者 秦春林

THANK YOU

weibo.com/[email protected]

Now, how about this game?

Thursday, August 2, 12