Отслеживание столкновений
Для отслеживания касаний используется встроенная функция didBeginContact, вызываемая при каждом столкновении физических объектов (врагов и патронов). Её код размещается вне других функций:
func didBeginContact(contact: SKPhysicsContact) {
// ... код ...
}
Проверка объектов столкновения
Определяем две переменные типа SKPhysicsBody:
let firstBody = contact.bodyA
let secondBody = contact.bodyB
Сравниваем categoryBitMask обоих объектов:
if (firstBody.categoryBitMask < secondBody.categoryBitMask) {
// ...код...
} else {
// ...код...
}
При создании переменных использовались значения 1 и 0 для врага и патрона соответственно. Более явное определение:
if firstBody.categoryBitMask > secondBody.categoryBitMask {
let enemy = firstBody.node as! SKSpriteNode
let bullet = secondBody.node as! SKSpriteNode
} else {
let enemy = secondBody.node as! SKSpriteNode
let bullet = firstBody.node as! SKSpriteNode
}
Теперь определены враг и патрон.
Фильтрация столкновений
Необходимо убедиться, что столкнулись именно враг и патрон, исключая столкновения корабля с кораблем или врага с врагом. Проверяем битовые маски:
if (firstBody.categoryBitMask & enemyCategory) != 0 && (secondBody.categoryBitMask & bulletCategory) != 0 {
// ...код...
}
enemyCategory и bulletCategory — битовые маски для категорий врагов и патронов.
Обработка столкновения
Для повышения читаемости создана отдельная функция:
func clashElements(bullet: SKSpriteNode, enemy: SKSpriteNode) {
// ...код...
}
Она принимает спрайты патрона и врага.
Анимация взрыва и звук
В функции clashElements воспроизводится анимация взрыва и звук:
let explosion = SKSpriteNode(imageNamed: "explosion")
enemy.addChild(explosion)
run(SKAction.playSoundFileNamed("explosion.mp3", waitForCompletion: false))
Удаление объектов
Объекты удаляются с экрана:
bullet.removeFromParent()
enemy.removeFromParent()
let wait = SKAction.wait(forDuration: 2.0)
let removeExplosion = SKAction.removeFromParent()
let sequence = SKAction.sequence([wait, removeExplosion])
explosion.run(sequence)
score += 5
Анимация взрыва удаляется через 2 секунды. score увеличивается на 5.
Управление кораблем с помощью акселерометра
Для управления кораблем акселерометром подключаем CoreMotion:
import CoreMotion
Создаем переменные:
let motionManager = CMMotionManager()
var xAccel: CGFloat = 0
В didBeginContact добавляем обработку данных акселерометра:
motionManager.accelerometerUpdateInterval = 0.2
motionManager.startAccelerometerUpdates(to: .main) { (data, error) in
guard let data = data else { return }
let xAccelNew = CGFloat(data.acceleration.x) * 0.75 + self.xAccel * 0.25
self.xAccel = xAccelNew
}
Функция updatePlayerPosition обновляет позицию игрока:
func updatePlayerPosition() {
player.position.x += xAccel * 50
if player.position.x < -350 {
player.position.x = 350
} else if player.position.x > 350 {
player.position.x = -350
}
}
Функция обеспечивает циклическое движение за границами экрана.
Реализованы стрельба, обработка столкновений и управление кораблем акселерометром, повышая интерактивность игры.