diff --git a/src/common.rs b/src/common.rs index 5711941..c14dad4 100644 --- a/src/common.rs +++ b/src/common.rs @@ -16,6 +16,7 @@ pub const PLAYER_SPAWN_DURATION: f32 = 0.1; pub const LAZER_SPEED: f32 = 1250.0; pub const LAZER_PARTICLE_INTERVAL: f32 = 0.02; // Duration in seconds between particles +pub const LAZER_FIRING_INTERVAL: f32 = 0.5; // Cooldown for lazers pub const SCENE_WIDTH: f32 = RES_X / 2.0 - 100.0; pub const SCENE_HEIGHT: f32 = RES_Y / 2.0 - 50.0; diff --git a/src/game_state.rs b/src/game_state.rs index 31d3e77..da2e20a 100644 --- a/src/game_state.rs +++ b/src/game_state.rs @@ -3,6 +3,7 @@ use crate::{ audio::PlayMusicEvent, bunker::{self, Bunker}, common::*, + lazer::{LazerData} }; use bevy::prelude::*; use std::{default::Default, time::Duration}; @@ -29,6 +30,8 @@ pub struct Store { pub lives: u8, pub player_count_down: f32, pub game_state: GameState, + pub lazers: Vec, + pub lazer_interval: f32, pub show_state: bool, } @@ -44,6 +47,8 @@ impl Default for Store { lives: 0, player_count_down: 3.0, game_state: GameState::InsertCoin, + lazers: vec![], + lazer_interval: 0.0, show_state: false, } } @@ -112,7 +117,7 @@ pub fn game_state_event_system( GameStateEvent::LooseLife => { if store.game_state == GameState::Play { store.lives -= 1; - if store.lives == 0 { + if store.lives <= 0 { store.game_state = GameState::GameOver; timer.set(STATE_TRANSITION_MENU); } else { @@ -153,7 +158,9 @@ pub fn update_system( timer.tick(time.delta()); // extra life(s) - if store.score >= store.score_new_life { + // I think this is what was causing your race condition. But honestly this could be a cool mechanic + // Like a final shot to revive mechanic + if store.score >= store.score_new_life && store.lives >= 1 { store.lives += 1; store.score_new_life += (store.score_new_life as f32 * SCORE_SCALE) as u32; } diff --git a/src/hit_detection.rs b/src/hit_detection.rs index 04dc882..fae0999 100644 --- a/src/hit_detection.rs +++ b/src/hit_detection.rs @@ -11,6 +11,7 @@ use crate::{ }; use bevy::prelude::*; + #[allow(clippy::too_many_arguments)] pub fn update_system( mut commands: Commands, @@ -20,12 +21,10 @@ pub fn update_system( mut play_sound_ew: EventWriter, alien_query: Query<(Entity, &Transform), With>, - mut lazer_query: Query<(&mut Lazer, &Transform)>, mut bunker_query: Query<(&mut TextureAtlas, Entity, &Transform), With>, alien_bullet_query: Query<(Entity, &Transform), With>, mut player_query: Query<&Transform, With>, ) { - // check if point:&Transform is in &target:Transform with size:Vec2 #[inline(always)] fn in_rect(point: &Transform, target: &Transform, size: Vec2) -> bool { let t_vec: Vec2 = (target.translation.x, target.translation.y).into(); @@ -35,39 +34,86 @@ pub fn update_system( } let commands = &mut commands; - - // get lazer singleton - let (mut lazer, lazer_transform) = lazer_query.get_single_mut().unwrap(); - // get a player singleton let player_transform = player_query.single_mut(); - // alien bullets + + for i in 0..store.lazers.len(){ + + // alien bullets + for (bullet_entity, bullet_transform) in &alien_bullet_query { + // hit player missile + if in_rect(bullet_transform, &store.lazers[i].transform, (16.0, 32.0).into()) { + commands.entity(bullet_entity).despawn(); + store.lazers[i].lazer = Lazer::Idle; + spawn_explosion( + commands, + &image, + 10, + ( + bullet_transform.translation.x, + bullet_transform.translation.y, + ) + .into(), + 150.0, + 0.0, + (10.0, 10.0).into(), + ); + } + } + + if let Lazer::Fired(_) = store.lazers[i].lazer { + // check bunkers + for (atlas, entity, bunker_transform) in &mut bunker_query { + if in_rect(&store.lazers[i].transform, bunker_transform, BUNKER_SIZE) { + hit_bunker(commands, entity, atlas); + store.lazers[i].lazer = Lazer::Idle; + spawn_explosion( + commands, + &image, + 5, + (store.lazers[i].transform.translation.x, store.lazers[i].transform.translation.y).into(), + 50.0, + 0.0, + (10.0, 10.0).into(), + ); + } + } + + for (alien_entity, enemy_transform) in &alien_query { + // Collision check + if in_rect(&store.lazers[i].transform, enemy_transform, ALIEN_SIZE) { + play_sound_ew.send(PlaySoundEvent::AlienHit); + commands.entity(alien_entity).despawn(); + store.lazers[i].lazer = Lazer::Idle; + store.aliens_killed += 1; + store.alien_speed += ALIENS_SPEED_KILL; + store.score += SCORE_ALIEN; + + spawn_explosion( + commands, + &image, + 10, + (store.lazers[i].transform.translation.x, store.lazers[i].transform.translation.y).into(), + 500.0, + 0.0, + (10.0, 10.0).into(), + ); + + if store.aliens_killed == ALIENS_TOTAL { + debug!("-- send new wave --"); + game_state_ew.send(GameStateEvent::NewWave); + } + } + } + } + } + + + for (bullet_entity, bullet_transform) in &alien_bullet_query { - // hit player missile - if in_rect(bullet_transform, lazer_transform, (16.0, 32.0).into()) { - commands.entity(bullet_entity).despawn(); - *lazer = Lazer::Idle; - spawn_explosion( - commands, - &image, - 10, - ( - bullet_transform.translation.x, - bullet_transform.translation.y, - ) - .into(), - 150.0, - 0.0, - (10.0, 10.0).into(), - ); - } else - // hit player if in_rect(bullet_transform, player_transform, PLAYER_SIZE) { commands.entity(bullet_entity).despawn(); game_state_ew.send(GameStateEvent::LooseLife); - // to prevent the rare race-condition when outstanding missile would cause an extra life - - *lazer = Lazer::Idle; spawn_explosion( commands, @@ -108,50 +154,5 @@ pub fn update_system( } } - if let Lazer::Fired(_) = *lazer { - // check bunkers - for (atlas, entity, bunker_transform) in &mut bunker_query { - if in_rect(lazer_transform, bunker_transform, BUNKER_SIZE) { - hit_bunker(commands, entity, atlas); - *lazer = Lazer::Idle; - spawn_explosion( - commands, - &image, - 5, - (lazer_transform.translation.x, lazer_transform.translation.y).into(), - 50.0, - 0.0, - (10.0, 10.0).into(), - ); - } - } - - // check aliens - for (alien_entity, enemy_transform) in &alien_query { - // Collision check - if in_rect(lazer_transform, enemy_transform, ALIEN_SIZE) { - play_sound_ew.send(PlaySoundEvent::AlienHit); - commands.entity(alien_entity).despawn(); - *lazer = Lazer::Idle; - store.aliens_killed += 1; - store.alien_speed += ALIENS_SPEED_KILL; - store.score += SCORE_ALIEN; - - spawn_explosion( - commands, - &image, - 10, - (lazer_transform.translation.x, lazer_transform.translation.y).into(), - 500.0, - 0.0, - (10.0, 10.0).into(), - ); - - if store.aliens_killed == ALIENS_TOTAL { - debug!("-- send new wave --"); - game_state_ew.send(GameStateEvent::NewWave); - } - } - } - } + } diff --git a/src/lazer.rs b/src/lazer.rs index 281b77b..3611f49 100644 --- a/src/lazer.rs +++ b/src/lazer.rs @@ -1,4 +1,4 @@ -use crate::{common::*, particle::*, player::Player}; +use crate::{common::*, particle::*, player::Player, game_state::Store}; use bevy::prelude::*; use rand::random; use std::time::Duration; @@ -10,89 +10,94 @@ pub enum Lazer { Idle, } +pub struct LazerData { + pub lazer: Lazer, + pub transform: Transform +} + #[derive(Event)] pub struct FireLazerEvent; pub fn fire_lazer_system( mut fire_lazer_event: EventReader, - mut lazer_query: Query<&mut Lazer>, + time: Res