Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Rigidbodies #62

Merged
merged 12 commits into from
Jan 27, 2024
Merged
1,591 changes: 1,073 additions & 518 deletions Cargo.lock

Large diffs are not rendered by default.

23 changes: 14 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@ default-run = "astratomic"
[dependencies]
bevy = {version = "0.12", features =["file_watcher"]}
bevy-inspector-egui = "0.22"
rand = { version = "0.8.5", features = ["small_rng"] }
fastrand = "2.0.1"
async-channel = "2.1.0"
smallvec = "1.11.2"
itertools = "0.12.0"
rand = { version = "0.8", features = ["small_rng"] }
fastrand = "2.0"
async-channel = "2.1"
smallvec = "1.12"
itertools = "0.12"

serde = "1.0"
serde_derive = "1.0"
bincode = "1.3.3"
serde-big-array = "0.5.1"
ron = "0.8.1"
bevy-async-task = "1.3.1"
bincode = "1.3"
serde-big-array = "0.5"
ron = "0.8"
bevy-async-task = "1.3"

contour = "0.12"
bevy_rapier2d = { version = "0.23", features = [ "simd-stable", "debug-render-2d", "parallel" ] }
geo = "0.27"
rotsprite = "0.1"

egui = "0.24"
bevy_egui = "0.24"
Expand Down
Binary file added assets/tree.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use serde::Deserialize;

use crate::prelude::*;

#[derive(Clone, Copy, Default, PartialEq, Debug, Serialize, Deserialize)]
#[derive(Clone, Copy, Default, PartialEq, Debug, Serialize, Deserialize, Eq)]
pub struct Atom {
pub color: [u8; 4],
pub id: u8,
Expand Down
36 changes: 34 additions & 2 deletions src/chunk.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bevy::render::render_resource::*;
use std::collections::HashSet;

use crate::prelude::*;
use crate::{prelude::*, rigidbody};

#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct Chunk {
Expand All @@ -10,13 +10,16 @@ pub struct Chunk {

#[serde(skip)]
pub texture: Handle<Image>,
#[serde(skip)]
pub entity: Option<Entity>,
}

impl Default for Chunk {
fn default() -> Self {
Self {
atoms: [Atom::default(); CHUNK_LEN],
texture: Handle::default(),
entity: None,
}
}
}
Expand Down Expand Up @@ -49,7 +52,11 @@ impl Chunk {
}
}

Chunk { atoms, texture }
Chunk {
atoms,
texture,
entity: None,
}
}

pub fn new_image() -> Image {
Expand Down Expand Up @@ -80,4 +87,29 @@ impl Chunk {

self.update_image_positions(image, &positions)
}

pub fn get_collider(&self, materials: &Materials) -> Option<Collider> {
rigidbody::get_collider(
&self.get_values(materials),
CHUNK_LENGHT as u32,
CHUNK_LENGHT as u32,
(0., 0.),
)
}

pub fn get_values(&self, materials: &Materials) -> Vec<f64> {
let mut values = vec![];

for row in self.atoms.chunks(CHUNK_LENGHT) {
for atom in row {
if materials[atom].is_solid() {
values.push(1.)
} else {
values.push(0.)
}
}
}

values
}
}
145 changes: 114 additions & 31 deletions src/chunk_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl DirtyRects {
}

#[derive(Component)]
pub struct ChunkTextures;
pub struct ChunksParent;

pub fn manager_setup(
mut commands: Commands,
Expand Down Expand Up @@ -203,18 +203,98 @@ pub fn manager_setup(

commands
.spawn((
Name::new("Chunks textures"),
Name::new("Chunks"),
VisibilityBundle::default(),
TransformBundle::from_transform(Transform::from_translation(vec3(
0.,
0.,
AUTOMATA_LAYER,
))),
ChunkTextures,
ChunksParent,
))
.push_children(&images_vec);
}

pub fn add_colliders(
mut commands: Commands,
chunk_manager: Res<ChunkManager>,
chunks: Query<(Entity, &ChunkComponent)>,
rigidbodies: Query<(&Transform, &Rigidbody)>,
materials: (Res<Assets<Materials>>, Res<MaterialsHandle>),
) {
let materials = materials.0.get(materials.1 .0.clone()).unwrap();

let mut rects = vec![];

for (transform, rigidbody) in &rigidbodies {
let l = std::f32::consts::SQRT_2 * (rigidbody.width as f32).max(rigidbody.height as f32);

let angle = std::f32::consts::FRAC_PI_4 + std::f32::consts::PI;
let mut top_left = transform.translation.xy();
top_left.y *= -1.;
top_left += vec2(angle.cos(), angle.sin()) * l / 2.;

let angle = std::f32::consts::FRAC_PI_4;
let mut down_right = transform.translation.xy();
down_right.y *= -1.;
down_right += vec2(angle.cos(), angle.sin()) * l / 2.;

/*{
//Some debug visualization
let mut top_left = top_left;
top_left.y *= -1.;
gizmos.circle_2d(top_left, 10., Color::RED);

let mut down_right = down_right;
down_right.y *= -1.;
gizmos.circle_2d(down_right, 10., Color::BLACK);
}*/

top_left /= CHUNK_LENGHT as f32;
down_right /= CHUNK_LENGHT as f32;

const LOADING_OFF: i32 = 2;
let bounds_rect = IRect::new(
top_left.x as i32 - LOADING_OFF,
top_left.y as i32 - LOADING_OFF,
down_right.x as i32 + LOADING_OFF,
down_right.y as i32 + LOADING_OFF,
);

rects.push(bounds_rect);
}

if !rects.is_empty() {
'chunks: for (ent, pos) in &chunks {
for (i, rect) in rects.iter().enumerate() {
//If on bounds continue by breaking this loop
if rect.contains(pos.0) {
break;
} else if i == rects.len() - 1 {
//If none contains, remove collider and go to next chunk
//Remove collider
if let Some(mut entity) = commands.get_entity(ent) {
entity.remove::<Collider>();
entity.remove::<bevy_rapier2d::prelude::RigidBody>();
}
continue 'chunks;
}
}

if let Some(chunk) = chunk_manager.chunks.get(&pos.0) {
let collider = chunk.get_collider(materials);

if let Some(collider) = collider {
commands
.entity(ent)
.insert(collider)
.insert(bevy_rapier2d::prelude::RigidBody::Fixed);
}
}
}
}
}

pub fn chunk_manager_update(
mut chunk_manager: ResMut<ChunkManager>,
mut dirty_rects_resource: ResMut<DirtyRects>,
Expand Down Expand Up @@ -268,16 +348,6 @@ pub fn chunk_manager_update(

// Spawn a task on the deferred scope for handling deferred dirty render rects.
deferred_scope.spawn(async move {
//Update all rendering, used when debugging
/*
for x in 0..CHUNKS_WIDTH {
for y in 0..CHUNKS_HEIGHT {
render_dirty_rects
.insert(IVec2::new(x as i32, y as i32), URect::new(0, 0, 63, 63));
}
}
*/

// Loop through deferred tasks
while let Ok(update) = dirty_render_rects_recv.recv().await {
update_dirty_rects(render_dirty_rects, update.chunk_pos);
Expand Down Expand Up @@ -390,6 +460,9 @@ pub fn update_chunks(chunks: &mut UpdateChunksType, dt: u8, dirty_rect: &URect)
}
}

#[derive(Component)]
pub struct ChunkComponent(pub IVec2);

//Still needs to add the return entity to a parent
pub fn add_chunk(
commands: &mut Commands,
Expand All @@ -410,25 +483,31 @@ pub fn add_chunk(
//Update chunk image
let image = images.get_mut(&chunk.texture).unwrap();
chunk.update_all(image);
chunk_manager.chunks.insert(index, chunk);

//Spawn Image
commands
.spawn(SpriteBundle {
texture: texture_copy,
sprite: Sprite {
anchor: Anchor::TopLeft,
let entity = commands
.spawn((
SpriteBundle {
texture: texture_copy,
sprite: Sprite {
anchor: Anchor::TopLeft,
..Default::default()
},
transform: Transform::from_xyz(pos.x, pos.y, 0.),
..Default::default()
},
transform: Transform::from_xyz(pos.x, pos.y, 0.),
..Default::default()
})
.id()
ChunkComponent(index),
))
.id();
chunk.entity = Some(entity);

chunk_manager.chunks.insert(index, chunk);
entity
}

pub fn update_manager_pos(
mut commands: Commands,
chunk_textures: Query<Entity, With<ChunkTextures>>,
chunk_textures: Query<Entity, With<ChunksParent>>,
image_entities: Query<(&Parent, Entity, &Handle<Image>)>,
player: Query<&Actor, With<Player>>,
resources: (
Expand Down Expand Up @@ -510,16 +589,17 @@ pub fn update_manager_pos(
}

#[derive(Resource, Default, Deref, DerefMut)]
struct ExtractedTextureUpdates(Vec<ExtractedTextureUpdate>);
pub struct ExtractedTextureUpdates(pub Vec<ExtractedTextureUpdate>);

struct ExtractedTextureUpdate {
id: AssetId<Image>,
#[derive(Clone)]
pub struct ExtractedTextureUpdate {
pub id: AssetId<Image>,
// TODO: determine a good size for the data smallvec array.
// The size of the array determines how many bytes we can store before it overflows and has
// to make a heap allocation. 256 is enough to store an 8x8 pixel dirty rect.
data: SmallVec<[u8; 256]>,
origin: Origin3d,
size: Extent3d,
pub data: SmallVec<[u8; 256]>,
pub origin: Origin3d,
pub size: Extent3d,
}

fn extract_chunk_texture_updates(
Expand Down Expand Up @@ -598,7 +678,10 @@ impl Plugin for ChunkManagerPlugin {
FixedUpdate,
chunk_manager_update.run_if(in_state(GameState::Game)),
)
.add_systems(Update, update_manager_pos.run_if(in_state(GameState::Game)))
.add_systems(
Update,
(update_manager_pos, add_colliders).run_if(in_state(GameState::Game)),
)
.add_systems(
PreUpdate,
clear_render_rect.run_if(in_state(GameState::Game)),
Expand Down
1 change: 1 addition & 0 deletions src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ impl Plugin for DebugPlugin {
)
.add_systems(PreUpdate, delete_image.run_if(in_state(GameState::Game)))
.add_plugins(WorldInspectorPlugin::new())
.add_plugins(RapierDebugRenderPlugin::default())
//Frame on console
.add_plugins((LogDiagnosticsPlugin::default(), FrameTimeDiagnosticsPlugin))
.init_resource::<PreviousMousePos>();
Expand Down
12 changes: 10 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ mod menu;
mod particles;
mod player;
mod puffin_plugin;
mod rigidbody;
mod prelude {
pub use crate::GameState;
pub use crate::{
actors::*, animation::*, atom::*, camera::*, chunk::*, chunk_group::*, chunk_manager::*,
consts::*, debug::*, geom_tools::*, manager_api::*, materials::*, menu::*, particles::*,
player::*, puffin_plugin::*,
player::*, puffin_plugin::*, rigidbody::*,
};
pub use bevy::input::mouse::MouseScrollUnit;
pub use bevy::input::mouse::MouseWheel;
Expand All @@ -43,6 +44,9 @@ mod prelude {
pub use std::io::{BufReader, BufWriter};
pub use std::sync::{Arc, RwLock};

pub use bevy_rapier2d::prelude::*;
pub use contour::ContourBuilder;

pub use crate::materials::Material;
pub use bevy_egui::EguiContext;
}
Expand All @@ -65,12 +69,16 @@ fn main() {
ParticlesPlugin,
MaterialsPlugin,
CameraPlugin,
RigidbodyPlugin,
))
.add_plugins((
RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(6.),
MenuPlugin,
))
.add_systems(Startup, setup);

if args.contains(&"-d".to_string()) || args.contains(&"--debug".to_string()) {
app.add_plugins(DebugPlugin);
app.add_plugins((DebugPlugin,));
}

if args.contains(&"-p".to_string()) || args.contains(&"--profiling".to_string()) {
Expand Down
7 changes: 5 additions & 2 deletions src/materials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ impl AssetLoader for MaterialsLoader {
}
}

pub fn setup(mut materials_handle: ResMut<MaterialsHandle>, asset_server: Res<AssetServer>) {
pub fn materials_setup(
mut materials_handle: ResMut<MaterialsHandle>,
asset_server: Res<AssetServer>,
) {
materials_handle.0 = asset_server.load("atoms.ron");
}

Expand All @@ -128,6 +131,6 @@ impl Plugin for MaterialsPlugin {
app.init_asset::<Materials>()
.init_resource::<MaterialsHandle>()
.init_asset_loader::<MaterialsLoader>()
.add_systems(Startup, setup);
.add_systems(Startup, materials_setup);
}
}
Loading
Loading