spritekit

Build 2D games and animations using SpriteKit. Use when creating game scenes with SKScene and SKView, adding sprites with SKSpriteNode, animating with SKAction sequences, simulating physics with SKPhysicsBody and contact detection, creating particle effects with SKEmitterNode, building tile maps, us

By dpearson2699 · 2,722 installs

npx skills add dpearson2699/swift-ios-skills --skill spritekit

Source repository · Upstream listing

SpriteKit Build 2D games and interactive animations for iOS 26+ using SpriteKit and Swift 6.3. Covers scene lifecycle, node hierarchy, actions, physics, particles, camera, touch handling, and SwiftUI integration. Contents [Scene Setup]( scene setup) [Nodes and Sprites]( nodes and sprites) [Actions and Animation]( actions and animation) [Physics]( physics) [Touch Handling]( touch handling) [Camera]( camera) [Particle Effects]( particle effects) [SwiftUI Integration]( swiftui integration) [Common Mistakes]( common mistakes) [Review Checklist]( review checklist) [References]( references) Scene Setup SpriteKit renders content through SKView , which presents an SKScene the root node of a tree that the framework animates and renders each frame. Creating a Scene Subclass SKScene and override lifecycle methods. The coordinate system origin is at the bottom left by default. Presenting a Scene (UIKit) Scale Modes Use .resizeFill when the scene should adapt to view size changes (rotation, multitasking). Use .aspectFill for fixed design game scenes. .aspectFit letterboxes; .fill stretches and may distort. Frame Cycle Each frame follows this order: 1. update( :) game logic 2. Evaluate actions 3. didEvaluateActions() post action logic 4. Simulate physics 5. didSimulatePhysics() post physics adjustments 6. Apply constraints 7. didApplyConstraints() 8. didFinishUpdate() final adjustments before rendering Override only the callbacks where work is needed. Nodes and Sprites Use SKNode (without a visual) as an invisible container or layout group. Child nodes inherit parent position, scale, rotation, alpha, and speed. SKSpriteNode is the primary visual node. Common Node Types Class Purpose SKSpriteNode Textured image or solid color SKLabelNode Text rendering SKShapeNode Vector paths (expensive per draw call) SKEmitterNode Particle effects SKCameraNode Viewport control SKTileMapNode Grid based tiles SKAudioNode Positional audio SKCropNode / SKEffectNode Masking / CIFilter SK3DNode Embedded SceneKit content Creating Sprites Drawing Order Set ignoresSiblingOrder = true on SKView for better performance; SpriteKit then uses zPosition to determine order. Without it, nodes draw in tree order. Naming and Searching Assign name to find nodes without instance variables. Use childNode(withName:) , enumerateChildNodes(withName:using:) , or subscript . Patterns: // searches the entire tree, matches any characters, .. refers to the parent. Actions and Animation SKAction objects define changes applied to nodes over time. Actions are immutable and reusable. Run with node.run( :) . Basic Actions Combining Actions Texture Animation Control the speed curve with timingMode ( .linear , .easeIn , .easeOut , .easeInEaseOut ). Assign keys to actions for later access: Physics SpriteKit provides a built in 2D physics engine. The scene's physicsWorld manages gravity and collision detection. Adding Physics Bodies Category and Contact Masks Use bit masks to control collisions and contact callbacks: categoryBitMask identifies the body. collisionBitMask controls physics response (bouncing). contactTestBitMask triggers didBegin / didEnd . Contact Detection Implement SKPhysicsContactDelegate and set physicsWorld.contactDelegate = self in didMove(to:) : Contact callbacks run during physics simulation. Make queuePlayerHit() set a flag or append an event, then apply node/body/world mutations in update( :) . Forces and Impulses Use .applyImpulse for jumps and projectile launches. Configure gravity with physicsWorld.gravity = CGVector(dx: 0, dy: 9.8) and per body with affectedByGravity . Touch Handling SKScene inherits from UIResponder . Override touchesBegan , touchesMoved , touchesEnded on the scene. Use nodes(at:) to hit test. For node level touch handling, subclass the node and set isUserInteractionEnabled = true . That node then receives touches directly instead of the scene. Camera SKCameraNode controls the visible portion of the scene. Add it as a child and assign to scene.camera . Following a Character Update the camera position in didSimulatePhysics() or use constraints: Camera Zoom and HUD Scale the camera node inversely: setScale(0.5) zooms in 2x, setScale(2.0) zooms out 2x. Nodes added as children of the camera stay fixed on screen (HUD elements): Particle Effects SKEmitterNode generates particle effects. Design emitters in Xcode's SpriteKit Particle File editor ( .sks ) or configure in code. One Shot Emitters Set numParticlesToEmit for finite effects and remove after completion: Set targetNode to the scene so particles stay in world space when the emitter moves: emitter.targetNode = self . SwiftUI Integration SpriteView embeds a SpriteKit scene in SwiftUI. SpriteView Options Pass options: [.allowsTransparency] for transparent backgrounds, .shouldCullNonVisibleNodes for offscreen culling, or .ignoresSiblingOrder for zPosition based draw order. Use debugOptions: [.showsFPS, .showsNodeCount] during development. Communicating Between SwiftUI and the Scene Pass data through a shared @Observable object. Store the scene in @State to avoid re creation on view re renders: Common Mistakes Creating a new scene on every SwiftUI re render Adding a child node that already has a parent A node can only have one parent. Remove from the current parent first or create a separate instance. Adding a node that already has a parent crashes. Forgetting to set contactTestBitMask Using SKShapeNode for performance critical rendering SKShapeNode uses a separate draw call per instance. Prefer SKSpriteNode with a texture for repeated elements to enable batched rendering. Not removing nodes that leave the screen Setting physicsWorld.contactDelegate too late Set physicsWorld.contactDelegate = self in didMove(to:) , not in update( :) or after a delay. Review Checklist [ ] Scene subclass overrides didMove(to:) for setup, not init [ ] scaleMode chosen appropriately for the game's design [ ] ignoresSiblingOrder set to true on SKView for performance [ ] zPosition used consistently when ignoresSiblingOrder is enabled [ ] Physics contactDelegate set in didMove(to:) [ ] Category, collision, and contact bit masks configured correctly [ ] contactTestBitMask set for any pair needing didBegin / didEnd callbacks [ ] Contact callbacks queue changes instead of mutating the physics world directly [ ] Static bodies use isDynamic = false [ ] SKShapeNode avoided in performance critical paths; SKSpriteNode preferred [ ] Actions that move nodes offscreen include .removeFromParent() in sequence [ ] One shot emitters remove themselves after particle lifetime expires [ ] Emitter targetNode set when particles should stay in world space [ ] Scene stored in @State when used with SpriteView in SwiftUI [ ] Texture atlases used for related sprites to reduce draw calls [ ] update( :) uses delta time for frame rate independent movement [ ] Nodes removed from parent before being re added elsewhere References See [references/spritekit patterns.md](references/spritekit patterns.md) for tile maps, texture atlases, shaders, scene transitions, game loop patterns, audio, and SceneKit embedding. [SpriteKit documentation](https://sosumi.ai/documentation/spritekit) [SKScene](https://sosumi.ai/documentation/spritekit/skscene) [SKSpriteNode](https://sosumi.ai/documentation/spritekit/skspritenode) [SKAction](https://sosumi.ai/documentation/spritekit/skaction) [SKPhysicsBody](https://sosumi.ai/documentation/spritekit/skphysicsbody) [SKEmitterNode](https://sosumi.ai/documentation/spritekit/skemitternode) [SKCameraNode](https://sosumi.ai/documentation/spritekit/skcameranode) [SpriteView](https://sosumi.ai/documentation/spritekit/spriteview) [SKTileMapNode](https://sosumi.ai/documentation/spritekit/sktilemapnode)