@@ -1,25 +1,20 @@
internal import CPlaydate
// / T h e c a c h e d ` p l a y d a t e - > s p r i t e ` C A P I t a b l e .
private var spriteAPI : UnsafePointer < playdate_sprite > { Playdate . spriteAPI . unsafelyUnwrapped }
// / A s p r i t e : a d r a w a b l e o b j e c t w i t h p o s i t i o n , z - o r d e r , a n d c o l l i s i o n
// / s u p p o r t . W r a p s ` L C D S p r i t e ` . S t a t i c m e m b e r s w r a p t h e g l o b a l s p r i t e
// / s y s t e m f u n c t i o n s .
// /
// / T h e b i n d i n g s t o r e s a b a c k - r e f e r e n c e t o e a c h ` S p r i t e ` w r a p p e r i n t h e
// / u n d e r l y i n g ` L C D S p r i t e ` ' s u s e r d a t a s l o t , s o c a l l b a c k s a n d q u e r i e s c a n
// / r e c o v e r t h e w r a p p e r . D o n o t m i x t h e s e w r a p p e r s w i t h C c o d e t h a t s e t s
// / i t s o w n s p r i t e u s e r d a t a ; u s e ` u s e r d a t a ` f o r p e r - s p r i t e s t o r a g e i n s t e a d .
// / A d r a w a b l e o b j e c t w i t h p o s i t i o n , z - o r d e r , a n d c o l l i s i o n s . W r a p s ` L C D S p r i t e ` ; s t a t i c
// / m e m b e r s w r a p t h e g l o b a l s p r i t e f u n c t i o n s . R e t a i n s i t s i m a g e , s t e n c i l , t i l e m a p , c l o s u r e s .
// / T h e C u s e r d a t a s l o t h o l d s t h e w r a p p e r b a c k - r e f e r e n c e ; d o n ' t s e t i t f r o m C ( u s e ` u s e r d a t a ` ) .
// / ` a d d ( ) ` r e t a i n s t h e s p r i t e u n t i l ` r e m o v e ( ) ` / ` r e m o v e A l l ( ) ` . O w n e d s p r i t e s f r e e t h e i r
// / ` L C D S p r i t e ` o n d e i n i t ; s p r i t e s c r e a t e d e l s e w h e r e g e t t r a n s i e n t , n o n - o w n i n g w r a p p e r s .
public final class Sprite {
let pointer : OpaquePointer
let isOwned : Bool
// / P o s i t i o n i n t h e s t a t i c ` d i s p l a y L i s t ` , o r - 1 w h e n n o t i n i t ; m a k e s
// / ` a d d ( ) ` / ` r e m o v e ( ) ` O ( 1 ) i n s t e a d o f s c a n n i n g t h e l i s t .
// / I n d e x i n ` d i s p l a y L i s t ` , o r - 1 w h e n a b s e n t ; m a k e s ` a d d ( ) ` / ` r e m o v e ( ) ` O ( 1 ) .
private var displayListIndex = - 1
// / P e r - s p r i t e c a l l b a c k s a n d r e t a i n e d r e s o u r c e s .
// / C a l l e d b y t h e C t r a m p o l i n e s ; r e s o u r c e s r e t a i n e d s o C n e v e r p o i n t s a t f r e e d o n e s .
var updateFunction : ( ( Sprite ) -> Void ) ?
var drawFunction : ( ( Sprite , _ bounds : Rect , _ drawRect : Rect ) -> Void ) ?
var collisionResponseFunction : ( ( Sprite , _ other : Sprite ) -> CollisionResponse ) ?
@@ -27,22 +22,19 @@ public final class Sprite {
private var retainedStencil : Graphics . Bitmap ?
private var retainedTilemap : Graphics . TileMap ?
// / F r e e - f o r m s t o r a g e f o r g a m e u s e ( t h e C u s e r d a t a s l o t i s r e s e r v e d
// / b y t h e b i n d i n g ) .
// / F r e e - f o r m g a m e s t o r a g e . N o t c o p i e d b y ` c o p y ( ) ` .
public var userdata : AnyObject ?
init ( pointer : OpaquePointer , isOwned : Bool ) {
self . pointer = pointer
self . isOwned = isOwned
// T r a n s i e n t w r a p p e r s f o r s p r i t e s c r e a t e d o u t s i d e t h e b i n d i n g m u s t n o t
// s t o r e a b a c k - r e f e r e n c e : i t w o u l d d a n g l e o n c e t h e w r a p p e r i s
// d e a l l o c a t e d , a n d o n l y o w n e d w r a p p e r s c l e a r i t i n ` d e i n i t ` .
// O n l y o w n e d w r a p p e r s c l e a r t h e b a c k - r e f e r e n c e i n d e i n i t ; o t h e r s w o u l d d a n g l e .
if isOwned {
spriteAPI . pointee . setUserdata . unsafelyUnwrapped ( pointer , Unmanaged . passUnretained ( self ) . toOpaque ( ) )
}
}
// / A l l o c a t e s a n e w s p r i t e .
// / A l l o c a t e s a s p r i t e , n o t y e t i n t h e d i s p l a y l i s t .
public convenience init ( ) {
self . init ( pointer : spriteAPI . pointee . newSprite . unsafelyUnwrapped ( ) . unsafelyUnwrapped , isOwned : true )
}
@@ -54,8 +46,7 @@ public final class Sprite {
}
}
// / R e t u r n s t h e S w i f t w r a p p e r s t o r e d i n t h e s p r i t e ' s u s e r d a t a , o r a
// / t r a n s i e n t u n o w n e d w r a p p e r f o r s p r i t e s c r e a t e d o u t s i d e t h e b i n d i n g .
// / T h e s t o r e d w r a p p e r , o r a t r a n s i e n t n o n - o w n i n g o n e f o r s p r i t e s c r e a t e d e l s e w h e r e .
static func wrapper ( for pointer : OpaquePointer ) -> Sprite {
if let userdata = spriteAPI . pointee . getUserdata . unsafelyUnwrapped ( pointer ) {
return Unmanaged < Sprite > . fromOpaque ( userdata ) . takeUnretainedValue ( )
@@ -63,8 +54,7 @@ public final class Sprite {
return Sprite ( pointer : pointer , isOwned : false )
}
// / C o p i e s t h e s p r i t e . C a l l b a c k s a n d r e t a i n e d r e s o u r c e s a r e c a r r i e d
// / o v e r t o t h e c o p y .
// / A l s o c o p i e s c a l l b a c k s a n d t h e r e t a i n e d i m a g e , s t e n c i l , a n d t i l e m a p ; n o t ` u s e r d a t a ` .
public func copy ( ) -> Sprite {
let copy = Sprite ( pointer : spriteAPI . pointee . copy . unsafelyUnwrapped ( pointer ) . unsafelyUnwrapped ,
isOwned : true )
@@ -77,38 +67,36 @@ public final class Sprite {
return copy
}
// MARK: - D i s p l a y l i s t
// MARK: - D i s p l a y l i s t a n d d r a w i n g
// / S p r i t e s c u r r e n t l y a d d e d t o t h e d i s p l a y l i s t , k e p t a l i v e h e r e .
// / K e e p s a d d e d s p r i t e s a l i v e w h i l e t h e C d i s p l a y l i s t r e f e r e n c e s t h e m .
nonisolated ( unsafe ) private static var displayList : [ Sprite ] = [ ]
// / W h e n ` t r u e ` , a l l s p r i t e s r e d r a w e v e r y f r a m e i n s t e a d o f o n l y w h e n
// / m a r k e d d i r t y .
// / ` t r u e ` r e d r a w s a l l s p r i t e s e v e r y f r a m e ; c a n b e f a s t e r w i t h m a n y m o v i n g s p r i t e s .
public static func setAlwaysRedraw ( _ flag : Bool ) {
spriteAPI . pointee . setAlwaysRedraw . unsafelyUnwrapped ( flag ? 1 : 0 )
}
// / M a r k s t h e g i v e n s c r e e n r e g i o n a s n e e d i n g a r e d r a w .
// / M a r k s ` r e c t ` ( s c r e e n c o o r d i n a t e s ) d i r t y . G r a p h i c s d r a w i n g c a l l s d o t h i s a l r e a d y .
public static func addDirtyRect ( _ rect : Graphics . Rect ) {
spriteAPI . pointee . addDirtyRect . unsafelyUnwrapped ( rect . cValue )
}
// / D r a w s e v e r y s p r i t e i n t h e d i s p l a y l i s t .
public static func drawAll ( ) {
spriteAPI . pointee . drawSprites . unsafelyUnwrapped ( )
}
// / U p d a t e s a n d t h e n d r a w s e v e r y s p r i t e i n t h e d i s p l a y l i s t .
// / C a l l s e a c h s p r i t e ' s u p d a t e f u n c t i o n , t h e n d r a w s a l l s p r i t e s .
public static func updateAndDrawAll ( ) {
spriteAPI . pointee . updateAndDrawSprites . unsafelyUnwrapped ( )
}
// / T h e n u m b e r o f s p r i t e s i n t h e d i s p l a y l i s t .
// / N u m b e r o f s p r i t e s i n t h e d i s p l a y l i s t .
public static var count : Int {
Int ( spriteAPI . pointee . getSpriteCount . unsafelyUnwrapped ( ) )
}
// / A d d s t h e s p r i t e t o t h e d i s p l a y l i s t .
// / A d d s t o t h e d i s p l a y l i s t ; r e p e a t e d a d d s r e t a i n o n l y o n c e .
public func add ( ) {
spriteAPI . pointee . addSprite . unsafelyUnwrapped ( pointer )
if displayListIndex < 0 {
@@ -117,12 +105,10 @@ public final class Sprite {
}
}
// / R e m o v e s t h e s p r i t e f r o m t h e d i s p l a y l i s t .
public func remove ( ) {
spriteAPI . pointee . removeSprite . unsafelyUnwrapped ( pointer )
guard displayListIndex >= 0 else { return }
// S w a p - r e m o v e : t h e k e e p - a l i v e l i s t i s u n o r d e r e d ( t h e O S k e e p s t h e
// d r a w o r d e r ) , s o t h e l a s t s p r i t e c a n t a k e t h e v a c a t e d s l o t .
// S w a p - r e m o v e : t h e k e e p - a l i v e l i s t i s u n o r d e r e d ( t h e O S k e e p s d r a w o r d e r ) .
let index = displayListIndex
let last = Sprite . displayList . removeLast ( )
if last !== self {
@@ -132,12 +118,10 @@ public final class Sprite {
displayListIndex = - 1
}
// / R e m o v e s t h e g i v e n s p r i t e s f r o m t h e d i s p l a y l i s t .
public static func remove ( _ sprites : [ Sprite ] ) {
for sprite in sprites { sprite . remove ( ) }
}
// / R e m o v e s e v e r y s p r i t e f r o m t h e d i s p l a y l i s t .
public static func removeAll ( ) {
spriteAPI . pointee . removeAllSprites . unsafelyUnwrapped ( )
for sprite in displayList { sprite . displayListIndex = - 1 }
@@ -146,36 +130,34 @@ public final class Sprite {
// MARK: - G e o m e t r y
// / T h e s p r i t e ' s b o u n d s . S e t t i n g t h i s p o s i t i o n s a n d s i z e s t h e s p r i t e .
public var bounds : Rect {
get { Rect ( spriteAPI . pointee . getBounds . unsafelyUnwrapped ( pointer ) ) }
set { spriteAPI . pointee . setBounds . unsafelyUnwrapped ( pointer , newValue . cValue ) }
}
// / M o v e s t h e s p r i t e s o i t s a n c h o r p o i n t i s a t ( x , y ) .
// / M o v e s s o ` c e n t e r ` i s a t ( ` x ` , ` y ` ) , r e c o m p u t i n g b o u n d s f r o m s i z e a n d ` c e n t e r ` .
public func moveTo ( x : Float , y : Float ) {
spriteAPI . pointee . moveTo . unsafelyUnwrapped ( pointer , x , y )
}
// / M o v e s t h e s p r i t e b y ( d x , d y ) .
public func moveBy ( dx : Float , dy : Float ) {
spriteAPI . pointee . moveBy . unsafelyUnwrapped ( pointer , dx , dy )
}
// / T h e s p r i t e ' s a n c h o r p o s i t i o n .
// / W h e r e t h e s p r i t e ' s ` c e n t e r ` p o i n t i s .
public var position : ( x : Float , y : Float ) {
var x : Float = 0 , y : Float = 0
spriteAPI . pointee . getPosition . unsafelyUnwrapped ( pointer , & x , & y )
return ( x , y )
}
// / S e t s t h e s p r i t e ' s s i z e w i t h o u t c h a n g i n g i t s i m a g e .
// / S i z e ` m o v e T o ( x : y : ) ` u s e s t o c o m p u t e b o u n d s .
public func setSize ( width : Float , height : Float ) {
spriteAPI . pointee . setSize . unsafelyUnwrapped ( pointer , width , height )
}
// / T h e a n c h o r p o i n t u s e d f o r p o s i t i o n i n g , w h e r e ( 0 , 0 ) i s t h e t o p
// / l e f t a n d ( 1 , 1 ) t h e b o t t o m r i g h t . D e f a u l t s t o ( 0 . 5 , 0 . 5 ) .
// / D r a w i n g c e n t e r a s a 0 . . . 1 f r a c t i o n o f s i z e ; ( 0 , 0 ) i s t o p l e f t , ( 1 , 1 ) b o t t o m r i g h t .
// / D e f a u l t ( 0 . 5 , 0 . 5 ) .
public var center : ( x : Float , y : Float ) {
get {
var x : Float = 0 , y : Float = 0
@@ -185,7 +167,7 @@ public final class Sprite {
set { spriteAPI . pointee . setCenter . unsafelyUnwrapped ( pointer , newValue . x , newValue . y ) }
}
// / D r a w o r d e r : h i g h e r v a l u e s d r a w o n t o p .
// / H i g h e r v a l u e s d r a w o n t o p .
public var zIndex : Int16 {
get { spriteAPI . pointee . getZIndex . unsafelyUnwrapped ( pointer ) }
set { spriteAPI . pointee . setZIndex . unsafelyUnwrapped ( pointer , newValue ) }
@@ -193,20 +175,20 @@ public final class Sprite {
// MARK: - A p p e a r a n c e
// / S e t s t h e s p r i t e ' s i m a g e , r e s i z i n g i t s b o u n d s t o m a t c h .
// / S e t s t h e i m a g e , d r a w n w i t h ` f l i p ` , a n d r e s i z e s b o u n d s t o m a t c h ; ` n i l ` r e m o v e s i t .
public func setImage ( _ image : Graphics . Bitmap ? , flip : Graphics . BitmapFlip = . unflipped ) {
retainedImage = image
spriteAPI . pointee . setImage . unsafelyUnwrapped ( pointer , image ? . pointer , flip . cValue )
}
// / T h e s p r i t e ' s i m a g e .
// / T h e i m a g e f r o m ` s e t I m a g e ( _ : f l i p : ) ` , e l s e a n o n - o w n i n g w r a p p e r o f t h e C o n e , o r ` n i l ` .
public var image : Graphics . Bitmap ? {
if let retainedImage { return retainedImage }
guard let image = spriteAPI . pointee . getImage . unsafelyUnwrapped ( pointer ) else { return nil }
return Graphics . Bitmap ( pointer : image , isOwned : false )
}
// / S e t s t h e s p r i t e ' s t i l e m a p , r e s i z i n g i t s b o u n d s t o m a t c h .
// / T h e t i l e m a p s e t h e r e . S e t t i n g r e s i z e s b o u n d s t o m a t c h ; ` n i l ` r e m o v e s i t .
public var tilemap : Graphics . TileMap ? {
get { retainedTilemap }
set {
@@ -215,28 +197,25 @@ public final class Sprite {
}
}
// / T h e m o d e u s e d t o d r a w t h e s p r i t e ' s i m a g e .
public func setDrawMode ( _ mode : Graphics . DrawMode ) {
spriteAPI . pointee . setDrawMode . unsafelyUnwrapped ( pointer , mode . cValue )
}
// / H o w t h e s p r i t e ' s i m a g e i s m i r r o r e d w h e n d r a w n .
public var imageFlip : Graphics . BitmapFlip {
get { Graphics . BitmapFlip ( spriteAPI . pointee . getImageFlip . unsafelyUnwrapped ( pointer ) ) }
set { spriteAPI . pointee . setImageFlip . unsafelyUnwrapped ( pointer , newValue . cValue ) }
}
// / S e t s t h e s t e n c i l a p p l i e d w h e n d r a w i n g t h e s p r i t e . I f ` t i l e ` i s
// / ` t r u e ` t h e i m a g e w i d t h m u s t b e a m u l t i p l e o f 3 2 .
// / P i x e l s d r a w o n l y w h e r e ` s t e n c i l ` i s w h i t e . S c r e e n s p a c e : i t d o e s n ' t m o v e w i t h t h e
// / s p r i t e . ` n i l ` c l e a r s i t . W i t h ` t i l e ` , i t r e p e a t s ; w i d t h m u s t b e a m u l t i p l e o f 3 2 .
public func setStencil ( _ stencil : Graphics . Bitmap ? , tile : Bool = false ) {
retainedStencil = stencil
spriteAPI . pointee . setStencilImage . unsafelyUnwrapped ( pointer , stencil ? . pointer , tile ? 1 : 0 )
}
// / S e t s a n 8 × 8 s t e n c i l p a t t e r n ( 8 r o w s o f i m a g e d a t a ) .
// / S e t s a n 8 × 8 s t e n c i l p a t t e r n , o n e b y t e p e r r o w .
public func setStencilPattern ( _ rows : ( UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 , UInt8 ) ) {
// T h e t u p l e i s a l r e a d y 8 c o n t i g u o u s b y t e s ; t h e C s i d e c o p i e s t h e
// p a t t e r n , s o p a s s i n g t h e s t a c k s t o r a g e d i r e c t l y i s s a f e .
// T h e t u p l e i s 8 c o n t i g u o u s b y t e s a n d C c o p i e s t h e m , s o s t a c k s t o r a g e i s s a f e .
withUnsafeBytes ( of : rows ) { buffer in
let pattern = UnsafeMutablePointer (
mutating : buffer . baseAddress . unsafelyUnwrapped . assumingMemoryBound ( to : UInt8 . self ) )
@@ -244,12 +223,22 @@ public final class Sprite {
}
}
// / ` I n l i n e A r r a y ` o v e r l o a d o f t h e t u p l e v a r i a n t .
@ available ( macOS 26 , * )
public func setStencilPattern ( _ rows : [ 8 of UInt8 ] ) {
// C c o p i e s t h e p a t t e r n , s o p a s s i n g t h e i n l i n e a r r a y ' s s t o r a g e i s s a f e .
rows . span . withUnsafeBufferPointer { buffer in
spriteAPI . pointee . setStencilPattern . unsafelyUnwrapped (
pointer , UnsafeMutablePointer ( mutating : buffer . baseAddress ) )
}
}
public func clearStencil ( ) {
retainedStencil = nil
spriteAPI . pointee . clearStencil . unsafelyUnwrapped ( pointer )
}
// / C l i p s t h e s p r i t e ' s d r a w i n g t o ` r e c t ` ( s c r e e n c o o r d i n a t e s ) .
// / ` r e c t ` i s i n s c r e e n c o o r d i n a t e s .
public func setClipRect ( _ rect : Graphics . Rect ) {
spriteAPI . pointee . setClipRect . unsafelyUnwrapped ( pointer , rect . cValue )
}
@@ -258,67 +247,63 @@ public final class Sprite {
spriteAPI . pointee . clearClipRect . unsafelyUnwrapped ( pointer )
}
// / C l i p s a l l s p r i t e s w i t h z - i n d e x i n ` s t a r t Z . . . e n d Z ` t o ` r e c t ` .
// / C l i p s s p r i t e s w i t h a z - i n d e x i n ` s t a r t Z . . . e n d Z ` ( i n c l u s i v e ) t o ` r e c t ` .
public static func setClipRectsInRange ( _ rect : Graphics . Rect , startZ : Int , endZ : Int ) {
spriteAPI . pointee . setClipRectsInRange . unsafelyUnwrapped ( rect . cValue , Int32 ( startZ ) , Int32 ( endZ ) )
}
// / C l e a r s c l i p r e c t s o f s p r i t e s w i t h a z - i n d e x i n ` s t a r t Z . . . e n d Z ` ( i n c l u s i v e ) .
public static func clearClipRectsInRange ( startZ : Int , endZ : Int ) {
spriteAPI . pointee . clearClipRectsInRange . unsafelyUnwrapped ( Int32 ( startZ ) , Int32 ( endZ ) )
}
// MARK: - B e h a v i o r f l a g s
// MARK: - F l a g s , r e d r a w , a n d t a g
// / W h e t h e r t h e s p r i t e ' s u p d a t e f u n c t i o n i s c a l l e d b y ` u p d a t e A n d D r a w A l l ( ) ` .
// / W h e t h e r ` u p d a t e A n d D r a w A l l ( ) ` c a l l s t h e u p d a t e f u n c t i o n .
public var updatesEnabled : Bool {
get { spriteAPI . pointee . updatesEnabled . unsafelyUnwrapped ( pointer ) != 0 }
set { spriteAPI . pointee . setUpdatesEnabled . unsafelyUnwrapped ( pointer , newValue ? 1 : 0 ) }
}
// / W h e t h e r t h e s p r i t e p a r t i c i p a t e s i n c o l l i s i o n s .
// / A l s o r e q u i r e s a ` c o l l i d e R e c t ` . D e f a u l t ` t r u e ` .
public var collisionsEnabled : Bool {
get { spriteAPI . pointee . collisionsEnabled . unsafelyUnwrapped ( pointer ) != 0 }
set { spriteAPI . pointee . setCollisionsEnabled . unsafelyUnwrapped ( pointer , newValue ? 1 : 0 ) }
}
// / W h e t h e r t h e s p r i t e i s d r a w n .
public var isVisible : Bool {
get { spriteAPI . pointee . isVisible . unsafelyUnwrapped ( pointer ) != 0 }
set { spriteAPI . pointee . setVisible . unsafelyUnwrapped ( pointer , newValue ? 1 : 0 ) }
}
// / M a r k i n g a s p r i t e o p a q u e t e l l s t h e s y s t e m i t d o e s n o t n e e d t o r e d r a w
// / a n y t h i n g b e h i n d i t .
// / O p a q u e s p r i t e s h i d e w h a t ' s b e h i n d t h e m . S e t a u t o m a t i c a l l y f o r i m a g e s w i t h o u t a m a s k .
public func setOpaque ( _ flag : Bool ) {
spriteAPI . pointee . setOpaque . unsafelyUnwrapped ( pointer , flag ? 1 : 0 )
}
// / F o r c e s t h e s p r i t e t o r e d r a w t h i s f r a m e .
public func markDirty ( ) {
spriteAPI . pointee . markDirty . unsafelyUnwrapped ( pointer )
}
// / M a r k s p a r t o f t h e s p r i t e ( i n s p r i t e - l o c a l c o o r d i n a t e s ) a s n e e d i n g
// / a r e d r a w .
// / ` r e c t ` i s r e l a t i v e t o t h e s p r i t e ' s t o p - l e f t c o r n e r .
public func markDirty ( rect : Rect ) {
spriteAPI . pointee . markDirtyRect . unsafelyUnwrapped ( pointer , rect . cValue )
}
// / A n i n t e g e r t a g f o r i d e n t i f y i n g s p r i t e s ( e . g . i n c o l l i s i o n s ) .
// / G a m e - d e f i n e d t a g , 0 – 2 5 5 , e . g . f o r c o l l i s i o n h a n d l i n g .
public var tag : UInt8 {
get { spriteAPI . pointee . getTag . unsafelyUnwrapped ( pointer ) }
set { spriteAPI . pointee . setTag . unsafelyUnwrapped ( pointer , newValue ) }
}
// / W h e n ` t r u e ` , t h e s p r i t e d r a w s i n s c r e e n c o o r d i n a t e s , i g n o r i n g t h e
// / g l o b a l d r a w o f f s e t .
// / ` t r u e ` d r a w s i n s c r e e n c o o r d i n a t e s ; c o l l i s i o n s s t a y i n w o r l d s p a c e .
public func setIgnoresDrawOffset ( _ flag : Bool ) {
spriteAPI . pointee . setIgnoresDrawOffset . unsafelyUnwrapped ( pointer , flag ? 1 : 0 )
}
// MARK: - C a l l b a c k s
// / S e t s t h e f u n c t i o n c a l l e d b y ` u p d a t e A n d D r a w A l l ( ) ` f o r t h i s s p r i t e .
// / C a l l e d b y ` u p d a t e A n d D r a w A l l ( ) ` ; ` n i l ` r e m o v e s i t .
public func setUpdateFunction ( _ update : ( ( Sprite ) -> Void ) ? ) {
updateFunction = update
if update != nil {
@@ -332,9 +317,8 @@ public final class Sprite {
}
}
// / S e t s a c u s t o m d r a w f u n c t i o n , c a l l e d w h e n t h e s p r i t e n e e d s t o d r a w .
// / ` b o u n d s ` i s t h e s p r i t e ' s b o u n d s ; ` d r a w R e c t ` i s t h e r e g i o n t h a t
// / n e e d s r e d r a w i n g .
// / R e c e i v e s ` b o u n d s ` a n d t h e d i r t y ` d r a w R e c t ` ; ` n i l ` r e m o v e s i t . R u n s o n l y w h i l e o n
// / s c r e e n w i t h a s i z e ( f r o m ` s e t S i z e ( w i d t h : h e i g h t : ) ` o r ` b o u n d s ` ) .
public func setDrawFunction ( _ draw : ( ( Sprite , _ bounds : Rect , _ drawRect : Rect ) -> Void ) ? ) {
drawFunction = draw
if draw != nil {
@@ -350,12 +334,12 @@ public final class Sprite {
// MARK: - C o l l i s i o n s
// / C l e a r s t h e c o l l i s i o n w o r l d . C a l l w h e n c h a n g i n g s c e n e s .
// / F r e e s a n d r e a l l o c a t e s t h e c o l l i s i o n d a t a , r e s e t t i n g i t . C a l l w h e n c h a n g i n g s c e n e s .
public static func resetCollisionWorld ( ) {
spriteAPI . pointee . resetCollisionWorld . unsafelyUnwrapped ( )
}
// / T h e r e c t ( i n s p r i t e - l o c a l c o o r d i n a t e s ) u s e d f o r c o l l i s i o n s .
// / R e l a t i v e t o t h e s p r i t e ' s b o u n d s .
public var collideRect : Rect {
get { Rect ( spriteAPI . pointee . getCollideRect . unsafelyUnwrapped ( pointer ) ) }
set { spriteAPI . pointee . setCollideRect . unsafelyUnwrapped ( pointer , newValue . cValue ) }
@@ -365,8 +349,7 @@ public final class Sprite {
spriteAPI . pointee . clearCollideRect . unsafelyUnwrapped ( pointer )
}
// / S e t s t h e f u n c t i o n d e c i d i n g h o w t h i s s p r i t e r e s p o n d s w h e n i t
// / c o l l i d e s w i t h ` o t h e r ` .
// / C h o o s e s t h i s s p r i t e ' s r e s p o n s e w h e n c o l l i d i n g w i t h ` o t h e r ` ; ` n i l ` r e m o v e s i t .
public func setCollisionResponseFunction ( _ filter : ( ( Sprite , _ other : Sprite ) -> CollisionResponse ) ? ) {
collisionResponseFunction = filter
if filter != nil {
@@ -381,7 +364,7 @@ public final class Sprite {
}
}
// / V i s i t s a n d f r e e s a C c o l l i s i o n i n f o a r r a y .
// / V i s i t s e a c h e n t r y o f a C c o l l i s i o n a r r a y , t h e n f r e e s i t ( C t r a n s f e r s o w n e r s h i p ) .
private static func visitCollisions ( _ pointer : UnsafeMutablePointer < SpriteCollisionInfo > ? ,
count : Int32 , _ visit : ( CollisionInfo ) -> Void ) {
guard let pointer else { return }
@@ -400,8 +383,7 @@ public final class Sprite {
return infos
}
// / R e t u r n s t h e c o l l i s i o n s t h a t w o u l d o c c u r i f t h e s p r i t e m o v e d t o w a r d
// / ( g o a l X , g o a l Y ) , w i t h o u t m o v i n g i t .
// / W h e r e a m o v e t o w a r d t h e g o a l w o u l d e n d a n d w h a t i t w o u l d h i t , w i t h o u t m o v i n g .
public func checkCollisions ( goalX : Float , goalY : Float )
-> ( actual : ( x : Float , y : Float ) , collisions : [ CollisionInfo ] ) {
var actualX : Float = 0 , actualY : Float = 0 , count : Int32 = 0
@@ -410,8 +392,7 @@ public final class Sprite {
return ( ( actualX , actualY ) , Sprite . collisionInfos ( result , count : count ) )
}
// / L i k e ` c h e c k C o l l i s i o n s ( g o a l X : g o a l Y : ) ` , b u t v i s i t s e a c h c o l l i s i o n
// / i n s t e a d o f b u i l d i n g a n a r r a y , a v o i d i n g p e r - c a l l a l l o c a t i o n s .
// / L i k e ` c h e c k C o l l i s i o n s ( g o a l X : g o a l Y : ) ` , b u t v i s i t s e a c h c o l l i s i o n w i t h o u t a l l o c a t i n g .
public func checkCollisions ( goalX : Float , goalY : Float ,
_ visit : ( CollisionInfo ) -> Void ) -> ( x : Float , y : Float ) {
var actualX : Float = 0 , actualY : Float = 0 , count : Int32 = 0
@@ -421,8 +402,8 @@ public final class Sprite {
return ( actualX , actualY )
}
// / M o v e s t h e s p r i t e t o w a r d ( g o a l X , g o a l Y ) , r e s o l v i n g c o l l i s i o n s , a n d
// / r e t u r n s w h e r e i t e n d e d u p a n d w h a t i t h i t .
// / M o v e s t o w a r d t h e g o a l , r e s o l v i n g c o l l i s i o n s . R e t u r n s t h e f i n a l p o s i t i o n ( t h e g o a l i f
// / n o t h i n g w a s h i t ) a n d t h e c o l l i s i o n s .
@ discardableResult
public func moveWithCollisions ( goalX : Float , goalY : Float )
-> ( actual : ( x : Float , y : Float ) , collisions : [ CollisionInfo ] ) {
@@ -432,8 +413,7 @@ public final class Sprite {
return ( ( actualX , actualY ) , Sprite . collisionInfos ( result , count : count ) )
}
// / L i k e ` m o v e W i t h C o l l i s i o n s ( g o a l X : g o a l Y : ) ` , b u t v i s i t s e a c h c o l l i s i o n
// / i n s t e a d o f b u i l d i n g a n a r r a y , a v o i d i n g p e r - c a l l a l l o c a t i o n s .
// / L i k e ` m o v e W i t h C o l l i s i o n s ( g o a l X : g o a l Y : ) ` , b u t v i s i t s c o l l i s i o n s w i t h o u t a l l o c a t i n g .
@ discardableResult
public func moveWithCollisions ( goalX : Float , goalY : Float ,
_ visit : ( CollisionInfo ) -> Void ) -> ( x : Float , y : Float ) {
@@ -444,7 +424,7 @@ public final class Sprite {
return ( actualX , actualY )
}
// / V i s i t s a n d f r e e s a C s p r i t e p o i n t e r a r r a y .
// / V i s i t s n o n - n u l l e n t r i e s o f a C s p r i t e a r r a y , t h e n f r e e s i t ( C t r a n s f e r s o w n e r s h i p ) .
private static func visitSprites ( _ pointer : UnsafeMutablePointer < OpaquePointer ? >? ,
count : Int32 , _ visit : ( Sprite ) -> Void ) {
guard let pointer else { return }
@@ -465,30 +445,28 @@ public final class Sprite {
return sprites
}
// / S p r i t e s w i t h c o l l i s i o n r e c t s c o n t a i n i n g t h e p o i n t .
// / S p r i t e s w h o s e c o l l i d e r e c t s c o n t a i n ( ` x ` , ` y ` ) .
public static func query ( atPoint x : Float , _ y : Float ) -> [ Sprite ] {
var count : Int32 = 0
let result = spriteAPI . pointee . querySpritesAtPoint . unsafelyUnwrapped ( x , y , & count )
return sprites ( result , count : count )
}
// / L i k e ` q u e r y ( a t P o i n t : _ : ) ` , v i s i t i n g e a c h s p r i t e w i t h o u t b u i l d i n g a n
// / a r r a y .
// / L i k e ` q u e r y ( a t P o i n t : _ : ) ` , b u t v i s i t s e a c h s p r i t e w i t h o u t a l l o c a t i n g .
public static func query ( atPoint x : Float , _ y : Float , _ visit : ( Sprite ) -> Void ) {
var count : Int32 = 0
let result = spriteAPI . pointee . querySpritesAtPoint . unsafelyUnwrapped ( x , y , & count )
visitSprites ( result , count : count , visit )
}
// / S p r i t e s w i t h c o l l i s i o n r e c t s i n t e r s e c t i n g t h e r e c t .
// / S p r i t e s w h o s e c o l l i d e r e c t s i n t e r s e c t t h e ` w i d t h ` × ` h e i g h t ` r e c t a t ( ` x ` , ` y ` ) .
public static func query ( inRect x : Float , _ y : Float , width : Float , height : Float ) -> [ Sprite ] {
var count : Int32 = 0
let result = spriteAPI . pointee . querySpritesInRect . unsafelyUnwrapped ( x , y , width , height , & count )
return sprites ( result , count : count )
}
// / L i k e ` q u e r y ( i n R e c t : _ : w i d t h : h e i g h t : ) ` , v i s i t i n g e a c h s p r i t e w i t h o u t
// / b u i l d i n g a n a r r a y .
// / L i k e ` q u e r y ( i n R e c t : _ : w i d t h : h e i g h t : ) ` , b u t v i s i t s e a c h s p r i t e w i t h o u t a l l o c a t i n g .
public static func query ( inRect x : Float , _ y : Float , width : Float , height : Float ,
_ visit : ( Sprite ) -> Void ) {
var count : Int32 = 0
@@ -496,15 +474,14 @@ public final class Sprite {
visitSprites ( result , count : count , visit )
}
// / S p r i t e s w i t h c o l l i s i o n r e c t s i n t e r s e c t i n g t h e l i n e s e g m e n t .
// / S p r i t e s w h o s e c o l l i d e r e c t s i n t e r s e c t t h e s e g m e n t ( ` x 1 ` , ` y 1 ` ) – ( ` x 2 ` , ` y 2 ` ) .
public static func query ( alongLine x1 : Float , _ y1 : Float , _ x2 : Float , _ y2 : Float ) -> [ Sprite ] {
var count : Int32 = 0
let result = spriteAPI . pointee . querySpritesAlongLine . unsafelyUnwrapped ( x1 , y1 , x2 , y2 , & count )
return sprites ( result , count : count )
}
// / L i k e ` q u e r y ( a l o n g L i n e : _ : _ : _ : ) ` , v i s i t i n g e a c h s p r i t e w i t h o u t b u i l d i n g
// / a n a r r a y .
// / L i k e ` q u e r y ( a l o n g L i n e : _ : _ : _ : ) ` , b u t v i s i t s e a c h s p r i t e w i t h o u t a l l o c a t i n g .
public static func query ( alongLine x1 : Float , _ y1 : Float , _ x2 : Float , _ y2 : Float ,
_ visit : ( Sprite ) -> Void ) {
var count : Int32 = 0
@@ -512,7 +489,7 @@ public final class Sprite {
visitSprites ( result , count : count , visit )
}
// / L i k e ` q u e r y ( a l o n g L i n e : ) ` , w i t h e n t r y / e x i t i n f o r m a t i o n f o r e a c h s p r i t e .
// / L i k e ` q u e r y ( a l o n g L i n e : _ : _ : _ : ) ` , p l u s e n t r y / e x i t d e t a i l s . S l o w e r ; u s e o n l y i f n e e d e d .
public static func queryInfo ( alongLine x1 : Float , _ y1 : Float ,
_ x2 : Float , _ y2 : Float ) -> [ QueryInfo ] {
var count : Int32 = 0
@@ -527,30 +504,28 @@ public final class Sprite {
return infos
}
// / S p r i t e s w h o s e c o l l i s i o n r e c t s o v e r l a p t h i s s p r i t e ' s .
// / S p r i t e s w h o s e c o l l i d e r e c t s o v e r l a p t h i s s p r i t e ' s .
public var overlappingSprites : [ Sprite ] {
var count : Int32 = 0
let result = spriteAPI . pointee . overlappingSprites . unsafelyUnwrapped ( pointer , & count )
return Sprite . sprites ( result , count : count )
}
// / L i k e ` o v e r l a p p i n g S p r i t e s ` , v i s i t i n g e a c h s p r i t e w i t h o u t b u i l d i n g a n
// / a r r a y .
// / L i k e ` o v e r l a p p i n g S p r i t e s ` , b u t v i s i t s e a c h s p r i t e w i t h o u t a l l o c a t i n g .
public func overlappingSprites ( _ visit : ( Sprite ) -> Void ) {
var count : Int32 = 0
let result = spriteAPI . pointee . overlappingSprites . unsafelyUnwrapped ( pointer , & count )
Sprite . visitSprites ( result , count : count , visit )
}
// / A l l s p r i t e s i n t h e d i s p l a y l i s t t h a t o v e r l a p a n o t h e r s p r i t e .
// / A l l o v e r l a p p i n g s p r i t e s a s c o n s e c u t i v e p a i r s : [ 0 ] a n d [ 1 ] o v e r l a p , [ 2 ] a n d [ 3 ] , e t c .
public static var allOverlappingSprites : [ Sprite ] {
var count : Int32 = 0
let result = spriteAPI . pointee . allOverlappingSprites . unsafelyUnwrapped ( & count )
return sprites ( result , count : count )
}
// / L i k e ` a l l O v e r l a p p i n g S p r i t e s ` , v i s i t i n g e a c h s p r i t e w i t h o u t b u i l d i n g
// / a n a r r a y .
// / L i k e ` a l l O v e r l a p p i n g S p r i t e s ` , b u t v i s i t s s p r i t e s ( s a m e p a i r o r d e r ) w i t h o u t a l l o c a t i n g .
public static func allOverlappingSprites ( _ visit : ( Sprite ) -> Void ) {
var count : Int32 = 0
let result = spriteAPI . pointee . allOverlappingSprites . unsafelyUnwrapped ( & count )