diff --git a/src/components.rs b/src/components.rs index bf824c2..28a1ba3 100644 --- a/src/components.rs +++ b/src/components.rs @@ -3,6 +3,7 @@ use bevy::{ prelude::{Component, Entity}, reflect as bevy_reflect, reflect::Reflect, + render::color::Color, }; use crate::types::Direction; @@ -58,6 +59,12 @@ pub struct Bomb { pub expiration_frame: usize, } +#[derive(Component)] +pub struct Fuse { + pub color: Color, + pub start_frame: usize, +} + #[derive(Default, Reflect, Component)] pub struct Fire { pub expiration_frame: usize, diff --git a/src/lib.rs b/src/lib.rs index 2a55739..f67420f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,6 +136,7 @@ pub fn run() { apply_deferred, explode_bombs, apply_deferred, + animate_fuse, player_burn, apply_deferred, finish_round, diff --git a/src/systems.rs b/src/systems.rs index 8f0e0d0..07c8921 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -415,21 +415,116 @@ pub fn bomb_drop( }); parent - .spawn((Text2dBundle { - text, - transform: Transform::from_xyz( - 0.0, - TILE_HEIGHT as f32 / 8.0 * 2.0, - 0.0, - ), - ..Default::default() - },)) + .spawn(( + Text2dBundle { + text, + transform: Transform::from_xyz( + 0.0, + TILE_HEIGHT as f32 / 8.0 * 2.0, + 0.0, + ), + ..Default::default() + }, + Fuse { + color: fuse_color, + start_frame: frame_count.frame, + }, + )) .add_rollback(); }); } } } +pub fn animate_fuse( + frame_count: Res, + fonts: Res, + query: Query<&Bomb>, + mut query2: Query<(&Parent, &mut Text, &Fuse, &mut Transform)>, +) { + for (parent, mut text, fuse, mut transform) in query2.iter_mut() { + const FUSE_ANIMATION_FRAME_COUNT: usize = (FPS as f32 * 0.1) as usize; + // TODO double check calculation + let percent_left = (FUSE_ANIMATION_FRAME_COUNT + - (frame_count.frame - fuse.start_frame) % FUSE_ANIMATION_FRAME_COUNT) + as f32 + / FUSE_ANIMATION_FRAME_COUNT as f32; + let fuse_char = match percent_left { + _ if (0.0..0.33).contains(&percent_left) => 'x', + _ if (0.33..0.66).contains(&percent_left) => '+', + _ if (0.66..=1.0).contains(&percent_left) => '*', + _ => unreachable!(), + }; + + let bomb = query.get(parent.get()).unwrap(); + let percent_left = (bomb.expiration_frame - frame_count.frame) as f32 + / (bomb.expiration_frame - fuse.start_frame) as f32; + + match percent_left { + _ if (0.66..1.0).contains(&percent_left) => { + text.sections = vec![ + TextSection { + value: fuse_char.into(), + style: TextStyle { + font: fonts.mono.clone(), + font_size: 2.0 * PIXEL_SCALE as f32, + color: fuse.color, + }, + }, + TextSection { + value: "ā”\n ā”‚".into(), + style: TextStyle { + font: fonts.mono.clone(), + font_size: 2.0 * PIXEL_SCALE as f32, + color: COLORS[0].into(), + }, + }, + ]; + let translation = &mut transform.translation; + translation.x = 0.0; + translation.y = TILE_HEIGHT as f32 / 8.0 * 2.0; + } + _ if (0.33..0.66).contains(&percent_left) => { + text.sections = vec![ + TextSection { + value: fuse_char.into(), + style: TextStyle { + font: fonts.mono.clone(), + font_size: 2.0 * PIXEL_SCALE as f32, + color: fuse.color, + }, + }, + TextSection { + value: "\nā”‚".into(), + style: TextStyle { + font: fonts.mono.clone(), + font_size: 2.0 * PIXEL_SCALE as f32, + color: COLORS[0].into(), + }, + }, + ]; + let translation = &mut transform.translation; + translation.x = TILE_WIDTH as f32 / 12.0; + translation.y = TILE_HEIGHT as f32 / 8.0 * 2.0; + } + _ if (0.0..0.33).contains(&percent_left) => { + text.sections = vec![TextSection { + value: fuse_char.into(), + style: TextStyle { + font: fonts.mono.clone(), + font_size: 2.0 * PIXEL_SCALE as f32, + color: fuse.color, + }, + }]; + let translation = &mut transform.translation; + translation.x = TILE_WIDTH as f32 / 12.0; + translation.y = TILE_HEIGHT as f32 / 8.0 * 1.0; + } + _ => (), + } + } +} + pub fn fire_tick( mut commands: Commands, frame_count: Res,