
一個基於ECS的2D遊戲引擎,並用100%Swift為iOS,MacOS,TVOS和Visionos編寫。
警告
?該項目不再由唯一的維護者更新。
?我搬到了戈多。查看Comedot ←我在Godot的2D遊戲的基於組件的框架!
重要的
❕章魚需要章魚。非遊戲功能被分為一個單獨的存儲庫,以供一般應用中使用。有關最後一個獨立版本,請參見4.0.0-Beta-5
如果您在堅持官方API時嘗試在Swift製作遊戲,這可能適合您! Octopuskit包裹並擴展了Apple的框架:
•對於靈活的實體 - 組件系統體系結構的GamePlayKit ,可以動態構成遊戲行為。
•用於2D圖形,物理和GPU著色器的SpriteKit 。
• SwiftUI用於快速設計具有聲明語法的流體,可擴展的HUD。
•金屬以確保引擎蓋下的最佳本地性能。
•獨立於OS的組件,您可以使用相同的代碼處理鼠標/觸摸或鍵盤/GAMEPAD輸入,並為iOS + MacOS本地編譯而無需催化劑。

Octopuskit是一項不斷的工作,我仍在學習,因此它可能會迅速變化而不維護向後兼容或更新文檔。
這個項目是我嘗試將游戲製作純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場景編輯器內置的場景並從共享名稱標識的Sprites創建多個實體
// 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中的核心概念,其中包含屬性以及構成遊戲中每個視覺或抽像元素的邏輯*。當組件添加到實體,更新幀時和/或將其從實體中刪除時,將其代碼運行。組件可能會查詢其實體對其他組件,並影響彼此的行為,以在運行時形成動態依賴性。該引擎配備了用於圖形,遊戲玩法,物理等的可自定義組件庫。
⛓系統只是特定類的組件的集合。他們沒有執行任何邏輯*,但是它們由數組中的場景安排,以確定性順序從所有幀中執行所有實體的組件,因此依賴其他組件的組件在其依賴項之後會更新。
*這些定義可能與其他引擎(例如Unity)不同,其中所有邏輯都包含在系統中。
?用戶界面元素(例如按鈕,列表和HUD)在SwiftUI中設計。這允許流體動畫,清晰的文本,矢量形狀,實時預覽,自動數據驅動的更新以及蘋果SF符號的1,500多個高質量圖標。
有關對象層次結構的詳細分解,請參見架構文檔。
您的主要工作流程將為圖形和遊戲玩法的每個“部分”編寫組件類,然後將它們組合在一起,以構建出現在屏幕上的實體,或者在“後端”上處理數據的抽象實體。
例如,說一個包含雲的component , hillscomponent和treescomponent或包含WorldMapComponent和多人遊戲的遊戲性的視差。
性能:儘管尚未完成廣泛的基準測試,但OK可以以每秒60幀的速度在iPhone XS上顯示超過5000個精靈;每個精靈由一個實體表示,每個幀都會更新每個幀,並響應觸摸輸入。
為Swift量身定制:Swift,Swift,Swift!該框架必須遵循Swift API設計的既定準則。一切都必須在Swift中有意義,並且盡可能多地使用Swift Idioms無縫地流動。
維生素2D :目前,OK主要是2D遊戲的框架,但它並不能阻止您使用Scenekit或低級金屬視圖之類的技術,並且可以用於非遊戲應用程序。
Ettins的肩膀:發動機利用SpriteKit,GamePlayKit,Swiftui和Apple提供的其他技術。它不應嘗試“與他們進行戰鬥”,更換它們或將它們隱藏在太多的抽像後面。
OK主要是通過自定義子類和SpriteKit和GamePlayKit類的擴展來實現的,而不會“掩蓋”它們或阻止您與基礎類互動。這使您可以逐步採用此框架,並讓您在可能的情況下將游戲與Xcode IDE工具(例如場景編輯器)集成在一起。
與Apple API的緊密耦合也確保您的遊戲是防前的;每當蘋果改進這些框架時,Actopuskit和您的遊戲也應該“免費”獲得一些好處。例如,當引入金屬時,SpriteKit被更新以自動使用金屬而不是openGL在引擎蓋下,從而使許多現有的遊戲都提高了性能。 (WWDC 2016,第610節)
代碼首先出現:確定主要是“編程”引擎;幾乎所有內容都是用代碼完成的。這也有助於源控制。 Xcode場景編輯器由於其不完整和錯誤(截至2018年5月,Xcode 9.4)而被降級為“二等公民”狀態,但在方便的情況下得到支持。請參閱下一點。
您可以在場景編輯器中設計高級佈局/模型,使用帶有名稱的佔位符節點(標識符。)然後,您可以從這些節點創建實體,並在代碼中添加組件。
現在,有了Swiftui,Apple平台編程即將重點關注代碼,而不是視覺編輯器。
可定制性和靈活性:發動機努力保持靈活性,並為您提供以各種方式構建遊戲的自由。由於您可以完全訪問引擎的源代碼,因此可以修改或擴展任何內容以滿足每個項目的確切需求。
您可以根據引擎支持順序使用以下任何方法來構建場景:
- 主要在代碼中執行節點的創建和放置。不經常使用Xcode場景編輯器來設計和預覽一些單獨的元素,例如具有特定位置等的實體,而不是整個場景,並使用
SKReferenceNode將它們加載到代碼中。
- 使用Xcode場景編輯器作為起點,創建可能加載的模板場景,以作為
OKScene的頂級SKReferenceNode實例加載。這種方法允許“ Wysiwyg”視覺設計和預覽。
- 在Xcode場景編輯器中幾乎完全創建場景,添加了IDE中的任何受支持的組件,動作,物理體,導航圖和紋理等。
將場景的自定義類設置為OKScene或IT的子類。通過調用OKViewController.loadAndPresentScene(fileNamed:withTransition:),例如在didEnter.from(_:)OKGameState的事件中,加載場景。
- 您不必使用此處建議的任何架構和模式;您不必使用遊戲狀態,並且您的遊戲對象甚至不必從任何確定的類中繼承。您可以使用自己的體系結構,只需將OK用於幾種輔助方法等,僅保留此框架所需的東西,而將其餘的排除在彙編之外。
自我範圍:如果您自己的項目不需要它們,則不需要下載或跟上任何其他第三方庫;確定使用的所有內容都在確定或Apple Framework中,因此它可以完全可用。
閱讀快速啟動和使用指南。您將需要Xcode 12,iOS 14和Macos Big Sur(儘管可以使用一些手動修改的舊版本。)
技能級別:中級:儘管沒有以專為絕對初學者設計的形式出現,這主要是因為我懶得從步驟零來編寫文檔,但它也不是“高級”級別的內容;如果您已經閱讀了Swift語言書,並試圖用Xcode製作SpriteKit遊戲,則可以使用OK!
如果您還不熟悉這些概念,那麼您還應該閱讀有關“繼承的組成”和“實體 - 組件 - 系統”模式,儘管OK的實現可能與您的期望有所不同。
另請參閱蘋果的Swiftui教程。
有關引擎架構的詳細概述,請參見體系結構。
卡住?請參閱提示和故障排除。
想知道是否有意按照自己的方式完成某事?編碼約定和設計決策可能有解釋。
是否想了解即將發生的事情或幫助丟失功能的發展?請參閱托多和路線圖。
貢獻者和支持者❤︎
該項目可以稱為章魚,“ OK”或“ OKIO”(對於“ Incopuskit in Inting Octopus”),但“ Iook”聽起來很奇怪。
命名是來自Rogue Amoeba,.io Domain和Anime Shinryaku等公司的靈感的結合! ika媽媽。
示例部分中最後一個])空間是為了清晰。 :)
許可證:Apache 2.0
合併了ShaderKit的著色器©Paul Hudson,根據MIT許可證獲得許可(請參閱相關文件中的標題)。
告訴我一切有多棒或可怕:Discord,Twitter或? ctopus? it@? nvading?
我很少檢查這些問題,因此提出問題的最佳方法可能是通過在GitHub存儲庫上打開問題。
支持我decade廢的生活方式,這樣我就可以專注於製作不足的東西:我的patreon
該項目與蘋果沒有任何隸屬關係。
Octopuskit©2023入侵章魚•Apache許可證2.0