Skip to content

Commit

Permalink
feat: Player life (#92)
Browse files Browse the repository at this point in the history
* Added life bar and fall damage!

Also some player movement improvements.

* Added life essentials

Respawn menu, damage animation, fuel bar, liquid damage.

* Added acid
  • Loading branch information
Zac8668 authored Jan 29, 2025
1 parent 6e002f0 commit bf48119
Show file tree
Hide file tree
Showing 8 changed files with 406 additions and 124 deletions.
8 changes: 4 additions & 4 deletions assets/atoms.ron
Original file line number Diff line number Diff line change
@@ -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 ),
])
79 changes: 37 additions & 42 deletions src/actors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,38 @@ pub struct Actor {
pub height: u8,
pub pos: IVec2,
pub vel: Vec2,
pub colliding: Option<f32>,
}

//Called before simulations
pub fn fill_actors(
mut chunk_manager: ResMut<ChunkManager>,
actors: Query<&Actor>,
actors: Query<(&Actor, Entity)>,
mut dirty_rects: ResMut<DirtyRects>,
materials: (Res<Assets<Materials>>, Res<MaterialsHandle>),
mut ev_damage: EventWriter<DamageEvent>,
) {
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));
}
}
}

Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down
15 changes: 12 additions & 3 deletions src/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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."),
}

Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down
66 changes: 33 additions & 33 deletions src/chunk_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
},
)
Expand Down Expand Up @@ -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 => {}
}
}

Expand Down
17 changes: 8 additions & 9 deletions src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.;
Expand All @@ -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.;
Expand All @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions src/materials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum Material {
},
Liquid {
flow: u8,
damage: f32,
},
Gas,
Object,
Expand Down Expand Up @@ -43,6 +44,14 @@ impl Material {
pub fn is_solid(&self) -> bool {
matches!(self, Material::Solid)
}

pub fn damage(&self) -> Option<f32> {
if let Material::Liquid { damage, .. } = self {
Some(*damage)
} else {
None
}
}
}

#[derive(Asset, TypePath, Debug, Deserialize)]
Expand Down
Loading

0 comments on commit bf48119

Please sign in to comment.