Finalize the circle command

This commit is contained in:
Dietrich 2022-08-22 14:17:26 +02:00
parent d16607ff4d
commit d8a5c67fd5
Signed by: dietrich
GPG Key ID: F0CE5A20AB5C4B27
6 changed files with 89 additions and 27 deletions

8
Cargo.lock generated
View File

@ -2933,18 +2933,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.143" version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.143" version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -8,9 +8,9 @@ default-run = "turtlers"
[dependencies] [dependencies]
bevy = { version = "0.8", features = ["dynamic"] } bevy = { version = "0.8", features = ["dynamic"] }
bevy-inspector-egui = "0.12.1" bevy-inspector-egui = "0.12"
bevy_prototype_lyon = "0.6" bevy_prototype_lyon = "0.6"
bevy_tweening = "0.5.0" bevy_tweening = "0.5"
num-traits = "0.2" num-traits = "0.2"
# Enable a small amount of optimization in debug mode # Enable a small amount of optimization in debug mode

1
TODO.md Normal file
View File

@ -0,0 +1 @@
*[x] Fix orientation after and during circles

View File

@ -1,5 +1,8 @@
use bevy_inspector_egui::Inspectable; use bevy_inspector_egui::Inspectable;
use std::ops::{Add, Div, Mul, Neg, Rem, Sub}; use std::{
f32::consts::PI,
ops::{Add, Div, Mul, Neg, Rem, Sub},
};
#[derive(Inspectable, Copy, Clone, Debug, PartialEq, Eq)] #[derive(Inspectable, Copy, Clone, Debug, PartialEq, Eq)]
pub enum AngleUnit<T: Default> { pub enum AngleUnit<T: Default> {
@ -40,6 +43,18 @@ impl<T: Default + Clone + Mul<T, Output = T>> Mul<T> for Angle<T> {
} }
} }
impl Angle<f32> {
pub fn limit_smaller_than_full_circle(self) -> Self {
match self.value {
AngleUnit::Degrees(v) => Self {
value: AngleUnit::Degrees(v % 360.),
},
AngleUnit::Radians(v) => Self {
value: AngleUnit::Radians(v % (2. * PI)),
},
}
}
}
impl<T: Default + Clone + Div<T, Output = T>> Div<T> for Angle<T> { impl<T: Default + Clone + Div<T, Output = T>> Div<T> for Angle<T> {
type Output = Self; type Output = Self;
@ -101,6 +116,14 @@ impl<T: Default + num_traits::float::Float> Angle<T> {
AngleUnit::Radians(_) => self, AngleUnit::Radians(_) => self,
} }
} }
pub fn to_degrees(self) -> Self {
match self.value {
AngleUnit::Degrees(_) => self,
AngleUnit::Radians(v) => Self {
value: AngleUnit::Degrees(v.to_degrees()),
},
}
}
} }
impl<T: Add<Output = T> + Default + num_traits::float::Float> Add for Angle<T> { impl<T: Add<Output = T> + Default + num_traits::float::Float> Add for Angle<T> {

View File

@ -42,12 +42,47 @@ impl Default for Turtle {
fill_color: Color::BLACK, fill_color: Color::BLACK,
}, },
commands: TurtleCommands::new(vec![ commands: TurtleCommands::new(vec![
TurtleCommand::Forward(Length(-100.)),
TurtleCommand::Circle {
radius: Length(150.),
angle: Angle::degrees(30.),
},
TurtleCommand::Forward(Length(100.)), TurtleCommand::Forward(Length(100.)),
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Circle {
radius: Length(20.),
angle: Angle::degrees(324.),
},
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Forward(Length(100.)),
TurtleCommand::Forward(Length(100.)),
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Circle {
radius: Length(20.),
angle: Angle::degrees(324.),
},
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Forward(Length(100.)),
TurtleCommand::Forward(Length(100.)),
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Circle {
radius: Length(20.),
angle: Angle::degrees(324.),
},
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Forward(Length(100.)),
TurtleCommand::Forward(Length(100.)),
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Circle {
radius: Length(20.),
angle: Angle::degrees(324.),
},
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Forward(Length(100.)),
TurtleCommand::Forward(Length(100.)),
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Circle {
radius: Length(20.),
angle: Angle::degrees(324.),
},
TurtleCommand::Right(Angle::degrees(90.)),
TurtleCommand::Forward(Length(100.)),
/* TurtleCommand::Forward(Length(100.)),
TurtleCommand::Circle { TurtleCommand::Circle {
radius: Length(70.), radius: Length(70.),
angle: Angle::degrees(60.), angle: Angle::degrees(60.),
@ -58,7 +93,7 @@ impl Default for Turtle {
TurtleCommand::Circle { TurtleCommand::Circle {
radius: Length(30.), radius: Length(30.),
angle: Angle::degrees(360. - 46.), angle: Angle::degrees(360. - 46.),
}, }, */
/* TurtleCommand::Backward(Length(100.)), /* TurtleCommand::Backward(Length(100.)),
TurtleCommand::Right(Angle(90.)), TurtleCommand::Right(Angle(90.)),
TurtleCommand::Forward(Length(100.)), TurtleCommand::Forward(Length(100.)),
@ -113,6 +148,7 @@ pub struct TurtleCommands {
pub struct TurtleState { pub struct TurtleState {
pub start: Vec2, pub start: Vec2,
pub heading: Angle<f32>, pub heading: Angle<f32>,
pub speed: u64,
pub index: u64, pub index: u64,
pub drawing: bool, pub drawing: bool,
} }
@ -125,6 +161,7 @@ impl TurtleCommands {
state: TurtleState { state: TurtleState {
start: Vec2::ZERO, start: Vec2::ZERO,
heading: Angle::degrees(0.), heading: Angle::degrees(0.),
speed: 2000,
index: 0, index: 0,
drawing: true, drawing: true,
}, },
@ -260,7 +297,7 @@ fn draw_lines(
let line_animator = Animator::new(Tween::new( let line_animator = Animator::new(Tween::new(
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
TweeningType::Once, TweeningType::Once,
Duration::from_millis(500), Duration::from_millis(tcmd.state.speed),
LineAnimationLens::new(start, end), LineAnimationLens::new(start, end),
)); ));
commands commands
@ -278,7 +315,7 @@ fn draw_lines(
let line_animator = Animator::new(Tween::new( let line_animator = Animator::new(Tween::new(
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
TweeningType::Once, TweeningType::Once,
Duration::from_millis(500), Duration::from_millis(tcmd.state.speed),
CircleAnimationLens { CircleAnimationLens {
start_pos: start, start_pos: start,
center, center,
@ -324,6 +361,7 @@ fn keypresses(
tcmd.state = TurtleState { tcmd.state = TurtleState {
start: Vec2::ZERO, start: Vec2::ZERO,
heading: Angle::degrees(0.), heading: Angle::degrees(0.),
speed: 2000,
index: 0, index: 0,
drawing: true, drawing: true,
}; };
@ -335,7 +373,7 @@ fn keypresses(
let line_animator = Animator::new(Tween::new( let line_animator = Animator::new(Tween::new(
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
TweeningType::Once, TweeningType::Once,
Duration::from_millis(500), Duration::from_millis(tcmd.state.speed),
LineAnimationLens::new(start, end), LineAnimationLens::new(start, end),
)); ));
commands commands

View File

@ -17,24 +17,24 @@ pub fn turtle_turn(
angle_to_turn: Angle<f32>, angle_to_turn: Angle<f32>,
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) { ) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
let start = state.heading; let start = state.heading;
let end = state.heading + (angle_to_turn * PI / 180.); let end = state.heading + angle_to_turn;
let animation = Tween::new( let animation = Tween::new(
// Use a quadratic easing on both endpoints // Use a quadratic easing on both endpoints
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
TweeningType::Once, TweeningType::Once,
// Animation time // Animation time
Duration::from_millis(500), Duration::from_millis(state.speed),
// Rotate the turtle // Rotate the turtle
TransformRotateZLens { TransformRotateZLens {
start: start.value(), start: start.to_radians().value(),
end: end.value(), end: end.to_radians().value(),
}, },
) )
.with_completed_event(state.index as u64); .with_completed_event(state.index as u64);
// Dont move and draw // Dont move and draw
let line = TurtleGraphElement::Noop; let line = TurtleGraphElement::Noop;
// Update the state // Update the state
state.heading = end % (2. * PI); state.heading = end.limit_smaller_than_full_circle();
(Some(animation), Some(line)) (Some(animation), Some(line))
} }
@ -49,7 +49,7 @@ pub fn turtle_move(
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
TweeningType::Once, TweeningType::Once,
// later to be controlled by speed // later to be controlled by speed
Duration::from_millis(500), Duration::from_millis(state.speed),
// set the start and end of the animation // set the start and end of the animation
TransformPositionLens { TransformPositionLens {
start: start.extend(0.), start: start.extend(0.),
@ -74,10 +74,9 @@ pub fn turtle_circle(
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) { ) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
let radius_tuple = Vec2::ONE * radius.abs(); let radius_tuple = Vec2::ONE * radius.abs();
let left_right = Angle::degrees(if radius >= 0. { 90. } else { -90. }); let left_right = Angle::degrees(if radius >= 0. { 90. } else { -90. });
println!("Heading: {}", state.heading.value());
let center = state.start let center = state.start
+ (Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle( + (Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle(
(state.heading + left_right.to_radians()).value(), ((state.heading + left_right).to_radians()).value(),
))); )));
let turtle_movement_animation = Tween::new( let turtle_movement_animation = Tween::new(
@ -85,7 +84,7 @@ pub fn turtle_circle(
EaseFunction::QuadraticInOut, EaseFunction::QuadraticInOut,
TweeningType::Once, TweeningType::Once,
// later to be controlled by speed // later to be controlled by speed
Duration::from_millis(500), Duration::from_millis(state.speed),
// set the start and end of the animation // set the start and end of the animation
CircleMovementLens { CircleMovementLens {
start: Transform { start: Transform {
@ -105,15 +104,16 @@ pub fn turtle_circle(
radii: radius_tuple, radii: radius_tuple,
angle, angle,
start: state.start, start: state.start,
end: state.start + 200., end: state.start,
} }
} else { } else {
TurtleGraphElement::Noop TurtleGraphElement::Noop
}; };
let end_pos = center let end_pos = center
+ Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle( + Vec2::new(radius.abs(), 0.).rotate(Vec2::from_angle(
(state.heading + angle).to_radians().value(), (state.heading + angle - left_right).to_radians().value(),
)); ));
state.start = end_pos; state.start = end_pos;
state.heading = state.heading + angle;
(Some(turtle_movement_animation), Some(line)) (Some(turtle_movement_animation), Some(line))
} }