gpt4 book ai didi

ios - 游戏引擎 Collison 位掩码... 为什么是 0x01 等?

转载 作者:可可西里 更新时间:2023-11-01 03:05:54 25 4
gpt4 key购买 nike

在 Sprite Kit(iOS 开发)和 Cocos2d-x(我知道这几乎是 Sprite Kit 的灵感来源,因此他们使用很多相同的工具)中遇到这种情况,我最终决定弄清楚为什么会这样:

当使用物理引擎时,我创建了一个 Sprite ,并向其添加了一个 physicsBody。大多数情况下,我了解如何设置类别、碰撞和接触位掩码,以及它们的工作原理。问题是实际的位掩码数:

Sprite 套件:

static const uint32_t missileCategory     =  0x1 << 0;
sprite.physicsBody.categoryBitMask = missileCategory;

Cocos2D-X:

sprite->getPhysicsBody()->setCategoryBitmask(0x01); // 0001

我完全不明白为什么我会在任何一种情况下都写 0x01 或 0x1 << 0。我有点明白他们使用的是十六进制,它与 32 位整数有关。据我所知,0x01 在二进制中是 0001,在十进制中是 1。而 0x02 在二进制中是 0010,在十进制中是 2。好的,所以有这些转换,但为什么我要把它们用于简单的东西,比如类别?

就我的逻辑而言,如果我有一个玩家类别、一个敌人类别、一个导弹类别和一个墙类别,那只有 4 个类别。为什么不为类别使用字符串?或者甚至只是任何非 CS 人员都能理解的二进制数字,例如 0、1、2 和 3?

最后,我很困惑为什么有 32 个不同的类别可用?我认为一个 32 位整数的数字是 0 到十亿个数字(当然是无符号的)。那么,为什么我没有数十亿个不同的可能类别?

是否有某种我不理解的优化?或者这只是他们使用的旧约定,但不需要?还是只有 2 个学期的大学类(class) CS 培训的人无法理解正在发生的事情?

最佳答案

使用位掩码的原因是它使您/程序能够轻松快速地计算两个对象之间是否发生碰撞。因此:这是某种优化。

假设我们有这三个类别

  • 导弹 0x1 << 0
  • 玩家 0x1 << 1
  • 0x1 << 2

现在我们有一个 Player例如,其类别设置为 player .它的碰撞位掩码设置为 missile | player | wall (+ 而不是 | 也可以)因为我们希望能够与所有三种类型发生碰撞:其他玩家、关卡墙和四处飞舞的子弹/导弹。

现在我们有一个 Missile类别设置为 missile冲突位掩码设置为 player | wall : 它不会与其他导弹碰撞,但会击中玩家和墙壁。

如果我们现在想评估两个对象是否可以相互碰撞,我们采用第一个对象的类别位掩码和第二个对象的碰撞位掩码,然后简单地 &他们:

上述设置在代码中类似于以下内容:

let player : UInt8 = 0b1 << 0  // 00000001 = 1
let missile : UInt8 = 0b1 << 1 // 00000010 = 2
let wall : UInt8 = 0b1 << 2 // 00000100 = 4

let playerCollision = player | missile | wall // 00000111 = 7
let missileCollision = player | wall // 00000101 = 5

后面的推理基本上是:

if player & missileCollision != 0 {
print("potential collision between player and missile") // prints
}
if missile & missileCollision != 0 {
print("potential collision between two missiles") // does not print
}

我们在这里使用了一些位运算,每个位代表一个类别。您可以简单地枚举位掩码 1、2、3、4、5... 但是您无法对它们进行任何数学运算。因为您不知道 5 作为类别位掩码是否真的是类别 5,或者它是类别 1 和类别 4 的对象。

然而,仅使用位我们就可以做到这一点:根据 7 的 2 次方的唯一表示是 4 + 2 + 1:因此,任何具有碰撞位掩码 7 的对象都会与类别 4、2 和 1 发生碰撞。位掩码为 5 的只是类别 1 和类别 4 的组合 - 没有其他方式。

现在因为我们不枚举 - 每个类别使用一位,而常规整数只有 32(或 64)位,我们只能有 32(或 64)个类别。

看看下面的代码和更广泛的代码,这些代码演示了如何在更一般的术语中使用掩码:

let playerCategory : UInt8 = 0b1 << 0
let missileCategory : UInt8 = 0b1 << 1
let wallCategory : UInt8 = 0b1 << 2

struct EntityStruct {
var categoryBitmask : UInt8
var collisionBitmask : UInt8
}

let player = EntityStruct(categoryBitmask: playerCategory, collisionBitmask: playerCategory | missileCategory | wallCategory)
let missileOne = EntityStruct(categoryBitmask: missileCategory, collisionBitmask: playerCategory | wallCategory)
let missileTwo = EntityStruct(categoryBitmask: missileCategory, collisionBitmask: playerCategory | wallCategory)
let wall = EntityStruct(categoryBitmask: wallCategory, collisionBitmask: playerCategory | missileCategory | wallCategory)

func canTwoObjectsCollide(first:EntityStruct, _ second:EntityStruct) -> Bool {
if first.categoryBitmask & second.collisionBitmask != 0 {
return true
}
return false
}

canTwoObjectsCollide(player, missileOne) // true
canTwoObjectsCollide(player, wall) // true
canTwoObjectsCollide(wall, missileOne) // true
canTwoObjectsCollide(missileTwo, missileOne) // false

这里的重要部分是方法 canTwoObjectsCollide不关心对象的类型或有多少类别。只要您坚持使用位掩码,就可以确定两个对象在理论上是否会发生碰撞(忽略它们的位置,这是另一天的任务)。

关于ios - 游戏引擎 Collison 位掩码... 为什么是 0x01 等?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34904564/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com