Cocos2d基础及基本函数

Cocos2d基础及基本函数

1.基本概念:

Scene对象其实是所有层的容器,与Layer一起组织各节点的图像显示。除了Scene外所有节点只有一个父节点,可以有无数个子节点。但注意这里的父子关系并不是面象对象中的继承关系,仅仅是addChild的方式建立起来的父子。

 

CCDirector类存储了cocos2d中大量的全局配置信息,而且管理所有的cocos2d场景,它可以访问正在运行的场景,运行替换场景等等。共有四种导演类型,其中默认的是kCCDirectorTypeDisplayLink

 

Tips: 在为对象建分组和层时一般通用的CCNode类而不是CCLayer类,因为CCLayer会接收键盘等的输入,增加不必要的开销。

 

2.节点处理:

CCNode* childNode = [CCNode node];

 

[myNode addChild:childNode z:0 tag:123];

 

CCNode* retrievedNode = [myNode getChildByTag:123];

 

[myNode removeChildByTag:123 cleanUp:YES];

(cleanUp的意思是将节点从父节点中删除)

 

[myNode removeChild: retrievedNode];

 

[myNode removeAllChildrenWithCleanUp:YES];

 

[myNode removeFromParentAndCleanUp:YES];

 

3.动作的处理方式

1)动作声明

通过以下声明可以让节点闪烁

CCAction* action = [CCBlink actionWithDuartion:10blinks:20];

action.tag = 234;

[myNode runAction:action];

 

如果之后想取得动作,可以通过标记来获得:

CCAction* retrievedAction = [myNode getActionByTag: 234];

 

[myNode stopActionByTag:234];

 

[myNode stopAction: action];

 

[myNode stopAllActions];

 

2)消息调度

节点可以对消息进行调度,其实就是每段时间调用一次方法,如碰撞检测。要使特定的方法每帧调用一次,可以如下:

-(void) scheduleUpdateMethod

{

[self scheduleUpdate];

}

 

-(void) update: (ccTime)delta

{

       //This method iscalled every frame;

}

 

参数delta表示方法自上次被调用到现在所经历过的时间。如果想以0.1秒的频率调用该方法可以如下:

-(void) scheduleUpdateMethod

{

       [selfschedule:@selector (updateTenTimesPerSecond: ) interval:0.1f];

}

 

-(void) updateTenTimesPerSecond: (ccTime)delta

{

       //This method iscalled according to its interval, ten times per second

}

 

Tips: 如果想用每帧更新,还是用scheduleUpdate好,反过来,如果在后面有可能要取消这个办法,还是用上面的方法,因为scheduleUpdate做不到。

 

3) @selector方法

在这里selector方法相当于是告诉编译器去找一个名为updateTenTimesPerSecond的方法,并用“:”来告诉这个函数只有一个参数,如果这个函数有多个参数时,就要用多个,千万别忘了:号,如:

-(void) example:(ccTime)delta sender:(id)senderflag:(bool)aBool

 

那么对应的selector语句应该是:

@selector(example:sender:flag:)

 

如果要取消用选择器调度的方法,可以用

[self unscheduleAllSelectors];

[self unscheduled:@selector(updateTenTimesPerSecond)];

但要注意,用这些方法不会使scheduleUpdate的调度更新方法停止。

 

这里注意,如果想以不同的时间来调度一个方法,可以用_cmd来简化工作,_cmd在所有的Ob-C中都可用,是当前方法的选择器。

-(void) scheduleUpdates

{

       [selfschedule:@selector(irregularUpdate:) interval:1];

}

 

-(void) irregularUpdate: (ccTime)delta

{

       [self unscheduled:_cmd];

       float nextUpdate= CCRANDOM_0_1() * 10;

       [selfschedule:_cmd interval:nextUpdate];

}

 

在更新中还有更新方法的优先级,可以用[selfscheduleUpdateWithPriority:1]来进行更新,数字越小更新等级越高。

 

3. CCScene类

CCDirector要求有派生自CCScene的类来进行runWithScene,replaceScene, pushScene等操作来修发当前场景,可以把CCScene封到一个派生自CCSceneTransition的类中,以便能够进行切换。

 

因为大多数时候场景对象本身不包含具体的游戏代码,而且基本不会从它派生类,所以一般都在CCLayer对象的“+(id)scene”方法中创建它们,如下:

+(id) scene

{

       CCScene *scene =[CCScene node];

       CCLayer *layer =[HelloWorld node];

       [sceneaddChild:layer];

 

       return scene;

}

 

然后可以在applicationDidFinishLaunching中结尾创建场景:

[[CCDirector sharedDirector] runWithScene: [HelloWorldscene]];

 

而在替换场景时,还可以使用过渡效果:

CCScene* scene = [HelloWorld scene];

CCSceneTransition* tran = [CCTransitionShrinkGrowtransitionWithDuration:2 scene: scene];

[[CCDirector sharedDirector] replaceScene: tran];

 

Tips:不能用self作为参数传给replaceScene以达到刷新场景的目的,会卡死的。

 

4. CCTransitionScene类

场景过渡就是任何从CCTransitionScene继承的类,如下例:

CCTransitionFade *tran = [CCTransitionFadetransitionWithDuration:1 scene:[HelloWorld scene] withColor:ccWHITE];

[[CCDirector sharedDirector] replaceScene: tran];

 

Tips: pushScene有过渡效果,但是popScene没有

 

4. CCLayer 类

有时候也许场景中的层不止一个,可以用如下方式来创建:

+(id) scene

{

       CCScene* scene =[CCScene node];

      

       CCLayer*backgroundLayer = [HelloWorldBackground node];

       [scene addChild:backgroundLayer];

 

       CCLayer* layer =[HelloWorld node];

       [sceneaddChild:layer];

 

       CCLayer*userInterfaceLayer = [HelloWorldUserInterface node];

       [scene addChild:userInterfaceLayer];

      

       return scene;

}

 

Tips: 可以在一个场景中用很多个层,但是注意不要让他们都能接收输入,这样会大大降低效率,一般只要一个层接收以后,再把消息传给别的层就好了。

 

5. 接收触摸事件

CCLayer启动可输入要用以下方式:

self.isTouchEnabled = YES;

这个部分是在init中完成的,但可以在任何地方进行修改,以下是调用的情况:

 

当单指接触到屏幕时被调用:

-(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

 

因为触摸事件都是由CocoaTouch API接收的,所以一定要把触摸位置转换成OpenGL坐标,用以下方法:

-(CGPoint) locationFromTouches: (NSSet *)touches

{

       UITouch *touch =[touches anyObject];

       CGPointtouchLocation = [touch locationInView: [touch view]];

       Return[[CCDirector sharedDirector] convertToGL: touchLocation];

}

不过此方法仅对单指触摸有效,因为它使用了[touchesanyObject]。要追踪多指触摸的位置,你必须分别追踪每个触摸的位置。而cocos2d支持的是有针对性的触摸处理,它把多指触模简单的分割成了独立事件,这样可以更方便的根据游戏需求去处理。更重要的是,它可以把特定的触摸事件从队列中移除,可以指定一个触摸事件为已处理事件,并阻止它传给别的层。这样就可以把触摸集中在一个特写区域内,你就可以很快识别出来,处理完后标记为已处理,传给其它层时就不用测了。

通过向层中添加如下方法来启用有针对性的触摸处理:

-(void) registerWithTouchDispatcher

{

[[CCTouchDispatchersharedDispatcher] addTargetDelegate:self priority:INT_MIN+1swallowsTouches:YES];

}

 

默认与多点的不同之处在于,默认用的方法是以(NSSet*)touches作为第一个参数,而你要用的方法是以“(UITouch *)touches”作为第一个参数。

 

6.接收加速计事件

以下方法启用加速计事件,与触摸类似:

self.isAccelerometerEnabled =YES;

同样也得用如下方法来接收加速计事件:

-(void) accelerometer: (UIAccelerometer*) accelerometer

   didAccelerate:(UIAcceleration *)acceleration

{

           CCLOG(@”acceleration: x:%f / y:%f / z:%f, acceleration.x,acceleration.y, acceleration.z);

}

 

7. CCSprite类

Cocos2d是通过图片来创建Sprite的

CCSprite* sprite = [CCSpritespriteWithFile:@”Default.png”];

[self addChild:sprite];

(iOS设备上文件是区分大小写的,但模拟器不区分,所以要注意因此引起的崩溃)

 

8. anchorPoint属性

每个Node都有anchorPoint属性,但是只有在节点要用纹理显示时才有作用,如CCSprite和CCLabelTTF,任何节点的anchorPoint属性都默认是(0.5,0.5),也就是纹理中心。(区间是0~1)

举例,下图因为其anchorPoint被设为0,0所以精灵正好可以完整显示在屏幕左下角:

CCSprite* sprite = [CCSpritespriteWithFile:@”Default.png”];

Sprite.anchorPoint =CGPointMake(0,0);

[self addChild:sprite];

 

(非常注意,现在iOS设备只支持尺寸为2的次幂的纹理,如果不是2次幂会被转换从而加大消耗)

 

8. CCLabelTTF类

用以下方式来显示文本:

CCLabelTTF* label =[CCLabelTTF labelWithString:@”text” fontName:@”AppleGothic” fontSize:32];

[self addChild:label];

在要重新发变文本时,用如下方法:

[label setString:@”new text”];

因为此文本是居中对齐的,如果要改就需要改锚点,如:

label.anchorPoint =CGPointMake(1, 0.5f);

 

9. 菜单

CCMenu是CCLayer的子类,只能接受CCMenuItem对象作为其子节点,其子类可以有CCMenuItemLabel(CCMenuItemAtlasFont, CCMenuItemFont), CCMenuItemSprite(CCMenuItemImage),  CCMenuItemToggle

 

创建方法有:

CCMenuItemFont* item1 =[CCMenuItemFont itemFromString:@”Go Back!” target:selfselector:@selector(menuItem1Touched:)];

 

用Sprite创建方法有:

CCMenuItemSprite* item2 = [CCMenuItemSpriteitemFromNormalSprite:normal selectedSprite:selected target:selfselector:@selector(menuItem2Touched:)];

 

10. 动作

CCAction是一个轻量级的类,可以做移动,旋转等,有3种动作是从CCAction直接派生的:

CCFollow A节点跟随B节点

CCRepeatForever 无限的重复一个动作

CCSpeed 在一个动作运行时修发其更新频率

 

可以让一个节点跟随另一个节点:

[label runAction: [CCFollow actionWithTarget:playerSprite]];

 

像轮子不停转:

CCRotateBy* rotateBy = [CCRotateBy actionWithDuration:2angle:360];

CCRepeatForever* repeat = [CCRepeatForeveractionWithAction:rotateBy];

CCSpeed* speedAction = [CCSpeed actionWithAction:repeatspeed:0.5f];

speedAction.tag = 1;

[myNode runAction:repeat];

因为CCSpeed动作的speed属性被设为0.5f,现在节点转一圈所需时间为原来的两倍。要修改其速度,发CCSpeed的speed属性就行。

 

1)间隔动作

由于动作会执行一段时间,如转3秒钟,因此通常做法是写一个更新方法,并加一些变量来存中间结果。如CCActionInterval动作封装了这部分逻辑,并将之转化为了带参的方法:

CCMoveTo* move = [CCMoveTo actionWithDuration:3position:CGPointMake(100,200)];

[myNode runAction:move];

(在3秒内移动100,200)

但此移动不匀速,用如下方式实现匀速:

CGPoint targetPos = CGPointMake(100,200);

float speed = 10;

float duration = ccpDistance(myNode.position, targetPos)/speed;

CCMoveTo* move = [CCMoveTo actionWithDuration: durationposition:targetPos];

 

2)动作序列

通常情况下,一个节点加几个动作时,它们会在同一时间运行,如果想让他们一个接一个的运行就要用到CCSequence.如以下变色:

CCTintTo* tint1 = [CCTintTo actionWithDuration:4 red:255green:0 blue:0];

CCTintTo* tint2 = [CCTintTo actionWithDuration:4 red:0green:255 blue:0];

CCTintTo* tint3 = [CCTintTo actionWithDuration:4 red:0green:0 blue:255];

CCSequence* sequence = [CCSequence actions:tint1, tint2,tint3, nil];

(CCRepeatForever* repeat = [CCRepeatForever actionWithAction:sequence];)

([label runAction:repeat];)

[label runAction:sequence];

但一定要注意sequence最后一个一定是nil。

 

3)流畅动作

节点在3秒内移动至100,200

CCMoveTo* move = [CCMoveTo actionWithDuration:3position:CGPointMake(100, 200)];

CCEaseInOut* ease = [CCEaseInOut actionWithAction:moverate:4];

[myNode runAction:ease];

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值