Adding rapier for collision detection
parent
1e15c5cfb2
commit
2d5ab5ea31
@ -0,0 +1,138 @@
|
||||
use bevy::{color::palettes::css::{BLUE, GREEN}, render::mesh::{SphereKind, SphereMeshBuilder}};
|
||||
use bevy_rapier3d::rapier::prelude::CollisionEventFlags;
|
||||
use games::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(BaseGamePlugin)
|
||||
.add_systems(Startup, (
|
||||
setup_physics_scene,
|
||||
position_camera.after(setup_camera)
|
||||
).chain())
|
||||
.add_systems(Update, (control_ball, read_events))
|
||||
.run();
|
||||
}
|
||||
|
||||
fn setup_physics_scene(
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>
|
||||
) {
|
||||
// Create the ground.
|
||||
// Make this a physical looking object
|
||||
commands
|
||||
.spawn((
|
||||
Collider::cuboid(100.0, 0.1, 100.0),
|
||||
Transform::from_xyz(0.0, -2.0, 0.0),
|
||||
Mesh3d(meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(50.0)))),
|
||||
MeshMaterial3d(materials.add(StandardMaterial {
|
||||
base_color: RED.into(),
|
||||
..Default::default()
|
||||
})),
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
SpotLight { color: WHITE.into(), intensity: 10_000_000.0, shadows_enabled: true, ..default() },
|
||||
Transform::from_xyz(0.0, 10.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
));
|
||||
|
||||
// Create the bouncing ball.
|
||||
commands
|
||||
.spawn((
|
||||
RigidBody::Dynamic,
|
||||
GravityScale(1.0),
|
||||
Collider::ball(0.5),
|
||||
ColliderMassProperties::Mass(2.0),
|
||||
Restitution::coefficient(0.7),
|
||||
ExternalImpulse::default(),
|
||||
Transform::from_xyz(0.0, 4.0, 0.0),
|
||||
Marker,
|
||||
ActiveEvents::all(),
|
||||
Mesh3d(meshes.add(SphereMeshBuilder::new(
|
||||
0.5,
|
||||
SphereKind::Uv {
|
||||
sectors: 10,
|
||||
stacks: 10,
|
||||
},
|
||||
))),
|
||||
MeshMaterial3d(materials.add(StandardMaterial {
|
||||
base_color: BLUE.into(),
|
||||
..Default::default()
|
||||
})),
|
||||
));
|
||||
|
||||
// Create a box that the ball can pass into/through
|
||||
// TODO: Transparent box to visualize area
|
||||
commands
|
||||
.spawn((
|
||||
Sensor,
|
||||
Marker,
|
||||
Collider::cuboid(1.0, 1.0, 1.0),
|
||||
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||
Mesh3d(meshes.add(Cuboid::new(2.0, 2.0, 2.0))),
|
||||
MeshMaterial3d(materials.add(StandardMaterial {
|
||||
base_color: GREEN.with_alpha(0.5).into(),
|
||||
alpha_mode: AlphaMode::Blend,
|
||||
..Default::default()
|
||||
})),
|
||||
));
|
||||
}
|
||||
|
||||
/// Position the world camera to get a better view
|
||||
fn position_camera(
|
||||
mut query: Query<(Entity, &mut Transform), (With<Camera>, With<Camera3d>)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
query.iter_mut().for_each(|(e, mut t)| {
|
||||
*t = Transform::from_xyz(10.0, 10.0, 10.0)
|
||||
.looking_at(Vec3::ZERO, Vec3::Y);
|
||||
})
|
||||
}
|
||||
|
||||
fn control_ball(
|
||||
keys: Res<ButtonInput<KeyCode>>,
|
||||
mut ball: Single<&mut ExternalImpulse>,
|
||||
) {
|
||||
if keys.pressed(KeyCode::ArrowUp) {
|
||||
ball.torque_impulse = Vec3::new(0.0, 0.0, 0.1);
|
||||
}
|
||||
|
||||
if keys.pressed(KeyCode::ArrowDown) {
|
||||
ball.torque_impulse = Vec3::new(0.0, 0.0, -0.1);
|
||||
}
|
||||
|
||||
if keys.pressed(KeyCode::ArrowLeft) {
|
||||
ball.torque_impulse = Vec3::new(0.1, 0.0, 0.0);
|
||||
}
|
||||
|
||||
if keys.pressed(KeyCode::ArrowRight) {
|
||||
ball.torque_impulse = Vec3::new(-0.1, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum WithinBounds {
|
||||
Enter(Entity, Entity),
|
||||
Exit(Entity, Entity),
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
struct Marker;
|
||||
|
||||
fn read_events(
|
||||
mut events: EventReader<CollisionEvent>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
events.read().filter_map(|collision_event| {
|
||||
match collision_event {
|
||||
CollisionEvent::Started(a, b, flags) => {
|
||||
(*flags == CollisionEventFlags::SENSOR).then_some(WithinBounds::Enter(*a, *b))
|
||||
},
|
||||
CollisionEvent::Stopped(a, b, flags) => {
|
||||
(*flags == CollisionEventFlags::SENSOR).then_some(WithinBounds::Exit(*a, *b))
|
||||
}
|
||||
}
|
||||
}).for_each(|within_bounds| {
|
||||
info!("Event: {:?}", within_bounds);
|
||||
})
|
||||
}
|
||||
Loading…
Reference in New Issue