SuperAPI AI 工具集

bevy-game-loop-harvest

编程与开发

查看项目

更新于 10-16 06:08

技能介绍

用途

本技能用于在 Bevy 引擎中实现作物生长与收获循环。当作物按计时器推进生长阶段,并且需要一条收获消息来记录产出时,可加载本技能。

主要能力

  • 生长推进:作物组件存储阶段索引与已用时间,生长在 Time<Fixed> 固定时钟上按间隔推进一个阶段。
  • 收获消息:Harvested 是一次性的产出事实,仅在最后一个阶段就绪时触发,由库存系统消费。
  • 离线追赶:读取 Time::elapsed_secs 与记录上次访问时间的资源对比,应用自上次访问以来的秒数,然后存储新的时间标记。
  • 季节缩放:Season 资源提供生长缩放系数,用于缩放整局中每株作物的生长速度。

使用方式

ECS 结构:

  • 组件:生长已用时间与你定义的阶段索引。
  • 资源:上次访问时间与季节缩放存放在资源中。
  • 系统:在 FixedUpdate 上推进生长,使用 .chain() 使收获读取生长刚写入的阶段。
  • 消息:Harvested 是一次性产出事实,库存系统应用它。

示例代码(生长与收获):

#[derive(Component)]
struct Crop {
    stage: u8,
    elapsed: f32,
    stage_seconds: f32,
    stages: u8,
}

#[derive(Message)]
struct Harvested {
    plot: Entity,
    yield_item: u32,
}

fn grow(time: Res<Time<Fixed>>, mut crops: Query<&mut Crop>) {
    let dt = time.delta_secs();
    for mut crop in &mut crops {
        if crop.stage + 1 >= crop.stages {
            continue;
        }
        crop.elapsed += dt;
        if crop.elapsed >= crop.stage_seconds {
            crop.elapsed = 0.0;
            crop.stage += 1;
        }
    }
}

fn harvest(
    mut commands: Commands,
    crops: Query<(Entity, &Crop)>,
    mut harvested: MessageWriter<Harvested>,
) {
    for (entity, crop) in &crops {
        if crop.stage + 1 < crop.stages {
            continue;
        }
        harvested.write(Harvested {
            plot: entity,
            yield_item: 7,
        });
        commands.entity(entity).despawn();
    }
}

pub struct HarvestPlugin;

impl Plugin for HarvestPlugin {
    fn build(&self, app: &mut App) {
        app.add_message::<Harvested>()
            .add_systems(FixedUpdate, (grow, harvest).chain());
    }
}

离线追赶示例:

#[derive(Resource)]
struct LastVisit {
    elapsed_secs: f32,
}

fn catch_up(time: Res<Time>, mut last: ResMut<LastVisit>, mut crops: Query<&mut Crop>) {
    let now = time.elapsed_secs();
    let gap = (now - last.elapsed_secs).max(0.0);
    last.elapsed_secs = now;
    if gap <= 0.0 {
        return;
    }
    for mut crop in &mut crops {
        let mut left = gap;
        while left > 0.0 && crop.stage + 1 < crop.stages {
            let need = (crop.stage_seconds - crop.elapsed).max(0.0);
            if left < need {
                crop.elapsed += left;
                left = 0.0;
            } else {
                left -= need;
                crop.elapsed = 0.0;
                crop.stage += 1;
            }
        }
    }
}

季节缩放示例:

#[derive(Resource)]
struct Season {
    growth_scale: f32,
}

fn season_grow(time: Res<Time<Fixed>>, season: Res<Season>, mut crops: Query<&mut Crop>) {
    let dt = time.delta_secs() * season.growth_scale.max(0.0);
    for mut crop in &mut crops {
        if crop.stage + 1 >= crop.stages {
            continue;
        }
        crop.elapsed += dt;
        if crop.elapsed >= crop.stage_seconds {
            crop.elapsed -= crop.stage_seconds;
            crop.stage += 1;
        }
    }
}

适用场景

  • 作物按计时器推进生长阶段,成熟后触发收获消息。
  • 需要离线追赶:玩家离开后再次进入时,按经过的时间补算生长。
  • 需要全局季节系数缩放所有作物生长速度。

限制与约束

  • 目标版本为 Bevy 0.20+。
  • 核心 ECS 类型包括:Component、Resource、Query、Commands、Startup、Update、Fixed / FixedMain(bevy::time)、.chain()、Plugin、DefaultPlugins、MinimalPlugins。消息与观察者属于所有权槽位,其 API 参见 bevy-events-messaging。
  • 除非用 .chain() 排序冲突系统,否则系统并行运行。
  • 两个都可变查询同一组件的系统必须排序(.chain())或拆分,使只有一个写入。
  • 不要在文档 URL 中固定 /0.20.0/。
  • 不要在本技能中发明物理、导航、网络或 XR crate。
  • 本机制不使用场景树节点或信号总线。
  • 不要使用虚构 API 或未命名的第三方 crate 作为求解器。

相关技能

前置:bevy-master、bevy-ecs-composition、bevy-inventory-system、bevy-data-resources、bevy-events-messaging。

补充:bevy-state-machines。