LionECS 0.0.4

LionECS 0.0.4

Tomasz Lewandowski 维护。



LionECS 0.0.4

  • 作者:
  • Tomasz Lewandowski

ECS (实体组件系统) 内核实现,用 Swift 编写。它没有发行依赖项,支持以下平台: iOS、macOS、tvOS、watchOS

需求

开发

项目使用以下工具进行开发

  1. XCodeGen
  2. Cocoapods
  3. SwiftLint
  4. Sourcery

安装

要开始使用 LionECS,您首先需要决定如何将其集成到项目中。LionECS 支持以下工具

Cocoapods

要使用 Cocoapods 安装 LionECS,按照以下步骤进行

  1. 在您的 Podfile 中添加以下条目
pod 'LionECS'
  1. 然后运行 pod install

Carthage

使用Carthage安装LionECS,请按照以下步骤操作

  1. 在您的Cartfile中添加以下条目
github "LionGameEngine/LionECS"
  1. 然后运行carthage update

Swift包管理器

使用Swift包管理器安装LionECS,请按照以下步骤操作

  1. 在您的Package.swift中添加以下包依赖项:.package(url: "https://github.com/LionGameEngine/LionECS.git", from: "0.0.4")
  2. 在您的Package.swift中添加以下目标依赖项:dependencies: ["LionECS"])

概览

以下是LionECS中使用的功能和概念的简要概述。

实体

实体代表ECS世界中的一个对象实例。它定义为一个包含id版本的二元组

public struct Entity: Identifiable, Equatable, Hashable {
    public let id: UInt64
    public let version: UInt64
}

组件

组件是简单的结构体,用于存储实体的数据。它们描述了实体的实际构成。每个实体可以有一个指定类型的组件。要创建组件类型,您需要创建一个实现PComponent协议的新结构体,这要求您返回组件标识符。不过,您可以通过简单地返回类型标识符作为默认标识符来做到这一点。例如

struct HealthComponent: PComponent {
    var health: Float
}

系统

系统根据您的查询操作一个或多个组件。要创建系统,您可以选择实现PSystem协议或从ComponentSystem继承(这为您提供了对世界的访问),并实现func update()

世界

世界表示一个单独的模拟。它包含并允许访问:实体管理器、实体请求器、系统和组件管理器。当它被更新时,它也会更新你所有的系统。

组件管理器

提供对组件数据的访问。一切都是通用的组件管理器,因此核心组件管理逻辑可以轻松切换。

默认核心支持structs枚举作为组件类型。

原型

描述实体实例具有的一组组件。

查询

查询

可以通过实体请求器执行查询。首先,你需要定义一个继承自PEntityQuery的查询。已经定义了EntityQuery。然后,使用实体请求器的queryEntities<Query: PEntityQuery>(query: Query)方法。

查询结果

所有查询都必须定义其结果。为EntityQuery定义的是EntityQueryResult。它定义了遍历满足查询的实体的方法。

示例

以下为损害系统的示例。首先,我们需要实现所需的组件

struct DamageComponent: PComponent {
    var damage: Float
}
struct HealthComponent: PComponent {
    var health: Float
}
struct DeadComponent: PComponent {}

然后定义在组件上运行的系统

class DamageSystem: ComponentSystem<ComponentManager> {
    override func update() {
        let query = EntityQuery<ComponentManager>(filters: [Requires<DamageComponent>(), Requires<HealthComponent>(), Excludes<DeadComponent>()])
        guard let result = try? entityRequester.queryEntities(query: query) else { return }
        result.forEach { (entity: Entity, health: inout HealthComponent, damage: DamageComponent) in
            defer {
                try? componentManager.removeComponent(DamageComponent.self, fromEntity: entity)
            }
            health.health -= damage.damage
        }
    }
}
class DeathSystem: ComponentSystem<ComponentManager> {
    override func update() {
        let query = EntityQuery<ComponentManager>(filters: [Requires<HealthComponent>(), Excludes<DeadComponent>()])
        guard let result = try? entityRequester.queryEntities(query: query) else { return }
        result.forEach { (entity: Entity, health: HealthComponent) in
            if health.health <= 0 {
                try? componentManager.addComponent(DeadComponent(), toEntity: entity)
            }
        }
    }
}

然后将其全部粘合在一起

class Game {
    let world: World<ComponentManager>
    let damageSystem: DamageSystem
    let deathSystem: DeathSystem
    let player: Entity
    
    init() {
        let playerPrototype = PrototypeBuilder()
            .add(HealthComponent.self)
            .build()
        let manager: ComponentManager = ComponentManager()
        world = World<ComponentManager>(componentManager: manager)
        damageSystem = world.getOrCreateSystem()
        deathSystem = world.getOrCreateSystem()
        player = world.entityManager.createEntity(withPrototype: playerPrototype)
        try! world.componentManager.updateComponent(HealthComponent(health: 123), ofEntity: player)
        try! world.componentManager.addComponent(DamageComponent(damage: 23), toEntity: player)
        gameloop {
            world.update()
        }
    }

    
    func gameloop(update: () -> Void) {
        while true {
            update()
        }
    }
}

欲查看更详细的示例,请参阅源代码。

贡献

该项目由 托马兹·莱万多夫斯基 创建。

如果您添加了新功能或修复了错误,您可以创建一个拉取请求。如果您有任何功能请求,请随时提交。

许可证

LionECS 在 MIT 许可证下发布。有关更多信息,请参阅 License.md