Посмотрите на синергию между SwiftUI, SpriteKit и Combine

Это третья статья в том, что начиналось как синглтон, а сейчас превращается в серию. В нем я хочу продолжить документировать свое путешествие по изучению синергии, которую я могу найти при реализации игры на основе SpriteKit в интерфейсе SwiftUI.

Сегодняшняя цель - взять то, что я узнал из первой и второй статей по этому поводу, и попытаться создать третье гибридное приложение. Планируется использовать три GameScenes, одну в качестве дисплея [как и раньше], а две другие в качестве поверхностей управления [на этот раз с использованием SpriteKit] с некоторыми дополнительными компонентами, чтобы попытаться объединить все это воедино. Поскольку это третья статья в серии, я решил сразу броситься на убийство. Вот анимированный GIF гола.

В этой статье я хочу попытаться как минимум столько же времени рассказать о том, почему я принял решение сделать что-то тем или иным образом, сколько я рассказываю вам, как я это сделал.

Путешествие

Я начал этот проект задним числом, завершив два предыдущих, по которым опубликовал статьи в прошлом месяце. Я пробовал создавать игры с SpriteKit, управляющим SwiftUI, и SwiftUI, управляющим SpriteKit. Как и следовало ожидать, SpriteKit выглядел явным победителем, хотя есть смысл смешивать его со SwiftUI. Вы можете найти ссылку на указанные статьи в самом конце статьи.

На этот раз я поставил перед собой задачу создать игру в понг. Игра стара, как деревья, датируется 1972 годом. На случай, если вы родились в этом веке, а не в прошлом, позвольте мне объяснить, что это было. Это была игра для двух игроков [необычная для того времени] с очень простой графикой. Вы управляли одной ракеткой, другой игрок - другим, и у вас был мяч, который вы отбивали из стороны в сторону. Это была игра в электронный пинг-понг.

Тогда вернемся к кодированию. В целом мне нравится синергия между SpriteKit и SwiftUI. Последний идеально подходит для упорядочивания / организации экрана - его механика компоновки с VStacks, HStacks и даже Grids очень проста в использовании - первый, SpriteKit, очень хорошо продуманный набор основных компонентов, необходимых для создания хорошей 2D-игры.

Сборка

В предыдущих статьях я использовал примитивы мировой физики гравитации, чтобы запустить шар (камень, как я его называл). В этой версии мне нужно было, чтобы мяч двигался вперед и назад, поэтому я использовал директивы SKAction, чтобы дать «импульс» для начала игры; за пределами которого я полагался на примитивы физического объекта, так что он подпрыгивает.

Еще одним большим изменением было использование SpriteKit в качестве поверхностей управления для управления моими лопастями SpriteKit. Я мог бы использовать одну панель управления / отображения, но я хотел зарезервировать возможность использовать в игре механизм компоновки SwiftUI. Я использовал SpriteKit в качестве поверхностей управления и отображения, потому что SwiftUI был недостаточно быстрым. SwiftUI хорош для статического контента и макета, SpriteKit - динамического контента. Я оставил дисплей счетчика очков на самих лопастях, чтобы проиллюстрировать вышеупомянутый пункт курсивом. Как видите, SwiftUI не работает достаточно быстро.

Мне нужно было сделать это нечетное математическое уравнение, потому что центр координат SwiftUI, хотя то же самое на оси X перевернуто на Y? Я не знаю, почему Apple так поступила - уверен, на то была веская причина.

Это странный фрагмент кода SwiftUI, который выглядит так.

.onReceive(leftPaddle) { ( point ) in
  let ry = 256 - point.y
  let np = CGPoint(x: point.x, y: ry)
  marker = np
}
.overlay(Text(returnText())
.font(.callout)
.foregroundColor(Color.white)
.position(marker))

Я подумал о создании протокола делегата, чтобы заставить три сцены SpriteKit разговаривать друг с другом и, конечно, с кодом SwiftUI, но решил попытаться уйти с сообщениями, используя структуру Combine, что я и сделал. Решение, которое по большей части работает хорошо.

Мне нужно было действие, чтобы вернуть свой мяч, если он каким-то образом выйдет из игры и остановится на жесте встряхивания, поэтому вы найдете для него расширение в представлении содержимого.

Сначала я использовал координаты мяча, чтобы определить, был ли он вне игры, но время от времени спрайт снова уходил в самоволку, поэтому мне пришлось придумать новый план, следовательно, больше спрайтов для захвата событий вне корта. . Вы не можете их увидеть, потому что они окрашены в черный цвет.

Я использовал SwiftUI, чтобы запустить игру, показать счет в конце и действительно перезапустить игру по запросу. Я также использовал его, чтобы обозначить свой двор. Все задачи, которые казались менее трудоемкими, чем если бы они были выполнены в чистой среде SpriteKit.

Я снова использовал «импульс», чтобы толкать мяч в сторону во время игры, когда игроки ударяют по мячу, чтобы убедиться, что он не просто пингует под углом 90 градусов между ракетками.

Наконец, как уже упоминалось, я использовал физические тела с параметрами, установленными для того, чтобы мяч отскакивал от краев и ракеток. Параметры, которые вам нужно настроить, чтобы игра стала быстрее, - вот эти. Жирным шрифтом выделена подвижность.

rock.physicsBody!.affectedByGravity = false
rock.physicsBody!.restitution = 0.8
rock.physicsBody!.linearDamping = 0
rock.physicsBody!.friction = 0.3
rock.physicsBody?.isDynamic = true
rock.physicsBody!.mass = 0.5
rock.physicsBody!.allowsRotation = true

Дополнительный кредит

В конечном счете, я построил самый минимум в игре, потому что я считаю, что это самый простой способ увидеть, что происходит, и потому, что он дает вам, читателю, возможность по-настоящему повеселиться, сделав это своей игрой.

Поиграйте с физикой [прочтите этот фрагмент @ Джереми Джейкобсона на эту тему], настройте свою игру или даже лучше создайте специальный второй экран [проверка Segue Shenanigans With SwiftUI], чтобы ваши игроки могли это сделать .

Добавьте немного звука в игру, ознакомившись с бумагой Дэвида Пайпера здесь.

Проведите дополнительное исследование механики столкновений в SpriteKit, прочтите статью @ John Watson на эту тему здесь. Представьте себе ракетку, которая выглядит примерно так, с мячом, который соответствует этим изгибам и бороздкам.

Попробуйте сетевую игру между двумя устройствами iOS [ознакомьтесь с этой статьей, чтобы помочь вам]. Настройте таблицу лидеров, чтобы отслеживать лучших игроков, попробуйте использовать GameKit, чтобы попасть туда, здесь ссылка от @ Abedalkareem Omreyh, чтобы вы тоже начали.

Сделайте каждую игру немного сложнее для победившего игрока [путем изменения физики], сохраняя ее свежей и гарантируя, что никто не доминирует в игре :)

Попробуйте свои силы в AI и научите компьютер быть вторым игроком. Несколько статей по этой теме на Medium. Это область, которую мне еще предстоит исследовать сам, - говорит об этом @ Сай Баладжи в этой статье.

Наконец, вот код, с которого можно начать. У вас есть три файла. ContentView с кодом SwiftUI. CtrlScene и GameScene.

Все это подводит меня к концу статьи. Надеюсь, вам не только понравилось это читать, но и я кое-что узнал. Следуйте за мной на medium.com, чтобы получить больше подобного контента, или посмотрите некоторые из моих предыдущих рассказов о программировании на Swift.