diff --git a/src/states/linear/systems_projectile.rs b/src/states/linear/systems_projectile.rs index dc51d2e..60a22a0 100644 --- a/src/states/linear/systems_projectile.rs +++ b/src/states/linear/systems_projectile.rs @@ -1,6 +1,6 @@ use crate::states::linear::*; use crate::{FACTOR, HEIGHT, WIDTH}; -use bevy::asset::AssetServer; +use bevy::asset::{AssetServer, ErasedAssetLoader}; use bevy::math::Vec2; use bevy::prelude::*; use std::f32::consts::{FRAC_PI_2, PI}; @@ -46,32 +46,7 @@ pub fn calculate_projectile_hits( // сортируем от ближайшего t к дальнему intersections.sort_by(|a, b| a.t.partial_cmp(&b.t).unwrap()); - - // // если есть точки пересечения - // if let Some(closest_hit) = intersections.first() { - // // собираем шарики - // let mut occupied: Vec = balls_on_track.iter().map(|b| b.track_progress).collect(); - // // сортируем прогресс для дальнейших вычислений - // occupied.sort_by(|a, b| a.partial_cmp(b).unwrap()); - // - // //считаем прогресс для точки попадания через мировые координаты и индекс сегмента на треке - // let hit_progress = calculate_progress(closest_hit, &track); - // - // let radius_norm = BALL_RADIUS / track.total_length; - // if is_occupied(hit_progress, &occupied, radius_norm) { - // proj.hit_result = Some(ProjectileHit { - // hit_progress, - // hit_position: closest_hit.world_pos, - // segment_index: closest_hit.segment_index, - // }); - // println!("Попадание в трек: {}", hit_progress); - // transform.translation = closest_hit.world_pos.extend(transform.translation.z); - // // убираем маркер поиска, добавляем маркер готовности ко вставке для другой системы - // commands - // .entity(entity) - // .remove::() - // .insert(InsertMarker); - // } + let mut occupied: Vec = balls_on_track.iter().map(|b| b.track_progress).collect(); occupied.sort_by(|a, b| a.partial_cmp(b).unwrap()); let radius_norm = BALL_RADIUS / track.total_length; @@ -95,9 +70,6 @@ pub fn calculate_projectile_hits( }); // записываем координаты точки попадания, до которой летит шарик - // вероятен момент, когда шарик летит, а в точке пересечения появится шарики на треке - // если вылезет такое, пофиксить через проверку всех точек пересечения, а не только - // конкретной, которая тут записана proj.target_position = Some(target_inter.world_pos); // Переключаем маркер: больше не ищем, готовы к вставке @@ -310,75 +282,55 @@ fn is_occupied(target: f32, occupied: &[f32], radius_norm: f32) -> bool { pub fn insert_projectile_into_track( mut commands: Commands, mut projectiles: Query<(Entity, &RoundBallProjectile), With>, - mut balls_on_track: Query<(Entity, &mut RoundBall)>, + mut balls_on_track: Query<(Entity, &mut RoundBall, &Transform)>, track: Res, asset_server: Res, ) { for (proj_entity, proj) in projectiles.iter_mut() { - let Some(hit) = proj.hit_result else { - continue; - }; + // let Some(hit) = proj.hit_result else { continue }; // артефактный код, пока просто закоментил + let proj_pos = proj.previous_position; - let Some(target_pos) = proj.target_position else { continue }; - let distance = proj.previous_position.distance(target_pos); + // ищем любой шарик, до которого снаряд долетел визуально + let mut target_found = None; + for (ball_entity, ball, ball_tf) in balls_on_track.iter() { + let ball_pos = ball_tf.translation.truncate(); + let distance = proj_pos.distance(ball_pos); - // расстояние, при котором встраивается шарик - const ARRIVAL_DIST: f32 = 5.0; - - if distance > ARRIVAL_DIST { - continue; + if distance < BALL_COLLISION_THRESHOLD { + target_found = Some((ball_entity, ball.track_progress, ball_pos)); + break; // нашли первую коллизию - дальше не ищем + } } - - // ищем шарик, в который попали (цель) - // собираем данные, чтобы не конфликтовать с мутабельным доступом ниже - let mut balls_data: Vec<_> = balls_on_track - .iter() - .map(|(entity, ball)| (entity, ball.track_progress)) - .collect(); - - // сортируем по близости к точке удара - balls_data.sort_by(|a, b| { - let diff_a = (a.1 - hit.hit_progress).abs(); - let diff_b = (b.1 - hit.hit_progress).abs(); - diff_a.partial_cmp(&diff_b).unwrap() - }); - - let Some((target_entity, original_target_progress)) = balls_data.first() else { - continue; - }; - // копируем значение - let original_progress = *original_target_progress; - - // размер сдвига посчитан в треке - let shift = track.min_spawn_gap; - // ставим на место шарика-цели, а сам шарик-цель сдвигаем вперед по треку - for (entity, mut ball) in balls_on_track.iter_mut() { - if entity == *target_entity { - ball.track_progress = (original_progress + shift).clamp(0.0, 1.0); + // target_entity - артефактный код, пока просто закоментил + let Some((target_entity, original_progress, target_ball_pos)) = target_found else { + continue; // ни с одним шариком не столкнулся - летит дальше + }; + + // entity - артефактный код, пока просто закоментил + // сдвигаем только те шарики, которые находятся после точки вставки + for (entity, mut ball, _) in balls_on_track.iter_mut() { + if ball.track_progress >= original_progress { + ball.track_progress = (ball.track_progress + track.min_spawn_gap).clamp(0.0, 1.0); } } - for (entity, mut ball) in balls_on_track.iter_mut() { - ball.track_progress = (ball.track_progress + shift).clamp(0.0, 1.0); - } - - // спавним новый шарик на месте цели + // спавним новый шарик ровно в позицию целевого commands.spawn(( Sprite { image: asset_server.load(proj.ball_type.asset_path()), custom_size: Some(Vec2::splat(ROUND_BALL_SIZE)), ..default() }, - Transform::from_translation(hit.hit_position.extend(ROUND_BALL_Z)), + Transform::from_translation(target_ball_pos.extend(ROUND_BALL_Z)), RoundBall { ball_type: proj.ball_type, - track_progress: original_progress, + track_progress: original_progress, // занимает место шарика, в который попали }, LinearStateMarker, + HitMarker, // маркер для системы уничтожения шариков )); - // деспавн шарика-снаряда commands.entity(proj_entity).despawn(); } -} +} \ No newline at end of file