首页 > 代码库 > SpriteBuilder 学习笔记二

SpriteBuilder 学习笔记二

Chapter 3  Controlling and Scrolling

@implementation GameScene {    __weak CCNode *_levelNode;    __weak CCPhysicsNode *_physicalNode;    __weak CCNode *_playerNode;    __weak CCNode *_backgroundNode;}

注意__weak关键字。总的来说,声明一个obejct pointer 变量而不是由类created 或者说owned的时候,最好都使用__weak,尤其是在cocos2d中,应该总是声明一个引用,当这个引用不是parent或者node的“兄弟”(sibling)时。如果没有__weak关键字,默认生成一个strong引用。

通过名字找到Player Node

在GameScene中添加代码:

- (void)didLoadFromCCB {    NSLog(@"GameScene created!");    // 使得可以接受输入的事件 (enable receiving input events)    // 这句话允许GameScene类去接受触摸事件    self.userInteractionEnabled = YES;    // load the current level 载入当前level    [self loadLevelNamed:nil];}
- (void)loadLevelNamed:(NSString*)levelCCB {    // 在scene中获取当前level的player,递归寻找    _playerNode = [self getChildByName:@"player" recursively:YES];    // 如果没有找到,NSAssert会抛出一个异常    NSAssert1(_playerNode, @"player node not found in level:%@", levelCCB);}

下面的代码用于实现通过触摸移动物体到触摸的位置

- (void)touchBegan:(CCTouch*)touch withEvent:(UIEvent*)event {    _playerNode.position = [touch locationInNode:self];}

NOTE:书中第一个参数类型为UITouch* 报错,改为CCTouch后即可实现功能。

查阅API,摘抄如下:

touchBegan:withEvent:

Called when a touch began. Behavior notes:

- (void)touchBegan:(CCTouch *)touch withEvent:(CCTouchEvent *)event

Parameters

touch

Contains the touch.

event

Current event information.

Discussion

  • If a touch is dragged inside a node which does not claim user interaction, a touchBegan event will be generated.
  • If node has exclusive touch, all other ongoing touches will be cancelled.
  • If a node wants to handle any touch event, the touchBegan method must be overridden in the node subclass. Overriding just touchMoved or touchEnded does not suffice.
  • To pass the touch further down the Cocos2D responder chain, call the super implementation, ie [super touchBegan:withEvent:].

See Also

  • CCTouch, CCTouchEvent

Declared In

CCResponder.h

 

分配Level-Node变量

在SpriteBuilder中分配变量和通过名字获取一个node是一样的,仅仅是个人习惯问题。但是不推荐频繁使用getChildByName:方法在schedule methond中(不太懂这是什么方法)和updata:方法中,特别是递归查找和a deep-node hierarch。

Caution:在SpriteBuilder中分配一个变量仅仅适用于CCB文件的直接descendants(后代--不知如何翻译),不可以对通过Sub File(CCBFile)导入的另一个CCB指定node为变量或者properties。这也是为何player node通过名字获取。

打开GameScene.ccb,

技术分享

 

note:A doc root var assigns a node to a correspondingly named ivar or property declared in the CCB root node‘s custom class

Doc root var:分配一个node,为在CCB根node的自定义类中声明的相对应名字的变量或者属性。

做完这步后,_levelNode变量会在它发送didLoadFromCCB消息之前被CCBReader分配,这是创建一个在CCB中包含的node的最简单,最有效的方法。

 

用CCActionMoveTo移动Player

为了平滑的移动player到指定位置,可以修改如下代码:

- (void)touchBegan:(CCTouch*)touch withEvent:(UIEvent*)event {   // _playerNode.position = [touch locationInNode:self];    CGPoint pos = [touch locationInNode:_levelNode];    CCAction *move = [CCActionMoveTo actionWithDuration:0.2 position:pos];    [_playerNode runAction:move];}

触摸点根据_levelNode转化。这一点很重要,保证了player可以在整个_levelNode上移动,而不是被禁锢在屏幕空间中。但是这一点目前还看不出来,因为还没有添加滚动(scrolling)。

但是此时,如果增加duration(持续时间),会发现移动的动作并没有叠加,player也不会停在你最后一次点击的地方。所以必须添加一个tag,有了这个tag,可以在执行新的动作之前,停止当前动作,代码更改如下:

- (void)touchBegan:(CCTouch*)touch withEvent:(UIEvent*)event {   // _playerNode.position = [touch locationInNode:self];    [_playerNode stopActionByTag:1];    CGPoint pos = [touch locationInNode:_levelNode];    CCAction *move = [CCActionMoveTo actionWithDuration:20.2 position:pos];    move.tag = 1;    [_playerNode runAction:move];}

 

滚动Level(Scrolling the Level)

在2D游戏中,更普遍的做法是相反方向移动content layer,已达到滚动效果

 

 

未完待续

 

SpriteBuilder 学习笔记二