From d27d27bb5ac673c5065f62d2d836d37e50aa86f9 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Wed, 16 Apr 2025 08:46:12 +0200 Subject: [PATCH] refactor: clean up formatting and improve readability in components and player logic --- src/components.rs | 12 +++++------ src/constants.rs | 3 ++- src/player.rs | 55 +++++++++++++++++++++++++++++++++-------------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/components.rs b/src/components.rs index 974f1fa..e7616ac 100644 --- a/src/components.rs +++ b/src/components.rs @@ -39,10 +39,10 @@ pub struct Captured { // New component for the tractor beam visual effect #[derive(Component)] pub struct TractorBeam { - pub target: Entity, // The entity being targeted (usually player) - pub timer: Timer, // How long the beam lasts - pub width: f32, // Visual width of the beam - pub active: bool, // Whether the beam is currently active + pub target: Entity, // The entity being targeted (usually player) + pub timer: Timer, // How long the beam lasts + pub width: f32, // Visual width of the beam + pub active: bool, // Whether the beam is currently active } #[derive(Component)] @@ -53,8 +53,8 @@ pub struct FormationTarget { // Enum defining different ways an enemy can attack #[derive(Component, Clone, Copy, PartialEq, Debug)] pub enum AttackPattern { - SwoopDive, // Original pattern: dive towards center, then off screen - DirectDive, // Dive straight down + SwoopDive, // Original pattern: dive towards center, then off screen + DirectDive, // Dive straight down Kamikaze(Vec3), // Dive towards a specific target location (e.g., player's last known position) - Needs target Vec3 CaptureBeam, // New pattern: Boss dives and attempts to capture the player with a tractor beam // Add more patterns later (e.g., FigureEight, Looping) diff --git a/src/constants.rs b/src/constants.rs index 4c3ec09..0b2c1c0 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -31,7 +31,8 @@ pub const BULLET_ENEMY_COLLISION_THRESHOLD: f32 = (BULLET_SIZE.x + ENEMY_SIZE.x) // 22.5 pub const PLAYER_ENEMY_COLLISION_THRESHOLD: f32 = (PLAYER_SIZE.x + ENEMY_SIZE.x) * 0.5; // 35.0 -pub const ENEMY_BULLET_PLAYER_COLLISION_THRESHOLD: f32 = (ENEMY_BULLET_SIZE.x + PLAYER_SIZE.x) * 0.5; +pub const ENEMY_BULLET_PLAYER_COLLISION_THRESHOLD: f32 = + (ENEMY_BULLET_SIZE.x + PLAYER_SIZE.x) * 0.5; // Tractor beam constants pub const TRACTOR_BEAM_WIDTH: f32 = 20.0; diff --git a/src/player.rs b/src/player.rs index acb1b96..9e7b359 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,7 +1,7 @@ use bevy::prelude::*; use std::time::Duration; -use crate::components::{Bullet, Enemy, Invincible, Player, Captured}; +use crate::components::{Bullet, Captured, Enemy, Invincible, Player}; use crate::constants::{ BULLET_SIZE, PLAYER_ENEMY_COLLISION_THRESHOLD, PLAYER_INVINCIBILITY_DURATION, PLAYER_SIZE, PLAYER_SPEED, WINDOW_HEIGHT, WINDOW_WIDTH, @@ -79,48 +79,68 @@ pub fn handle_captured_player( ) { // First, collect data from all captured players let mut to_process = Vec::new(); - + for (entity, transform, captured) in player_query.iter() { // Check if the boss exists let boss_exists = enemy_query.get(captured.boss_entity).is_ok(); let boss_pos = if boss_exists { - enemy_query.get(captured.boss_entity).map(|t| t.translation).ok() + enemy_query + .get(captured.boss_entity) + .map(|t| t.translation) + .ok() } else { None }; - + // Create a copy of the timer to check if it would finish let mut timer_copy = captured.timer.clone(); timer_copy.tick(time.delta()); - - to_process.push((entity, transform.translation, boss_pos, timer_copy.finished())); + + to_process.push(( + entity, + transform.translation, + boss_pos, + timer_copy.finished(), + )); } - + // Now process each player separately for (entity, current_pos, boss_pos_opt, timer_would_finish) in to_process { if let Ok((mut transform, mut captured)) = player_mut_query.get_mut(entity) { // Tick the real timer captured.timer.tick(time.delta()); - + match boss_pos_opt { Some(boss_pos) => { // Boss exists, update player position let target_pos = boss_pos - Vec3::new(0.0, PLAYER_SIZE.y + 10.0, 0.0); transform.translation = current_pos.lerp(target_pos, 0.2); - }, + } None => { // Boss is gone, release player but lose a life println!("Boss is gone, releasing captured player!"); commands.entity(entity).remove::(); - lose_life_and_respawn(&mut commands, &mut lives, &mut respawn_timer, &mut next_state, entity); + lose_life_and_respawn( + &mut commands, + &mut lives, + &mut respawn_timer, + &mut next_state, + entity, + ); } } - + // If capture duration expires, player escapes but loses a life if timer_would_finish || captured.timer.finished() { println!("Player escaped from capture after timer expired!"); commands.entity(entity).remove::(); - lose_life_and_respawn(&mut commands, &mut lives, &mut respawn_timer, &mut next_state, entity); + lose_life_and_respawn( + &mut commands, + &mut lives, + &mut respawn_timer, + &mut next_state, + entity, + ); } } } @@ -137,10 +157,10 @@ fn lose_life_and_respawn( // Lose a life lives.count = lives.count.saturating_sub(1); println!("Lives remaining: {}", lives.count); - + // Destroy player commands.entity(player_entity).despawn(); - + if lives.count > 0 { respawn_timer.timer.reset(); respawn_timer.timer.unpause(); @@ -192,7 +212,10 @@ pub fn check_player_enemy_collisions( mut respawn_timer: ResMut, mut next_state: ResMut>, // Resource to change state // Query player without Invincible component - relies on run_if condition too - player_query: Query<(Entity, &Transform), (With, Without, Without)>, // Don't check collisions for captured players + player_query: Query< + (Entity, &Transform), + (With, Without, Without), + >, // Don't check collisions for captured players enemy_query: Query<(Entity, &Transform), With>, ) { // This system only runs if player exists and is not invincible, due to run_if @@ -271,4 +294,4 @@ pub fn manage_invincibility( } } } -} \ No newline at end of file +}