linear track plugin
This commit is contained in:
parent
c1e53bdab0
commit
68c895ec14
6 changed files with 160 additions and 0 deletions
4
src/states/linear/components.rs
Normal file
4
src/states/linear/components.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct LinearStateMarker;
|
||||||
17
src/states/linear/components_track.rs
Normal file
17
src/states/linear/components_track.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Track{
|
||||||
|
pub start_point: Vec2,
|
||||||
|
pub start_direction: Vec2, // будет нормализовано при построении
|
||||||
|
pub segments: Vec<PathSegment>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// линия всегда строится от точки старта по направлению
|
||||||
|
// направление изменяется сегментами поворота
|
||||||
|
// left при истине - поворот против часовой стрелки, ложь - по часовой
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum PathSegment{
|
||||||
|
Line { length: f32 },
|
||||||
|
Turn { radius: f32, left: bool },
|
||||||
|
}
|
||||||
13
src/states/linear/mod.rs
Normal file
13
src/states/linear/mod.rs
Normal file
|
|
@ -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::*;
|
||||||
22
src/states/linear/plugin.rs
Normal file
22
src/states/linear/plugin.rs
Normal file
|
|
@ -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<Entity, With<LinearStateMarker>>) {
|
||||||
|
for entity in query.iter() {
|
||||||
|
commands.entity(entity).despawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
60
src/states/linear/systems.rs
Normal file
60
src/states/linear/systems.rs
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/states/linear/systems_track.rs
Normal file
44
src/states/linear/systems_track.rs
Normal file
|
|
@ -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,
|
||||||
|
));
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue