移动球拍
我们需要移动它!移动球拍需要接收触摸事件。你可以在 MyScene 中实现以下方法以接收触摸事件:
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event; -(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event; -(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event; |
在此之前,还需要新加一个属性。在 MyScene.m 中@implementation 语句前加入:
@interface MyScene() @property (nonatomic) BOOL isFingerOnPaddle; @end |
这个属性用于保存玩家是否触摸到了球拍。这对于实现球拍的移动是有用的。
然后,在 MyScene.m 中实现 touchesBegan:withEvent: 方法:
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { /* 触摸开始时调用 */ UITouch* touch = [touches anyObject]; CGPoint touchLocation = [touch locationInNode:self]; SKPhysicsBody* body = [self.physicsWorld bodyAtPoint:touchLocation]; if (body && [body.node.name isEqualToString: paddleCategoryName]) { NSLog(@"Began touch on paddle"); self.isFingerOnPaddle = YES; } } |
上述代码获取触摸并得到触摸在屏幕中的位置。然后用physicasWorld的 bodyAtPoint:方法找出触摸位置所处的物体(如果有的话)。然后判断是否有这样一个物体存在,以及这个物体是不是球拍。早先我们为球拍指定了一个名字——你可以通过物体的名字来判断它是否是指定的对象。如果触摸位置就是球拍所处的位置,将isFingerOnPaddle 设为 YES 并在控制台中输出一个消息。
你已经摸到我了;)
接下来实现 touchesMoved:withEvent:方法:
-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { // 1 如果用户触摸到球拍 if (self.isFingerOnPaddle) { // 2 获取触摸位置 UITouch* touch = [touches anyObject]; CGPoint touchLocation = [touch locationInNode:self]; CGPoint previousLocation = [touch previousLocationInNode:self]; // 3 获得球拍节点 SKSpriteNode* paddle = (SKSpriteNode*)[self childNodeWithName: paddleCategoryName]; // 4 计算球拍将移动的x位置 int paddleX = paddle.position.x + (touchLocation.x - previousLocation.x); // 5 限制球拍的移动在屏幕范围之内 paddleX = MAX(paddleX, paddle.size.width/2); paddleX = MIN(paddleX, self.size.width - paddle.size.width/2); // 6 更新球拍的坐标 paddle.position = CGPointMake(paddleX, paddle.position.y); } } |
这就是球拍的移动方式。
注意:如你所见,代码直接操作了球拍的坐标。这是由于球拍是静态的。对于动态物体,不应该直接改变其坐标。因为这样会破坏物理引擎模拟的状态,导致不可预料的行为。
你别不信,如果你将球拍改为动态物体,将重力加速度设置为低重力状态,例如:
self.physicsWorld.gravity = CGPointMake(-0.1, -0.1); |
试试看,一切都乱了,不是吗?
还有最后一个触摸方法 touchesEnded:withEvent: 需要实现,我们在这里进行变量的重置:
-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { self.isFingerOnPaddle = NO; } |
将 isFingerOnPaddle 设置为 NO;确保用户手指离开并再次触摸屏幕之后,变量被重置。
SpriteKit 的第一次亲密接触!
啊,不是你想象的那种接触!(本图片来自 DeviantArt.com 的 hugoo13,受知识共享协议保护)
迄今为止,我们的游戏中只有一个会在屏幕中四处乱蹦的小球,和一个通过触摸来进行移动的球拍。
对于真正的游戏,还需要设定某种规则以判定玩家输赢。我们设定,如果球落到了屏幕底部而不是球拍上为输。但如何使用SpriteKit 来判断这种情况?
SpriteKit 可以判断两个物体间发生的接触。但是为实现这个目的,需要遵循几个固定的步骤。我先简单描述一下每个步骤,稍后再细讲:
注意:位掩码?如果你从未使用过它,不要担心。尽管一开始他们看起来很复杂,但却非常有用!
什么是位掩码?位掩码是一连串的二进制数。比如:1011 1000。其实并不复杂。
为什么说它很有用?首先,你可以从这个二进制数读取对象状态,也可以将对象状态单独设置到这个数的某一个二进制位。只需要进行一个 AND 或 OR 操作:
强大的位掩码 :)
它以一种非常紧凑的方式(比如一个变量)存储大量信息,同时存取、操作存储在其中的信息也很方便。