Stavo dando uno sguardo approfondito a Mele SpriteKit & GameplayKit codice di esempio e ho trovato un Progetto chiamato 'DemoBots' scritto in Swift. Ci sono alcuni concetti molto interessanti usati in quei progetti che ho voluto adattare ai miei progetti.Come interpretare questo codice di esempio Swift SpriteKit di un corpo fisico sistema bitmask
Stavo già lavorando con l'incapsulamento della gestione delle collisioni in una classe di gestore qualcosa che è molto simile al modo in cui le collisioni vengono gestite in quel codice di esempio.
In questo progetto ho trovato il seguente codice per una struttura chiamata 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
}
}
Questa struct viene utilizzato ogni volta che si imposta la proprietà .collisionBitmask
/.contactBitmask
/.categoryBitmask
di un SKPhysicsBody
come questa: (ho implementato questo componente utilizzando guida alla progettazione & entità)
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
}
}
Fin qui tutto bene. Venendo da Objective-C il mio problema è che io non comprendere appieno che cosa quelle seguenti righe di codice fuori del RPColliderType Struct fanno:
/// 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
}
Questo significa che ogni volta che lo chiamo calcolato (questo è ciò che essi sono chiamati in swift, right?) property - Lo faccio quando lo assegno ad un SKPhysicsBody
- lo aggiunge a quei dizionari di classe statici. Ma ho un problema nell'interpretazione dei comandi 'mask
'/'reduce
'/'union
'.
Che cosa fa veramente?
Grazie per una spiegazione così dettagliata. Quasi un po 'come hai scritto quel pezzo di codice di esempio !? Però. Dalla mia comprensione questo è un pezzo di codice molto elegante, non è vero? –
Prego. Il codice è un buon esempio di come usare 'OptionSetType' per gestire le maschere di bit di categoria, collisione e contatto. – 0x141E