Skip to content

Commit

Permalink
feat: Rigidbody and non-solid interaction (#78)
Browse files Browse the repository at this point in the history
* Added rigid interaction with non-solid
  • Loading branch information
Zac8668 authored Jan 31, 2024
1 parent b280004 commit 66c9ff6
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 20 deletions.
4 changes: 3 additions & 1 deletion src/actors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,9 @@ impl Plugin for ActorsPlugin {
app.add_systems(
FixedUpdate,
(
fill_actors.before(chunk_manager_update),
fill_actors
.before(chunk_manager_update)
.before(update_particles),
unfill_actors.after(chunk_manager_update),
update_actors.after(unfill_actors),
)
Expand Down
3 changes: 3 additions & 0 deletions src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ pub const RIGIDBODY_LAYER: f32 = 1000.;
pub const NORMAL_BUTTON: Color = Color::rgb(0.15, 0.15, 0.15);
pub const HOVERED_BUTTON: Color = Color::rgb(0.25, 0.25, 0.25);
pub const PRESSED_BUTTON: Color = Color::rgb(0.35, 0.75, 0.35);

//How much the rigidbody needs to be submerged to totally cut of gravity
//pub const STOP_RATE: f32 = 0.05;
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ mod prelude {

pub use crate::materials::Material;
pub use bevy_egui::EguiContext;

pub use bevy_rapier2d::prelude::RigidBody as RapierRigidbody;
}

use prelude::*;
Expand All @@ -72,7 +74,7 @@ fn main() {
RigidbodyPlugin,
))
.add_plugins((
RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(6.),
RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(1.),
MenuPlugin,
))
.add_systems(Startup, setup);
Expand Down
6 changes: 1 addition & 5 deletions src/particles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,10 @@ pub fn update_particles(

if particle.state == PartState::Normal
&& !materials[atom.id].is_void()
&& !materials[atom.id].is_object()
{
//Hit something!
//If our previous pos is free
if materials[prev_atom.id].is_void()
|| materials[prev_atom.id].is_object()
{
if materials[prev_atom.id].is_void() {
particle_send
.try_send(DeferredParticleUpdate {
remove: Some((
Expand All @@ -178,7 +175,6 @@ pub fn update_particles(
break;
} else if particle.state == PartState::Looking
&& materials[prev_atom.id].is_void()
|| materials[prev_atom.id].is_object()
{
particle_send
.try_send(DeferredParticleUpdate {
Expand Down
13 changes: 9 additions & 4 deletions src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,14 @@ pub fn tool_system(
let n = 6;

for i in 0..=n {
let angle = fastrand::f32() * std::f32::consts::TAU;
let rand_angle = fastrand::f32() * std::f32::consts::TAU;

let vec = new_tool_front - bound_slope * 2.
let mut vec = new_tool_front - bound_slope * 2.
+ bound_slope * 2.5 * i as f32 / n as f32
+ vec2(angle.cos(), angle.sin());
+ vec2(rand_angle.cos(), rand_angle.sin());

vec += tool_slope * 7. * angle.sin().max(0.);

let chunk_pos = global_to_chunk(vec.as_ivec2());
if let (Some(atom), tool_atom) = (
chunk_manager.get_mut_atom(chunk_pos),
Expand Down Expand Up @@ -429,7 +432,9 @@ impl Plugin for PlayerPlugin {
(
update_player.before(update_actors),
update_player_sprite.after(update_actors),
tool_system.before(chunk_manager_update),
tool_system
.before(chunk_manager_update)
.before(update_particles),
clear_input.after(update_player).after(tool_system),
)
.run_if(in_state(GameState::Game)),
Expand Down
64 changes: 55 additions & 9 deletions src/rigidbody.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,26 @@ pub fn add_rigidbodies(
handles: Query<(Entity, &RigidbodyHandle), Without<Hydrated>>,
) {
for (ent, handle) in &handles {
let image = images.get(handle.0.clone()).unwrap().clone();
let Some(image) = images.get(handle.0.clone()) else {
continue;
};

let rigidbody = Rigidbody {
atoms: image_atoms(&image),
atoms: image_atoms(image),
height: image.height() as u8,
width: image.width() as u8,
filled: vec![],
};

let collider = get_collider(&image_values(&image), image.width(), image.height()).unwrap();
let collider = get_collider(&image_values(image), image.width(), image.height()).unwrap();

commands
.spawn(collider)
.insert(rigidbody)
.insert(bevy_rapier2d::prelude::RigidBody::Dynamic)
.insert(RapierRigidbody::Dynamic)
.insert(bevy_rapier2d::prelude::Velocity::zero())
.insert(bevy_rapier2d::prelude::ExternalImpulse::default())
.insert(ReadMassProperties::default())
.insert(SpriteBundle {
texture: handle.0.clone(),
sprite: Sprite {
Expand All @@ -64,21 +69,25 @@ pub fn add_rigidbodies(
}

pub fn update_rigidibodies(
mut commands: Commands,
mut chunk_manager: ResMut<ChunkManager>,
mut rigidbodies: Query<(&Transform, &mut Rigidbody)>,
mut rigidbodies: Query<(&Transform, &mut Rigidbody, &Velocity, &ReadMassProperties)>,
materials: (Res<Assets<Materials>>, Res<MaterialsHandle>),
mut dirty_rects: ResMut<DirtyRects>,
) {
puffin::profile_function!();

let materials = materials.0.get(materials.1 .0.clone()).unwrap();

for (transform, mut rigidbody) in &mut rigidbodies {
for (transform, mut rigidbody, velocity, mass_prop) in &mut rigidbodies {
let (width, height) = (rigidbody.width as usize, rigidbody.height as usize);
let angle = -transform.rotation.to_euler(EulerRot::XYZ).2;
let mut top_left = transform.translation.xy();
top_left.y *= -1.;

//let mut stop_count = 0;
//let mut total = 0;

//This fills the chunks with Object atoms
for (y, x) in (0..height).cartesian_product(0..width) {
let pos = top_left + vec2(x as f32, y as f32).rotate(Vec2::from_angle(angle));
Expand All @@ -87,15 +96,50 @@ pub fn update_rigidibodies(
let rotated_atom = rigidbody.atoms[y * width + x];
if materials[&rotated_atom].is_solid() {
update_dirty_rects_3x3(&mut dirty_rects.current, chunk_pos);
//total += 1;

if let Some(atom) = chunk_manager.get_mut_atom(chunk_pos) {
if materials[atom.id].is_void() {
*atom = Atom::object();
if !materials[atom.id].is_solid() && !materials[atom.id].is_object() {
if materials[atom.id].is_liquid() || materials[atom.id].is_powder() {
let mut point = pos;
point.y *= -1.;

let center_of_mass =
mass_prop.local_center_of_mass + transform.translation.xy();
let vel_point =
velocity.linear_velocity_at_point(point, center_of_mass);

/*Apply impulse to rigidbody
*external_impulse += ExternalImpulse::at_point(
vel_point / mass_prop.mass,
point,
center_of_mass,
);*/

//Spawn particle
commands.spawn(Particle {
atom: *atom,
velocity: vel_point.normalize_or_zero()
* (vel_point.length() * mass_prop.mass / 1000.).min(16.),
pos: pos.round(),
..Default::default()
});
update_dirty_rects(&mut dirty_rects.render, chunk_pos);
}

rigidbody.filled.push(chunk_pos);
*atom = Atom::object();
}
}
}
}

/*
let stop_treshold = total as f32 * STOP_RATE;
let new_gravity = ((stop_treshold - stop_count as f32) / stop_treshold).clamp(0., 1.);
gravity_scale.0 = new_gravity;
*/
}
}

Expand Down Expand Up @@ -182,7 +226,9 @@ impl Plugin for RigidbodyPlugin {
.add_systems(
FixedUpdate,
(
update_rigidibodies.before(chunk_manager_update),
update_rigidibodies
.before(chunk_manager_update)
.before(update_particles),
unfill_rigidbodies.after(chunk_manager_update),
)
.run_if(in_state(GameState::Game)),
Expand Down

0 comments on commit 66c9ff6

Please sign in to comment.