diff --git a/assets/atoms.ron b/assets/atoms.ron index 3882159..d88e248 100644 --- a/assets/atoms.ron +++ b/assets/atoms.ron @@ -1,22 +1,22 @@ ([ //0 Void Void, - //1 Dummy atom Object, - //2 Sand Powder ( inertial_resistance: 0.1), //3 Water - Liquid ( flow: 5 ), + Liquid ( flow: 5, damage: 0.0 ), //4 Gravel Powder ( inertial_resistance: 0.92), //5 Lava - Liquid ( flow: 1 ), + Liquid ( flow: 1, damage: 15.0 ), //6 Grass Solid, //7 Dirt Solid, //8 Rock Solid, + //9 Acid + Liquid ( flow: 5, damage: 3.0 ), ]) \ No newline at end of file diff --git a/src/actors.rs b/src/actors.rs index 350c996..05ce0dd 100644 --- a/src/actors.rs +++ b/src/actors.rs @@ -6,29 +6,38 @@ pub struct Actor { pub height: u8, pub pos: IVec2, pub vel: Vec2, + pub colliding: Option, } //Called before simulations pub fn fill_actors( mut chunk_manager: ResMut, - actors: Query<&Actor>, + actors: Query<(&Actor, Entity)>, mut dirty_rects: ResMut, materials: (Res>, Res), + mut ev_damage: EventWriter, ) { let materials = materials.0.get(&materials.1 .0).unwrap(); + let mut damages = 0.; - for actor in actors.iter() { + for (actor, ent) in actors.iter() { for x_off in 0..actor.width as i32 { for y_off in 0..actor.height as i32 { let pos = global_to_chunk(actor.pos + ivec2(x_off, y_off)); if let Some(atom) = chunk_manager.get_mut_atom(pos) { if materials[atom.id].is_void() { *atom = Atom::object(); + } else if let Some(damage) = materials[atom.id].damage() { + damages += damage / (actor.width * actor.height) as f32; } } update_dirty_rects_3x3(&mut dirty_rects.current, pos); } } + + if damages > 0. { + ev_damage.send(DamageEvent::new(ent, damages)); + } } } @@ -78,6 +87,8 @@ pub fn update_actors( let materials = materials.0.get(&materials.1 .0).unwrap(); for mut actor in actors.iter_mut() { + actor.colliding = None; + let mut prev = actor.pos; for v in Line::new(actor.pos, actor.vel.as_ivec2()) { let move_hor = match (prev.x != v.x, prev.y != v.y) { @@ -96,61 +107,45 @@ pub fn update_actors( ); if on_ground(&chunk_manager, &actor, materials) { let starting_y = actor.pos.y; - match moved_x { + if !moved_x { //If we can't move to the left or right //Check if we can get up a stair-like structure - false => { - for i in 1..=UP_WALK_HEIGHT { - let moved_y = move_y(&mut chunk_manager, &mut actor, -1, materials); - //Abort if we couldn't move up, or if we moved up but couldn't move sideways on the last step - if !moved_y - || i == UP_WALK_HEIGHT - && !move_x( - &mut chunk_manager, - &mut actor, - (v.x - prev.x).signum(), - materials, - ) - { - abort_stair( - &mut chunk_manager, - &mut actor, - starting_y, - 1, - materials, - ); - break; - } - } - } - //If we can move to the left or right - //Check if we can snap back to the ground - true => { - for i in 1..=DOWN_WALK_HEIGHT { - if !move_y(&mut chunk_manager, &mut actor, 1, materials) - && on_ground(&chunk_manager, &actor, materials) - { - break; - } else if i == DOWN_WALK_HEIGHT { - abort_stair( + for i in 1..=UP_WALK_HEIGHT { + let moved_y = move_y(&mut chunk_manager, &mut actor, -1, materials); + //Abort if we couldn't move up, or if we moved up but couldn't move sideways on the last step + if !moved_y + || i == UP_WALK_HEIGHT + && !move_x( &mut chunk_manager, &mut actor, - starting_y, - -1, + (v.x - prev.x).signum(), materials, - ); - } + ) + { + abort_stair( + &mut chunk_manager, + &mut actor, + starting_y, + 1, + materials, + ); + break; } } } } } else { - move_y( + let prev_vel = actor.vel.length(); + let moved_y = move_y( &mut chunk_manager, &mut actor, (v.y - prev.y).signum(), materials, ); + + if !moved_y && (v.y - prev.y).signum() != 0 && actor.colliding.is_none() { + actor.colliding = Some(prev_vel); + } } prev = v; diff --git a/src/atom.rs b/src/atom.rs index 0f72122..708c907 100644 --- a/src/atom.rs +++ b/src/atom.rs @@ -102,6 +102,15 @@ impl Atom { 255, ]; } + 9 => { + //Acid + atom.color = [ + (10 + rand::rng().random_range(-10_i16..10_i16)) as u8, + (230 + rand::rng().random_range(-10_i16..10_i16)) as u8, + (40 + rand::rng().random_range(-5_i16..5_i16)) as u8, + 255, + ]; + } _ => panic!("Atom not found, invalid ID."), } @@ -124,7 +133,7 @@ pub fn update_powder( // Get atom speed let mut speed = get_speed(chunks, cur_pos); - if speed < TERM_VEL { + if speed < ATOM_TERM_VEL { speed += GRAVITY; set_speed(chunks, cur_pos, speed); } @@ -177,7 +186,7 @@ pub fn update_liquid( // Get fall speed let mut speed = get_speed(chunks, pos); - if speed < TERM_VEL { + if speed < ATOM_TERM_VEL { speed += GRAVITY; set_speed(chunks, pos, speed); } @@ -234,7 +243,7 @@ pub fn update_atom(chunks: &mut UpdateChunksType, pos: IVec2, dt: u8) -> HashSet // Add gravity let mut vel = get_vel(chunks, cur_pos); - if vel.y < TERM_VEL as i32 { + if vel.y < ATOM_TERM_VEL as i32 { vel += GRAVITY as i32 * IVec2::Y; set_vel(chunks, cur_pos, vel); } diff --git a/src/chunk_manager.rs b/src/chunk_manager.rs index 45101bd..72b6191 100644 --- a/src/chunk_manager.rs +++ b/src/chunk_manager.rs @@ -458,7 +458,7 @@ pub fn update_chunks(chunks: &mut UpdateChunksType, dt: u8, dirty_rect: &URect) Material::Powder { inertial_resistance, } => update_powder(chunks, pos, dt, inertial_resistance), - Material::Liquid { flow } => update_liquid(chunks, pos, flow, dt), + Material::Liquid { flow, .. } => update_liquid(chunks, pos, flow, dt), _ => HashSet::new(), }, ) @@ -586,43 +586,43 @@ pub fn update_manager_pos( (chunks, new_diff) }); } - } + } else { + match task_executor.poll() { + Poll::Ready(v) => { + if let Ok((mut file_chunks, diff)) = v { + let chunk_textures = chunk_textures.single(); + for _ in 0..diff.x.abs() { + chunk_manager.move_manager( + &mut commands, + &mut images, + &chunk_textures, + &image_entities, + &mut file_chunks, + MoveDir::X(diff.x.signum()), + ); + } - match task_executor.poll() { - Poll::Ready(v) => { - if let Ok((mut file_chunks, diff)) = v { - let chunk_textures = chunk_textures.single(); - for _ in 0..diff.x.abs() { - chunk_manager.move_manager( - &mut commands, - &mut images, - &chunk_textures, - &image_entities, - &mut file_chunks, - MoveDir::X(diff.x.signum()), - ); - } + for _ in 0..diff.y.abs() { + chunk_manager.move_manager( + &mut commands, + &mut images, + &chunk_textures, + &image_entities, + &mut file_chunks, + MoveDir::Y(diff.y.signum()), + ); + } - for _ in 0..diff.y.abs() { - chunk_manager.move_manager( - &mut commands, - &mut images, - &chunk_textures, - &image_entities, - &mut file_chunks, - MoveDir::Y(diff.y.signum()), - ); + let pool = AsyncComputeTaskPool::get(); + saving_task.0 = Some(pool.spawn(async move { + let file = File::create("assets/world/world").unwrap(); + let mut buffered = BufWriter::new(file); + bincode::serialize_into(&mut buffered, &file_chunks).unwrap(); + })); } - - let pool = AsyncComputeTaskPool::get(); - saving_task.0 = Some(pool.spawn(async move { - let file = File::create("assets/world/world").unwrap(); - let mut buffered = BufWriter::new(file); - bincode::serialize_into(&mut buffered, &file_chunks).unwrap(); - })); } + Poll::Pending => {} } - Poll::Pending => {} } } diff --git a/src/consts.rs b/src/consts.rs index c1d2348..8bdc37c 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -12,7 +12,6 @@ pub const QUARTER_CHUNK_LEN: usize = CHUNK_LEN / 4; // Actor consts pub const UP_WALK_HEIGHT: usize = 3; -pub const DOWN_WALK_HEIGHT: usize = 4; // Player consts pub const FUEL_MAX: f32 = 50.; @@ -21,9 +20,9 @@ pub const FUEL_COMSUMPTON: f32 = 0.48; pub const JETPACK_FORCE: f32 = 1.5; pub const JETPACK_MAX: f32 = 3.; -pub const JUMP_MAG: f32 = 9.; -pub const PRESSED_JUMP_MAG: f32 = 0.6; -pub const TIME_JUMP_PRESSED: f64 = 0.8; +pub const JUMP_MAG: f32 = 5.; +pub const PRESSED_JUMP_MAG: f32 = 0.2; +pub const TIME_JUMP_PRESSED: f32 = 0.8; pub const RUN_SPEED: f32 = 2.5; pub const TOOL_DISTANCE: f32 = 32.; @@ -32,14 +31,14 @@ pub const TOOL_RANGE: f32 = 16.; pub const ZOOM_LOWER_BOUND: f32 = 0.15; pub const ZOOM_UPPER_BOUND: f32 = 0.30; -// Engine consts +pub const PLAYER_TERM_VEL: u8 = 20; + +pub const DAMAGE_FEED_TIME: f32 = 0.2; -//This was a "scale" const for the atoms, but we can just zoom in, so it was removed -//Made the code less verbose and simpler, we can readd if it makes sense -//pub const ATOM_SIZE: usize = 3; +// Engine consts pub const GRAVITY: u8 = 1; -pub const TERM_VEL: u8 = 10; +pub const ATOM_TERM_VEL: u8 = 20; pub const FRAMES_SLEEP: u8 = 1; //Has to be even pub const LOAD_WIDTH: i32 = 32; diff --git a/src/materials.rs b/src/materials.rs index 7281595..32aaa36 100644 --- a/src/materials.rs +++ b/src/materials.rs @@ -16,6 +16,7 @@ pub enum Material { }, Liquid { flow: u8, + damage: f32, }, Gas, Object, @@ -43,6 +44,14 @@ impl Material { pub fn is_solid(&self) -> bool { matches!(self, Material::Solid) } + + pub fn damage(&self) -> Option { + if let Material::Liquid { damage, .. } = self { + Some(*damage) + } else { + None + } + } } #[derive(Asset, TypePath, Debug, Deserialize)] diff --git a/src/player.rs b/src/player.rs index 43904a7..942993f 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,3 +1,5 @@ +use bevy::color::palettes::css::*; +use bevy::color::palettes::tailwind::*; use bevy::sprite::Anchor; use crate::prelude::*; @@ -32,7 +34,8 @@ pub enum PlayerState { #[default] Idle, Walking, - Jumping(f64), + Dead, + Jumping(f32), Jetpack(bool), } @@ -42,6 +45,9 @@ pub struct Tool; #[derive(Component)] pub struct ToolFront; +#[derive(Component)] +pub struct Life(f32); + pub fn player_setup( mut commands: Commands, asset_server: Res, @@ -63,6 +69,7 @@ pub fn player_setup( width: 10, pos, vel: vec2(0., 0.), + colliding: None, }; let player_handle = asset_server.load("player/player_sheet.png"); @@ -106,33 +113,89 @@ pub fn player_setup( player_actor.width as f32 / 2., player_actor.height as f32 / 2., ), + Life(100.), )) .add_child(tool_ent); + + //Life + commands.spawn(( + Node { + width: Val::Px(180.), + height: Val::Px(20.), + border: UiRect::left(Val::Px(180.)), + margin: UiRect::all(Val::Px(20.)), + align_items: AlignItems::Center, + justify_content: JustifyContent::Center, + ..default() + }, + BackgroundColor(MAROON.into()), + BorderColor(RED.into()), + Outline { + width: Val::Px(6.), + offset: Val::Px(6.), + color: Color::WHITE, + }, + PlayerLifeNode, + )); + + //Fuel + commands.spawn(( + Node { + width: Val::Px(20.), + height: Val::Px(180.), + border: UiRect::top(Val::Px(180.)), + margin: UiRect::all(Val::Px(20.)), + align_items: AlignItems::Center, + justify_content: JustifyContent::Center, + justify_self: JustifySelf::End, + ..default() + }, + BackgroundColor(LIGHT_GOLDENROD_YELLOW.into()), + BorderColor(YELLOW.into()), + Outline { + width: Val::Px(6.), + offset: Val::Px(6.), + color: Color::WHITE, + }, + PlayerFuelNode, + )); +} + +#[derive(Event)] +pub struct DamageEvent { + ent: Entity, + damage: f32, +} + +impl DamageEvent { + pub fn new(ent: Entity, damage: f32) -> Self { + Self { ent, damage } + } } -/// Updates player +#[derive(Component)] +pub struct PlayerLifeNode; + +#[derive(Component)] +pub struct PlayerFuelNode; + +/// Updates player input stuff pub fn update_player( input: (Res, EventReader), - mut player: Query<(&mut Actor, &mut Player, &mut AnimationIndices)>, + mut player: Query<(&mut Actor, &mut Player)>, chunk_manager: ResMut, materials: (Res>, Res), time: Res