diff --git a/src/states/linear/components.rs b/src/states/linear/components.rs new file mode 100644 index 0000000..8fb44ec --- /dev/null +++ b/src/states/linear/components.rs @@ -0,0 +1,4 @@ +use bevy::prelude::*; + +#[derive(Component)] +pub struct LinearStateMarker; \ No newline at end of file diff --git a/src/states/linear/components_track.rs b/src/states/linear/components_track.rs new file mode 100644 index 0000000..36ab136 --- /dev/null +++ b/src/states/linear/components_track.rs @@ -0,0 +1,17 @@ +use bevy::prelude::*; + +#[derive(Component)] +pub struct Track{ + pub start_point: Vec2, + pub start_direction: Vec2, // будет нормализовано при построении + pub segments: Vec, +} + +// линия всегда строится от точки старта по направлению +// направление изменяется сегментами поворота +// left при истине - поворот против часовой стрелки, ложь - по часовой +#[derive(Clone, Copy)] +pub enum PathSegment{ + Line { length: f32 }, + Turn { radius: f32, left: bool }, +} \ No newline at end of file diff --git a/src/states/linear/mod.rs b/src/states/linear/mod.rs new file mode 100644 index 0000000..c9c5a5f --- /dev/null +++ b/src/states/linear/mod.rs @@ -0,0 +1,13 @@ +pub mod plugin; + +mod components; +pub use components::*; + +mod systems; +pub use systems::*; + +mod components_track; +pub use components_track::*; + +mod systems_track; +pub use systems_track::*; diff --git a/src/states/linear/plugin.rs b/src/states/linear/plugin.rs new file mode 100644 index 0000000..d1b4e7f --- /dev/null +++ b/src/states/linear/plugin.rs @@ -0,0 +1,22 @@ +use bevy::prelude::*; +use crate::states::AppState::LinearState; +use crate::states::linear::*; + +pub struct LinearPlugin; + +impl Plugin for LinearPlugin { + fn build(&self, app: &mut App) { + app + .add_systems(OnEnter (LinearState), (setup, setup_linear_track).chain()) + .add_systems(Update, (draw_track_gizmos).run_if(in_state(LinearState))) + .add_systems(OnExit (LinearState), cleanup); + } +} + +fn setup(mut commands: Commands) {} + +fn cleanup(mut commands: Commands, query: Query>) { + for entity in query.iter() { + commands.entity(entity).despawn(); + } +} \ No newline at end of file diff --git a/src/states/linear/systems.rs b/src/states/linear/systems.rs new file mode 100644 index 0000000..ab89b70 --- /dev/null +++ b/src/states/linear/systems.rs @@ -0,0 +1,60 @@ +use crate::states; +use bevy::prelude::*; +use states::linear::*; +use std::f32::consts::{FRAC_PI_2, PI}; + +const PINK: Color = Color::srgb_u8(250, 0, 155); +const BLUE: Color = Color::srgb_u8(0, 0, 255); +const GREEN: Color = Color::srgb_u8(0, 255, 0); + +pub fn draw_track_gizmos(query: Query<&Track>, mut gizmos: Gizmos) { + println!("Рисуем трек из примитивов"); + for track in &query { + let mut current_pos = track.start_point; + let mut current_dir = track.start_direction.normalize(); + + // точка старта + gizmos.circle_2d(current_pos, 5.0, BLUE); + + // рисуем сегменты + for segment in &track.segments { + match segment { + PathSegment::Line { length } => { + let end_pos = current_pos + current_dir * length; + gizmos.line_2d(current_pos, end_pos, PINK); + current_pos = end_pos + } + + PathSegment::Turn { radius, left } => { + // вычисляем направление поворота и знак для угла + let (normal, sign): (Vec2, f32) = if *left { + (Vec2::new(-current_dir.y, current_dir.x), -1.0) + } else { + (Vec2::new(current_dir.y, -current_dir.x), 1.0) + }; + + let center = current_pos + normal * radius; + let start_vec = current_pos - center; + let initial_vec = if *left { + -start_vec.perp() + } else { + -start_vec + }; + + gizmos.arc_2d( + Isometry2d::new(center, Rot2::radians(initial_vec.to_angle())), + FRAC_PI_2, + *radius, + GREEN, + ); + // current_pos = center + current_dir * radius; + // current_pos = center + normal.perp() * radius; + current_pos = center + normal.perp() * radius * sign; + current_dir = normal; + } + } + } + // рисуем финиш + gizmos.circle_2d(current_pos, 5.0, Color::WHITE); + } +} diff --git a/src/states/linear/systems_track.rs b/src/states/linear/systems_track.rs new file mode 100644 index 0000000..0a223f0 --- /dev/null +++ b/src/states/linear/systems_track.rs @@ -0,0 +1,44 @@ +use crate::states::linear::*; +use crate::{FACTOR, HEIGHT, WIDTH}; +use bevy::prelude::*; + +pub const CENTER_X: f32 = 0.0; +pub const CENTER_Y: f32 = 0.0; + +// pub const FACTOR_RADIUS: f32 = FACTOR as f32 / 2.0; + +pub const STEP: f32 = FACTOR as f32 / SCALE; +pub const SCALE: f32 = 2.0; + + +pub fn setup_linear_track(mut commands: Commands) { + println!("Построение трека начато"); + + commands.spawn(( + Track { + start_point: Vec2 { + x: CENTER_X - FACTOR as f32 * 7.0, + y: CENTER_Y - FACTOR as f32 * 4.0, + }, + start_direction: Vec2::X, + segments: vec![ + PathSegment::Line { length: STEP * 2.0 }, + PathSegment::Turn { radius: STEP, left: true }, + PathSegment::Line { length: STEP }, + PathSegment::Turn { radius: STEP, left: false }, + PathSegment::Line { length: STEP * 10.0 }, + PathSegment::Turn { radius: STEP, left: true }, + PathSegment::Line { length: STEP * 4.0 }, + PathSegment::Turn { radius: STEP, left: true }, + PathSegment::Turn { radius: STEP, left: false }, + PathSegment::Line { length: STEP * 2.0 }, + PathSegment::Turn { radius: STEP, left: true }, + PathSegment::Line { length: STEP * 6.0 }, + PathSegment::Turn { radius: STEP, left: true }, + PathSegment::Line { length: STEP * 1.0 }, + PathSegment::Turn { radius: STEP, left: true }, + ], + }, + LinearStateMarker, + )); +}