如何解释这个物理体位掩码系统的Swift SpriteKit示例代码

如何解释这个物理体位掩码系统的Swift SpriteKit示例代码,第1张

概述我正在深入研究Apples SpriteKit& GameplayKit示例代码,发现了一个名为’DemoBots’的项目,用 Swift编写.在项目中使用了一些非常有趣的概念,我想要适应我的项目. 我已经在将碰撞处理封装到一个处理程序类中,这与在该示例代码中处理碰撞的方式非常相似. 在这个项目中,我找到了一个名为RPColliderType的结构的代码: struct RPColliderTyp 我正在深入研究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的代码使用尾随闭包而不是传递函数来减少.从文档中,

If you need to pass a closure Expression to a function as the function’s final argument and the closure Expression@H_@R_403_6939@_67@ is long,it can be useful to write it as a trailing closure instead. A trailing closure is a closure Expression that is@H_@R_403_6939@_67@ written outsIDe of (and after) the parentheses of the function call it supports.

reduce迭代数组并使用初始值和每个数组元素作为参数调用闭包,返回的值用作下一次迭代的初始值:

let mask = array?.reduce(RPCollIDerType()) {    initial,collIDerType in    return initial.union(collIDerType)}

其中initial保持RPCollIDerType数组元素的中间并集,collIDerType是数组的当前元素.

此时,mask是一个RPCollIDerType对象,我们可以将其转换为UInt32

mask?.rawValue

这是collisionMask计算属性的返回值.

总结

以上是内存溢出为你收集整理的如何解释这个物理体位掩码系统的Swift SpriteKit示例代码全部内容,希望文章能够帮你解决如何解释这个物理体位掩码系统的Swift SpriteKit示例代码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/web/1016487.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存