Adding rapier for collision detection

main
Elijah Voigt 4 months ago
parent 1e15c5cfb2
commit 2d5ab5ea31

285
Cargo.lock generated

@ -105,6 +105,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "alsa"
version = "0.9.1"
@ -967,6 +973,19 @@ version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df7370d0e46b60e071917711d0860721f5347bc958bf325975ae6913a5dfcf01"
[[package]]
name = "bevy_rapier3d"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf74109573c2c82b05b217cb6101f7e71e6c53ad622aed6c370cc5783c59eb8"
dependencies = [
"bevy",
"bitflags 2.9.1",
"log",
"nalgebra",
"rapier3d",
]
[[package]]
name = "bevy_reflect"
version = "0.16.1"
@ -1782,6 +1801,19 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "crossbeam"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.15"
@ -1791,6 +1823,25 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.12"
@ -1915,6 +1966,15 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "ena"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5"
dependencies = [
"log",
]
[[package]]
name = "encase"
version = "0.10.0"
@ -2144,6 +2204,7 @@ name = "games"
version = "0.1.0"
dependencies = [
"bevy",
"bevy_rapier3d",
]
[[package]]
@ -2393,6 +2454,7 @@ version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash",
"serde",
@ -2719,6 +2781,16 @@ dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "matrixmultiply"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
dependencies = [
"autocfg",
"rawpointer",
]
[[package]]
name = "memchr"
version = "2.7.5"
@ -2808,6 +2880,34 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "nalgebra"
version = "0.33.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b"
dependencies = [
"approx",
"glam",
"matrixmultiply",
"nalgebra-macros",
"num-complex",
"num-rational",
"num-traits",
"simba",
"typenum",
]
[[package]]
name = "nalgebra-macros"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ndk"
version = "0.8.0"
@ -2920,6 +3020,25 @@ dependencies = [
"winapi",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
"num-traits",
]
[[package]]
name = "num-derive"
version = "0.4.2"
@ -2931,6 +3050,26 @@ dependencies = [
"syn",
]
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@ -3250,6 +3389,15 @@ dependencies = [
"num-traits",
]
[[package]]
name = "ordered-float"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01"
dependencies = [
"num-traits",
]
[[package]]
name = "overload"
version = "0.1.1"
@ -3294,6 +3442,31 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "parry3d"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec55ce6f725367f8149f750575e79a8879d71b7257c02273259f9375822821f"
dependencies = [
"approx",
"arrayvec",
"bitflags 2.9.1",
"downcast-rs 2.0.1",
"either",
"ena",
"hashbrown",
"log",
"nalgebra",
"num-derive",
"num-traits",
"ordered-float 5.0.0",
"rstar",
"simba",
"slab",
"spade",
"thiserror 2.0.12",
]
[[package]]
name = "paste"
version = "1.0.15"
@ -3461,6 +3634,19 @@ name = "profiling"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773"
dependencies = [
"profiling-procmacros",
]
[[package]]
name = "profiling-procmacros"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "quick-xml"
@ -3544,12 +3730,42 @@ version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684"
[[package]]
name = "rapier3d"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a35ec3d01c4f918675411442024a1fbfb7eafdd878a6e82479ff6e461a9092fc"
dependencies = [
"approx",
"arrayvec",
"bit-vec 0.8.0",
"bitflags 2.9.1",
"crossbeam",
"downcast-rs 2.0.1",
"log",
"nalgebra",
"num-derive",
"num-traits",
"ordered-float 5.0.0",
"parry3d",
"profiling",
"rustc-hash 2.1.1",
"simba",
"thiserror 2.0.12",
]
[[package]]
name = "raw-window-handle"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]]
name = "read-fonts"
version = "0.29.3"
@ -3634,6 +3850,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
[[package]]
name = "robust"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839"
[[package]]
name = "rodio"
version = "0.20.1"
@ -3662,6 +3884,17 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
[[package]]
name = "rstar"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb"
dependencies = [
"heapless",
"num-traits",
"smallvec",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
@ -3738,6 +3971,15 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "safe_arch"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
dependencies = [
"bytemuck",
]
[[package]]
name = "same-file"
version = "1.0.6"
@ -3831,6 +4073,19 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simba"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa"
dependencies = [
"approx",
"num-complex",
"num-traits",
"paste",
"wide",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
@ -3902,6 +4157,18 @@ dependencies = [
"serde",
]
[[package]]
name = "spade"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a14e31a007e9f85c32784b04f89e6e194bb252a4d41b4a8ccd9e77245d901c8c"
dependencies = [
"hashbrown",
"num-traits",
"robust",
"smallvec",
]
[[package]]
name = "spin"
version = "0.9.8"
@ -4260,6 +4527,12 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
[[package]]
name = "typenum"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "unicode-bidi"
version = "0.3.18"
@ -4666,7 +4939,7 @@ dependencies = [
"ndk-sys 0.5.0+25.2.9519653",
"objc",
"once_cell",
"ordered-float",
"ordered-float 4.6.0",
"parking_lot",
"profiling",
"range-alloc",
@ -4695,6 +4968,16 @@ dependencies = [
"web-sys",
]
[[package]]
name = "wide"
version = "0.7.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03"
dependencies = [
"bytemuck",
"safe_arch",
]
[[package]]
name = "winapi"
version = "0.3.9"

@ -3,6 +3,9 @@ name = "games"
version = "0.1.0"
edition = "2024"
[dependencies.bevy_rapier3d]
version = "0.30.0"
[dependencies.bevy]
version = "0.16.1"
features = ["wayland", "dynamic_linking"]

@ -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);
})
}

@ -1,12 +1,9 @@
use bevy::input::mouse::MouseMotion;
use games::*;
fn main() {
App::new()
.init_resource::<Thing>()
.add_plugins(BaseGamePlugin {
camera: CameraType::Camera3d,
})
.add_plugins(BaseGamePlugin)
.add_systems(Startup, init_ui)
.add_systems(
Update,

@ -1,31 +1,17 @@
use super::*;
/// A good starting place for creating a game building on top of the base Bevy app
pub struct BaseGamePlugin {
pub camera: CameraType,
}
pub struct BaseGamePlugin;
impl Plugin for BaseGamePlugin {
fn build(&self, app: &mut App) {
app.add_plugins(DefaultPlugins).add_plugins(DebuggingPlugin);
// Add a camera setup system and startup
app.add_systems(
Startup,
match self.camera {
CameraType::Camera2d => setup_camera_2d,
CameraType::Camera3d => setup_camera_3d,
},
);
app.add_plugins(DefaultPlugins)
.add_plugins(DebuggingPlugin)
.add_plugins(RapierPhysicsPlugin::<NoUserData>::default())
.add_systems(Startup, setup_camera);
}
}
/// For selecting the type of camera this game requires
pub enum CameraType {
Camera2d,
Camera3d,
}
/// System to toggle the visibility of entities based on their state
pub fn toggle_state_visibility<S: States + Component>(
mut q: Query<(Entity, &mut Visibility, &S)>,
@ -41,10 +27,6 @@ pub fn toggle_state_visibility<S: States + Component>(
});
}
fn setup_camera_2d(mut commands: Commands) {
commands.spawn((Camera { ..default() }, Camera2d));
}
fn setup_camera_3d(mut commands: Commands) {
commands.spawn((Camera { ..default() }, Camera3d { ..default() }));
pub fn setup_camera(mut commands: Commands) {
commands.spawn((Camera3d { ..default() }, Camera { ..default() }));
}

@ -6,11 +6,15 @@ pub struct DebuggingPlugin;
impl Plugin for DebuggingPlugin {
fn build(&self, app: &mut App) {
app.init_state::<DebuggingState>()
.add_plugins(RapierDebugRenderPlugin::default().disabled())
.add_systems(Startup, init_debug_ui)
.add_systems(
Update,
(
toggle_state_visibility::<DebuggingState>
(
toggle_state_visibility::<DebuggingState>,
toggle_rapier_debug_render,
)
.run_if(state_changed::<DebuggingState>),
toggle_debug_state.run_if(on_keyboard_press(KeyCode::F12)),
),
@ -57,3 +61,11 @@ fn init_debug_ui(mut commands: Commands) {
},
));
}
/// Simple system that enables/disables rapier debug visuals when the debugging state changes
fn toggle_rapier_debug_render(
state: Res<State<DebuggingState>>,
mut context: ResMut<DebugRenderContext>,
) {
context.enabled = *state.get() == DebuggingState::On;
}

@ -1,3 +1,5 @@
#![allow(ambiguous_glob_reexports)]
mod base_game;
mod debug;
mod scheduling;
@ -7,9 +9,10 @@ pub use std::fmt::Display;
pub use bevy::{
color::palettes::css::{BLACK, RED, WHITE},
input::{ButtonState, keyboard::KeyboardInput},
input::{ButtonState, keyboard::KeyboardInput, mouse::MouseMotion},
prelude::*,
};
pub use bevy_rapier3d::prelude::*;
pub use base_game::*;
pub use debug::*;

Loading…
Cancel
Save