如何解释这个物理体位掩码系统的Swift SpriteKit示例代码
我正在深入研究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 } } 每次设置SKPhysicsBody的.collisionBitmask / .contactBitmask / .categoryBitmask属性时都会使用此结构:(我已使用组件和实体设计指南实现了这一点) 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 } } 到现在为止还挺好.来自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 } 这是否意味着每次我调用计算(这是他们在swift中调用的,对吧?)属性 – 当我将它分配给SKPhysicsBody时我会这样做 – 它将它添加到那些静态类词典中.但我在解释’mask’/’reduce’/’union’命令时遇到了问题. 这到底是做什么的? 解决方法
collisionMask是computed属性,它返回一个UInt32值,该值可以用作物理主体的碰撞位掩码.如果将计算属性分解为其功能部分,则更容易理解该计算属性的工作原理.
但是首先,让我们添加一个PlayerBotBot应该与DefineCollisions字典碰撞的RPColliderType对象数组: RPColliderType.definedCollisions[.PlayerBot] = [.Obstacle,.TaskBot] 此时,definedCollisions字典包含一个单独的项目,其中PlayerBot和[.Obstacle,.TaskBot]分别作为键和值.可以把它想象成可以与PlayerBot碰撞的类别是Obstacle和TaskBot. 我们现在可以使用.PlayerBot从字典中检索值(即数组): let array = RPColliderType.definedCollisions[.PlayerBot] 由于collisionMask是在RPColliderType中定义的,因此self用作字典键.此外,数组是可选的,因为对应于该键的值可能不存在于字典中. 然后,代码使用reduce方法将RPColliderType对象数组合成一个RPColliderType对象. reduce有两个参数:一个初始值(与数组元素的类型相同)和一个以值作为参数并返回值的函数(或闭包).在这种情况下,初始值是一个新的RPColliderType对象,闭包的参数和返回值也是RPColliderType对象: array?.reduce(RPColliderType(),aFunction) Apple的代码使用尾随闭包而不是传递函数来减少.从文档中,
reduce迭代数组并使用初始值和每个数组元素作为参数调用闭包,返回的值用作下一次迭代的初始值: let mask = array?.reduce(RPColliderType()) { initial,colliderType in return initial.union(colliderType) } 其中initial保持RPColliderType数组元素的中间并集,colliderType是数组的当前元素. 此时,mask是一个RPColliderType对象,我们可以将其转换为UInt32 mask?.rawValue 这是collisionMask计算属性的返回值. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |