wrire up ammo and health in head_ui
This commit is contained in:
@@ -153,6 +153,7 @@ fn sync(
|
|||||||
new_state = Some(BackpackHead {
|
new_state = Some(BackpackHead {
|
||||||
head: head.0,
|
head: head.0,
|
||||||
health: hp.health(),
|
health: hp.health(),
|
||||||
|
ammo: 1.,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,16 +5,29 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
pub use backpack_ui::BackpackAction;
|
pub use backpack_ui::BackpackAction;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
|
||||||
pub struct BackpackHead {
|
pub struct BackpackHead {
|
||||||
pub head: usize,
|
pub head: usize,
|
||||||
pub health: f32,
|
pub health: f32,
|
||||||
|
pub ammo: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackpackHead {
|
impl BackpackHead {
|
||||||
|
pub fn new(head: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
head,
|
||||||
|
health: 1.0,
|
||||||
|
ammo: 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn damage(&self) -> f32 {
|
pub fn damage(&self) -> f32 {
|
||||||
1. - self.health
|
1. - self.health
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ammo_used(&self) -> f32 {
|
||||||
|
1. - self.ammo
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource, Default)]
|
#[derive(Resource, Default)]
|
||||||
@@ -37,6 +50,7 @@ fn setup(mut commands: Commands) {
|
|||||||
.map(|i| BackpackHead {
|
.map(|i| BackpackHead {
|
||||||
head: i,
|
head: i,
|
||||||
health: 1.,
|
health: 1.,
|
||||||
|
ammo: 1.,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::{
|
|||||||
sounds::PlaySound,
|
sounds::PlaySound,
|
||||||
};
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_ui_gradients::{AngularColorStop, BackgroundGradient, ConicGradient, Position};
|
use bevy_ui_gradients::{AngularColorStop, BackgroundGradient, ConicGradient, Gradient, Position};
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
pub static HEAD_COUNT: usize = 18;
|
pub static HEAD_COUNT: usize = 18;
|
||||||
@@ -35,9 +35,10 @@ pub struct HeadsImages {
|
|||||||
pub heads: Vec<Handle<Image>>,
|
pub heads: Vec<Handle<Image>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource, Default)]
|
#[derive(Resource, Default, Reflect)]
|
||||||
|
#[reflect(Resource)]
|
||||||
pub struct ActiveHeads {
|
pub struct ActiveHeads {
|
||||||
heads: [Option<usize>; 5],
|
heads: [Option<BackpackHead>; 5],
|
||||||
current_slot: usize,
|
current_slot: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,8 +47,13 @@ pub struct HeadChanged(pub usize);
|
|||||||
|
|
||||||
pub fn plugin(app: &mut App) {
|
pub fn plugin(app: &mut App) {
|
||||||
app.register_type::<HeadDamage>();
|
app.register_type::<HeadDamage>();
|
||||||
|
app.register_type::<ActiveHeads>();
|
||||||
|
|
||||||
app.add_systems(OnEnter(GameState::Playing), setup);
|
app.add_systems(OnEnter(GameState::Playing), setup);
|
||||||
app.add_systems(Update, update.run_if(in_state(GameState::Playing)));
|
app.add_systems(
|
||||||
|
Update,
|
||||||
|
(update, update_ammo, update_health).run_if(in_state(GameState::Playing)),
|
||||||
|
);
|
||||||
app.add_observer(on_select_active_head);
|
app.add_observer(on_select_active_head);
|
||||||
app.add_observer(on_swap_backpack);
|
app.add_observer(on_swap_backpack);
|
||||||
}
|
}
|
||||||
@@ -82,7 +88,13 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, assets: Res<UIA
|
|||||||
commands.insert_resource(HeadsImages { heads });
|
commands.insert_resource(HeadsImages { heads });
|
||||||
|
|
||||||
commands.insert_resource(ActiveHeads {
|
commands.insert_resource(ActiveHeads {
|
||||||
heads: [Some(0), Some(3), Some(6), Some(8), Some(9)],
|
heads: [
|
||||||
|
Some(BackpackHead::new(0)),
|
||||||
|
Some(BackpackHead::new(3)),
|
||||||
|
Some(BackpackHead::new(6)),
|
||||||
|
Some(BackpackHead::new(8)),
|
||||||
|
Some(BackpackHead::new(9)),
|
||||||
|
],
|
||||||
current_slot: 0,
|
current_slot: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -117,6 +129,7 @@ fn spawn_head_ui(
|
|||||||
ImageNode::new(selector),
|
ImageNode::new(selector),
|
||||||
HeadSelector(head_slot),
|
HeadSelector(head_slot),
|
||||||
));
|
));
|
||||||
|
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
Node {
|
Node {
|
||||||
position_type: PositionType::Absolute,
|
position_type: PositionType::Absolute,
|
||||||
@@ -125,12 +138,20 @@ fn spawn_head_ui(
|
|||||||
ImageNode::new(bg),
|
ImageNode::new(bg),
|
||||||
));
|
));
|
||||||
parent.spawn((
|
parent.spawn((
|
||||||
|
Name::new("head-icon"),
|
||||||
Node {
|
Node {
|
||||||
position_type: PositionType::Absolute,
|
position_type: PositionType::Absolute,
|
||||||
// width: Val::Px(66.0),
|
|
||||||
// height: Val::Px(66.0),
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
|
BorderRadius::all(Val::Px(9999.)),
|
||||||
|
BackgroundGradient::from(ConicGradient {
|
||||||
|
stops: vec![
|
||||||
|
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.9), 0.),
|
||||||
|
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.9), PI * 1.5),
|
||||||
|
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.0), PI * 1.5),
|
||||||
|
],
|
||||||
|
position: Position::CENTER,
|
||||||
|
}),
|
||||||
ImageNode::default(),
|
ImageNode::default(),
|
||||||
Visibility::Hidden,
|
Visibility::Hidden,
|
||||||
HeadImage(head_slot),
|
HeadImage(head_slot),
|
||||||
@@ -140,16 +161,7 @@ fn spawn_head_ui(
|
|||||||
position_type: PositionType::Absolute,
|
position_type: PositionType::Absolute,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
BorderRadius::all(Val::Px(9999.)),
|
|
||||||
ImageNode::new(regular),
|
ImageNode::new(regular),
|
||||||
BackgroundGradient::from(ConicGradient {
|
|
||||||
stops: vec![
|
|
||||||
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.9), 0.),
|
|
||||||
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.9), PI * 1.5),
|
|
||||||
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.0), PI * 1.5),
|
|
||||||
],
|
|
||||||
position: Position::CENTER,
|
|
||||||
}),
|
|
||||||
));
|
));
|
||||||
parent
|
parent
|
||||||
.spawn((Node {
|
.spawn((Node {
|
||||||
@@ -187,7 +199,7 @@ fn update(
|
|||||||
for (HeadImage(head), mut vis, mut image) in head_image.iter_mut() {
|
for (HeadImage(head), mut vis, mut image) in head_image.iter_mut() {
|
||||||
if let Some(head) = res.heads[*head] {
|
if let Some(head) = res.heads[*head] {
|
||||||
*vis = Visibility::Visible;
|
*vis = Visibility::Visible;
|
||||||
image.image = heads_images.heads[head].clone();
|
image.image = heads_images.heads[head.head].clone();
|
||||||
} else {
|
} else {
|
||||||
*vis = Visibility::Hidden;
|
*vis = Visibility::Hidden;
|
||||||
}
|
}
|
||||||
@@ -202,6 +214,31 @@ fn update(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_ammo(res: Res<ActiveHeads>, mut gradients: Query<(&mut BackgroundGradient, &HeadImage)>) {
|
||||||
|
if res.is_changed() {
|
||||||
|
for (mut gradient, HeadImage(head)) in gradients.iter_mut() {
|
||||||
|
if let Some(head) = res.heads[*head] {
|
||||||
|
let ammo_used = head.ammo_used();
|
||||||
|
let Gradient::Conic(gradient) = &mut gradient.0[0] else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let angle = PI * 2. * ammo_used;
|
||||||
|
gradient.stops[1].angle = Some(angle);
|
||||||
|
gradient.stops[2].angle = Some(angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_health(res: Res<ActiveHeads>, mut query: Query<(&mut Node, &HeadDamage)>) {
|
||||||
|
if res.is_changed() {
|
||||||
|
for (mut node, HeadDamage(head)) in query.iter_mut() {
|
||||||
|
node.height =
|
||||||
|
Val::Percent(res.heads[*head].map(|head| head.damage()).unwrap_or(0.) * 100.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn on_select_active_head(
|
fn on_select_active_head(
|
||||||
trigger: Trigger<SelectActiveHead>,
|
trigger: Trigger<SelectActiveHead>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
@@ -217,7 +254,7 @@ fn on_select_active_head(
|
|||||||
}
|
}
|
||||||
|
|
||||||
commands.trigger(PlaySound::Selection);
|
commands.trigger(PlaySound::Selection);
|
||||||
commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap()));
|
commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap().head));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_swap_backpack(
|
fn on_swap_backpack(
|
||||||
@@ -233,16 +270,13 @@ fn on_swap_backpack(
|
|||||||
let current_active_slot = res.current_slot;
|
let current_active_slot = res.current_slot;
|
||||||
|
|
||||||
let current_active_head = res.heads[current_active_slot];
|
let current_active_head = res.heads[current_active_slot];
|
||||||
res.heads[current_active_slot] = Some(head.head);
|
res.heads[current_active_slot] = Some(*head);
|
||||||
|
|
||||||
if let Some(old_active) = current_active_head {
|
if let Some(old_active) = current_active_head {
|
||||||
backpack.heads[backpack_slot] = BackpackHead {
|
backpack.heads[backpack_slot] = old_active;
|
||||||
head: old_active,
|
|
||||||
health: 1.,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
backpack.heads.remove(backpack_slot);
|
backpack.heads.remove(backpack_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap()));
|
commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap().head));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user