Swift iOS игра: Стрельба и столкновения (Урок 3)

Отслеживание столкновений

Для отслеживания касаний используется встроенная функция 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
    }
}

Функция обеспечивает циклическое движение за границами экрана.

Реализованы стрельба, обработка столкновений и управление кораблем акселерометром, повышая интерактивность игры.

Что будем искать? Например,программа