测试已测试 | ✓ |
Lang语言 | SwiftSwift |
许可 | MIT |
发布上次发布 | 2017年4月 |
SwiftSwift 版本 | 3.0 |
SPM支持 SPM | ✓ |
由 Luiz Fernando 维护。
用 Swift 编写的 iOS 实体基础游戏框架。
该框架使用传统的实体-组件-系统,同时还包括空间的概念,这在以下文章中有描述:这篇文章
此 pod 还附带一个子 pod GPEngine/Serialization
,允许使用 SwiftyJSON(见 序列化)将空间/子空间/实体/组件从 JSON 序列化到 JSON。
此引擎与经典 ECS 引擎非常相似,但增加了 Spaces
的抽象。
╔══════════╗
║ Engine ║
╚═════╤════╝ ╔════════╗╔════════╗╔════════╗
├──────╢ Entity ╟╢ Entity ╟╢ Entity ╟...
│ ╚════════╝╚════════╝╚════════╝
│ ╔════════╗╔════════╗╔════════╗
└──────╢ System ╟╢ System ╟╢ System ╟...
╚════════╝╚════════╝╚════════╝
以这种方式,您不能轻松地将实体分组(例如,将敌人分为前景和背景敌人,背景敌人不与玩家交互)。这是可以通过组件/类型标志指定来实现的,但 Spaces 旨在将其作为一个显式的抽象。
空间是实体的容器,实体独立地行动,从而在组合在一起的实体之间减少了一层抽象。为了帮助进行此类抽象,还提出了 Subspaces
的概念,该概念旨在针对系统分别分离空间/实体相关的数据(如单独的物理引擎实例,渲染相机位置等)。
╔══════════╗
║ Engine ║
╚═════╤════╝
╔═══╧═══╗ ╔════════╗╔════════╗╔════════╗
║ Space ╟─┬─╢ Entity ╟╢ Entity ╟╢ Entity ╟...
╚═══╤═══╝ │ ╚════════╝╚════════╝╚════════╝
│ │ ╔══════════╗
│ └─╢ Subspace ║
│ ╚══════════╝
╔═══╧═══╗ ╔════════╗╔════════╗╔════════╗
║ Space ╟─┬─╢ Entity ╟╢ Entity ╟╢ Entity ╟...
╚═══╤═══╝ │ ╚════════╝╚════════╝╚════════╝
│ │ ╔══════════╗╔══════════╗
│ └─╢ Subspace ╟╢ Subspace ║
│ ╚══════════╝╚══════════╝
│
│ ╔════════╗╔════════╗╔════════╗
└──────╢ System ╟╢ System ╟╢ System ╟...
╚════════╝╚════════╝╚════════╝
在此,实体被分组到空间中,其中每个空间完全隔离。还引入了子空间,这些空间有助于存储系统用来处理数据的状态。酷的一点是,空间只需要添加对其相关的子空间;如果子空间不需要渲染(例如,一个仍然“存活”但位于门后的不同游戏房间),则不需要添加 RenderingSubspace!
系统仍然是全局的,因为理想情况下它们应该是无状态的(通过子空间的帮助)。然后,系统将查询空间以获取具有相关组件的实体以及需要的子空间,如果可用,则使用其声明的逻辑对其采取行动。系统始终独立地对每个空间采取行动,就像它们是隔离的经典 ECS 引擎一样。
支持Xcode 8.2 & Swift 3.0或更高版本。
GPEngine也以Swift包的形式提供。
import PackageDescription
let package = Package(
name: "project_name",
targets: [],
dependencies: [
.Package(url: "https://github.com/LuizZak/GPEngine.git", majorVersion: 2, minor: 2)
]
)
LuizZak, [email protected]
GPEngine遵循MIT许可协议。更多详细信息请参阅LICENSE文件。
(此可选功能在
pod 'GPEngine/Serialization'
您可以使用GameSerializer类序列化实体或整个空间(包括子空间/实体/组件)。
这允许您保存部分或完整的游戏状态,以及从预制的JSON结构中执行数据驱动的游戏状态初始化。
(有关如何将内容序列化的信息,请见下文的
) 序列化要求
let myProvider = MyTypeProvider() // Implements SerializationTypeProvider
let gameSerializer = GameSerializer(typeProvider: myProvider)
let mySerialized = try gameSerializer.serialize(myEntity)
// .serialize(_:) returns a Serialized object, call .serialize() on it to receive a JSON that you can store:
let json = mySerialized.serialized()
// Store json somewhere...
要反序列化实体,请使用以下过程
let json = // Retrieve entity JSON from somewhere...
// Retrieve it back to a Serialized object
// If this fails, that means you got a bad JSON :(
let mySerialized = try Serialized.deserialized(from: json)
// Requires explicit ': Entity' type annotation
let myEntity: Entity = try gameSerializer.extract(from: mySerialized)
// If we reached here, entity was deserialized correctly! Success!
Space
的序列化和反序列化过程类似,并使用了相同的方法名。
从Serialized.serialized()
返回的序列化JSON遵循以下结构
{
"contentType": "<String - one of the raw values of Serialized.ContentType>",
"typeName": "<String - type name returned by your SerializationTypeProvider to retrieve the class to instantiate back>",
"data": "<Any - this is the JSON returned by the object's serialize() method>"
}
序列化容器可以通过将它们添加到data
字段中来嵌套于彼此之中,并通过
GameSerializer.extract<T: Serializable>(from: Serialized)
这是一个协议,必须实现以在反序列化期间提供您的自定义组件/子空间类型。
GameSerializer调用您的类型提供程序并提供序列化的类型名称,您必须返回Swift元类型(例如MyComponent.self
)。
协议默认实现用于检索类型的序列化名称的方法,并返回
String(describing: Type.self)
可以使用一个数组来实现简单的类型提供程序,该数组存储游戏中所有已知可序列化类型,并使用预实现的
BasicSerializationTypeProvider
class Provider: BasicSerializationTypeProvider {
// Requirement from `BasicSerializationTypeProvider`
var serializableTypes: [Serializable.Type] = [
MySerializableComponent.self,
MySerializableSubspace.self
]
// Now `serializedName(for:)`/`deserialized(from:)` are automatically stubbed using `serializableTypes` array.
}
为了序列化实体和空间,您需要遵循以下要求
Component
Serializable
是用于通过JSON编码/解码对象的基本协议
/// Describes an object that can be serialized to and back from a JSON object.
/// Implementers of this protocol should take care of guaranteeing that the inner
/// state of the object remains the same when deserializing from a previously
/// serialized object.
public protocol Serializable {
/// Initializes an instance of this type from a given serialized state.
///
/// - Parameter json: A state that was previously serialized by an instance
/// of this type using `serialized()`
/// - Throws: Any type of error during deserialization.
init(json: JSON) throws
/// Serializes the state of this component into a JSON object.
///
/// - Returns: The serialized state for this object.
func serialized() -> JSON
}
要检查您的实体和空间是否完全可序列化,请使用实体的
GameSerializer.canSerialize(_:)
GameSerializer.diagnoseSerialize(on:)
方法或在您的空间上。 系统旨在为无状态,因此默认不支持序列化。但这不会阻止您将其添加到序列化类型提供程序中,并实现它们上的Serializable协议,从而使它们可序列化。