SpriteKit для Swift: полное руководство с примерами
1. Что это и зачем нужна
SpriteKit — это фреймворк от Apple для создания 2D-игр и интерактивных приложений под iOS, macOS, tvOS и watchOS. Написанный на Swift и Objective-C, он предоставляет разработчикам готовую инфраструктуру для рендеринга спрайтов, анимации, физики, обработки касаний и управления звуком. В отличие от сторонних движков (Unity, Godot), SpriteKit полностью интегрирован в экосистему Apple, что даёт доступ к Metal (для высокопроизводительного рендеринга), Game Center, ARKit и другим нативным API.
Зачем использовать SpriteKit? Если вы разрабатываете 2D-игру для устройств Apple — от простых головоломок до платформеров и аркад — SpriteKit станет оптимальным выбором. Он избавляет от необходимости писать низкоуровневый код для отрисовки кадров, коллизий и анимации. Фреймворк оптимизирован для работы с Retina-дисплеями, поддерживает частицы, шейдеры и процедурную генерацию текстур. Для инди-разработчиков и образовательных проектов SpriteKit — это баланс между мощностью и простотой освоения.
В этой статье мы разберём установку, основные классы и методы, напишем рабочие примеры и дадим советы по производительности. Материал рассчитан на разработчиков, знакомых с основами Swift и Xcode.
2. Установка
SpriteKit не устанавливается через менеджеры пакетов (pip, npm и т.д.), так как это встроенный фреймворк Apple. Для его использования достаточно создать проект в Xcode с шаблоном Game и выбрать SpriteKit:
// Установка не требуется — фреймворк встроен в SDK.
// Для добавления в существующий проект:
// 1. Откройте Xcode -> File -> Add Packages...
// 2. Или просто импортируйте фреймворк в коде:
import SpriteKit
Если вы создаёте проект вручную, добавьте фреймворк через настройки цели: Target -> General -> Frameworks, Libraries, and Embedded Content -> нажмите "+" и выберите SpriteKit.framework.
3. Быстрый старт — минимальный рабочий пример
Создадим простое приложение, которое показывает вращающийся спрайт на экране. Это классический "Hello, World!" для SpriteKit.
import SpriteKit
import UIKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Создаём SKView
let skView = SKView(frame: view.bounds)
view.addSubview(skView)
// Создаём сцену
let scene = SKScene(size: skView.bounds.size)
scene.backgroundColor = .systemBlue
// Создаём спрайт
let sprite = SKSpriteNode(color: .white, size: CGSize(width: 100, height: 100))
sprite.position = CGPoint(x: scene.size.width / 2, y: scene.size.height / 2)
scene.addChild(sprite)
// Вращаем спрайт
let rotate = SKAction.rotate(byAngle: .pi * 2, duration: 2.0)
sprite.run(SKAction.repeatForever(rotate))
// Показываем сцену
skView.presentScene(scene)
skView.showsFPS = true
skView.showsNodeCount = true
}
}
Этот код создаёт синий фон, белый квадрат в центре и заставляет его вращаться. SKView — это окно рендеринга, SKScene — сцена, а SKSpriteNode — спрайт. SKAction управляет анимацией.
4. Основные методы/функции/классы
Ниже приведены ключевые классы и методы SpriteKit. Для каждого дана сигнатура, описание и пример.
4.1. SKScene — сцена
Сигнатура:
class SKScene: SKEffectNode {
convenience init(size: CGSize)
func didMove(to view: SKView)
func update(_ currentTime: TimeInterval)
}
Что делает: Управляет всеми объектами на экране. didMove(to:) вызывается при первом показе сцены, update(_:) — каждый кадр для обновления логики.
Пример:
class GameScene: SKScene {
override func didMove(to view: SKView) {
backgroundColor = .green
let label = SKLabelNode(text: "Привет, SpriteKit!")
label.position = CGPoint(x: size.width / 2, y: size.height / 2)
addChild(label)
}
override func update(_ currentTime: TimeInterval) {
// Логика игры, вызывается 60 раз в секунду
}
}
4.2. SKSpriteNode — спрайт
Сигнатура:
class SKSpriteNode: SKNode {
convenience init(imageNamed: String)
convenience init(color: UIColor, size: CGSize)
var texture: SKTexture?
var size: CGSize
var position: CGPoint
}
Что делает: Отображает текстуру или цветной прямоугольник. Основной строительный блок 2D-игр.
Пример:
let player = SKSpriteNode(imageNamed: "hero")
player.position = CGPoint(x: 100, y: 100)
player.setScale(0.5) // Уменьшаем вдвое
addChild(player)
4.3. SKAction — действия
Сигнатура:
class SKAction: NSObject, NSCopying, NSSecureCoding {
class func move(to location: CGPoint, duration: TimeInterval) -> SKAction
class func rotate(byAngle radians: CGFloat, duration: TimeInterval) -> SKAction
class func fadeOut(withDuration duration: TimeInterval) -> SKAction
class func sequence(_ actions: [SKAction]) -> SKAction
class func group(_ actions: [SKAction]) -> SKAction
}
Что делает: Анимирует свойства узлов (позиция, поворот, прозрачность). Поддерживает последовательности и группы.
Пример:
let move = SKAction.move(to: CGPoint(x: 300, y: 300), duration: 1.0)
let fade = SKAction.fadeOut(withDuration: 0.5)
let sequence = SKAction.sequence([move, fade])
sprite.run(sequence)
4.4. SKPhysicsBody — физическое тело
Сигнатура:
class SKPhysicsBody: NSObject, NSCopying, NSSecureCoding {
convenience init(rectangleOf size: CGSize)
convenience init(circleOfRadius radius: CGFloat)
var isDynamic: Bool
var affectedByGravity: Bool
var categoryBitMask: UInt32
var contactTestBitMask: UInt32
var collisionBitMask: UInt32
}
Что делает: Добавляет физику узлу: гравитацию, столкновения, контакты.
Пример:
let ball = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
ball.physicsBody = SKPhysicsBody(circleOfRadius: 25)
ball.physicsBody?.isDynamic = true
ball.physicsBody?.affectedByGravity = true
ball.physicsBody?.categoryBitMask = 1
ball.physicsBody?.contactTestBitMask = 2
addChild(ball)
4.5. SKLabelNode — текст
Сигнатура:
class SKLabelNode: SKNode {
convenience init(text: String?)
var fontName: String?
var fontSize: CGFloat
var fontColor: UIColor?
var text: String?
}
Что делает: Отображает текст на сцене. Поддерживает шрифты и цвета.
Пример:
let scoreLabel = SKLabelNode(text: "Score: 0")
scoreLabel.fontName = "Helvetica-Bold"
scoreLabel.fontSize = 24
scoreLabel.fontColor = .white
scoreLabel.position = CGPoint(x: 100, y: 50)
addChild(scoreLabel)
4.6. SKTexture — текстура
Сигнатура:
class SKTexture: NSObject, NSSecureCoding, NSCopying {
convenience init(imageNamed: String)
convenience init(rect: CGRect, in texture: SKTexture)
var size: CGSize
}
Что делает: Управляет изображениями для спрайтов. Позволяет вырезать части текстур (спрайт-листы).
Пример:
let fullTexture = SKTexture(imageNamed: "spritesheet")
let cropRect = CGRect(x: 0, y: 0, width: 64, height: 64)
let subTexture = SKTexture(rect: cropRect, in: fullTexture)
let node = SKSpriteNode(texture: subTexture)
4.7. SKPhysicsContactDelegate — обработка контактов
Сигнатура:
protocol SKPhysicsContactDelegate: AnyObject {
func didBegin(_ contact: SKPhysicsContact)
func didEnd(_ contact: SKPhysicsContact)
}
Что делает: Уведомляет о начале и завершении контакта между физическими телами.
Пример:
class GameScene: SKScene, SKPhysicsContactDelegate {
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
}
func didBegin(_ contact: SKPhysicsContact) {
print("Контакт начался!")
// Обработка столкновения
}
}
4.8. SKEmitterNode — эмиттер частиц
Сигнатура:
class SKEmitterNode: SKNode {
convenience init(fileNamed: String)
var particleTexture: SKTexture?
var particleBirthRate: CGFloat
var particleLifetime: CGFloat
var particleSpeed: CGFloat
}
Что делает: Создаёт эффекты частиц: дым, огонь, звёзды. Можно настроить через редактор Xcode.
Пример:
if let fire = SKEmitterNode(fileNamed: "Fire.sks") {
fire.position = CGPoint(x: 200, y: 100)
addChild(fire)
}
4.9. SKCameraNode — камера
Сигнатура:
class SKCameraNode: SKNode {
var xScale: CGFloat
var yScale: CGFloat
}
Что делает: Позволяет двигать и масштабировать вид сцены без перемещения всех узлов.
Пример:
let camera = SKCameraNode()
camera.position = CGPoint(x: 0, y: 0)
self.camera = camera
addChild(camera)
// Приближение:
camera.setScale(2.0)
5. Реальный практический пример (100-200 строк кода)
Создадим мини-игру "Ловец звёзд": игрок управляет корзиной, ловит падающие звёзды и избегает бомб. Пример демонстрирует физику, контакты, действия и пользовательский ввод.
import SpriteKit
import UIKit
class StarCatcherScene: SKScene, SKPhysicsContactDelegate {
let player = SKSpriteNode(color: .brown, size: CGSize(width: 100, height: 20))
var score = 0
let scoreLabel = SKLabelNode(text: "Score: 0")
let starCategory: UInt32 = 1
let bombCategory: UInt32 = 2
let playerCategory: UInt32 = Также в библиотеке
WebSocket библиотеки для Node.js: ws, Socket.IO и uWebSockets.js
Работа с Excel в TypeScript: библиотеки, примеры и инструменты
Мониторинг приложений C++: инструменты и библиотеки