Ich habe einen tiefen Blick in Apples SpriteKit & GameplayKit Beispielcode und fand ein Projekt namens "DemoBots" in Swift geschrieben. In diesen Projekten wurden einige sehr interessante Konzepte verwendet, die ich in meine Projekte integrieren wollte.Wie man diesen Swift SpriteKit Beispielcode eines Physikkörper Bitmaskensystems interpretiert
Ich arbeitete bereits mit der Kapselung der Kollisions-Behandlung in eine Handler-Klasse etwas, das sehr ähnlich zu der Art ist, wie Kollisionen in diesem Beispiel-Code behandelt werden.
In diesem Projekt fand ich den folgenden Code für eine Struktur RPColliderType
genannt:
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
}
}
Diese Struktur verwendet wird, jedes Mal, wenn die .collisionBitmask
/.contactBitmask
/.categoryBitmask
Eigenschaft eines SKPhysicsBody
wie folgt festgelegt: (Ich habe umgesetzt diese mit Komponente & Einheit Design Guide)
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
}
}
so weit so gut. Von Objective-C ist mein Problem, dass ich nicht vollständig verstehen, was die folgenden Codezeilen aus dem RPColliderType Struct tun:
/// 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
}
das bedeutet, dass jedes Mal, wenn ich nenne das berechnet (das ist, was sie genannt werden in swift, richtig?) Eigentum - ich tue das, wenn ich es einer SKPhysicsBody
zuweisen - es fügt diese zu diesen statischen Klassenwörterbüchern hinzu. Aber ich habe ein Problem bei der Interpretation der Befehle 'mask
'/'reduce
'/'union
'.
Was macht das wirklich?
Vielen Dank für solch eine detaillierte Erklärung. Fast ein bisschen wie du dieses Stück Beispielcode geschrieben hast !? Jedoch. Aus meiner Sicht ist dies ein sehr elegantes Stück Code, nicht wahr? –
Gern geschehen. Der Code ist ein gutes Beispiel für die Verwendung von 'OptionSetType' zum Verwalten von Kategorien-, Kollisions und Kontaktbitmasken. – 0x141E