diff --git a/snake-game/src/startup.rs b/snake-game/src/startup.rs index df60d3a..e519891 100644 --- a/snake-game/src/startup.rs +++ b/snake-game/src/startup.rs @@ -20,7 +20,7 @@ pub fn startup(mut commands: Commands) { commands.insert_resource(ClearColor(SKY_600.into())); commands.insert_resource(SnakePath::default()); - // commands.spawn(Observer::new(crate::observers::clean_snake_path)); + commands.spawn(Observer::new(crate::observers::clean_snake_path)); commands.spawn(Observer::new(crate::observers::grow_up_snake)); commands.spawn(Observer::new(crate::observers::handle_collisions)); diff --git a/snake-game/src/tools.rs b/snake-game/src/tools.rs index 91564f0..bc1609c 100644 --- a/snake-game/src/tools.rs +++ b/snake-game/src/tools.rs @@ -33,29 +33,46 @@ pub fn define_log_layer() -> Option { } /// Разбиение изменения координаты по границам сетки +/// Элементы выходного вектора представляют пары значений, где первое обозначает промежуточное значение координаты, +/// а второе - изменение координаты относительно предыдущего значения (дельта). +/// Если движение начинается на границе сетки и оно не нулевое (начальное и конечное значение координвты отличаются), +/// то размер выходного вектора всегда больше 1 и второе значение первой пары (дельта) равно 0. +/// На основе этой логики происходит в дальнейшем распознавание момента прохождения узла сетки и генерируется соответствующее событие. pub fn split_by_grid(src: f32, dst: f32, grid: f32) -> Vec<(f32, f32)> { + if dst == src { + return vec![(dst, 0.0)]; + } if grid <= 0.0 { return vec![(dst, dst - src)]; }; - let old_grid = src / grid; - let new_grid = dst / grid; - - let old_grid_right = old_grid.ceil(); - let new_grid_right = new_grid.ceil(); - let mut output = Vec::with_capacity(2); if src < dst { + let src_grid = src / grid; + let dst_grid = dst / grid; + + let src_grid_right = src_grid.ceil(); + let dst_grid_left = dst_grid.floor(); + let mut src: f32 = src; - for step in old_grid_right as i32..new_grid_right as i32 { + for step in src_grid_right as i32..=dst_grid_left as i32 { let step = step as f32 * grid; output.push((step, step - src)); src = step; } - output.push((dst, dst - src)); + if src != dst { + output.push((dst, dst - src)); + } } else { + let src_grid = src / grid; + let dst_grid = dst / grid; + + let dst_grid_right = dst_grid.ceil(); + let dst_grid_right = if dst_grid_right == dst { dst_grid_right + 1.0 } else { dst_grid_right }; + let src_grid_left = src_grid.floor(); + let mut dst: f32 = dst; - for step in new_grid_right as i32..old_grid_right as i32 { + for step in dst_grid_right as i32..=src_grid_left as i32 { let step = step as f32 * grid; output.push((dst, dst - step)); dst = step; @@ -84,9 +101,9 @@ mod test { // движение влево assert_eq!(split_by_grid(4.0, 1.0, 5.0), vec![(1.0, -3.0)]); - assert_eq!(split_by_grid(5.0, 3.0, 5.0), vec![(3.0, -2.0)]); + assert_eq!(split_by_grid(5.0, 3.0, 5.0), vec![(5.0, 0.0), (3.0, -2.0)]); assert_eq!(split_by_grid(6.0, 3.0, 5.0), vec![(5.0, -1.0), (3.0, -2.0)]); - assert_eq!(split_by_grid(10.0, 3.0, 5.0), vec![(5.0, -5.0), (3.0, -2.0)]); + assert_eq!(split_by_grid(10.0, 3.0, 5.0), vec![(10.0, 0.0), (5.0, -5.0), (3.0, -2.0)]); assert_eq!(split_by_grid(11.0, 3.0, 5.0), vec![(10.0, -1.0), (5.0, -5.0), (3.0, -2.0)]); assert_eq!(split_by_grid(3.0, -2.0, 5.0), vec![(0.0, -3.0), (-2.0, -2.0)]); assert_eq!(split_by_grid(7.0, -6.0, 5.0), vec![(5.0, -2.0), (0.0, -5.0), (-5.0, -5.0), (-6.0, -1.0)]); @@ -96,17 +113,15 @@ mod test { assert_eq!(split_by_grid(1.0, 4.0, 0.0), vec![(4.0, 3.0)]); assert_eq!(split_by_grid(4.0, 1.0, 0.0), vec![(1.0, -3.0)]); - // Сценарии со стартом в узле сетки + // сценарии со стартом в узле сетки assert_eq!(split_by_grid(0.0, 1.5, 5.0), vec![(0.0, 0.0), (1.5, 1.5)]); assert_eq!(split_by_grid(5.0, 7.0, 5.0), vec![(5.0, 0.0), (7.0, 2.0)]); assert_eq!(split_by_grid(0.0, -1.5, 5.0), vec![(0.0, 0.0), (-1.5, -1.5)]); assert_eq!(split_by_grid(5.0, 3.0, 5.0), vec![(5.0, 0.0), (3.0, -2.0)]); - } - #[test] - fn debug_split_by_grid() { - assert_eq!(split_by_grid(0.0, -1.5, 5.0), vec![(0.0, 0.0), (-1.5, -1.5)]); - // assert_eq!(split_by_grid(0.0, -1.0, 5.0), vec![(0.0, 0.0), (-1.0, -1.0)]); - // assert_eq!(split_by_grid(-5.0, -6.0, 5.0), vec![(-5.0, 0.0), (-6.0, -1.0)]); + // сценарии с нулевым движением + assert_eq!(split_by_grid(5.0, 5.0, 5.0), vec![(5.0, 0.0)]); + assert_eq!(split_by_grid(0.0, 0.0, 5.0), vec![(0.0, 0.0)]); + assert_eq!(split_by_grid(0.0, 0.0, 0.0), vec![(0.0, 0.0)]); } }