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

但是……

这真是出人意料…

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

为了监听球和砖之间的碰撞,你需要修改球的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 中也不提倡。

源代码

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

下一步

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

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

 


以下是一个简单的基于libbpf的容器逃逸监测程序示例: ```C #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include <linux/bpf.h> #include <bpf/libbpf.h> #define BPF_PROGRAM "\ int kprobe__do_exit(struct pt_regs *ctx) {\n\ bpf_trace_printk(\"Container escape detected!\\n\");\n\ return 0;\n\ }\n" int main() { struct bpf_insn insn_buf[256]; // 将BPF程序编译成BPF字节码 int prog_len = bpf_asm(BPF_PROGRAM, insn_buf, sizeof(insn_buf)); if (prog_len < 0) { fprintf(stderr, "Failed to compile BPF program: %s\n", strerror(-prog_len)); return EXIT_FAILURE; } // 加载BPF程序 int prog_fd = bpf_load_program(BPF_PROG_TYPE_KPROBE, insn_buf, prog_len, "GPL", 0, NULL, 0); if (prog_fd < 0) { fprintf(stderr, "Failed to load BPF program: %s\n", strerror(errno)); return EXIT_FAILURE; } // 安装BPF程序到目标kprobe int ret = bpf_attach_kprobe(prog_fd, BPF_PROBE_ENTRY, "do_exit"); if (ret < 0) { fprintf(stderr, "Failed to attach BPF program to kprobe: %s\n", strerror(-ret)); return EXIT_FAILURE; } // 等待BPF程序输出 char buf[1024]; ssize_t len = read(ret, buf, sizeof(buf)); if (len < 0) { fprintf(stderr, "Failed to read BPF output: %s\n", strerror(errno)); return EXIT_FAILURE; } // 关闭BPF句柄 close(prog_fd); return EXIT_SUCCESS; } ``` 该程序的作用是在容器逃逸时打印一条警告信息。具体实现方式是使用BPF程序来监测系统中的`do_exit`函数,并在函数调用时输出一条警告信息。BPF程序被编译成BPF字节码后,使用libbpf库提供的函数将其加载到内核中,并使用`bpf_attach_kprobe`函数将其安装到`do_exit`函数上。最后,程序等待BPF程序输出并关闭BPF句柄。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值