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]]
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",

View File

@ -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

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 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<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> {
type Output = Self;
@ -101,6 +116,14 @@ impl<T: Default + num_traits::float::Float> Angle<T> {
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> {

View File

@ -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<f32>,
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

View File

@ -17,24 +17,24 @@ pub fn turtle_turn(
angle_to_turn: Angle<f32>,
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
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<Tween<Transform>>, Option<TurtleGraphElement>) {
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))
}