首页 > 代码库 > 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 学习笔记二