139 lines
4.3 KiB
Rust
139 lines
4.3 KiB
Rust
use std::time::Duration;
|
|
|
|
use bevy::prelude::{Quat, Transform, Vec2, Vec3};
|
|
use bevy_prototype_lyon::prelude::Path;
|
|
use bevy_tweening::{
|
|
lens::{TransformPositionLens, TransformRotateZLens},
|
|
Animator, EaseFunction, Tween,
|
|
};
|
|
|
|
use crate::{
|
|
datatypes::angle::Angle,
|
|
primitives::{
|
|
animation::{CircleAnimationLens, CircleMovementLens, LineAnimationLens},
|
|
bundles::{TurtleDrawCircle, TurtleDrawLine},
|
|
},
|
|
turtle::{Precision, TurtleGraphElement, TurtleState},
|
|
};
|
|
|
|
pub struct TurtleStep {
|
|
pub turtle_animation: Option<Tween<Transform>>,
|
|
pub line_segment: Option<TurtleGraphElement>,
|
|
pub line_animation: Option<Animator<Path>>,
|
|
}
|
|
|
|
pub fn turtle_turn(state: &mut TurtleState, angle_to_turn: Angle<Precision>) -> TurtleStep {
|
|
let start = state.heading;
|
|
let end = state.heading + angle_to_turn;
|
|
let animation = Tween::new(
|
|
EaseFunction::QuadraticInOut,
|
|
Duration::from_millis(state.speed),
|
|
TransformRotateZLens {
|
|
start: start.to_radians().value(),
|
|
end: end.to_radians().value(),
|
|
},
|
|
)
|
|
.with_completed_event(state.index as u64);
|
|
// Don't draw as the position does not change
|
|
let line = TurtleGraphElement::Noop;
|
|
// Update the state
|
|
state.heading = end.limit_smaller_than_full_circle();
|
|
TurtleStep {
|
|
turtle_animation: Some(animation),
|
|
line_segment: Some(line),
|
|
line_animation: None,
|
|
}
|
|
}
|
|
|
|
pub fn turtle_move(state: &mut TurtleState, length: Precision) -> TurtleStep {
|
|
let start = state.start;
|
|
let end = state.start + (Vec2::from_angle(state.heading.to_radians().value()) * length);
|
|
let turtle_movement_animation = Tween::new(
|
|
EaseFunction::QuadraticInOut,
|
|
Duration::from_millis(state.speed),
|
|
TransformPositionLens {
|
|
start: start.extend(0.),
|
|
end: end.extend(0.),
|
|
},
|
|
)
|
|
.with_completed_event(state.index as u64);
|
|
let line = if state.drawing {
|
|
TurtleGraphElement::TurtleLine(TurtleDrawLine::new(start, end, state.index))
|
|
} else {
|
|
TurtleGraphElement::Noop
|
|
};
|
|
let line_animator = Animator::new(Tween::new(
|
|
EaseFunction::QuadraticInOut,
|
|
Duration::from_millis(state.speed),
|
|
LineAnimationLens::new(start, end),
|
|
));
|
|
state.start = end;
|
|
TurtleStep {
|
|
turtle_animation: Some(turtle_movement_animation),
|
|
line_segment: Some(line),
|
|
line_animation: Some(line_animator),
|
|
}
|
|
}
|
|
|
|
pub fn turtle_circle(
|
|
state: &mut TurtleState,
|
|
radius: Precision,
|
|
angle: Angle<Precision>,
|
|
) -> TurtleStep {
|
|
let radii = Vec2::ONE * radius.abs();
|
|
let left_right = Angle::degrees(if radius >= 0. { 90. } else { -90. });
|
|
let center = state.start
|
|
+ (Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle(
|
|
((state.heading + left_right).to_radians()).value(),
|
|
)));
|
|
|
|
let turtle_movement_animation = Tween::new(
|
|
EaseFunction::QuadraticInOut,
|
|
Duration::from_millis(state.speed),
|
|
CircleMovementLens {
|
|
start: Transform {
|
|
translation: state.start.extend(0.),
|
|
rotation: Quat::from_rotation_z(state.heading.to_radians().value()),
|
|
scale: Vec3::ONE,
|
|
},
|
|
end: angle,
|
|
center,
|
|
},
|
|
)
|
|
.with_completed_event(state.index as u64);
|
|
let end_pos = center
|
|
+ Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle(
|
|
(state.heading + angle - left_right).to_radians().value(),
|
|
));
|
|
let line = if state.drawing {
|
|
TurtleGraphElement::TurtleCircle(TurtleDrawCircle::new(
|
|
center,
|
|
radii,
|
|
Angle::degrees(0.),
|
|
state.index,
|
|
state.start,
|
|
end_pos,
|
|
))
|
|
} else {
|
|
TurtleGraphElement::Noop
|
|
};
|
|
let line_animator = Animator::new(Tween::new(
|
|
EaseFunction::QuadraticInOut,
|
|
Duration::from_millis(state.speed),
|
|
CircleAnimationLens {
|
|
start_pos: state.start,
|
|
center,
|
|
radii,
|
|
start: Angle::degrees(0.),
|
|
end: angle,
|
|
},
|
|
));
|
|
state.start = end_pos;
|
|
state.heading = state.heading + angle;
|
|
TurtleStep {
|
|
turtle_animation: Some(turtle_movement_animation),
|
|
line_segment: Some(line),
|
|
line_animation: Some(line_animator),
|
|
}
|
|
}
|