Skip to content
Snippets Groups Projects
Verified Commit 438336cc authored by Louis's avatar Louis :fire:
Browse files

Implement basic physics for kinematic bodies

parent 5dfcad5c
No related branches found
No related tags found
No related merge requests found
mod _plugin {
use crate::system::AppState;
use bevy::prelude::*;
use bevy_rapier2d::prelude::*;
pub struct DebugPlugin;
impl Plugin for DebugPlugin {
fn build(&self, app: &mut App) {
app.add_systems(OnEnter(AppState::InGame), |mut commands: Commands| {
commands.spawn((
TransformBundle::from_transform(Transform::from_xyz(0.0, -400.0, 0.0)),
RigidBody::Fixed,
Collider::cuboid(200.0, 50.0),
));
});
}
}
}
pub use _plugin::DebugPlugin;
mod physics;
mod player;
mod _plugin {
......@@ -7,9 +8,12 @@ mod _plugin {
pub struct EntityPluginSet;
impl PluginGroup for EntityPluginSet {
fn build(self) -> PluginGroupBuilder {
PluginGroupBuilder::start::<Self>().add(super::player::PlayerSetupPlugin)
PluginGroupBuilder::start::<Self>()
.add(super::player::PlayerSetupPlugin)
.add(super::physics::PhysicsPlugin)
}
}
}
pub use _plugin::EntityPluginSet;
pub use physics::{Acceleration, PhysicsLimits, PhysicsSet, Velocity, GRAVITY_ACC, GRAVITY_VEC};
use crate::system::run_in_game;
use bevy::prelude::*;
use bevy_rapier2d::prelude::KinematicCharacterController;
pub const GRAVITY_ACC: f32 = -384.0;
pub const GRAVITY_VEC: Vec2 = Vec2::new(0.0, GRAVITY_ACC);
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, SystemSet)]
pub struct PhysicsSet;
#[derive(Component, Clone, Copy, Debug, Default, Deref, DerefMut)]
pub struct Velocity(Vec2);
#[derive(Component, Clone, Copy, Debug, Default, Deref, DerefMut)]
pub struct Acceleration(Vec2);
#[derive(Component, Clone, Copy, Debug, Default)]
pub struct PhysicsLimits {
pub velocity: (Option<Vec2>, Option<Vec2>),
pub acceleration: (Option<Vec2>, Option<Vec2>),
}
impl PhysicsLimits {
pub fn limit_velocity(&self, velocity: Vec2) -> Vec2 {
match self.velocity {
(None, None) => velocity,
(Some(min), None) => velocity.max(min),
(None, Some(max)) => velocity.min(max),
(Some(min), Some(max)) => velocity.min(max).max(min),
}
}
pub fn limit_acceleration(&self, acceleration: Vec2) -> Vec2 {
match self.acceleration {
(None, None) => acceleration,
(Some(min), None) => acceleration.max(min),
(None, Some(max)) => acceleration.min(max),
(Some(min), Some(max)) => acceleration.min(max).max(min),
}
}
}
impl Acceleration {
pub fn gravity() -> Self {
Acceleration(GRAVITY_VEC)
}
}
fn apply_acceleration(
time: Res<Time>,
mut query: Query<(&mut Velocity, &Acceleration, Option<&PhysicsLimits>)>,
) {
let dt = time.delta_seconds();
for (mut velocity, acceleration, limits) in &mut query {
**velocity += **acceleration * dt;
**velocity = limits
.copied()
.unwrap_or_default()
.limit_velocity(**velocity);
}
}
fn apply_velocity_to_kinematics(
time: Res<Time>,
mut query: Query<(&mut KinematicCharacterController, &Velocity)>,
) {
let dt = time.delta_seconds();
for (mut controller, velocity) in &mut query {
controller.translation = Some(**velocity * dt);
}
}
pub struct PhysicsPlugin;
impl Plugin for PhysicsPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
Update,
(apply_acceleration, apply_velocity_to_kinematics)
.chain()
.in_set(PhysicsSet)
.run_if(run_in_game),
);
}
}
......@@ -2,25 +2,41 @@ use crate::assets::AssetHandles;
use crate::system::AppState;
use bevy::prelude::*;
use crate::entities::{Acceleration, PhysicsLimits, Velocity, GRAVITY_ACC};
use bevy_rapier2d::prelude::*;
#[derive(Component, Clone, Copy, Debug)]
pub struct Player;
pub fn spawn_player(mut commands: Commands, assets: Res<AssetHandles>) {
commands
.spawn((SpriteSheetBundle {
commands.spawn((
Player,
SpriteSheetBundle {
sprite: TextureAtlasSprite::new(3),
texture_atlas: assets.atlas("beige_blob"),
..Default::default()
},))
.with_children(|builder| {
builder.spawn((
TransformBundle::from_transform(Transform::from_xyz(0.0, -32.0, 0.0)),
},
RigidBody::KinematicPositionBased,
KinematicCharacterController {
custom_shape: Some((
Collider::capsule(Vec2::new(0.0, 8.0), Vec2::new(0.0, -48.0), 48.0),
KinematicCharacterController {
offset: CharacterLength::Absolute(0.01),
..Default::default()
},
));
});
Vec2::new(0.0, -32.0),
0.0,
)),
snap_to_ground: Some(CharacterLength::Absolute(0.5)),
offset: CharacterLength::Absolute(0.03),
..Default::default()
},
Acceleration::gravity(),
Velocity::default(),
PhysicsLimits {
velocity: (
Some(Vec2::new(f32::NEG_INFINITY, GRAVITY_ACC)),
Some(Vec2::new(f32::INFINITY, (-GRAVITY_ACC) * 2.0)),
),
acceleration: Default::default(),
},
));
}
pub struct PlayerSetupPlugin;
......
pub mod assets;
pub mod debug;
pub mod entities;
pub mod system;
......@@ -5,6 +5,7 @@ fn main() {
.add_plugins(game_core::assets::AssetLoadingPlugin)
.add_plugins(game_core::system::SystemPluginSet)
.add_plugins(game_core::entities::EntityPluginSet)
.add_plugins(game_core::debug::DebugPlugin)
.add_plugins(bevy_rapier2d::plugin::RapierPhysicsPlugin::<()>::pixels_per_meter(128.0))
.add_plugins(micro_banimate::BanimatePluginGroup)
.add_plugins(micro_musicbox::CombinedAudioPlugins::<
......
......@@ -17,6 +17,7 @@ mod _plugin {
pub struct PhysDebugPlugin;
impl Plugin for PhysDebugPlugin {
fn build(&self, app: &mut App) {
info!("Including Debug Physics Plugin");
app.add_plugins(bevy_rapier2d::render::RapierDebugRenderPlugin {
mode: DebugRenderMode::all(),
style: DebugRenderStyle::default(),
......@@ -36,6 +37,7 @@ mod _plugin {
#[cfg(feature = "phys-debug")]
{
info!("Rendering physics debug information");
plugins.add(phys_debug::PhysDebugPlugin)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment