先日、crates.ioでbevy_rapier2dなるクレートを見つけました。
面白そうだったので少し触ってみました。
Rustで簡単な物理エンジン用いたゲームを作りたい人には参考になるかもしれません。
出来たもの
コード
Cargo.toml
[dependencies]
bevy = "0.15.0"
bevy_rapier2d = "0.28.0"
main.rs
#![windows_subsystem = "windows"]
use bevy::prelude::*;
use bevy_rapier2d::prelude::*;
#[derive(Component)]
pub struct PhisicNode;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(100.0))
.add_plugins(RapierDebugRenderPlugin::default())
.add_systems(Startup, setup)
.add_systems(Update, (
spawn_physics,
delete_physics
))
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2d::default());
commands
.spawn(Collider::cuboid(500.0, 10.0))
.insert(Transform::from(Transform::from_xyz(0.0, -340.0, 0.0)));
commands
.spawn(Collider::cuboid(10.0, 100.0))
.insert(Transform::from(Transform::from_xyz(-510.0, -250.0, 0.0)));
commands
.spawn(Collider::cuboid(10.0, 100.0))
.insert(Transform::from(Transform::from_xyz(510.0, -250.0, 0.0)));
}
fn spawn_physics(
mut commands: Commands,
q_windows: Query<&Window, With<bevy::window::PrimaryWindow>>,
mouse_input: Res<ButtonInput<MouseButton>>,
) {
if q_windows.single().cursor_position().is_none(){return;}
if !mouse_input.just_released(MouseButton::Left) && !mouse_input.pressed(MouseButton::Right){return;}
let pos = q_windows.single().cursor_position().unwrap();
let width = q_windows.single().width();
let height = q_windows.single().height();
let px = pos.x - (width * 0.5);
let py = -pos.y + (height * 0.5);
if mouse_input.just_released(MouseButton::Left){
commands
.spawn(RigidBody::Dynamic)
.insert(Collider::cuboid(50.0, 50.0))
.insert(Restitution::coefficient(0.8))
.insert(Transform::from(Transform::from_xyz(px, py, 0.0)))
.insert(PhisicNode);
}
if mouse_input.pressed(MouseButton::Right){
commands
.spawn(RigidBody::Dynamic)
.insert(Collider::ball(20.0))
.insert(Restitution::coefficient(0.25))
.insert(Transform::from(Transform::from_xyz(px, py, 0.0)))
.insert(PhisicNode);
}
}
fn delete_physics(
mut commands: Commands,
physics: Query<(Entity, &PhisicNode)>,
keyboard_input: Res<ButtonInput<KeyCode>>,
){
if !keyboard_input.just_pressed(KeyCode::Delete){return;}
for (e, _p) in physics.iter(){
commands.entity(e).despawn();
}
}
感想
軽く触った感じですと、bevyのecsのやり方に従って物理エンジンの処理が簡単に書けるのが印象的でした。
Githubの実施例もわかりやすいものが多く、処理がスムーズに書けました。
参考にさせていただいたサイト
https://www.rapier.rs/
https://docs.rs/bevy_rapier2d/latest/bevy_rapier2d/
https://github.com/dimforge/bevy_rapier/tree/master/bevy_rapier2d/examples