14 个版本

0.7.0 2024 年 8 月 5 日
0.6.85 2024 年 7 月 29 日
0.6.9 2024 年 8 月 5 日
0.5.0 2024 年 7 月 24 日

73游戏开发

Download history 61/week @ 2024-07-19 754/week @ 2024-07-26 248/week @ 2024-08-02 22/week @ 2024-08-09

1,085 每月下载量

MIT 协议

60KB
1.5K SLoC

Dark Iron ECS

Dark Iron

功能

  • 实体创建:轻松创建实体并将组件附加到它们。
  • 事件处理:实现基于自定义事件和事件处理器的驱动架构。
  • 协程:创建在特定间隔或延迟执行的协程。
  • 查询:根据组件高效查询实体。
  • 系统:通过处理查询的实体实现游戏逻辑和行为。
  • 扩展:通过自定义扩展扩展 ECS 的功能。
  • 链式构建:世界可以通过一系列方法创建。

示例

演示了如何使用 dark_iron_ecs 库在 Rust 中创建实体组件系统(ECS)。示例包括创建组件、查询实体以及设置系统与这些组件交互。

设置

首先,将 dark_iron_ecs 依赖项添加到您的 Cargo.toml

[dependencies]
dark_iron_ecs = "*"  # Replace with the actual version

导入

对于此示例,必要的导入

use dark_iron_ecs::core::{
    coroutine::{Coroutine, CoroutineState, WaitAmountOfSeconds},
    entity_manager::EntityManager,
    extension::Extension,
    query::{Query, Without},
    resources::Resource,
    system::SystemSchedule,
    world::World,
};

组件

定义您的组件。组件是与实体关联的数据。

struct Position {
    x: f32,
    y: f32,
}

struct Name(String);

struct Health(i32);

系统

定义系统以在具有特定组件的实体上操作。系统是处理实体的函数。

fn test_system(q: Query<(&Health,)>, entity_manager: &mut EntityManager) {
    entity_manager.create_entity((Health(500),));
    for health in q.fetch() {
        println!("{:?}", health.0);
    }
}

fn test_system_1(
    q: Query<(&Health,)>,
    q2: Query<(&Health,), Without<(&Name,)>>,
    mut camera: Resource<Camera>,
) {
    for health in q.fetch() {
        println!("q {:?}", health.0);
    }

    for health in q2.fetch() {
        println!("q2 {:?}", health.0);
    }

    println!("Hello from test_system_1");
    camera.x += 1.0;
    println!("{:?} {:?} {:?}", camera.x, camera.y, camera.z);
}

事件

定义可以在世界中发布和订阅的事件。

struct CollisionEvent;

资源

定义系统可全局访问的资源。

struct Camera {
    x: f32,
    y: f32,
    z: f32,
}

扩展

定义易于扩展的世界。

pub struct ExtensionExample;
impl Extension for ExtensionExample {
    fn build(&self, world: &mut World) {
        world.create_entity((Health(100),));
    }
}

主函数

设置世界,创建实体,添加系统,并运行 ECS。

use dark_iron_ecs::core::{
    coroutine::{Coroutine, CoroutineState, WaitAmountOfSeconds},
    entity_manager::EntityManager,
    query::{Query, Without},
    resources::Resource,
    system::SystemSchedule,
    world::World,
};

fn main() {
    let mut world = World::new();

    let entity1 = world.create_entity_with_id((Health(100),));

    let entity2 = world.create_entity_with_id((Name("Enemy 2".to_string()), Health(200)));

    let entity3 = world.create_entity_with_id((
        Position { x: 0.0, y: 0.0 },
        Name("Enemy 3".to_string()),
        Health(300),
    ));

    if let Some(health) = entity1.get_component::<Health>(&world){
        println!("Component {:?}", health.0);
    }

    let mut counter = 10;
    world
        .create_entity((Velocity(0.0, 0.0),))
        .subscribe_event(|_world: &World, _t: CollisionEvent| {
            println!("Collision Event Hit");
        })
        .remove_component::<Health>(entity3)
        .add_component_to_entity(entity3, Health(400))
        .add_coroutine(Coroutine::new("Test Coroutine", move |world| {
            if counter == 10 {
                println!("Coroutine Started");
            }

            counter -= 1;
            if counter == 0 {
                println!("Coroutine Finished");
                world.remove_entity(entity3);
                world.create_entity((Health(900),));
                world.add_component_to_entity(entity1, Name("Player".to_string()));
                world.remove_component::<Health>(entity2);
                world.publish_event(CollisionEvent);
                return CoroutineState::Finished;
            }

            println!("Coroutine Running");
            CoroutineState::Yielded(WaitAmountOfSeconds {
                amount_in_seconds: 1.0,
            })
        }))
        .add_resource(Camera {
            x: 1000.0,
            y: 0.0,
            z: 0.0,
        })
        .add_system(SystemSchedule::Startup, test_system)
        .add_systems(SystemSchedule::Update, (test_system_1,))
        .run_startup()
        .add_extension(ExtensionExample)
        .build();

    let q = world.create_query::<&Health>();
    let q1 = world.create_query_with_constraint::<&Health, Without<&Name>>();

    for health in q.fetch() {
        println!("{:?}", health.0);
    }

    for health in q1.fetch() {
        println!("{:?}", health.0);
    }


    loop {
        world.run_update();
        world.update_coroutines(1.0);
        std::thread::sleep(std::time::Duration::from_secs(1));
    }
}

运行项目

要运行项目,请使用 Cargo

cargo run

这将编译并运行您的 ECS 示例,演示如何使用 dark_iron_ecs 库创建和管理实体、组件、系统、事件和资源。

许可

本项目采用 MIT 许可协议。有关详细信息,请参阅 LICENSE 文件。

MIT 许可协议

本文件授予任何人获得本软件及其相关文档文件(以下简称“软件”)的副本的权利,免费使用软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许向软件提供者提供软件的人进行上述行为,但须遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“原样”提供,不提供任何形式的保证,无论是明示的、暗示的,包括但不限于对适销性、特定用途适用性和非侵权的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论是基于合同、侵权或其他原因,无论索赔、损害或其他责任是否由软件本身、软件的使用或其他与软件相关的行为引起。

无运行时依赖