Latest commit ffecb05

use bevy::{prelude::*, tasks::prelude::*};
use rand::random;

#[derive(Component)]
struct Velocity(Vec2);

fn spawn_system(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
    commands.spawn_bundle(OrthographicCameraBundle::new_2d());
    let image_handle = asset_server.load("branding/icon.png");
    for _ in 0..128 {
        commands
            .spawn_bundle(SpriteBundle {
                texture: image_handle.clone(),
                transform: Transform::from_scale(Vec3::splat(0.1)),
                ..Default::default()
            })
            .insert(Velocity(
                20.0 * Vec2::new(random::<f32>() - 0.5, random::<f32>() - 0.5),
            ));
    }
}

// 根据sprite的速度来移动它们
fn move_system(
    pool: Res<ComputeTaskPool>,
    mut sprites: Query<(&mut Transform, &Velocity)>,
) {
    // 使用批处理的32个Sprite在ComputeTaskPool上并行计算每个Sprite的新位置
    // 这个例子仅用于演示,究竟是使用ParallelIterator还是Iterator,查看ParallelIterator文档
    sprites.par_for_each_mut(&pool, 32, |(mut transform, velocity)| {
        transform.translation += velocity.0.extend(0.0);
    });
}

// 窗口外弹出sprite
fn bounce_system(
    pool: Res<ComputeTaskPool>,
    windows: Res<Windows>,
    mut sprites: Query<(&Transform, &mut Velocity)>,
) {
    let window = windows.get_primary().expect("No primary window.");
    let width = window.width();
    let height = window.height();
    let left = width / -2.0;
    let right = width - 2.0;
    let bottom = height / -2.0;
    let top = height / 2.0;
    sprites
        // 选择批处理大小为32,以限制ParallelIterator的开销,因为取反向量非常便宜
        .par_for_each_mut(&pool, 32, |(transform, mut v)| {
            if !(left < transform.translation.x
                && transform.translation.x < right
                && bottom < transform.translation.y
                && transform.translation.y < top)
            {
                // 为简单起见,只需将速度反过来即可,不要用现实中的弹跳方式
                v.0 = -v.0;
            }
        });
}

/// 用ParallelIterator来说明如何并行查询
fn main() {
    App::new()
        .add_plugin(DefaultPlugins)
        .add_startup_system(spawn_system)
        .add_system(move_system)
        .add_system(bounce_system)
        .run();
}