Sim*_*per 5 bit-masks sprite-kit swift swift-dictionary gameplay-kit
我正在深入研究Apples SpriteKit和GameplayKit示例代码,并发现了一个名为'DemoBots'的项目,用Swift编写.在项目中使用了一些非常有趣的概念,我想要适应我的项目.
我已经在将碰撞处理封装到一个处理程序类中,这与在该示例代码中处理碰撞的方式非常相似.
在这个项目中,我找到了一个名为的结构的代码RPColliderType:
struct RPColliderType: OptionSetType, Hashable, CustomDebugStringConvertible {
// MARK: Static properties
/// A dictionary to specify which `ColliderType`s should be notified of contacts with other `ColliderType`s.
static var requestedContactNotifications = [RPColliderType: [RPColliderType]]()
/// A dictionary of which `ColliderType`s should collide with other `ColliderType`s.
static var definedCollisions = [RPColliderType: [RPColliderType]]()
// MARK: Properties
let rawValue: UInt32
// MARK: Options
static var Obstacle: RPColliderType { return self.init(rawValue: 1 << 0) }
static var PlayerBot: RPColliderType { return self.init(rawValue: 1 << 1) }
static var TaskBot: RPColliderType { return self.init(rawValue: 1 << 2) }
// MARK: Hashable
var hashValue: Int {
return Int(rawValue)
}
// MARK: SpriteKit Physics Convenience
/// A value that can be assigned to a 'SKPhysicsBody`'s `categoryMask` property.
var categoryMask: UInt32 {
return rawValue
}
/// A value that can be assigned to a 'SKPhysicsBody`'s `collisionMask` property.
var collisionMask: UInt32 {
// Combine all of the collision requests for this type using a bitwise or.
let mask = RPColliderType.definedCollisions[self]?.reduce(RPColliderType()) { initial, colliderType in
return initial.union(colliderType)
}
// Provide the rawValue of the resulting mask or 0 (so the object doesn't collide with anything).
return mask?.rawValue ?? 0
}
/// A value that can be assigned to a 'SKPhysicsBody`'s `contactMask` property.
var contactMask: UInt32 {
// Combine all of the contact requests for this type using a bitwise or.
let mask = RPColliderType.requestedContactNotifications[self]?.reduce(RPColliderType()) { initial, colliderType in
return initial.union(colliderType)
}
// Provide the rawValue of the resulting mask or 0 (so the object doesn't need contact callbacks).
return mask?.rawValue ?? 0
}
// MARK: ContactNotifiableType Convenience
/**
Returns `true` if the `ContactNotifiableType` associated with this `ColliderType` should be
notified of contact with the passed `ColliderType`.
*/
func notifyOnContactWithColliderType(colliderType: RPColliderType) -> Bool {
if let requestedContacts = RPColliderType.requestedContactNotifications[self] {
return requestedContacts.contains(colliderType)
}
return false
}
}
Run Code Online (Sandbox Code Playgroud)
每次设置这样的.collisionBitmask/ .contactBitmask/ .categoryBitmaskproperty 时都会使用这个结构SKPhysicsBody:(我已经使用组件和实体设计指南实现了这个)
class RPPhysicsComponent: GKComponent {
var physicsBody: SKPhysicsBody
init(physicsBody: SKPhysicsBody, colliderType: RPColliderType) {
self.physicsBody = physicsBody
self.physicsBody.categoryBitMask = colliderType.categoryMask
self.physicsBody.collisionBitMask = colliderType.collisionMask
self.physicsBody.contactTestBitMask = colliderType.contactMask
}
}
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.来自Objective-C我的问题是我不完全理解RPColliderType Struct之后的代码行:
/// A value that can be assigned to a 'SKPhysicsBody`'s `collisionMask` property.
var collisionMask: UInt32 {
// Combine all of the collision requests for this type using a bitwise or.
let mask = RPColliderType.definedCollisions[self]?.reduce(RPColliderType()) { initial, colliderType in
return initial.union(colliderType)
}
// Provide the rawValue of the resulting mask or 0 (so the object doesn't collide with anything).
return mask?.rawValue ?? 0
}
Run Code Online (Sandbox Code Playgroud)
这是否意味着每次我调用计算(这是他们在swift中调用的,对吧?)属性 - 当我将它分配给它时我会这样做SKPhysicsBody- 它将它添加到那些静态类字典中.但我在解释' mask'/' reduce'/' union'命令时遇到问题.
这到底是做什么的?
collisionMask是计算属性,它返回一个UInt32可用作物理体碰撞位掩码的值。如果将这个计算属性分解为其功能部分,就更容易理解它是如何工作的。
但首先,让我们将应该碰撞的RPColliderType对象数组添加到字典中:PlayerBotdefinedCollisions
RPColliderType.definedCollisions[.PlayerBot] = [.Obstacle, .TaskBot]\nRun Code Online (Sandbox Code Playgroud)\n\n此时,definedCollisions字典包含一个项目,其中PlayerBot和[.Obstacle, .TaskBot]分别作为键和值。将此视为可以与 a 和 发生冲突PlayerBot的Obstacle类别TaskBot。
我们现在可以用来.PlayerBot从字典中检索值(即数组):
let array = RPColliderType.definedCollisions[.PlayerBot]\nRun Code Online (Sandbox Code Playgroud)\n\n由于collisionMask是在 中定义的RPColliderType,self因此用作字典键。此外,array是可选的,因为与该键对应的值可能不存在于字典中。
然后,代码使用该方法将对象数组组合RPColliderType成单个对象。接受两个参数:一个初始值(与数组元素的类型相同)和一个将值作为参数并返回值的函数(或闭包)。在这种情况下,初始值是一个新对象,闭包的参数和返回值也是对象:RPColliderTypereducereduceRPColliderTypeRPColliderType
array?.reduce(RPColliderType(), aFunction)\nRun Code Online (Sandbox Code Playgroud)\n\nApple 的代码使用尾随闭包而不是将函数传递给reduce. 从文档中,
\n\n\n如果需要将闭包表达式作为函数\xe2\x80\x99s 最终参数传递给函数,并且闭包表达式\n 很长,则将其写为尾随闭包可能会很有用。尾随闭包是一个闭包表达式,\n 写在它支持的函数调用的括号之外(及其之后)。
\n
reduce迭代数组并使用初始值和每个数组元素作为参数调用闭包,并且返回的值用作下一次迭代的初始值:
let mask = array?.reduce(RPColliderType()) {\n initial, colliderType in\n return initial.union(colliderType)\n}\nRun Code Online (Sandbox Code Playgroud)\n\n其中initial保留数组元素的中间并集RPColliderType,并且colliderType是 的当前元素array。
此时,mask是一个RPColliderType我们可以转换为 a 的UInt32对象
mask?.rawValue\nRun Code Online (Sandbox Code Playgroud)\n\n这是计算属性的返回值collisionMask。
| 归档时间: |
|
| 查看次数: |
178 次 |
| 最近记录: |