Вступление
В этом руководстве, четвертом выпуске серии SpriteKit From Scratch , мы рассмотрим различные визуальные и звуковые функции, предоставляемые SpriteKit, чтобы добавить больше деталей и разнообразия в ваши игры. Это включает системы частиц, фильтры, освещение и аудио.
Чтобы следовать за мной, вы можете использовать проект, который вы создали в предыдущем уроке этой серии, или загрузить свежую копию с GitHub .
Графика, используемая для игры в этой серии, может быть найдена на GraphicRiver . GraphicRiver — отличный источник для поиска иллюстраций и графики для ваших игр.
1. Системы частиц
В SpriteKit, термин система частиц ссылается на один узел эмиттера, представленный классом SKEmitterNode
. Он определяет положение системы в вашей сцене и все частицы, которые она создает. Излучатель определяет различные виды поведения частиц, которые он генерирует.
Системы частиц лучше всего использовать в играх SpriteKit, где вам нужно генерировать большое количество идентичных или похожих спрайтов, которым не нужно иметь конкретное местоположение или выполнять какие-либо действия.
В этом уроке мы собираемся добавить две системы частиц, когда автомобиль сталкивается с препятствием:
- кратковременный эффект взрыва
- эффект дыма, который остается в сцене на неопределенный срок
Хотя системы частиц могут быть созданы программно, это гораздо проще сделать с помощью встроенного редактора Xcode. Все свойства системы частиц могут быть изменены в этом редакторе, а сделанные вами изменения немедленно визуализируются. Это гораздо проще, чем запускать игру после каждого внесенного изменения.
Сначала мы собираемся создать эффект взрыва. Создайте новый файл в своем проекте и выберите iOS> Resource> SpriteKit Particle File template.
В появившемся меню выберите « Огонь» в качестве шаблона частиц . Назовите файл Explosion или что-то подобное.
После того, как Xcode создал файл, вы видите, что в вашем проекте есть два новых файла, Explosion.sks и spark.png .
Explosion.sks содержит систему частиц, и это файл, с которым мы будем работать. Второй файл, spark.png , представляет собой простое изображение, используемое шаблоном частиц Fire для создания визуального эффекта. Если вы откроете Explosion.sks , вы увидите оживление огня.
Наиболее важные изменения, которые нам необходимо внести в эту систему частиц, — это перемещение частиц наружу от эмиттера во всех направлениях и непрерывное появление новых частиц.
Чтобы сделать первое изменение, откройте инспектор атрибутов и в разделе « Частицы » измените диапазон углов на 360 ° .
Прямо сейчас вы можете видеть, что частицы теперь движутся наружу в форме круга.
Чтобы остановить систему частиц от непрерывного создания новых частиц, мы можем указать максимальное значение. Это значение говорит системе частиц, сколько всего частиц она должна создать. Значение по умолчанию 0 означает, что максимума нет, что приводит к непрерывному созданию новых частиц.
Помимо указания максимального значения, мы также собираемся изменить несколько других свойств, чтобы создать лучший эффект взрыва. В разделе « Частицы » Инспектора атрибутов измените следующие значения:
Мы устанавливаем для параметра « Скорость рождения» значение, превышающее свойство « Максимум», поскольку оно определяет, сколько частиц создается в секунду . Мы хотим, чтобы взрыв произошел очень быстро. Таким образом, вместо того, чтобы иметь 1000 частиц, порождаемых в течение полных секунды, что могло бы произойти при коэффициенте рождаемости 1000, мы указываем коэффициент рождаемости 5000. Это означает, что все частицы создаются всего за 0,2 секунды.
Установив Lifetime> Start на 3, частицы живут в течение 3 секунд. Свойство Lifetime Range можно использовать для добавления вариаций времени жизни частиц.
Наконец, мы устанавливаем Speed> Start на 200, чтобы частицы очень быстро вылетали из эмиттера, как это произошло бы при реальном взрыве.
После внесения этих изменений вы можете видеть, что система частиц выглядит совсем иначе и больше похожа на настоящий взрыв.
Обратите внимание, что, хотя анимация периодически повторяется в редакторе Xcode, система частиц анимируется только один раз при добавлении в вашу сцену.
Когда система частиц взрыва завершена, пришло время перейти к системе частиц дыма. Создайте новый файл Smoke , используя тот же шаблон, который мы использовали для взрыва. Единственное отличие — это шаблон Particle , который мы установили на Smoke .
Единственное изменение, которое нам нужно внести в эту систему частиц, — это движение дыма по кругу, а не просто прямо вверх. Для этого измените свойство Angle> Range на 360 °, как мы делали для системы частиц взрыва. После этого система частиц дыма должна выглядеть примерно так:
Когда обе системы частиц готовы, мы можем добавить их к нашей сцене. Для этого мы загружаем каждый из файлов, которые мы создали как объекты SKEmitterNode
а затем добавляем их в сцену как обычный узел. Откройте MainScene.swift и замените реализацию didBeginContact(_:)
следующим:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
func didBeginContact(contact: SKPhysicsContact) {
if contact.bodyA.node == player ||
if let explosionPath = NSBundle.mainBundle().pathForResource(«Explosion», ofType: «sks»),
let smokePath = NSBundle.mainBundle().pathForResource(«Smoke», ofType: «sks»),
let explosion = NSKeyedUnarchiver.unarchiveObjectWithFile(explosionPath) as?
let smoke = NSKeyedUnarchiver.unarchiveObjectWithFile(smokePath) as?
player.removeAllActions()
camera?.removeAllActions()
player.hidden = true
player.removeFromParent()
explosion.position = player.position
smoke.position = player.position
addChild(smoke)
addChild(explosion)
}
}
}
|
Как и в предыдущей реализации didBeginContact(_:)
, мы выполняем ту же проверку, что и раньше, чтобы увидеть, является ли какой-либо из узлов, участвующих в столкновении, автомобильным узлом. Затем мы используем необязательную привязку, чтобы получить пути к системным файлам взрывчатых и дымовых частиц. Мы используем эти пути для создания из них объектов SKEmitterNode
.
Затем мы удаляем все действия с камер и узлов плеера и скрываем узел плеера, удаляя его со сцены. Мы удаляем машину, чтобы избежать новых столкновений, которые затем приводят к большему количеству взрывов.
Мы также устанавливаем положение узлов-эмиттеров в положение машины и добавляем их в сцену. В результате SpriteKit немедленно начинает анимировать системы частиц, как только они добавляются в сцену.
Создайте и запустите свою игру. Вы должны увидеть систему частиц взрыва, как только автомобиль столкнется с препятствием. За этим следует дым после того, как огонь рассеялся.
2. Фильтры сцены и узлы эффектов
В SpriteKit есть специальный тип узла (представленный классом SKEffectNode
), который может использовать объект фильтра Core Image (представленный классом CIFilter
) для визуализации своих дочерних узлов с различными эффектами. Класс SKScene
также является подклассом SKEffectNode
, что означает, что вы также можете применить фильтр ко всей сцене.
К сожалению, на момент написания этого руководства было несколько проблем, связанных с этими фильтрами и узлами эффектов в iOS 9. В настоящее время, когда эффект включен для узла эффекта, все его дочерние элементы скрываются, что приводит к эффект не виден.
Несмотря на то, что мы не можем внедрить это в нашу игру и посмотреть, как она выглядит, мы все равно можем выполнить код, который будет использоваться для создания эффекта. В этом случае следующий метод является примером добавления и постепенного исчезновения эффекта размытия для всей сцены.
01
02
03
04
05
06
07
08
09
10
11
12
|
func addBlurFilter() {
let blurFilter = CIFilter(name: «CIGaussianBlur»)
blurFilter?.setDefaults()
blurFilter?.setValue(0.0, forKey: «inputRadius»)
filter = blurFilter
shouldEnableEffects = true
runAction(SKAction.customActionWithDuration(1.0, actionBlock: { (node: SKNode, elapsedTime: CGFloat) in
let currentRadius = elapsedTime * 10.0
blurFilter?.setValue(currentRadius, forKey: «inputRadius»)
}))
}
|
Мы создаем объект CIFilter
определенного типа. Если вы хотите взглянуть на некоторые другие доступные вам встроенные фильтры, ознакомьтесь со справочником по фильтру основных изображений . Мы гарантируем, что этот фильтр имеет все входные значения по умолчанию, а затем вручную устанавливаем inputRadius
на 0.0 , что означает, что изначально не было размытия.
Затем мы назначаем filter
свойству filter
текущей сцены и устанавливаем для shouldEnableEffects
значение true
чтобы включить его. Наконец, мы запускаем пользовательский SKAction
который постепенно увеличивает входной радиус фильтра до 10 .
Надеемся, что в будущем выпуске iOS проблемы, влияющие на узлы эффектов, будут исправлены, поскольку они предоставляют способ добавить некоторые уникальные и интересные эффекты в ваши сцены SpriteKit.
3. Световые узлы
SpriteKit также включает в себя отличную систему освещения, которая позволяет сделать ваши сцены более реалистичными. SKLightNode
света очень просты в реализации и создаются с помощью класса SKLightNode
. Узел источника света определяет определенные свойства, такие как цвет источника света (включая цвет окружающей среды) и его силу на расстоянии.
В нашей сцене мы собираемся создать один белый свет, который будет прикреплен к машине. Этот свет будет освещать препятствия перед автомобилем, а также создавать тени.
Давайте начнем с создания источника света в didMoveToView(_:)
вашего класса MainScene
.
01
02
03
04
05
06
07
08
09
10
|
override func didMoveToView(view: SKView) {
…
let light = SKLightNode()
light.lightColor = UIColor.whiteColor()
light.falloff = 0.5
player.addChild(light)
}
|
С помощью этого кода мы создаем новый объект SKLightNode
, меняем его свойство lightColor
на белое и lightColor
его свойство lightColor
со значения по умолчанию от 1 до 0,5 .
Как и при настройке обнаружения физических столкновений в SpriteKit, вы должны указать, какие источники света взаимодействуют с какими узлами в сцене с помощью битовых масок. Когда SpriteKit визуализирует источники света в сцене, он использует логический оператор AND в categoryBitMask
lightingBitMask
и lightingBitMask
и shadowCastBitMask
каждого другого узла, чтобы определить, как должен выглядеть этот конкретный узел.
В нашей игре мы хотим, чтобы препятствия взаимодействовали со светом, чтобы они отбрасывали тени на сцену. Для этого добавьте следующие две строки в конец метода spawnObstacle(_:)
класса MainScene
:
1
2
3
4
5
6
7
|
func spawnObstacle(timer: NSTimer) {
…
obstacle.lightingBitMask = 0xFFFFFFFF
obstacle.shadowCastBitMask = 0xFFFFFFFF
}
|
При установке битовой маски со всеми включенными битами препятствия взаимодействуют с каждым источником света в сцене.
Создайте и запустите ваше приложение. Вы увидите, что, когда ваша машина движется по сцене, каждое препятствие имеет динамическую тень, которая всегда направлена в сторону от центра автомобиля.
Как видите, источники света в SpriteKit очень просты в использовании и могут добавлять приятные эффекты в ваши сцены.
4. Аудио узлы
Наконец, мы рассмотрим аудио узлы в SpriteKit. Аудио узлы используются для добавления звуковых эффектов в сцену. Эти специальные узлы представлены классом SKAudioNode
. Поскольку SKAudioNode
является подклассом SKNode
, вы можете добавлять и SKNode
их в любом месте сцены, как обычный узел.
В дополнение к регулярному воспроизведению звука и одинаковому звучанию независимо от того, как устроена ваша сцена (например, фоновая музыка), SpriteKit позволяет использовать позиционное аудио для создания действительно захватывающего эффекта. Это делается путем указания узла listener
для вашей сцены, откуда звук будет «слышен».
Аудио узлы являются позиционными по умолчанию. Это означает, что, если вы не хотите использовать эту функциональность в определенных случаях, вы можете установить для positional
свойства определенного узла значение false
.
Хотя мы не будем реализовывать это в нашей игре, ниже приведен пример метода добавления узла фоновой музыки, который зацикливается, пока он является частью сцены. В методе мы также добавляем узел звука взрыва, который начинает играть, когда мы говорим об этом.
Обратите внимание, что мы импортируем фреймворк AVFoundation вверху. Это необходимо для доступа и работы со свойством SKAudioNode
объекта SKAudioNode
. Как видите, аудио узлы очень просты в настройке и работе в SpriteKit.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
import AVFoundation
func addAudioNode() {
listener = player
let backgroundMusic = SKAudioNode(fileNamed: «backgroundMusic»)
backgroundMusic.positional = false
let explosion = SKAudioNode(fileNamed: «explosion»)
explosion.autoplayLooped = false
addChild(backgroundMusic)
addChild(explosion)
do {
try explosion.avAudioNode?.engine?.start() // Called when you want to play sound
} catch {
// Do something with the error
}
}
|
Вывод
Теперь вам должно быть удобно работать с некоторыми более продвинутыми эффектами в SpriteKit, включая системы частиц, фильтры, свет и звук. Эти комбинированные эффекты могут сильно повлиять на внешний вид вашей игры и на ее увлекательность.
В следующем и последнем учебнике этой серии мы рассмотрим некоторые из лучших практик, которые следует учитывать при работе со SpriteKit. Я также покажу вам, как создавать текстурные атласы и сохранять / загружать сцены.
Как всегда, обязательно оставляйте свои комментарии и отзывы в комментариях ниже.