Upload
imshining-devcamp
View
1.717
Download
9
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
iOS DevCampProduced by CSDN
Website: http://devcamp.csdn.netWeibo: http://weibo.com/cmdnclub
Thursday, August 2, 12
怎样灵活使用Cocos2D
秦春林
Thursday, August 2, 12
Don’t reinvent the wheel
Thursday, August 2, 12
“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
4,000+ games
Thursday, August 2, 12
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
How simple?
Thursday, August 2, 12
layer: GameLayer
scene: GameScene
Action: CCMoveTo
UIView:EAGLView
sprite: player
Thursday, August 2, 12
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
Anything thats gets drawn or contains things that get drawn is a CCNode
Thursday, August 2, 12
CCSprite
CCParticleSystem
CCMenuItem
CCMenuItemLabel
CCSpriteBatchNode
CCScene
CCLayer
CCNode
CCMenu
CCMenuItemSprite
CCMenuItemToggle
CCTransitionScene
CCLabelTTF
CCTMXLayer
CCLabelBMFont
Thursday, August 2, 12
Just like UIView
Thursday, August 2, 12
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
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
- (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
CCScene
GamePlaySceneCCLayer
Background
CCLayer
GamePlay
Thursday, August 2, 12
CCLayer is a subclass of CCNode that implements:
- UIAccelerometerDelegate- CCStandardTouchDelegate- CCTargetedTouchDelegate
Thursday, August 2, 12
Thursday, August 2, 12
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
! //! // 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
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
A sample:How dose CCMenu work?
Thursday, August 2, 12
-(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
Which item is clicked?
Thursday, August 2, 12
-(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
GameLayer
Which Layer handle touch events?
Priority = 0
Priority = 2
Priority = 1
Thursday, August 2, 12
Return YES to claim the touch.-(BOOL)ccTouchBegan
! //* priority used by the menu for the event handler! kCCMenuHandlerPriority = -128,
Thursday, August 2, 12
Thursday, August 2, 12
CCSprite is a 2d image
Thursday, August 2, 12
+(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
CCSprite CCSpriteFrame CCSpriteFrameCache
frame
CCTexture
0
32
1
(setDisplayFrame)
Thursday, August 2, 12
CCSpriteSheetThursday, August 2, 12
CCSpriteBatchNode
All CCSprites added to a CCSpriteBatchNode are drawn in one OpenGL ES draw call.
CCTMXLayer
CCLabelBMFont
Thursday, August 2, 12
CCDirector
CCScene
LevelCompletedScene
CCScene
GamePlayScene
CCLayer
CCLayer
CCLayer
CCLayer
CCLayer
CCLayer
startScene
GameOlayScene
CompleteScene
.....
.....
Thursday, August 2, 12
-(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
How does CCAction work?
Thursday, August 2, 12
@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
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
Simple,but powerful
Thursday, August 2, 12
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
Thursday, August 2, 12
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
A game in 6 steps
Thursday, August 2, 12
setp 1
Thursday, August 2, 12
what have the template done for us?
initPhysics
createMenu
draw
addNewSpriteAtPosition
update
ccTouchesEnded
Thursday, August 2, 12
! 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
setp 2
Create the dynamic blocks
Thursday, August 2, 12
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
-(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
setp 3
Touch events
Thursday, August 2, 12
- (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
setp 4
Penguin animation
Thursday, August 2, 12
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
setp 5
Fun with Particle Systems
Thursday, August 2, 12
setp 6
music & effect
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"Penguino.mp3"];
[[SimpleAudioEngine sharedEngine] playEffect:@"PenguinSqueak3.mp3"];
Thursday, August 2, 12
more features
Labels and FontsParticle systemTiled mapsDraw & updateEffects & Grid & CameraTransitionsDrawingPrimitivesRenderTexture
......Shader (2.0)
Thursday, August 2, 12
Thursday, August 2, 12