use bevy::prelude::*;
use heron::{
rapier_plugin::{PhysicsWorld, ShapeCastCollisionType},
*,
};
fn main() {
App::new()
.insert_resource(WindowDescriptor {
height: 900.0,
width: 900.0,
..Default::default()
})
.add_plugins(DefaultPlugins)
.add_plugin(PhysicsPlugin::default()) .add_startup_system(setup)
.add_system(ray_cast_from_center)
.add_system(shape_cast_from_center)
.add_system(move_targeter)
.run();
}
#[derive(Component)]
struct Targeter;
#[derive(Component)]
struct ShapeCastIgnored;
fn setup(mut commands: Commands) {
commands.spawn_bundle(Camera2dBundle::default());
for (size, pos) in &[
(Vec2::new(800.0, 2.0), Vec3::new(0.0, -300.0, 0.0)),
(Vec2::new(800.0, 2.0), Vec3::new(0.0, 300.0, 0.0)),
(Vec2::new(2.0, 800.0), Vec3::new(-300.0, 0.0, 0.0)),
(Vec2::new(2.0, 800.0), Vec3::new(300.0, 0.0, 0.0)),
(Vec2::new(2.0, 100.0), Vec3::new(200.0, 0.0, 0.0)),
(Vec2::new(2.0, 100.0), Vec3::new(-200.0, 0.0, 0.0)),
(Vec2::new(100.0, 2.0), Vec3::new(0.0, 100.0, 0.0)),
(Vec2::new(100.0, 2.0), Vec3::new(0.0, -100.0, 0.0)),
] {
commands
.spawn_bundle(SpriteBundle {
sprite: Sprite {
color: Color::WHITE,
custom_size: Some(*size),
..Default::default()
},
transform: Transform::from_translation(*pos),
..Default::default()
})
.insert(RigidBody::Static)
.insert(CollisionShape::Cuboid {
half_extends: size.extend(0.0) / 2.0,
border_radius: None,
});
}
commands
.spawn_bundle(SpriteBundle {
sprite: Sprite {
color: Color::RED,
custom_size: Some(Vec2::new(10., 10.)),
..Default::default()
},
transform: Transform::from_xyz(0., 150., 1.),
..Default::default()
})
.insert(Targeter);
commands.spawn_bundle(SpriteBundle {
sprite: Sprite {
color: Color::BLUE,
custom_size: Some(Vec2::new(10., 10.)),
..Default::default()
},
transform: Transform::default(),
..Default::default()
});
commands
.spawn_bundle(SpriteBundle {
sprite: Sprite {
color: Color::ORANGE,
custom_size: Some(Vec2::new(100., 100.)),
..Default::default()
},
transform: Transform::from_xyz(200., 200., 0.),
..Default::default()
})
.insert(RigidBody::Static)
.insert(CollisionShape::Cuboid {
half_extends: Vec3::new(50., 50., 0.),
border_radius: None,
})
.insert(ShapeCastIgnored);
}
fn ray_cast_from_center(
mut commands: Commands,
physics_world: PhysicsWorld,
mut targeter: Query<&Transform, With<Targeter>>,
keyboard_input: Res<Input<KeyCode>>,
) {
if !keyboard_input.just_pressed(KeyCode::R) {
return;
}
let targeter_transform = if let Ok(transform) = targeter.get_single_mut() {
transform
} else {
return;
};
let world_center = Vec3::default();
let result = physics_world.ray_cast(
world_center,
targeter_transform.translation - world_center,
true,
);
if let Some(collision_info) = dbg!(result) {
commands.spawn_bundle(SpriteBundle {
sprite: Sprite {
color: Color::GREEN,
custom_size: Some(Vec2::new(10., 10.)),
..Default::default()
},
transform: Transform::from_translation(collision_info.collision_point),
..Default::default()
});
}
}
fn shape_cast_from_center(
mut commands: Commands,
physics_world: PhysicsWorld,
ignored_entities: Query<(), With<ShapeCastIgnored>>,
mut targeter: Query<&Transform, With<Targeter>>,
keyboard_input: Res<Input<KeyCode>>,
) {
if !keyboard_input.just_pressed(KeyCode::S) {
return;
}
let targeter_transform = if let Ok(transform) = targeter.get_single_mut() {
transform
} else {
return;
};
let world_center = Vec3::default();
let shape_size = Vec2::new(30., 30.);
let shape = CollisionShape::Cuboid {
half_extends: shape_size.extend(0.) / 2.,
border_radius: None,
};
let result = physics_world.shape_cast_with_filter(
&shape,
world_center,
Quat::IDENTITY,
targeter_transform.translation - world_center,
CollisionLayers::default(),
|entity| ignored_entities.get(entity).is_err(),
);
if let Some(collision) = dbg!(result) {
if let ShapeCastCollisionType::Collided(info) = collision.collision_type {
commands.spawn_bundle(SpriteBundle {
sprite: Sprite {
color: Color::YELLOW,
custom_size: Some(shape_size),
..Default::default()
},
transform: Transform::from_translation(info.self_end_position),
..Default::default()
});
}
}
}
fn move_targeter(
keyboard_input: Res<Input<KeyCode>>,
mut targeter: Query<&mut Transform, With<Targeter>>,
) {
const SPEED: f32 = 5.;
let mut transform = if let Ok(transform) = targeter.get_single_mut() {
transform
} else {
return;
};
let mut direction = Vec3::new(0., 0., 0.);
if keyboard_input.pressed(KeyCode::Left) {
direction += Vec3::new(-SPEED, 0., 0.);
}
if keyboard_input.pressed(KeyCode::Right) {
direction += Vec3::new(SPEED, 0., 0.);
}
if keyboard_input.pressed(KeyCode::Up) {
direction += Vec3::new(0., SPEED, 0.);
}
if keyboard_input.pressed(KeyCode::Down) {
direction += Vec3::new(0., -SPEED, 0.);
}
transform.translation += direction;
}