Przyjrzałem się uważnie przykładowi Apples SpriteKit & GameplayKit i znalazłem projekt o nazwie "DemoBots" napisany w języku Swift. Jest kilka bardzo interesujących pojęć używanych w tych projektach, które chciałem dostosować do moich projektów.Jak interpretować ten przykładowy kod Swift SpriteKit systemu maski bitów ciała fizycznego
Już pracowałem z enkapsulacją obsługi kolizji w klasie obsługi czegoś, co jest bardzo podobne do sposobu obsługi kolizji w tym przykładowym kodzie.
W tym projekcie znalazłem następujący kod dla struktury zwane 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
}
}
Ta struktura jest używana za każdym razem ustawić właściwość danego SKPhysicsBody
jak ta .collisionBitmask
/.contactBitmask
/.categoryBitmask
: (i wdrożyły przy użyciu instrukcji projektowania elementu &
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
}
}
Jak dotąd tak dobrze. Jadąc z Objective-C, moim problemem jest to, że nie w pełni zrozumieć, co te następujące linie kodu wyjścia z RPColliderType Struct zrobić:
/// 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
}
Czy to oznacza, że za każdym razem zadzwonię że obliczane (to, co nazywa się w szybkiej, prawej?) właściwości - robię to, gdy przypisuję ją do SKPhysicsBody
- dodaje to do tych statycznych słowników klas. Ale mam problem z interpretacją poleceń "mask
"/"reduce
"/"union
".
Co tak naprawdę robi?
Dziękuję za tak szczegółowe wyjaśnienie. Prawie tak jak napisałeś ten przykładowy kod !? Jednak. Z mojego rozumienia tego jest bardzo elegancki kawałek kodu, prawda? –
Nie ma za co. Kod jest dobrym przykładem użycia 'OptionSetType' do zarządzania kategoriami, kolizjami i maskami bitów kontaktu. – 0x141E