use bevy::prelude::*;
use bevy_gauge::prelude::*;
#[derive(Component, Default, Debug, AttributeComponent)]
struct Life {
#[read("Life")]
max: f32,
#[write("Life.current")]
#[init_from("Life")]
current: f32,
}
#[derive(Component, Default, Debug)]
struct AliveStatus {
alive: bool,
}
impl AttributeDerived for AliveStatus {
fn should_update(&self, attrs: &Attributes) -> bool {
let attr_alive = attrs.value("Alive") > 0.0;
self.alive != attr_alive
}
fn update_from_attributes(&mut self, attrs: &Attributes) {
self.alive = attrs.value("Alive") > 0.0;
}
}
register_derived!(AliveStatus);
#[derive(Resource)]
struct Entities {
hero: Entity,
}
#[derive(Resource)]
struct DemoStep(usize);
fn main() {
App::new()
.add_plugins(MinimalPlugins)
.add_plugins(AttributesPlugin)
.add_systems(Startup, spawn)
.add_systems(Update, demo)
.run();
}
fn spawn(mut commands: Commands) {
let hero = commands
.spawn((
Name::new("Hero"),
Life::default(),
AliveStatus { alive: true },
attributes! {
"Life" => 100.0,
"Alive" => 1.0,
},
))
.id();
commands.insert_resource(Entities { hero });
commands.insert_resource(DemoStep(0));
println!("--- Hero spawned ---\n");
}
fn demo(
handles: Res<Entities>,
mut attributes: AttributesMut,
mut q_life: Query<&mut Life>,
q_alive: Query<&AliveStatus>,
mut step: ResMut<DemoStep>,
) {
let hero = handles.hero;
match step.0 {
0 => {
println!("=== Initial state (current initialized from max via #[init_from]) ===\n");
print_state(hero, &mut attributes, &q_life, &q_alive);
println!("=== Taking 60 damage ===\n");
if let Ok(mut life) = q_life.get_mut(hero) {
life.current -= 60.0;
}
}
1 => {
print_state(hero, &mut attributes, &q_life, &q_alive);
println!("=== Taking 50 more damage (lethal) ===\n");
if let Ok(mut life) = q_life.get_mut(hero) {
life.current -= 50.0;
}
attributes.set_base(hero, "Alive", 0.0);
}
2 => {
print_state(hero, &mut attributes, &q_life, &q_alive);
println!("=== Resurrecting (set Alive back to 1.0) ===\n");
attributes.set_base(hero, "Alive", 1.0);
if let Ok(mut life) = q_life.get_mut(hero) {
life.current = life.max;
}
}
3 => {
print_state(hero, &mut attributes, &q_life, &q_alive);
println!("--- Done ---");
std::process::exit(0);
}
_ => {}
}
step.0 += 1;
}
fn print_state(
entity: Entity,
attributes: &mut AttributesMut,
q_life: &Query<&mut Life>,
q_alive: &Query<&AliveStatus>,
) {
let life_val = attributes.evaluate(entity, "Life");
let current_val = attributes.evaluate(entity, "Life.current");
let alive_val = attributes.evaluate(entity, "Alive");
println!(" Attributes:");
println!(" Life: {life_val:.0}");
println!(" Life.current: {current_val:.1}");
println!(" Alive: {alive_val:.0}");
if let Ok(life) = q_life.get(entity) {
println!(" Life component: max={:.0}, current={:.1}", life.max, life.current);
}
if let Ok(status) = q_alive.get(entity) {
println!(" AliveStatus: alive={}", status.alive);
}
println!();
}