
2D -игровой двигатель, основанный на ECS и написанный на 100% Swift для iOS, MacOS, TVOS и Visionos.
Осторожность
? Этот проект больше не обновляется единственным сопровождающим.
? Я переехал в Годо. Проверьте Comedot ← Мои основы для компонентов для 2D игр в Годо!
Важный
❕ Octopuskit требует осьминога. Неигровая функциональность была разделена на отдельный репозиторий для использования в общих приложениях. Для последней автономной версии см. 4.0.0-бета-5
Если вы пытались сделать игру в Swift, придерживаясь официальных API, это может быть для вас! Octopuskit Обертывает и расширяет рамки Apple:
• Gameplaykit для гибкой архитектуры сущности-компонента, чтобы динамически сочинять поведение игры.
• Spritekit для 2D -графики, физики и шейдеров графических процессоров.
• Swiftui для быстрого проектирования жидкости, масштабируемых HUD с декларативным синтаксисом.
• Металл , чтобы обеспечить наилучшее нативное производительность под капотом.
• ОС-независимые компоненты позволяют обрабатывать мышь/сенсорную или клавиатуру/геймпад с тем же кодом, и компилируются на IOS + MacOS без необходимости катализатора.

Octopuskit - это постоянная работа , и я все еще учусь по ходу дела, поэтому она может быстро измениться без поддержания обратной совместимости или обновления документации.
Этот проект является результатом моих попыток сделать игры в Pure Swift. Я влюбился в язык, но не мог найти никаких двигателей, которые поддерживали его или имели такую архитектуру, которую я нашел интуитивно понятной, поэтому я начал делать свои собственные.
Добро пожаловать! - Shinryakutako
Хотите погрузиться? Добавьте Octopuskit в качестве зависимости Swift Package Manager в проект Swiftui и используйте шаблон QuickStart (который также служит небольшой демонстрацией.)
? Использование с Swiftui
import SwiftUI
import OctopusKit
struct ContentView : View {
// The coordinator object manages your game's scenes and global state.
@ StateObject var gameCoordinator = OKGameCoordinator ( states : [
MainMenu ( ) ,
Lobby ( ) ,
Gameplay ( ) ] )
var body : some View {
// The container view combines SpriteKit with SwiftUI,
// and presents the coordinator's current scene.
OKContainerView ( )
. environmentObject ( gameCoordinator )
. statusBar ( hidden : true )
}
}? Создание анимированного спрайта
var character = OKEntity ( components : [
// Start with a blank texture.
NodeComponent ( node : SKSpriteNode ( color : . clear , size : CGSize ( widthAndHeight : 42 ) ) ) ,
// Load texture resources.
TextureDictionaryComponent ( atlasName : " PlayerCharacter " ) ,
// Animate the sprite with textures whose names begin with the specified prefix.
TextureAnimationComponent ( initialAnimationTexturePrefix : " Idle " ) ] )? Добавление управления игроком
// Add a component to the scene that will be updated with input events.
// Other components that handle player input will query this component.
// This lets us handle asynchronous events in sync with the frame-update cycle.
// A shared event stream is more efficient than forwarding events to every entity.
// PointerEventComponent is an OS-agnostic component for touch or mouse input.
let sharedPointerEventComponent = PointerEventComponent ( )
scene . entity ? . addComponent ( sharedPointerEventComponent )
character . addComponents ( [
// A relay component adds a reference to a component from another entity,
// and also fulfills the dependencies of other components in this entity.
RelayComponent ( for : sharedPointerEventComponent ) ,
// This component checks the entity's PointerEventComponent (provided here by a relay)
// and syncs the entity's position to the touch or mouse location in every frame.
PointerControlledPositioningComponent ( ) ] )? Динамическое удаление управления игроком или переход на другой метод ввода
character . removeComponent ( ofType : PointerControlledPositioningComponent . self )
character . addComponents ( [
// Add a physics body to the sprite.
PhysicsComponent ( ) ,
RelayComponent ( for : sharedKeyboardEventComponent ) ,
// Apply a force to the body based on keyboard input in each frame.
KeyboardControlledForceComponent ( ) ] )? Пользовательский компонент, специфичный для игры
class AngryEnemyComponent : OKComponent , RequiresUpdatesPerFrame {
override func didAddToEntity ( withNode node : SKNode ) {
node . colorTint = . angryMonster
}
override func update ( deltaTime seconds : TimeInterval ) {
guard let behaviorComponent = coComponent ( EnemyBehaviorComponent . self ) else { return }
behaviorComponent . regenerateHP ( )
behaviorComponent . chasePlayerWithExtraFervor ( )
}
override func willRemoveFromEntity ( withNode node : SKNode ) {
node . colorTint = . mildlyInconveniencedMonster
}
}? Использование пользовательского закрытия для изменения анимации на основе движения игрока
// Add a component that executes the supplied closure every frame.
character . addComponent ( RepeatingClosureComponent { component in
// Check if the entity of this component has the required dependencies at runtime.
// This approach allows dynamic behavior modification instead of halting the game.
if let physicsBody = component . coComponent ( PhysicsComponent . self ) ? . physicsBody ,
let animationComponent = component . coComponent ( TextureAnimationComponent . self )
{
// Change the animation depending on whether the body is stationary or mobile.
animationComponent . textureDictionaryPrefix = physicsBody . isResting ? " Idle " : " Moving "
}
} )
// This behavior could be better encapsulated in a custom component,
// with many different game-specific animations depending on many conditions.? Загрузка сцены, построенной в редакторе сцены Xcode, и создание нескольких объектов из спрайтов, идентифицированных по общему имени
// Load a ".sks" file as a child node.
if let editorScene = SKReferenceNode ( fileNamed : " EditorScene.sks " ) {
scene . addChild ( editorScene )
}
// Search the entire tree for all nodes named "Turret",
// and give them properties of "tower defense" turrets,
// and make them independently draggable by the player.
for turretNode in scene [ " //Turret " ] {
// Create a new entity for each node found.
scene . addEntity ( OKEntity ( components : [
NodeComponent ( node : turretNode ) ,
RelayComponent ( for : sharedPointerEventComponent ) ,
// Hypothetical game-specific components.
HealthComponent ( ) ,
AttackComponent ( ) ,
MonsterTargetingComponent ( ) ,
// Track the first touch or mouse drag that begins inside the sprite.
NodePointerStateComponent ( ) ,
// Let the player select and drag a specific sprite.
// This differs from the PointerControlledPositioningComponent in a previous example,
// which repositions nodes regardless of where the pointer began.
PointerControlledDraggingComponent ( ) ] ) )
}
// Once the first monster wave starts, you could replace PointerControlledDraggingComponent
// with PointerControlledShootingComponent to make the turrets immovable but manually-fired.OctopuSkit использует архитектуру «компонента сущности-компонента», где:
? Игра организована в такие штаты , как Mainmenu , играя и остановившись . Каждое состояние связано с представлением Swiftui , который отображает пользовательский интерфейс, и сцена Spritekit , которая представляет игровой процесс для этого состояния с использованием объектов , компонентов и систем .
Вы можете разделить свою игру на столько или немногие штаты, сколько хотите. Например, один «PlayState», который также обрабатывает главное меню, пауза, кат -сцены и т. Д.
Государства, сцены и взгляды Swiftui могут иметь отношения для многих ко многим, которые могут измениться во время выполнения.
? Сущности - это просто коллекции компонентов . Они не содержат логики, за исключением удобных конструкторов, которые инициализируют группы связанных компонентов.
? Компоненты (которые также можно назвать поведением, эффектами, функциями или чертами) являются основной концепцией в Octopuskit, содержащей свойства, а также логику*, которая составляет каждый визуальный или абстрактный элемент игры. Компонент запускает свой код, когда он добавляется в сущность, когда обновляется кадр и/или когда он удален из сущности. Компоненты могут запросить свою сущность для других компонентов и повлиять на поведение друг друга, чтобы сформировать динамические зависимости во время выполнения. Двигатель поставляется с библиотекой настраиваемых компонентов для графики, игрового процесса, физики и т. Д.
⛓ Системы - это просто коллекции компонентов конкретного класса. Они не выполняют никакой логики*, но они расположены сценой в массиве для выполнения компонентов из всех сущностей в детерминированном порядке в каждом кадре, так что компоненты, которые полагаются на другие компоненты, обновляются после их зависимостей.
* Эти определения могут отличаться от других двигателей, таких как единство, где вся логика содержится в системах.
? Элементы пользовательского интерфейса , такие как кнопки, списки и HUD, разработаны в Swiftui . Это позволяет анимации жидкости, острый текст, векторные формы, превью в прямом эфире, автоматические обновления, управляемые данными, и более 1500 высококачественных икон от символов SF Apple.
См. Архитектурную документацию для подробной разбивки иерархии объекта.
Ваш основной рабочий процесс будет писать классы компонентов для каждой «части» графики и игрового процесса, а затем объединить их для создания сущностей, которые появляются на экране, или абстрактных сущностей, которые обрабатывают данные о «бэкэнде».
Например, говорится, что параллаксбэкбалообразность , содержащая облака , Hillscomponent и TreaScomponent , или GameSessionEntity, содержащий мировой карпонент и многопользовательскую связь.
Производительность: хотя обширные тесты еще не были сделаны, OK может отображать более 5000 спрайтов на iPhone XS в 60 кадрах в секунду ; Каждый спрайт, представленный объектом с несколькими компонентами, обновляемыми каждым кадром, и реагирует на сенсорный ввод.
Приспособлен для Swift : Swift, Swift, Swift! Структура должна следовать установленным руководящим принципам для Swift API Design. Все должно иметь смысл внутри быстро и плавно течь со Swift Idioms как можно больше.
Витамин 2D : На данный момент OK-это, прежде всего, основа для 2D игр, но он не мешает вам использовать такие технологии, как SceneKit или низкоуровневые виды металлов, и это может использоваться для неэгровых приложений.
Плечи эттинов : двигатель использует Spritekit, Gameplaykit, Swiftui и другие технологии, предоставленные Apple. Он не должен пытаться «бороться» с ними, заменить их или скрывать слишком много абстракций.
OK в основном реализуется посредством пользовательских подклассов и расширений классов Spritekit и Gameplaykit, без «застывания» их или блокирования вас от взаимодействия с базовыми классами. Это позволяет вам постепенно принимать эту структуру и позволяет интегрировать вашу игру с инструментами Xcode IDE, такими как редактор сцены, где это возможно.
Тесная связь с APPE APIS также гарантирует, что ваша игра будет защищена от будущей; Всякий раз, когда Apple улучшает эти рамки, Octopuskit и ваши игры также должны получать некоторые преимущества «бесплатно». Например, когда был введен металл, Spritekit был обновлен для автоматического использования металла вместо OpenGL под капотом, что дало многим существующим играм повышение производительности. (WWDC 2016, сессия 610)
Код выходит на первое место : OK - это в первую очередь «программный» двигатель; Почти все сделано в коде. Это также помогает с контролем источника. Редактор сцены Xcode передается в статус «гражданина второго класса» из-за его неполноты и ошибок (по состоянию на май 2018 года, Xcode 9.4), но он поддерживается везде везде. Смотрите следующий пункт.
Вы можете разработать макет/макеты на высоком уровне в редакторе сцены, используя узлы заполнителей с именами (идентификаторы.) Вы можете создать сущности из этих узлов и добавить им компоненты в коде.
Теперь с Swiftui, программирование для Apple Platforms в любом случае направляется к акценту на код вместо визуальных редакторов.
Настраиваемость и гибкость : двигатель стремится быть гибким и дает вам свободу структурировать вашу игру различными способами. Поскольку у вас есть полный доступ к исходному коду двигателя, вы можете изменить или расширить все, что соответствует точным потребностям каждого проекта.
Вы можете использовать любой из следующих подходов к созданию ваших сцен, в порядке поддержки двигателя:
- Выполните создание и размещение узлов в основном в коде. Используйте редактор сцены Xcode нечасто, чтобы спроектировать и предварительно просмотреть несколько отдельных элементов, таких как объекты с определенными позициями и т. Д., Не целые сцены, и используйте
SKReferenceNodeдля загрузки их в код.
- Используйте редактор сцены Xcode в качестве отправной точки, чтобы создать шаблонные сцены, которые могут быть загружены в качестве экземпляров
SKReferenceNodeна верхнем уровнеOKScene. Этот подход позволяет модифицировать визуальный дизайн и предварительный просмотр "Wysiwyg".
- Создайте сцену почти полностью в редакторе сцены XCode, добавив любые поддерживаемые компоненты, действия, физические тела, навигационные графики и текстуры и т. Д. Прямо в IDE.
Установите пользовательский класс сцены какOKSceneили подкласс. Загрузите сцену, позвонивOKViewController.loadAndPresentScene(fileNamed:withTransition:), например, во времяdidEnter.from(_:)СобытиеOKGameState.
- Вам не нужно использовать ни одной из архитектур и шаблонов, предложенных здесь; Вам не нужно использовать игровые состояния, и ваши игровые объекты даже не должны наследовать от каких -либо классов OK. Вы можете использовать свою собственную архитектуру и просто использовать OK для нескольких вспомогательных методов и т. Д., Сохраняя только то, что вам нужно из этой структуры и исключая остальные из -за компиляции.
Самоуровенька : вам не нужно загружать или не отставать от любых других сторонних библиотек, если ваш собственный проект не требует их; Все, что использует OK, находится внутри OK или Apple Frameworks, поэтому оно поставляется с полным использованием из коробки.
Прочитайте Руководство по QuickStart и использованию. Вам понадобятся Xcode 12, iOS 14 и MacOS Big SUR (хотя OK может работать на более старых версиях с некоторыми ручными модификациями.)
Уровень квалификации: промежуточный : хотя OK не представлен в форме, предназначенной для абсолютных начинающих, в основном потому, что я слишком ленив, чтобы писать документацию из Step Zero, это также не «продвинутый» уровень уровня; Если вы прочитали книгу о Swift Language и попытались сделать игру Spritekit в Xcode, вы готовы использовать OK!
Вам также следует прочитать о шаблонах «композиции над наследством» и моделей «субъекта - компонента - система», если вы еще не знакомы с этими понятиями, хотя реализация ОК может отличаться от того, что вы ожидаете.
Также см. Учебные пособия Apple для Swiftui.
Подробный обзор архитектуры двигателя см. В архитектуре.
Застрял? Смотрите советы и устранение неполадок.
Хотите знать, было ли что -то намеренно сделано таким, каким оно есть, или почему? Конвенции кодирования и дизайнерские решения могут иметь объяснение.
Хотите следить за тем, что произойдет или поможет с разработкой недостающих функций? Смотрите Todo & Roadmap.
Авторы и сторонники ❤︎
Этот проект может быть названа Octopuskit, «OK» или «Okio» (для «Octopuskit, вторгаясь на осьминога»), но «iook» звучит странно.
Наименование - это сочетание вдохновения от таких компаний, как Rogue Amoeba, домен .io и аниме Shinryaku! Ика Мусум .
Пространство перед последним ]) в разделе «Примеры» для ясности. :)
Лицензия: Apache 2.0
Включает шейдеры от Shaderkit © Пол Хадсон, лицензированный по лицензии MIT (см. Заголовки в соответствующих файлах).
Расскажи мне, как все круто или ужасно: Discord, Twitter или? Cotopus?it@?nvading?ctopus.ⓘⓞ
Я редко проверяю их, поэтому лучший способ задать вопрос - это может быть открыт проблему в репозитории GitHub.
Поддержите свой декадентский образ жизни, чтобы я мог сосредоточиться на создании нелистых вещей: мой патрион
Этот проект никоим образом не связан с Apple.
Octopuskit © 2023 Вторжение осьминога • Лицензия Apache 2.0