/bevy_rts_cursor

A game world cursor for real-time strategy games.

Primary LanguageRustMIT LicenseMIT

3D Entity Selection Cursor

A Bevy plugin for selecting game entities in world space. Built with aevyrie's amazing bevy_mod_raycast plugin.

bevy_cursor_demo

Features

  • Select entities in world space
  • Raycast based cursor for 3D environments
  • Drag-and-drop selection
  • Selected entities are accessible via Res<Cursor> resource

Quickstart

Provide game-space bounds with Bounds2D and add the CursorPlugin to your game.

pub const GAME_BOUNDS: Bounds2D = Bounds2D {
    min_x: 0.,
    min_z: 0.,
    max_x: 10.,
    max_z: 10.,
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugin(CursorPlugin {
            bounds: GAME_BOUNDS,
            ..Default::default()
        })
        .add_startup_system(setup)
        .run();
}

Add the RaycastSource::<RayReflector> to your Camera3dBundle.

fn setup_cameras(mut commands: Commands) {
    commands
        .spawn((Camera3dBundle {
            transform: Transform::from_xyz(10., 15., 10.)
            .looking_at(Vec3::ZERO, Vec3::Y),
            ..default()
        },))
        .insert(RaycastSource::<RayReflector>::new()); // Designate the camera as our source;
}

Mark surfaces you want to interact with the cursor with a CursorReflector component.

    commands
        .spawn(PbrBundle {
            mesh: meshes.add(Mesh::from(shape::Plane {
                size: 20.,
            })),
            ..Default::default()
        })
        .insert(CursorReflector);

Add Pickable to the entities you want to select.

    commands
        .spawn(PbrBundle {
            mesh: meshes.add(Mesh::from(shape::Box::new(0.5, 0.5, 0.5))),
            ..Default::default()
        })
        .insert(Pickable);

Access selected entities with the Res<Cursor> resource.

pub fn select_destination(
    mut commands: Commands,
    cursor: Res<Cursor>,
    buttons: Res<Input<MouseButton>>,
) {
    if buttons.just_pressed(MouseButton::Left) {
        for unit in &cursor.selection.selected_units {
            commands.entity(*unit).insert(Destination(cursor.location));
        }
    }
}

Demo

To run a minimal demo, clone this repository and run:

cargo run --example move_units

License

This project is licensed under the MIT license.