gpt4 book ai didi

rust - 用Bevy 0.4拖动 Sprite 可以接受的方法是什么?

转载 作者:行者123 更新时间:2023-12-03 11:29:35 52 4
gpt4 key购买 nike

在尝试Bevy时,我需要拖放 Sprite 。
不幸的是,这似乎尚未准备就绪,或者我没有在文档中找到它。
实现这个目标的最惯用的方式是什么?
到目前为止,我尝试过的是in my answer,但是我很乐意接受另一个更好/更快/更惯用的解决方案。

最佳答案

不幸的是,我没有足够的经验来了解什么是惯用的,但是,这是我如何在应用程序中实现 Sprite 拖动的概述,这对我来说是一种好方法:

  • 我有一个“光标位置”实体,它带有一个转换组件(以及用于标识的Cursor组件),我在系统中每帧将其更新到光标的位置。
  • 每个可拖动对象都有一个HoverableDraggable组件。我在一个系统中遍历那些对象,每个对象都在其中向实体添加/删除HoveredDragged组件,以指示它们是悬停还是拖动。
  • 我有一个检查对象是否被丢弃的系统,如果有,它会给它一个Dropped组件。
  • 我有一个系统,当实体获取“Dragged”组件(使用Added<C>过滤器)时运行,该系统将父对象设置为“光标位置”实体。
  • 和另一个系统,用于当实体获取“已删除”组件时清除父组件。

  • 对我来说,拥有许多责任范围较小的系统感觉很好。由于我缺乏经验,我很想听到反对意见。
    当然,在本概述中我遗漏了很多东西,所以这是我的代码供引用。由于这是根据我的实际代码改编而成的,因此对于一个最小的示例,有些奇怪和不必要的代码:
    #![allow(clippy::type_complexity)]

    use bevy::{prelude::*, render::camera::Camera};

    fn main() {
    App::build()
    .init_resource::<State>()
    .add_resource(WindowDescriptor {
    title: "Bevy".to_string(),
    width: 1024.0,
    height: 768.0,
    vsync: true,
    ..Default::default()
    })
    .add_plugins(DefaultPlugins)
    .add_plugin(MyPlugin)
    .run();
    }

    pub struct MyPlugin;

    impl Plugin for MyPlugin {
    fn build(&self, app: &mut AppBuilder) {
    app.add_startup_system(setup.system())
    .add_system_to_stage(stage::PRE_UPDATE, cursor_state.system())
    .add_system_to_stage(stage::UPDATE, cursor_transform.system())
    .add_system_to_stage(stage::UPDATE, draggable.system())
    .add_system_to_stage(stage::UPDATE, hoverable.system())
    .add_system_to_stage(stage::POST_UPDATE, drag.system())
    .add_system_to_stage(stage::POST_UPDATE, drop.system())
    .add_system_to_stage(stage::POST_UPDATE, material.system());
    }
    }

    const SPRITE_SIZE: f32 = 55.0;

    fn setup(
    commands: &mut Commands,
    asset_server: Res<AssetServer>,
    mut materials: ResMut<Assets<ColorMaterial>>,
    ) {
    let bevy_texture = asset_server.load("sprites/bevy-icon.png");

    commands
    .spawn(Camera2dBundle::default())
    .spawn(())
    .with(CursorState::default())
    .spawn((Transform::default(), GlobalTransform::default(), Cursor));

    for _ in 0..4 {
    commands
    .spawn(SpriteBundle {
    material: materials.add(bevy_texture.clone().into()),
    sprite: Sprite::new(Vec2::new(SPRITE_SIZE, SPRITE_SIZE)),
    ..Default::default()
    })
    .with(Hoverable)
    .with(Draggable);
    }
    }

    #[derive(Default)]
    struct CursorState {
    cursor_world: Vec2,
    cursor_moved: bool,
    }

    struct Cursor;

    struct Draggable;
    struct Dragged;
    struct Dropped;

    struct Hoverable;
    struct Hovered;

    fn cursor_state(
    mut state: ResMut<State>,
    e_cursor_moved: Res<Events<CursorMoved>>,
    windows: Res<Windows>,
    mut q_cursor_state: Query<&mut CursorState>,
    q_camera: Query<&Transform, With<Camera>>,
    ) {
    let event_cursor_screen = state.er_cursor_moved.latest(&e_cursor_moved);

    for mut cursor_state in q_cursor_state.iter_mut() {
    if let Some(event_cursor_screen) = event_cursor_screen {
    let window = windows.get_primary().unwrap();
    let cam_transform = q_camera.iter().last().unwrap();
    cursor_state.cursor_world =
    cursor_to_world(window, cam_transform, event_cursor_screen.position);

    cursor_state.cursor_moved = true;
    } else {
    cursor_state.cursor_moved = false;
    }
    }
    }

    fn cursor_transform(
    commands: &mut Commands,
    q_cursor_state: Query<&CursorState>,
    mut q_cursor: Query<(Entity, &mut Transform), With<Cursor>>,
    ) {
    let cursor_state = q_cursor_state.iter().next().unwrap();

    for (cursor_e, mut transform) in q_cursor.iter_mut() {
    transform.translation.x = cursor_state.cursor_world.x;
    transform.translation.y = cursor_state.cursor_world.y;
    commands.remove_one::<Parent>(cursor_e);
    }
    }

    fn hoverable(
    commands: &mut Commands,
    q_cursor_state: Query<&CursorState>,
    q_hoverable: Query<(Entity, &Transform, &Sprite), (With<Hoverable>, Without<Dragged>)>,
    ) {
    let cursor_state = q_cursor_state.iter().next().unwrap();

    if cursor_state.cursor_moved {
    for (entity, transform, sprite) in q_hoverable.iter() {
    let half_width = sprite.size.x / 2.0;
    let half_height = sprite.size.y / 2.0;

    if transform.translation.x - half_width < cursor_state.cursor_world.x
    && transform.translation.x + half_width > cursor_state.cursor_world.x
    && transform.translation.y - half_height < cursor_state.cursor_world.y
    && transform.translation.y + half_height > cursor_state.cursor_world.y
    {
    commands.insert_one(entity, Hovered);
    } else {
    commands.remove_one::<Hovered>(entity);
    }
    }
    }
    }

    fn material(
    mut materials: ResMut<Assets<ColorMaterial>>,
    q_hoverable: Query<
    (&Handle<ColorMaterial>, Option<&Hovered>, Option<&Dragged>),
    With<Hoverable>,
    >,
    ) {
    let mut first = true;

    for (material, hovered, dragged) in q_hoverable.iter() {
    let (red, green, alpha) = if dragged.is_some() {
    (0.0, 1.0, 1.0)
    } else if first && hovered.is_some() {
    first = false;
    (1.0, 0.0, 1.0)
    } else if hovered.is_some() {
    (1.0, 1.0, 0.5)
    } else {
    (1.0, 1.0, 1.0)
    };

    materials.get_mut(material).unwrap().color.set_r(red);
    materials.get_mut(material).unwrap().color.set_g(green);
    materials.get_mut(material).unwrap().color.set_a(alpha);
    }
    }

    fn cursor_to_world(window: &Window, cam_transform: &Transform, cursor_pos: Vec2) -> Vec2 {
    // get the size of the window
    let size = Vec2::new(window.width() as f32, window.height() as f32);

    // the default orthographic projection is in pixels from the center;
    // just undo the translation
    let screen_pos = cursor_pos - size / 2.0;

    // apply the camera transform
    let out = cam_transform.compute_matrix() * screen_pos.extend(0.0).extend(1.0);
    Vec2::new(out.x, out.y)
    }

    fn draggable(
    commands: &mut Commands,
    i_mouse_button: Res<Input<MouseButton>>,
    q_pressed: Query<Entity, (With<Hovered>, With<Draggable>)>,
    q_released: Query<Entity, With<Dragged>>,
    ) {
    if i_mouse_button.just_pressed(MouseButton::Left) {
    if let Some(entity) = q_pressed.iter().next() {
    commands.insert_one(entity, Dragged);
    }
    } else if i_mouse_button.just_released(MouseButton::Left) {
    for entity in q_released.iter() {
    commands.remove_one::<Dragged>(entity);

    commands.insert_one(entity, Dropped);
    }
    }
    }

    fn drag(
    commands: &mut Commands,
    mut q_dragged: Query<(Entity, &mut Transform, &GlobalTransform), Added<Dragged>>,
    q_cursor: Query<(Entity, &GlobalTransform), With<Cursor>>,
    ) {
    if let Some((cursor_e, cursor_transform)) = q_cursor.iter().next() {
    for (entity, mut transform, global_transform) in q_dragged.iter_mut() {
    let global_pos = global_transform.translation - cursor_transform.translation;

    commands.insert_one(entity, Parent(cursor_e));

    transform.translation.x = global_pos.x;
    transform.translation.y = global_pos.y;
    }
    }
    }

    fn drop(
    commands: &mut Commands,
    mut q_dropped: Query<(Entity, &mut Transform, &GlobalTransform), Added<Dropped>>,
    ) {
    for (entity, mut transform, global_transform) in q_dropped.iter_mut() {
    let global_pos = global_transform.translation;

    transform.translation.x = global_pos.x;
    transform.translation.y = global_pos.y;

    commands.remove_one::<Parent>(entity);
    commands.remove_one::<Dropped>(entity);
    }
    }

    #[derive(Default)]
    struct State {
    er_cursor_moved: EventReader<CursorMoved>,
    }
    此代码适用于bevy 0.4。

    关于rust - 用Bevy 0.4拖动 Sprite 可以接受的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65396065/

    52 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com