Merge branch 'main' of github.com:Back777space/among-me

This commit is contained in:
LorrensP-2158466
2025-04-06 23:18:14 +02:00
3 changed files with 54 additions and 41 deletions

View File

@@ -164,7 +164,7 @@ fn spawn_level(
pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())),
), ),
( (
round_door.clone(), door.clone(),
pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())), pos.with_rotation(Quat::from_rotation_y(180.0_f32.to_radians())),
), ),
( (
@@ -180,7 +180,7 @@ fn spawn_level(
pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())),
), ),
( (
round_door.clone(), door.clone(),
pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())), pos.with_rotation(Quat::from_rotation_y(0.0_f32.to_radians())),
), ),
( (
@@ -193,7 +193,7 @@ fn spawn_level(
vec![ vec![
(wall.clone(), pos), (wall.clone(), pos),
( (
round_door.clone(), door.clone(),
pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())), pos.with_rotation(Quat::from_rotation_y(90.0_f32.to_radians())),
), ),
( (
@@ -206,7 +206,7 @@ fn spawn_level(
vec![ vec![
(wall.clone(), pos), (wall.clone(), pos),
( (
round_door.clone(), door.clone(),
pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())), pos.with_rotation(Quat::from_rotation_y(270.0_f32.to_radians())),
), ),
( (

View File

@@ -1,7 +1,7 @@
use std::time::Duration; use std::time::Duration;
use bevy::{ use bevy::{
prelude::*, prelude::*,
time::Stopwatch, time::Stopwatch,
}; };
use bevy_kira_audio::{prelude::Volume, Audio, AudioControl, AudioTween}; use bevy_kira_audio::{prelude::Volume, Audio, AudioControl, AudioTween};
@@ -27,7 +27,7 @@ pub struct Monster {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum MonsterState { pub enum MonsterState {
Lurking, Lurking,
Hunting, Hunting,
Wandering, Wandering,
Dormant, Dormant,
} }
@@ -74,7 +74,7 @@ fn spawn_monster(
// mut materials: ResMut<Assets<StandardMaterial>>, // mut materials: ResMut<Assets<StandardMaterial>>,
) { ) {
let spawn_position = Vec3::new(20.0, 0.5, 20.0); let spawn_position = Vec3::new(20.0, 0.5, 20.0);
commands.spawn(( commands.spawn((
Monster::default(), Monster::default(),
MonsterPathfinding { MonsterPathfinding {
@@ -100,16 +100,16 @@ fn update_monster_state(
player_query: Query<&Transform, With<Player>>, player_query: Query<&Transform, With<Player>>,
) { ) {
let mut rand = rand::rng(); let mut rand = rand::rng();
if let Ok((mut monster, monster_transform, mut pathfinding, mut danger)) = monster_query.get_single_mut() { if let Ok((mut monster, monster_transform, mut pathfinding, mut danger)) = monster_query.get_single_mut() {
let player_pos = if let Ok(player_transform) = player_query.get_single() { let player_pos = if let Ok(player_transform) = player_query.get_single() {
Some(player_transform.translation) Some(player_transform.translation)
} else { } else {
None None
}; };
monster.state_timer.tick(time.delta()); monster.state_timer.tick(time.delta());
// when timer expires, potentially change state // when timer expires, potentially change state
if monster.state_timer.just_finished() { if monster.state_timer.just_finished() {
let next_state = match monster.state { let next_state = match monster.state {
@@ -150,7 +150,7 @@ fn update_monster_state(
MonsterState::Dormant MonsterState::Dormant
} }
}; };
// set state // set state
monster.state = next_state.clone(); monster.state = next_state.clone();
monster.state_timer = match next_state { monster.state_timer = match next_state {
@@ -159,16 +159,16 @@ fn update_monster_state(
MonsterState::Wandering => Timer::from_seconds(30.0, TimerMode::Once), MonsterState::Wandering => Timer::from_seconds(30.0, TimerMode::Once),
MonsterState::Hunting => Timer::from_seconds(15.0, TimerMode::Once), MonsterState::Hunting => Timer::from_seconds(15.0, TimerMode::Once),
}; };
// reset pathfinding when state changes // reset pathfinding when state changes
pathfinding.current_target = None; pathfinding.current_target = None;
println!("new state={:?}", monster.state); println!("new state={:?}", monster.state);
} }
// override state in some cases // override state in some cases
if let Some(player_pos) = player_pos { if let Some(player_pos) = player_pos {
let distance = monster_transform.translation.distance(player_pos); let distance = monster_transform.translation.distance(player_pos);
// if player is very close and monster isn't hunting, switch to hunting // if player is very close and monster isn't hunting, switch to hunting
if distance < monster.detection_range * 0.5 && monster.state != MonsterState::Hunting { if distance < monster.detection_range * 0.5 && monster.state != MonsterState::Hunting {
if rand.random_bool(0.75) { // 75% chance to notice player if rand.random_bool(0.75) { // 75% chance to notice player
@@ -178,7 +178,7 @@ fn update_monster_state(
pathfinding.current_target = None; pathfinding.current_target = None;
} }
} }
} }
} }
} }
@@ -188,10 +188,10 @@ fn move_monster(
player_query: Query<&Transform, With<Player>>, player_query: Query<&Transform, With<Player>>,
) { ) {
let mut rand = rand::rng(); let mut rand = rand::rng();
if let Ok((monster, mut transform, mut velocity, mut pathfinding)) = monster_query.get_single_mut() { if let Ok((monster, mut transform, mut velocity, mut pathfinding)) = monster_query.get_single_mut() {
pathfinding.wander_target_timer.tick(time.delta()); pathfinding.wander_target_timer.tick(time.delta());
// move based on state // move based on state
match monster.state { match monster.state {
MonsterState::Dormant => { MonsterState::Dormant => {
@@ -206,17 +206,17 @@ fn move_monster(
0.0, 0.0,
rand.random_range(-range..range) rand.random_range(-range..range)
); );
let base_pos = if let Ok(player_transform) = player_query.get_single() { let base_pos = if let Ok(player_transform) = player_query.get_single() {
player_transform.translation player_transform.translation
} else { } else {
transform.translation transform.translation
}; };
pathfinding.current_target = Some(base_pos + random_offset); pathfinding.current_target = Some(base_pos + random_offset);
pathfinding.wander_target_timer = Timer::from_seconds(10.0, TimerMode::Once); pathfinding.wander_target_timer = Timer::from_seconds(10.0, TimerMode::Once);
} }
// move toward target at slow pace // move toward target at slow pace
if let Some(target) = pathfinding.current_target { if let Some(target) = pathfinding.current_target {
move_towards_target(&mut transform, &mut velocity, target, monster.speed * 0.65); move_towards_target(&mut transform, &mut velocity, target, monster.speed * 0.65);
@@ -232,12 +232,12 @@ fn move_monster(
0.0, 0.0,
rand.random_range(-range..range) rand.random_range(-range..range)
); );
pathfinding.current_target = Some(player_transform.translation + random_offset); pathfinding.current_target = Some(player_transform.translation + random_offset);
pathfinding.wander_target_timer = Timer::from_seconds(7.0, TimerMode::Once); pathfinding.wander_target_timer = Timer::from_seconds(7.0, TimerMode::Once);
} }
} }
// move toward target at medium pace // move toward target at medium pace
if let Some(target) = pathfinding.current_target { if let Some(target) = pathfinding.current_target {
move_towards_target(&mut transform, &mut velocity, target, monster.speed * 0.85); move_towards_target(&mut transform, &mut velocity, target, monster.speed * 0.85);
@@ -247,9 +247,9 @@ fn move_monster(
// chase the motherfucker // chase the motherfucker
if let Ok(player_transform) = player_query.get_single() { if let Ok(player_transform) = player_query.get_single() {
move_towards_target( move_towards_target(
&mut transform, &mut transform,
&mut velocity, &mut velocity,
player_transform.translation, player_transform.translation,
monster.speed * 1.1 monster.speed * 1.1
); );
} }
@@ -267,7 +267,7 @@ fn move_towards_target(
let direction = (target - transform.translation).normalize_or_zero(); let direction = (target - transform.translation).normalize_or_zero();
let direction = Vec3::new(direction.x, 0.0, direction.z).normalize_or_zero(); let direction = Vec3::new(direction.x, 0.0, direction.z).normalize_or_zero();
velocity.linvel = direction * speed; velocity.linvel = direction * speed;
if direction.length_squared() > 0.01 { if direction.length_squared() > 0.01 {
let look_direction = Vec3::new(direction.x, 0.0, direction.z).normalize_or_zero(); let look_direction = Vec3::new(direction.x, 0.0, direction.z).normalize_or_zero();
if look_direction != Vec3::ZERO { if look_direction != Vec3::ZERO {
@@ -285,33 +285,43 @@ fn play_monster_sounds(
player_query: Query<&Transform, With<Player>>, player_query: Query<&Transform, With<Player>>,
) { ) {
let mut rand = rand::rng(); let mut rand = rand::rng();
if let (Ok((mut monster, monster_transform)), Ok(player_transform)) = if let (Ok((mut monster, monster_transform)), Ok(player_transform)) =
(monster_query.get_single_mut(), player_query.get_single()) { (monster_query.get_single_mut(), player_query.get_single()) {
monster.footstep_timer.tick(time.delta()); monster.footstep_timer.tick(time.delta());
let distance = monster_transform.translation.distance(player_transform.translation); let distance = monster_transform.translation.distance(player_transform.translation);
// play footstep sound if the timer finished // play footstep sound if the timer finished
if monster.footstep_timer.just_finished() { if monster.footstep_timer.just_finished() {
match monster.state { match monster.state {
MonsterState::Hunting => { MonsterState::Hunting => {
monster.footstep_timer = Timer::from_seconds(1.5, TimerMode::Once); monster.footstep_timer = Timer::from_seconds(10.0, TimerMode::Once);
monster.speed = 2.0
}, },
MonsterState::Lurking | MonsterState::Wandering => { MonsterState::Lurking | MonsterState::Wandering => {
monster.footstep_timer = Timer::from_seconds( monster.footstep_timer = Timer::from_seconds(
rand.random_range(3.0..7.0), 10.0,
TimerMode::Once TimerMode::Once
); );
monster.speed = 1.0
}, },
MonsterState::Dormant => { MonsterState::Dormant => {
monster.footstep_timer = Timer::from_seconds( monster.footstep_timer = Timer::from_seconds(
rand.random_range(10.0..20.0), 10.0,
TimerMode::Once TimerMode::Once
); );
monster.speed = 0.0
} }
} }
play_footstep_segment(audio, &audio_assets, distance, &monster.state, monster.footstep_timer.duration().as_secs_f32()); play_footstep_segment(
audio,
&audio_assets,
distance,
&monster.state,
monster.footstep_timer.duration().as_secs_f32(),
monster.speed
);
if monster.state == MonsterState::Hunting && rand.random_bool(0.3) { if monster.state == MonsterState::Hunting && rand.random_bool(0.3) {
println!("Monster growl!"); println!("Monster growl!");
@@ -325,7 +335,8 @@ fn play_footstep_segment(
audio_assets: &Res<AudioAssets>, audio_assets: &Res<AudioAssets>,
distance: f32, distance: f32,
state: &MonsterState, state: &MonsterState,
dur: f32 dur: f32,
speed: f32
) { ) {
let base_volume: f32 = match state { let base_volume: f32 = match state {
MonsterState::Dormant => 0.6, MonsterState::Dormant => 0.6,
@@ -333,23 +344,25 @@ fn play_footstep_segment(
MonsterState::Wandering => 0.8, MonsterState::Wandering => 0.8,
MonsterState::Hunting => 1.0, MonsterState::Hunting => 1.0,
}; };
// adjust volume based on distance (closer = louder) // adjust volume based on distance (closer = louder)
let distance_factor: f32 = 1.0 - (distance / 100.0).clamp(0.0, 1.0); let distance_factor: f32 = (1.0 - distance / 30.0).clamp(0.0, 1.0);
let volume = base_volume * distance_factor; let volume = base_volume * distance_factor;
// play only a short segment of the footstep sound // play only a short segment of the footstep sound
// by only playing the last part // by only playing the last part
let mut start_time = 30.0 - dur; let mut start_time = 30.0 - dur;
// let mut rand = rand::rng(); // let mut rand = rand::rng();
// start_time += rand.random_range(0.0..5.0); // start_time += rand.random_range(0.0..5.0);
audio.stop();
audio.play(audio_assets.monster_footsteps.clone()) audio.play(audio_assets.monster_footsteps.clone())
.with_volume(volume as f64) .with_volume(volume as f64)
.start_from((start_time as f64).min(27.0)) .start_from((start_time as f64).min(27.0))
.fade_in(AudioTween::linear(Duration::from_millis(100))) .fade_in(AudioTween::linear(Duration::from_millis(100)))
.with_playback_rate(speed as f64)
.handle(); .handle();
println!("Monster footstep: State={:?}, Distance={:.2}, Volume={:.2}, Dur={:1}, Start={:1}", println!("Monster footstep: State={:?}, Distance={:.2}, Volume={:.2}, Dur={:1}, Start={:1}",
state, distance, volume, dur, (start_time as f64).min(27.0)); state, distance, volume, dur, (start_time as f64).min(27.0));
} }

View File

@@ -457,9 +457,9 @@ pub fn handle_spotlight(
pub fn update_flashlight_charge(time: Res<Time>, mut flashlight_query: Query<&mut Flashlight>) { pub fn update_flashlight_charge(time: Res<Time>, mut flashlight_query: Query<&mut Flashlight>) {
for mut flashlight in flashlight_query.iter_mut() { for mut flashlight in flashlight_query.iter_mut() {
if flashlight.is_on { if flashlight.is_on {
flashlight.charge = flashlight.charge - time.delta_secs() * 0.1; flashlight.charge = flashlight.charge - time.delta_secs() * 0.2;
} else { } else {
flashlight.charge = flashlight.charge + time.delta_secs() * 0.1; flashlight.charge = flashlight.charge + time.delta_secs() * 0.2;
} }
flashlight.charge = flashlight.charge.clamp(0.0, 4.0); flashlight.charge = flashlight.charge.clamp(0.0, 4.0);
if flashlight.charge <= 0.0 { if flashlight.charge <= 0.0 {