diff --git a/Cargo.lock b/Cargo.lock index d24aa70..f31c2f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2933,18 +2933,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 8ace4b0..f3eb87b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,9 @@ default-run = "turtlers" [dependencies] bevy = { version = "0.8", features = ["dynamic"] } -bevy-inspector-egui = "0.12.1" +bevy-inspector-egui = "0.12" bevy_prototype_lyon = "0.6" -bevy_tweening = "0.5.0" +bevy_tweening = "0.5" num-traits = "0.2" # Enable a small amount of optimization in debug mode diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..127d397 --- /dev/null +++ b/TODO.md @@ -0,0 +1 @@ +*[x] Fix orientation after and during circles \ No newline at end of file diff --git a/src/datatypes/angle.rs b/src/datatypes/angle.rs index 6a0e7fb..b7b716b 100644 --- a/src/datatypes/angle.rs +++ b/src/datatypes/angle.rs @@ -1,5 +1,8 @@ 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)] pub enum AngleUnit { @@ -40,6 +43,18 @@ impl> Mul for Angle { } } +impl Angle { + 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> Div for Angle { type Output = Self; @@ -101,6 +116,14 @@ impl Angle { 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 + Default + num_traits::float::Float> Add for Angle { diff --git a/src/turtle.rs b/src/turtle.rs index 733f6f8..cb13ff7 100644 --- a/src/turtle.rs +++ b/src/turtle.rs @@ -42,12 +42,47 @@ impl Default for Turtle { fill_color: Color::BLACK, }, commands: TurtleCommands::new(vec![ - TurtleCommand::Forward(Length(-100.)), - TurtleCommand::Circle { - radius: Length(150.), - angle: Angle::degrees(30.), - }, 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 { radius: Length(70.), angle: Angle::degrees(60.), @@ -58,7 +93,7 @@ impl Default for Turtle { TurtleCommand::Circle { radius: Length(30.), angle: Angle::degrees(360. - 46.), - }, + }, */ /* TurtleCommand::Backward(Length(100.)), TurtleCommand::Right(Angle(90.)), TurtleCommand::Forward(Length(100.)), @@ -113,6 +148,7 @@ pub struct TurtleCommands { pub struct TurtleState { pub start: Vec2, pub heading: Angle, + pub speed: u64, pub index: u64, pub drawing: bool, } @@ -125,6 +161,7 @@ impl TurtleCommands { state: TurtleState { start: Vec2::ZERO, heading: Angle::degrees(0.), + speed: 2000, index: 0, drawing: true, }, @@ -260,7 +297,7 @@ fn draw_lines( let line_animator = Animator::new(Tween::new( EaseFunction::QuadraticInOut, TweeningType::Once, - Duration::from_millis(500), + Duration::from_millis(tcmd.state.speed), LineAnimationLens::new(start, end), )); commands @@ -278,7 +315,7 @@ fn draw_lines( let line_animator = Animator::new(Tween::new( EaseFunction::QuadraticInOut, TweeningType::Once, - Duration::from_millis(500), + Duration::from_millis(tcmd.state.speed), CircleAnimationLens { start_pos: start, center, @@ -324,6 +361,7 @@ fn keypresses( tcmd.state = TurtleState { start: Vec2::ZERO, heading: Angle::degrees(0.), + speed: 2000, index: 0, drawing: true, }; @@ -335,7 +373,7 @@ fn keypresses( let line_animator = Animator::new(Tween::new( EaseFunction::QuadraticInOut, TweeningType::Once, - Duration::from_millis(500), + Duration::from_millis(tcmd.state.speed), LineAnimationLens::new(start, end), )); commands diff --git a/src/turtle_movement.rs b/src/turtle_movement.rs index bf26ec3..b9adaab 100644 --- a/src/turtle_movement.rs +++ b/src/turtle_movement.rs @@ -17,24 +17,24 @@ pub fn turtle_turn( angle_to_turn: Angle, ) -> (Option>, Option) { let start = state.heading; - let end = state.heading + (angle_to_turn * PI / 180.); + let end = state.heading + angle_to_turn; let animation = Tween::new( // Use a quadratic easing on both endpoints EaseFunction::QuadraticInOut, TweeningType::Once, // Animation time - Duration::from_millis(500), + Duration::from_millis(state.speed), // Rotate the turtle TransformRotateZLens { - start: start.value(), - end: end.value(), + start: start.to_radians().value(), + end: end.to_radians().value(), }, ) .with_completed_event(state.index as u64); // Dont move and draw let line = TurtleGraphElement::Noop; // Update the state - state.heading = end % (2. * PI); + state.heading = end.limit_smaller_than_full_circle(); (Some(animation), Some(line)) } @@ -49,7 +49,7 @@ pub fn turtle_move( EaseFunction::QuadraticInOut, TweeningType::Once, // later to be controlled by speed - Duration::from_millis(500), + Duration::from_millis(state.speed), // set the start and end of the animation TransformPositionLens { start: start.extend(0.), @@ -74,10 +74,9 @@ pub fn turtle_circle( ) -> (Option>, Option) { let radius_tuple = Vec2::ONE * radius.abs(); let left_right = Angle::degrees(if radius >= 0. { 90. } else { -90. }); - println!("Heading: {}", state.heading.value()); let center = state.start + (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( @@ -85,7 +84,7 @@ pub fn turtle_circle( EaseFunction::QuadraticInOut, TweeningType::Once, // later to be controlled by speed - Duration::from_millis(500), + Duration::from_millis(state.speed), // set the start and end of the animation CircleMovementLens { start: Transform { @@ -105,15 +104,16 @@ pub fn turtle_circle( radii: radius_tuple, angle, start: state.start, - end: state.start + 200., + end: state.start, } } else { TurtleGraphElement::Noop }; let end_pos = center + 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.heading = state.heading + angle; (Some(turtle_movement_animation), Some(line)) }