
Mesin game 2D berdasarkan ECS dan ditulis dalam 100% Swift untuk iOS, macOS, TVOS dan visiono.
Peringatan
? Proyek ini tidak lagi diperbarui oleh pemelihara tunggal.
? Saya telah pindah ke Godot. Lihatlah ComEdot ← Kerangka kerja berbasis komponen saya untuk game 2D di Godot!
Penting
❕ Octopuskit membutuhkan octopuscore. Fungsionalitas non-game dibagi menjadi repositori terpisah untuk digunakan dalam aplikasi umum. Untuk versi mandiri terakhir, lihat 4.0.0-beta-5
Jika Anda sudah mencoba membuat game di Swift sambil tetap berpegang pada API resmi, ini mungkin untuk Anda! Octopuskit membungkus dan memperluas kerangka kerja Apple:
• Gameplaykit untuk arsitektur sistem-komponen-komponen yang fleksibel untuk secara dinamis menyusun perilaku game.
• SpriteKit untuk grafik 2D, fisika, dan shader GPU.
• SwiftUi untuk merancang cairan yang cepat dan scalable dengan sintaks deklaratif.
• Logam untuk memastikan kinerja asli terbaik di bawah kap.
• Komponen OS-independen memungkinkan Anda menangani input mouse/sentuh atau keyboard/gamepad dengan kode yang sama, dan kompilasi secara asli untuk iOS + macOS tanpa memerlukan katalis.

Octopuskit adalah pekerjaan yang konstan yang sedang berlangsung dan saya masih belajar saat saya pergi, sehingga dapat berubah dengan cepat tanpa mempertahankan kompatibilitas ke belakang atau memperbarui dokumentasi.
Proyek ini adalah hasil dari upaya saya untuk membuat game di Pure Swift. Saya jatuh cinta dengan bahasa tersebut tetapi tidak dapat menemukan mesin yang mendukungnya atau memiliki jenis arsitektur yang saya temukan intuitif, jadi saya mulai membuatnya sendiri.
Umpan balik selamat datang! - Shinryakutako
Ingin menyelam? Tambahkan Octopuskit sebagai ketergantungan manajer paket Swift ke proyek SwiftUi, dan gunakan template QuickStart (yang juga berfungsi sebagai demo kecil.)
? Menggunakan dengan 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 )
}
}? Membuat sprite animasi
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 " ) ] )? Menambahkan kontrol pemain
// 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 ( ) ] )? Secara dinamis menghapus kontrol pemain atau mengubah ke metode input yang berbeda
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 ( ) ] )? Komponen khusus permainan khusus
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
}
}? Menggunakan penutupan khusus untuk mengubah animasi berdasarkan gerakan pemain
// 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.? Memuat adegan yang dibangun di editor adegan Xcode dan membuat banyak entitas dari sprite yang diidentifikasi dengan nama bersama
// 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 menggunakan arsitektur "entitas-komponen-sistem", di mana:
? Sebuah permainan disusun ke negara -negara seperti Mainmenu , bermain dan berhenti . Setiap negara dikaitkan dengan tampilan SwiftUi yang menampilkan antarmuka pengguna, dan adegan spritekit yang menyajikan gameplay untuk keadaan tersebut menggunakan entitas , komponen , dan sistem .
Anda dapat membagi permainan Anda menjadi sebanyak atau sesedikit negara yang Anda inginkan. misalnya satu "playstate" tunggal yang juga menangani menu utama, berhenti, cutscene dll.
Negara, adegan, dan pandangan SwiftUi mungkin memiliki banyak hubungan yang dapat berubah selama runtime.
? Entitas hanyalah koleksi komponen . Mereka tidak mengandung logika, kecuali untuk konstruktor kenyamanan yang menginisialisasi kelompok komponen terkait.
? Komponen (yang juga bisa disebut perilaku, efek, fitur, atau sifat) adalah konsep inti dalam gurita, berisi sifat -sifat serta logika* yang membentuk setiap elemen visual atau abstrak dari permainan. Komponen menjalankan kodenya ketika ditambahkan ke entitas, ketika bingkai diperbarui, dan/atau ketika dihapus dari suatu entitas. Komponen dapat meminta entitas mereka untuk komponen lain dan mempengaruhi perilaku masing -masing untuk membentuk dependensi dinamis selama runtime. Mesin dilengkapi dengan pustaka komponen yang dapat disesuaikan untuk grafik, gameplay, fisika dll.
⛓ Sistem hanyalah koleksi komponen dari kelas tertentu. Mereka tidak melakukan logika apa pun*, tetapi mereka diatur oleh adegan dalam array untuk menjalankan komponen dari semua entitas dalam urutan deterministik setiap bingkai, sehingga komponen yang mengandalkan komponen lain diperbarui setelah ketergantungan mereka.
* Definisi ini mungkin berbeda dari mesin lain, seperti Unity, di mana semua logika terkandung dalam sistem.
? Elemen antarmuka pengguna seperti tombol, daftar dan HUD dirancang di SwiftUi . Hal ini memungkinkan animasi cairan, teks yang tajam, bentuk vektor, pratinjau langsung, pembaruan berbasis data otomatis, dan lebih dari 1.500 ikon berkualitas tinggi dari simbol SF Apple.
Lihat dokumentasi arsitektur untuk rincian terperinci dari hierarki objek.
Alur kerja utama Anda akan menulis kelas komponen untuk setiap "bagian" dari grafik dan gameplay, kemudian menggabungkannya untuk membangun entitas yang muncul di layar, atau entitas abstrak yang menangani data pada "backend."
EG mengatakan paralaks kembaligroundentitas yang berisi komponen awan , komponen bukit dan komponen treescomponent , atau permainan yang berisi komponen worldmapponent dan kompleks Syncayers .
Kinerja: Meskipun tolok ukur yang luas belum dilakukan, OK dapat menampilkan lebih dari 5000 sprite pada iPhone XS pada 60 frame per detik ; Setiap sprite diwakili oleh entitas dengan beberapa komponen yang diperbarui setiap bingkai, dan menanggapi input sentuhan.
Disesuaikan untuk Swift : Swift, Swift, Swift! Kerangka kerja harus mengikuti pedoman yang ditetapkan untuk desain API Swift. Semuanya harus masuk akal dalam cepat dan mengalir mulus dengan idiom cepat sebanyak mungkin.
Vitamin 2D : Saat ini, OK terutama merupakan kerangka kerja untuk game 2D, tetapi tidak mencegah Anda menggunakan teknologi seperti scenekit atau tampilan logam tingkat rendah, dan dapat digunakan untuk aplikasi non-game.
Bahu Ettins : Mesin memanfaatkan Spritekit, Gameplaykit, SwiftUi dan teknologi lain yang disediakan oleh Apple. Seharusnya tidak mencoba untuk "melawan" mereka, menggantinya, atau menyembunyikannya di balik terlalu banyak abstraksi.
OK sebagian besar diimplementasikan melalui subkelas khusus dan ekstensi kelas Spritekit dan Gameplaykit, tanpa "mengaburkan" mereka atau menghalangi Anda untuk berinteraksi dengan kelas dasar. Ini memungkinkan Anda untuk mengadopsi kerangka kerja ini secara bertahap, dan memungkinkan Anda mengintegrasikan game Anda dengan alat Xcode IDE seperti editor adegan jika memungkinkan.
Kopling ketat dengan Apple API juga memastikan bahwa permainan Anda tahan masa depan; Setiap kali Apple meningkatkan kerangka kerja ini, Octopuskit dan game Anda juga harus mendapatkan beberapa manfaat "gratis." Misalnya, ketika logam diperkenalkan, SpriteKit diperbarui untuk secara otomatis menggunakan logam alih -alih OpenGL di bawah kap, memberikan banyak game yang ada peningkatan kinerja. (WWDC 2016, Sesi 610)
Kode Come First : OK terutama mesin "terprogram"; Hampir semuanya dilakukan dalam kode. Ini juga membantu dengan kontrol sumber. Editor adegan Xcode diturunkan ke status "warga negara kelas dua" karena ketidaklengkapan dan bugnya (pada Mei 2018, Xcode 9.4), tetapi didukung di mana pun nyaman. Lihat poin berikutnya.
Anda dapat merancang tata letak/mockup tingkat tinggi di editor adegan, menggunakan node placeholder dengan nama (pengidentifikasi.) Anda kemudian dapat membuat entitas dari node tersebut dan menambahkan komponen ke dalamnya dalam kode.
Sekarang dengan SwiftUi, pemrograman untuk platform Apple sedang menuju fokus pada kode alih -alih editor visual.
Kustomisasi & Fleksibilitas : Mesin berusaha untuk menjadi fleksibel dan memberi Anda kebebasan untuk menyusun permainan Anda dengan berbagai cara. Karena Anda memiliki akses penuh ke kode sumber mesin, Anda dapat memodifikasi atau memperluas apa pun sesuai dengan kebutuhan yang tepat dari setiap proyek.
Anda dapat menggunakan salah satu dari pendekatan berikut untuk membangun adegan Anda, dalam urutan dukungan mesin:
- Lakukan pembuatan dan penempatan node kebanyakan dalam kode. Gunakan Editor Xcode Scene jarang, untuk merancang dan melihat beberapa elemen individu seperti entitas dengan posisi tertentu dll., Bukan seluruh adegan, dan menggunakan
SKReferenceNodeuntuk memuatnya dalam kode.
- Gunakan Editor Adegan Xcode sebagai titik awal Anda, untuk membuat adegan templat yang dapat dimuat sebagai contoh
SKReferenceNodetingkat atas dari sebuahOKScene. Pendekatan ini memungkinkan sedikit desain dan pratinjau visual "wysiwyg".
- Buat adegan hampir seluruhnya di editor adegan Xcode, menambahkan komponen, tindakan, badan fisika, grafik navigasi, dan tekstur yang didukung, dll. Tepat di IDE.
Atur kelas adegan kustom sebagaiOKSceneatau subclass darinya. Muat adegan dengan meneleponOKViewController.loadAndPresentScene(fileNamed:withTransition:), misalnya selamadidEnter.from(_:)acaraOKGameState.
- Anda tidak harus menggunakan salah satu arsitektur dan pola yang disarankan di sini; Anda tidak perlu menggunakan status game, dan objek game Anda bahkan tidak perlu mewarisi dari kelas OK. Anda dapat menggunakan arsitektur Anda sendiri, dan hanya menggunakan OK untuk beberapa metode pembantu dll., Hanya menjaga apa yang Anda butuhkan dari kerangka kerja ini dan tidak termasuk sisanya dari kompilasi.
Mandiri : Anda tidak perlu mengunduh atau mengikuti perpustakaan pihak ketiga lainnya jika proyek Anda sendiri tidak memerlukannya; Segala sesuatu yang digunakan OK ada dalam kerangka kerja OK atau Apple, jadi ia benar-benar dapat digunakan di luar kotak.
Baca panduan QuickStart dan penggunaan. Anda akan membutuhkan Xcode 12, iOS 14 dan MacOS Big Sur (meskipun OK dapat bekerja pada versi yang lebih lama dengan beberapa modifikasi manual.)
Level Keterampilan: Menengah : Meskipun OK tidak disajikan dalam bentuk yang dirancang untuk pemula absolut, terutama karena saya terlalu malas untuk menulis dokumentasi dari Langkah Zero, juga bukan hal -hal yang "maju"; Jika Anda telah membaca buku bahasa Swift dan telah berusaha membuat game Spritekit di Xcode, Anda siap menggunakan OK!
Anda juga harus membaca tentang pola "komposisi atas warisan" dan "entitas -komponen -sistem" jika Anda belum terbiasa dengan konsep -konsep itu, meskipun implementasi OK dari ini mungkin berbeda dari yang Anda harapkan.
Lihat juga tutorial Apple untuk SwiftUi.
Untuk tinjauan terperinci tentang arsitektur mesin, lihat arsitektur.
Terjebak? Lihat Tip & Pemecahan Masalah.
Ingin tahu apakah ada sesuatu yang sengaja dilakukan seperti itu, atau mengapa? Konvensi pengkodean & keputusan desain mungkin memiliki penjelasan.
Ingin mengawasi apa yang akan datang atau membantu dengan pengembangan fitur yang hilang? Lihat Todo & Roadmap.
Kontributor & Pendukung ❤︎
Proyek ini dapat disebut sebagai Octopuskit, "OK" atau "Okio" (untuk "Octopuskit dengan Menyerang Octopus") tetapi "Iook" terdengar aneh.
Penamaan adalah kombinasi inspirasi dari perusahaan seperti Rogue Amoeba, domain .io, dan anime shinryaku! Ika Musume .
Ruang sebelum yang terakhir ]) di bagian Contoh adalah untuk kejelasan. :)
Lisensi: Apache 2.0
Menggabungkan shader dari shaderkit © Paul Hudson, dilisensikan di bawah lisensi MIT (lihat header dalam file yang relevan).
Katakan padaku betapa luar biasa atau mengerikan semuanya: Perselisihan, Twitter atau ?ctopus?it@?nvading?ctopus.ⓘⓞ
Saya jarang memeriksa ini, jadi cara terbaik untuk mengajukan pertanyaan mungkin melalui membuka masalah di repositori GitHub.
Dukung gaya hidup dekaden saya sehingga saya dapat fokus membuat hal -hal yang tidak dapat dijual: patreon saya
Proyek ini tidak berafiliasi dengan Apple.
Octopuskit © 2023 Menyerang gurita • Lisensi Apache 2.0