From dece3a352f811c10d9b546f0b501f4e3a9c2e2cf Mon Sep 17 00:00:00 2001 From: Crizomb Date: Sun, 4 Jan 2026 17:54:46 +0100 Subject: [PATCH] warning signs, timer --- assets/sprites/timer.png | Bin 0 -> 269 bytes assets/sprites/warning.png | Bin 0 -> 247 bytes src/core/collectible.rs | 19 ++++---- src/core/game_state.rs | 7 ++- src/core/wave.rs | 95 ++++++++++++++++++++++++++++++++++--- 5 files changed, 105 insertions(+), 16 deletions(-) create mode 100644 assets/sprites/timer.png create mode 100644 assets/sprites/warning.png diff --git a/assets/sprites/timer.png b/assets/sprites/timer.png new file mode 100644 index 0000000000000000000000000000000000000000..ae0da02ce613560a86e46c9e098b223b552afcc7 GIT binary patch literal 269 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|j(fT|hFJ6_ zr#LYGyC(Gi;?W5Qk1f`hDD-+IHS59Eo^W2nSsPcTI!*iW_vD-ZTZ_~F*Vh{z&XVwv zTYqxD{mg|4C1+pg9pw;+b)NkHIiHc?oqdN7ELhc~m7emy|KX>f#u`-{+BD7xu(7eV z-7Z&1dU$fitdC47?;mg{sKp5J0KuA?zopr0BtjBQ2+n{ literal 0 HcmV?d00001 diff --git a/assets/sprites/warning.png b/assets/sprites/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..2f9a397d01bfe7db8a75c467bc6001844584e994 GIT binary patch literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|HhQ`^hFJ7Y zoxGQ~*+8V_ykMr0YgAdo8mH49nVY#5onp#UPG#3p30Bd+@w_-?ozb`I^7-`z8rm1O z2fG#tIdH63)ZJs3QXAYAfBzr=Kg-(zTnE4>nl{`FA175 vJXp^9_U$CyPY;iNy3FKKAO7u__EWPN&q7rUtoK*|9nawD>gTe~DWM4fSxRKG literal 0 HcmV?d00001 diff --git a/src/core/collectible.rs b/src/core/collectible.rs index 7af81c5..90c8818 100644 --- a/src/core/collectible.rs +++ b/src/core/collectible.rs @@ -9,6 +9,7 @@ use bevy::prelude::*; const ASSETS_NAME: [&str; 3] = ["speed_item.png", "shield_item.png", "kirby_item.png"]; const COLLECTABLE_COLLIDER_RADIUS: f32 = 50.0; const KIRBY_SPAWN_TIMER_DURATION: Duration = Duration::from_secs(2); +pub const COLLECTABLE_SCALE: f32 = 2.5; #[derive(Clone, Copy)] pub enum CollectableType { @@ -33,7 +34,7 @@ pub fn collectable_spawn( commands.spawn(( Collectable(collectable_type), SphereCollider::new(COLLECTABLE_COLLIDER_RADIUS), - Transform::from_translation(pos.extend(0.0)).with_scale(Vec3::splat(2.5)), + Transform::from_translation(pos.extend(0.0)).with_scale(Vec3::splat(COLLECTABLE_SCALE)), sprite, )); } @@ -42,6 +43,7 @@ pub fn collectable_actions_system( mut commands: Commands, mut kirby_query: Query<(&mut Kirby, &SphereCollider, &Transform)>, collectable_query: Query<(Entity, &Collectable, &SphereCollider, &Transform)>, + asset_server: Res, ) { for (mut kirby, kirby_collider, kirby_tf) in &mut kirby_query { for (collectible_entity, collectible, c_collider, collectable_tf) in collectable_query { @@ -54,7 +56,7 @@ pub fn collectable_actions_system( match &collectible.0 { CollectableType::SpeedBoost => speed_boost(&mut kirby), CollectableType::ShieldBoost => shield_boost(&mut kirby), - CollectableType::NewKirby => new_kirby(kirby_pos, &mut commands), + CollectableType::NewKirby => new_kirby(kirby_pos, &mut commands, &asset_server), } commands.entity(collectible_entity).despawn(); @@ -70,15 +72,16 @@ fn shield_boost(kirby: &mut Kirby) { kirby.shield_factor *= 0.8; } -fn new_kirby(kirby_pos: Vec3, commands: &mut Commands) { - commands.spawn(KirbySpawnHandler { - timer: Timer::new(KIRBY_SPAWN_TIMER_DURATION, TimerMode::Once), - position: kirby_pos, - }); +fn new_kirby(kirby_pos: Vec3, commands: &mut Commands, asset_server: &Res) { + commands.spawn(( + KirbySpawnHandler { timer: Timer::new(KIRBY_SPAWN_TIMER_DURATION, TimerMode::Once), position: kirby_pos }, + Sprite::from_image(asset_server.load("sprites/timer.png")), + Transform::from_translation(kirby_pos).with_scale(Vec3::splat(COLLECTABLE_SCALE)), + )); } #[derive(Component)] -#[require(DispawnOnGameOver)] +#[require(DispawnOnGameOver, Sprite, Transform)] struct KirbySpawnHandler { timer: Timer, position: Vec3, diff --git a/src/core/game_state.rs b/src/core/game_state.rs index 6af38ae..b4d9799 100644 --- a/src/core/game_state.rs +++ b/src/core/game_state.rs @@ -1,6 +1,9 @@ use bevy::{ecs::system::SystemParam, prelude::*}; -use crate::core::{kirby::Kirby, wave::BubbleWaves}; +use crate::core::{ + kirby::Kirby, + wave::{BubbleWaves, EnnemyWaveLock}, +}; #[derive(Event)] pub struct EndGameEvent { @@ -44,6 +47,7 @@ fn reset_resource(mut res: ResMut) { #[derive(SystemParam)] struct GameRes<'w> { bubble_waves: ResMut<'w, BubbleWaves>, + ennemy_wave_lock: ResMut<'w, EnnemyWaveLock>, } fn on_reset_world( @@ -56,6 +60,7 @@ fn on_reset_world( commands.entity(e).despawn(); } reset_resource(game_res.bubble_waves); + reset_resource(game_res.ennemy_wave_lock); println!("Set state"); commands.set_state(GameState::Starting); } diff --git a/src/core/wave.rs b/src/core/wave.rs index a2dcd87..9f406ef 100644 --- a/src/core/wave.rs +++ b/src/core/wave.rs @@ -1,19 +1,31 @@ -use std::thread::panicking; +use std::{thread::panicking, time::Duration}; -use bevy::prelude::*; +use bevy::{ecs::system::lifetimeless::SCommands, prelude::*}; use rand::distr::slice::Empty; use crate::{ core::{ bubble::{Bubble, bubble_spawn_wave}, - collectible::{CollectableType, collectable_spawn}, - game_state::{EndGameEvent, EndGameReason, Resetable}, + collectible::{COLLECTABLE_SCALE, CollectableType, collectable_spawn}, + game_state::{DispawnOnGameOver, EndGameEvent, EndGameReason, Resetable}, kirby::Kirby, life::Life, }, map::map::{BOTTOM, LEFT, RIGHT, TOP}, }; +#[derive(Event)] +pub struct NextWaveEvent; + +#[derive(Component)] +#[require(DispawnOnGameOver)] +pub struct NextWaveTimer { + timer: Timer, +} + +#[derive(Event)] +struct NextWaveTimerTimeout; + pub struct BubbleType { pub color: Color, pub move_force: f32, @@ -97,17 +109,81 @@ impl Resetable for BubbleWaves { } } +#[derive(Resource, Default)] // Default is false +pub struct EnnemyWaveLock(bool); + +impl Resetable for EnnemyWaveLock { + fn reset(&mut self) { + *self = EnnemyWaveLock::default() + } +} + fn no_ennemy_left(bubble_query: Query<(), With>) -> bool { bubble_query.is_empty() } -fn change_wave(mut bubble_wave: ResMut, mut commands: Commands, asset_server: Res) { +#[derive(Component)] +#[require(Sprite, Transform, DispawnOnGameOver)] +struct WarningSign; + +fn change_wave( + mut lock: ResMut, + bubble_wave: Res, + mut commands: Commands, + asset_server: Res, +) { + // Beetwen moment where all ennemies are killed and NextWaveTimer trigger the spawn of the new ennemy + // there is some time, and change_wave will be called every frame during this instance + // that's why there is an ugly-ass lock + if lock.0 { + return; + } + lock.0 = true; let max_bubble_wave = bubble_wave.waves.len(); if bubble_wave.current_wave >= max_bubble_wave { commands.trigger(EndGameEvent { reason: EndGameReason::Victory }); return; } + let current_bubble_wave = &bubble_wave.waves[bubble_wave.current_wave]; + for bubble_splash in current_bubble_wave { + commands.spawn(( + WarningSign, + Sprite::from_image(asset_server.load("sprites/warning.png")), + Transform::from_translation(bubble_splash.center.extend(0.0)).with_scale(Vec3::splat(COLLECTABLE_SCALE)), + )); + } + println!("change wave"); + commands.trigger(NextWaveEvent); + commands.spawn((NextWaveTimer { timer: Timer::new(Duration::from_secs(1), TimerMode::Once) },)); +} + +fn next_wave_timer_system( + next_wave_timer_query: Single<(&mut NextWaveTimer, Entity)>, + time: Res