- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在 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/
IO 设备如何知道属于它的内存中的值在memory mapped IO 中发生了变化? ? 例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们更改 memory[0] 中的值时,VGA
我目前正在开发一个使用Facebook sdk登录(通过FBLoginView)的iOS应用。 一切正常,除了那些拥有较旧版本的facebook的人。 当他们按下“使用Facebook登录”按钮时,他
假设我有: this - is an - example - with some - dashesNSRange将使用`rangeOfString:@“-”拾取“-”的第一个实例,但是如果我只想要最后
Card.io SDK提供以下详细信息: 卡号,有效期,月份,年份,CVV和邮政编码。 如何从此SDK获取国家名称。 - (void)userDidProvideCreditCardInfo:(Car
iOS 应用程序如何从网络服务下载图片并在安装过程中将它们安装到用户的 iOS 设备上?可能吗? 最佳答案 您无法控制应用在用户设备上的安装,因此无法在安装过程中下载其他数据。 只需在安装后首次启动应
我曾经开发过一款企业版 iOS 产品,我们公司曾将其出售给大型企业,供他们的员工使用。 该应用程序通过 AppStore 提供,企业用户获得了公司特定的配置文件(包含应用程序配置文件)以启用他们有权使
我正在尝试将 Card.io SDK 集成到我的 iOS 应用程序中。我想为 CardIO ui 做一个简单的本地化,如更改取消按钮标题或“在此保留信用卡”提示文本。 我在 github 上找到了这个
我正在使用 CardIOView 和 CardIOViewDelegate 类,没有可以设置为 YES 的 BOOL 来扫描 collectCardholderName。我可以看到它在 CardIOP
我有一个集成了通话工具包的 voip 应用程序。每次我从我的 voip 应用程序调用时,都会在 native 电话应用程序中创建一个新的最近通话记录。我在 voip 应用程序中也有自定义联系人(电话应
iOS 应用程序如何知道应用程序打开时屏幕上是否已经有键盘?应用程序运行后,它可以接收键盘显示/隐藏通知。但是,如果应用程序在分屏模式下作为辅助应用程序打开,而主应用程序已经显示键盘,则辅助应用程序不
我在模拟器中收到以下错误: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedIm
如 Apple 文档所示,可以通过 EAAccessory Framework 与经过认证的配件(由 Apple 认证)进行通信。但是我有点困惑,因为一些帖子告诉我它也可以通过 CoreBluetoo
尽管现在的调试器已经很不错了,但有时找出应用程序中正在发生的事情的最好方法仍然是古老的 NSLog。当您连接到计算机时,这样做很容易; Xcode 会帮助弹出日志查看器面板,然后就可以了。当您不在办公
在我的 iOS 应用程序中,我定义了一些兴趣点。其中一些有一个 Kontakt.io 信标的名称,它绑定(bind)到一个特定的 PoI(我的意思是通常贴在信标标签上的名称)。现在我想在附近发现信标,
我正在为警报提示创建一个 trigger.io 插件。尝试从警报提示返回数据。这是我的代码: // Prompt + (void)show_prompt:(ForgeTask*)task{
您好,我是 Apple iOS 的新手。我阅读并搜索了很多关于推送通知的文章,但我没有发现任何关于 APNS 从 io4 到 ios 6 的新更新的信息。任何人都可以向我提供 APNS 如何在 ios
UITabBar 的高度似乎在 iOS 7 和 8/9/10/11 之间发生了变化。我发布这个问题是为了让其他人轻松找到答案。 那么:在 iPhone 和 iPad 上的 iOS 8/9/10/11
我想我可以针对不同的 iOS 版本使用不同的 Storyboard。 由于 UI 的差异,我将创建下一个 Storyboard: Main_iPhone.storyboard Main_iPad.st
我正在写一些东西,我将使用设备的 iTunes 库中的一部分音轨来覆盖 2 个视频的组合,例如: AVMutableComposition* mixComposition = [[AVMutableC
我创建了一个简单的 iOS 程序,可以顺利编译并在 iPad 模拟器上运行良好。当我告诉 XCode 4 使用我连接的 iPad 设备时,无法编译相同的程序。问题似乎是当我尝试使用附加的 iPad 时
我是一名优秀的程序员,十分优秀!