用 SpriteKit 做一个逃逸游戏 (5)

翻译 2014年02月07日 13:20:06

但是……

这真是出人意料…

嗯……怎么样?出乎你的意料了吧!当球碰上砖块之后,砖块是被弹开,而不是被击碎?

为了监听球和砖之间的碰撞,你需要修改球的contactTestBitMask(注意,在 initWithSize 方法中已经有对应的赋值语句了,你只需要在等号右边在加上一个 category 常量):

ball.physicsBody.contactTestBitMask = bottomCategory | blockCategory;

在 bottomCategory 和 blockCategory 之间是位运算符OR。这会将这两个类别所对应的二进制位上都设为1,其他位则为0。

现在,不管是球和地发生碰撞,还是球和砖发生碰撞,都将调用委托方法。

接下来需要处理委托消息。在 didBeginContact: 方法最后加入:

if (firstBody.categoryBitMask == ballCategory && secondBody.categoryBitMask == blockCategory) {

         [secondBody.node removeFromParent];

         //TODO: check if the game has been won    

}

上述代码判断碰撞是否来自于球与砖。如果是,将发生碰撞的砖块移除。

想必你已经明白位掩码,尤其是 contactTestBitMask 是怎么回事了。前面提及,物体还有一个collisionBitMask 位掩码。它决定了当两个物体发生碰撞时,它们能否相互作用(即作用力与反作用力)。例如,它决定了球是被砖块弹开,还是直接从砖块上穿过。

如果你想使用 collisionBitMask,可以给球的collisionBitMask 赋值,这样当砖块被消灭时,球将直接穿过。

隐含内容: 使用 collisionBitMask

ball.physicsBody.collisionBitMask = paddleCategory

设置 collisionBitMask 为 paddleCategory 表示球会只会和球拍发生相互作用,而不会和砖块发生相互作用。对于屏幕四边的笼子,其 collisionBitMask 保持默认值,不赋予任何类别掩码。

    block.physicsBody.collisionBitMask = 0;

这一行语句则将砖块的 collisionBitMask 设置为0。这表示砖块不会对其他碰撞物体发生作用力。

你是否完成了这个挑战(指 collisionBitMask 的使用)并尝到了胜利的滋味?现在也该到让你在游戏赢得胜利的时候了:]

在游戏中获胜

为了让玩家能在游戏中获胜,在 MyScene.m 中加入这个方法:

-(BOOL)isGameWon {

     int numberOfBricks = 0;

     for (SKNode* node in self.children) {

         if ([node.name isEqual: blockCategoryName]) {

             numberOfBricks++;

         }

     }

     return numberOfBricks <= 0;

}

在方法中遍历游戏场景中的所有子节点,判断屏幕中还剩下多少砖块。对于每个子节点,我们都要检查它的节点名是否等于 blockCategoryName。如果所有砖块都被干掉了,判定玩家获胜,返回 YES。

回到 didBeginContact:方法,将最终的 TODO 行修改为下面的 if 语句:

    if ([self isGameWon]) {

         GameOverScene* gameWonScene = [[GameOverScene alloc] initWithSize:self.frame.size playerWon:YES];

         [self.view presentScene:gameWonScene];

     }

这段代码调用新方法判断玩家是否获胜,如是,则在即将显示的 GameOverScene窗口中告诉玩家已经获胜。

结束触摸

在你玩游戏的时候,你可能注意到,小球在被球拍击中时,有时会非常快有时会非常慢。

通过 MyScene.m 的 update: 方法,你可以防止这种速度的变化:

-(void)update:(CFTimeInterval)currentTime {

     /* 刷新每一帧都会调用 */

     SKNode* ball = [self childNodeWithName: ballCategoryName];

     static int maxSpeed = 1000;

     float speed = sqrt(ball.physicsBody.velocity.dx*ball.physicsBody.velocity.dx + ball.physicsBody.velocity.dy * ball.physicsBody.velocity.dy);

     if (speed > maxSpeed) {

         ball.physicsBody.linearDamping = 0.4f;

     } else {

         ball.physicsBody.linearDamping = 0.0f;

     }

}

update:方法在刷新每一帧之前调用。之前没有在 MyScene.m 中实现 update: 方法,因此默认将调用默认实现。这里,我们用自己的实现覆盖了默认实现。首先我们获取小球对象,检查它的velocity 属性,即其运动速度。如果 velocity 很大,则加大球的线性阻尼系数,这样球就会慢下来。

编译运行程序,开始游戏。你会发现一旦球的速度变得太快,就会恢复到正常水平。

注意: 你可能想直接通过改变球的 velocity 来防止球体速度过快,这样也许你会更容易控制球的运动。这种做法在 Box2D 中是禁止的,在 SpriteKit 中也不提倡。

源代码

本教程源代码可以在这里下载。

下一步

很显然,这个游戏十分简单。但你可以从这里开始,加入许多有趣的东西。比如给砖块加上生命值,加入不同的砖块,小球必须击打多次才能摧毁它们。有的砖块可以加分,有的则会减分,甚至让球拍向砖块发射激光,一切只取决于你的想象力!

请留下您的建议,希望本教程对你有用。

 


实例介绍Cocos2d-x物理引擎:碰撞检测

碰撞检测是使用物理引擎的一个重要目的,使用物理引擎可以进行精确的碰撞检测,而且执行的效率也很高。在Cocos2d-x 3.x中使用事件派发机制管理碰撞事件,EventListenerPhysicsCo...

用 SpriteKit 做一个逃逸游戏 (1)

原文:http://www.raywenderlich.com/49721/how-to-create-a-breakout-game-using-spritekitSpriteKit 是苹果的新的游...
  • kmyhy
  • kmyhy
  • 2014年01月15日 15:46
  • 8485

用 SpriteKit 做一个逃逸游戏 (4)

在代码中怎样使用?首先,为不同的物体类别创建常量。在 MyScene.m 中的常量声明语句后加入下列语句: static const uint32_t ballCategory  = 0x1 ...
  • kmyhy
  • kmyhy
  • 2014年02月07日 13:18
  • 4018

用 SpriteKit 做一个逃逸游戏 (5)

但是…… 这真是出人意料… 嗯……怎么样?出乎你的意料了吧!当球碰上砖块之后,砖块是被弹开,而不是被击碎? 为了监听球和砖之间的碰撞,你需要修改球的contactTe...

用 SpriteKit 做一个逃逸游戏 (3)

移动球拍我们需要移动它!移动球拍需要接收触摸事件。你可以在 MyScene 中实现以下方法以接收触摸事件: -(void)touchesBegan:(NSSet*)touches withEven...
  • kmyhy
  • kmyhy
  • 2014年02月07日 13:12
  • 3625

用 SpriteKit 做一个逃逸游戏 (2)

在initWithSize:方法末尾加入下列代码: // 1 创建物理形状(以屏幕为边界)     SKPhysicsBody* borderBody = [SKPhysicsBody bo...
  • kmyhy
  • kmyhy
  • 2014年01月20日 16:21
  • 4791

用 SpriteKit 做一个逃逸游戏 (4)

在代码中怎样使用? 首先,为不同的物体类别创建常量。在 MyScene.m 中的常量声明语句后加入下列语句: static const uint32_t ballCategor...

做一个像植物大战僵尸的Flash游戏5

现在,我们来到了这个教程的第5个阶段。 在这个阶段,我们会修改一个漏洞,这个漏洞允许植物开火只要有僵尸与植物处于同一行,不论僵尸是在植物的左边还是右边。同时我们也会增加僵尸攻击植物的功能。 首先,...

html5--用cavas做一个小游戏

无标题文档 开始游戏 // JavaScript Documentvar canvas; var context; var speedX=5; var speedY=5; var ...

SpriteKit游戏开发点滴[5]旋转 & Anchorpoint

最近在做关于旋转的动画效果,遇到了些问题,在解决问题的过程中对SpriteKit中的旋转有所更加深入的了解,在此进行个总结。 我想实现下面的这个效果:一个水管绕着白色星球的中心进行旋转。 最自然...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用 SpriteKit 做一个逃逸游戏 (5)
举报原因:
原因补充:

(最多只允许输入30个字)