diff --git a/assets/sprites/background.png b/assets/sprites/background.png new file mode 100644 index 0000000..ab14f40 Binary files /dev/null and b/assets/sprites/background.png differ diff --git a/assets/sprites/sun.png b/assets/sprites/sun.png new file mode 100644 index 0000000..c908fa1 Binary files /dev/null and b/assets/sprites/sun.png differ diff --git a/src/health.rs b/src/health.rs new file mode 100644 index 0000000..847112a --- /dev/null +++ b/src/health.rs @@ -0,0 +1,126 @@ +use bevy::prelude::*; + +use std::ops::{Add,Sub,AddAssign,SubAssign}; + +pub struct HealthPlugin; + +impl Plugin for HealthPlugin { + fn build(&self, app: &mut App) { + app.add_systems(PostUpdate, despawn_killed) + .add_observer(recieve_damage); + } +} + +/// Component that holds health information of damageable entity +#[derive(Component)] +pub struct Health{ + health: u32, + max_health: u32, +} + +impl Default for Health { + /// Create entity with minimum hp to not despawn immediatly + fn default() -> Self { + Self { health: 1, max_health: 1 } + } +} + +impl Add for Health { + type Output = u32; + + fn add(self, rhs: u32) -> Self::Output { + if u32::MAX - self.health < rhs { + u32::MAX + } + else { + self.health + rhs + } + } +} + +impl Sub for Health { + type Output = u32; + + fn sub(self, rhs: u32) -> Self::Output { + if self.health < rhs { + 0 + } + else { + self.health - rhs + } + } +} + +impl AddAssign for Health { + fn add_assign(&mut self, rhs: u32) { + if u32::MAX - self.health < rhs { + self.health = u32::MAX; + } + else { + self.health += rhs; + } + } +} + +impl SubAssign for Health { + fn sub_assign(&mut self, rhs: u32) { + if self.health < rhs { + self.health = 0; + } + else { + self.health -= rhs; + } + } +} + +impl Health { + /// Create new health component with set health and max health + pub fn new(health: u32, max_health: u32) -> Self { + Self { + health, + max_health + } + } + /// Create new health from max health + pub fn new_full(max_health: u32) -> Self { + Self { + health: max_health, + max_health + } + } +} + +/// Event sent on an vulnerable entity to damage it. +#[derive(EntityEvent)] +pub struct Damage{ + entity: Entity, + damage: u32 +} + +/// Marks entity to recieve [`Damage`] events. +#[derive(Component)] +#[require(Health)] +pub struct Vulnerable; + +/// Marks entity to not despawn when health drops to zero. +#[derive(Component)] +#[require(Health)] +pub struct Unkillable; + +/// Despawn all killable entites with health equal to zero +pub fn despawn_killed(mut commands: Commands, query: Query<(Entity, &Health), Without>) { + for (entity, health) in query { + if health.health == 0 { + commands.entity(entity).despawn(); + } + } +} + +/// Process damage event for vulnerable entities +pub fn recieve_damage(event: On, mut query: Query<&mut Health, With>) { + let Ok(mut health) = query.get_mut(event.entity) else { + return; + }; + + *health -= event.damage; +} diff --git a/src/level/mod.rs b/src/level/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/main.rs b/src/main.rs index e7a11a9..1f83b97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,12 @@ +use bevy::prelude::*; + +use crate::health::HealthPlugin; + +mod plant; +mod zombie; +mod health; +mod level; + fn main() { - println!("Hello, world!"); + App::new().add_plugins(DefaultPlugins).add_plugins(HealthPlugin).run(); } diff --git a/src/plant/mod.rs b/src/plant/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/zombie/mod.rs b/src/zombie/mod.rs new file mode 100644 index 0000000..e69de29