Compare commits
2 Commits
ee2c869a03
...
5f4e47f540
Author | SHA1 | Date | |
---|---|---|---|
5f4e47f540 | |||
f9a4c1d81a |
53
src/animation_step.rs
Normal file
53
src/animation_step.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use bevy::prelude::{Commands, Query, Transform, With};
|
||||
use bevy_tweening::Animator;
|
||||
|
||||
use crate::{
|
||||
turtle::{TurtleCommands, TurtleGraphElement, TurtleShape},
|
||||
turtle_movement::TurtleStep,
|
||||
};
|
||||
|
||||
pub(crate) fn run_animation_step(
|
||||
commands: &mut Commands,
|
||||
tcmd: &mut TurtleCommands,
|
||||
turtle: &mut Query<&mut Animator<Transform>, With<TurtleShape>>,
|
||||
) {
|
||||
loop {
|
||||
match tcmd.get_next() {
|
||||
Some(TurtleStep {
|
||||
turtle_animation: Some(turtle_animation),
|
||||
line_segment: Some(graph_element_to_draw),
|
||||
line_animation: Some(line_animation),
|
||||
}) => {
|
||||
let mut turtle = turtle.single_mut();
|
||||
turtle.set_tweenable(turtle_animation);
|
||||
match graph_element_to_draw {
|
||||
TurtleGraphElement::TurtleLine(line) => {
|
||||
commands.spawn_bundle(line).insert(line_animation);
|
||||
}
|
||||
TurtleGraphElement::Noop => (),
|
||||
TurtleGraphElement::TurtleCircle(circle) => {
|
||||
commands.spawn_bundle(circle).insert(line_animation);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// In case a rotation is performed the line drawing can be skipped
|
||||
Some(TurtleStep {
|
||||
turtle_animation: Some(turtle_animation),
|
||||
line_segment: Some(_),
|
||||
line_animation: None,
|
||||
}) => {
|
||||
let mut turtle = turtle.single_mut();
|
||||
turtle.set_tweenable(turtle_animation);
|
||||
return;
|
||||
}
|
||||
Some(_) => {
|
||||
println!("without animation");
|
||||
}
|
||||
None => {
|
||||
println!("nothing to draw");
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
use std::f32::consts::PI;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_prototype_lyon::prelude::*;
|
||||
|
||||
|
@ -4,6 +4,8 @@ use std::{
|
||||
ops::{Add, Div, Mul, Neg, Rem, Sub},
|
||||
};
|
||||
|
||||
use crate::turtle::Precision;
|
||||
|
||||
#[derive(Inspectable, Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum AngleUnit<T: Default> {
|
||||
Degrees(T),
|
||||
@ -43,7 +45,7 @@ impl<T: Default + Clone + Mul<T, Output = T>> Mul<T> for Angle<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Angle<f32> {
|
||||
impl Angle<Precision> {
|
||||
pub fn limit_smaller_than_full_circle(self) -> Self {
|
||||
match self.value {
|
||||
AngleUnit::Degrees(v) => Self {
|
||||
|
@ -1,4 +1,6 @@
|
||||
use bevy_inspector_egui::Inspectable;
|
||||
|
||||
use crate::turtle::Precision;
|
||||
|
||||
#[derive(Inspectable, Default, Copy, Clone, Debug)]
|
||||
pub struct Length(pub f32);
|
||||
pub struct Length(pub Precision);
|
||||
|
@ -1,10 +1,10 @@
|
||||
mod animation_step;
|
||||
mod datatypes;
|
||||
mod debug;
|
||||
mod paths;
|
||||
mod primitives;
|
||||
mod turtle;
|
||||
mod turtle_movement;
|
||||
mod turtle_shapes;
|
||||
use bevy::{prelude::*, window::close_on_esc};
|
||||
|
||||
use bevy_prototype_lyon::prelude::*;
|
||||
|
@ -5,15 +5,24 @@ use crate::{
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn geometry_task() -> Vec<TurtleCommand> {
|
||||
vec![
|
||||
let mut before = vec![
|
||||
TurtleCommand::Forward(Length(100.)),
|
||||
TurtleCommand::Right(Angle::degrees(90.)),
|
||||
TurtleCommand::Backward(Length(100.)),
|
||||
TurtleCommand::Right(Angle::degrees(90.)),
|
||||
TurtleCommand::Forward(Length(100.)),
|
||||
TurtleCommand::Right(Angle::degrees(45.)),
|
||||
//TurtleCommand::PenUp,
|
||||
TurtleCommand::Forward(Length(100.)),
|
||||
];
|
||||
for _ in 0..10 {
|
||||
let mut dash = vec![
|
||||
TurtleCommand::PenUp,
|
||||
TurtleCommand::Forward(Length(5.)),
|
||||
TurtleCommand::PenDown,
|
||||
TurtleCommand::Forward(Length(5.)),
|
||||
];
|
||||
before.append(&mut dash);
|
||||
}
|
||||
let mut after = vec![
|
||||
TurtleCommand::Right(Angle::degrees(90.)),
|
||||
TurtleCommand::Forward(Length(50.)),
|
||||
TurtleCommand::Right(Angle::degrees(90.)),
|
||||
@ -28,5 +37,7 @@ pub fn geometry_task() -> Vec<TurtleCommand> {
|
||||
TurtleCommand::Forward(Length(100.)),
|
||||
TurtleCommand::Right(Angle::degrees(150.)),
|
||||
TurtleCommand::Forward(Length(100.)),
|
||||
]
|
||||
];
|
||||
before.append(&mut after);
|
||||
before
|
||||
}
|
||||
|
@ -2,3 +2,4 @@ pub mod animation;
|
||||
pub mod bundles;
|
||||
pub mod components;
|
||||
pub mod turtle_primitives;
|
||||
pub mod turtle_shapes;
|
||||
|
@ -5,7 +5,7 @@ use bevy_prototype_lyon::{
|
||||
};
|
||||
use bevy_tweening::Lens;
|
||||
|
||||
use crate::datatypes::angle::Angle;
|
||||
use crate::{datatypes::angle::Angle, turtle::Precision};
|
||||
|
||||
pub(crate) struct LineAnimationLens {
|
||||
start: Vec2,
|
||||
@ -29,8 +29,8 @@ pub(crate) struct CircleAnimationLens {
|
||||
pub start_pos: Vec2,
|
||||
pub center: Vec2,
|
||||
pub radii: Vec2,
|
||||
pub start: Angle<f32>,
|
||||
pub end: Angle<f32>,
|
||||
pub start: Angle<Precision>,
|
||||
pub end: Angle<Precision>,
|
||||
}
|
||||
|
||||
impl Lens<Path> for CircleAnimationLens {
|
||||
@ -54,7 +54,7 @@ impl Lens<Path> for CircleAnimationLens {
|
||||
pub(crate) struct CircleMovementLens {
|
||||
pub center: Vec2,
|
||||
pub start: Transform,
|
||||
pub end: Angle<f32>,
|
||||
pub end: Angle<Precision>,
|
||||
}
|
||||
|
||||
impl Lens<Transform> for CircleMovementLens {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use bevy::prelude::{Bundle, Color, Component, Name, Transform, Vec2};
|
||||
use bevy_inspector_egui::Inspectable;
|
||||
use bevy_prototype_lyon::{
|
||||
entity::ShapeBundle,
|
||||
prelude::{DrawMode, FillMode, GeometryBuilder, PathBuilder, StrokeMode},
|
||||
@ -7,18 +8,21 @@ use bevy_prototype_lyon::{
|
||||
|
||||
use crate::{
|
||||
datatypes::angle::Angle,
|
||||
turtle::{Colors, TurtleCommand, TurtleCommands},
|
||||
turtle::{Colors, Precision, TurtleCommand, TurtleCommands},
|
||||
};
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub(crate) struct TurtleDrawLine {
|
||||
use super::turtle_shapes;
|
||||
|
||||
#[derive(Bundle, Inspectable, Default)]
|
||||
pub struct TurtleDrawLine {
|
||||
#[bundle]
|
||||
#[inspectable(ignore)]
|
||||
line: ShapeBundle,
|
||||
name: Name,
|
||||
marker: LineMarker,
|
||||
}
|
||||
|
||||
#[derive(Component, Default)]
|
||||
#[derive(Component, Default, Inspectable)]
|
||||
struct LineMarker;
|
||||
|
||||
impl TurtleDrawLine {
|
||||
@ -38,23 +42,24 @@ impl TurtleDrawLine {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
#[derive(Bundle, Inspectable, Default)]
|
||||
|
||||
pub(crate) struct TurtleDrawCircle {
|
||||
pub struct TurtleDrawCircle {
|
||||
#[bundle]
|
||||
#[inspectable(ignore)]
|
||||
line: ShapeBundle,
|
||||
name: Name,
|
||||
marker: CircleMarker,
|
||||
}
|
||||
|
||||
#[derive(Component, Default)]
|
||||
#[derive(Component, Default, Inspectable)]
|
||||
struct CircleMarker;
|
||||
|
||||
impl TurtleDrawCircle {
|
||||
pub(crate) fn new(
|
||||
center: Vec2,
|
||||
radii: Vec2,
|
||||
angle: Angle<f32>,
|
||||
angle: Angle<Precision>,
|
||||
index: u64,
|
||||
start: Vec2,
|
||||
end: Vec2,
|
||||
@ -89,6 +94,8 @@ pub struct Turtle {
|
||||
colors: Colors,
|
||||
commands: TurtleCommands,
|
||||
name: Name,
|
||||
#[bundle]
|
||||
shape: ShapeBundle,
|
||||
}
|
||||
|
||||
impl Default for Turtle {
|
||||
@ -97,6 +104,14 @@ impl Default for Turtle {
|
||||
colors: Colors::default(),
|
||||
commands: TurtleCommands::new(vec![]),
|
||||
name: Name::new("Turtle"),
|
||||
shape: GeometryBuilder::build_as(
|
||||
&turtle_shapes::turtle(),
|
||||
DrawMode::Outlined {
|
||||
fill_mode: FillMode::color(Color::MIDNIGHT_BLUE),
|
||||
outline_mode: StrokeMode::new(Color::BLACK, 1.0),
|
||||
},
|
||||
Transform::identity(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,31 +3,33 @@ use std::f32::consts::PI;
|
||||
use bevy::prelude::Vec2;
|
||||
use bevy_prototype_lyon::prelude::{Path, PathBuilder};
|
||||
|
||||
use crate::turtle::Precision;
|
||||
|
||||
pub fn turtle() -> Path {
|
||||
let polygon = &[
|
||||
[-2.5f32, 14.0f32],
|
||||
[-1.25f32, 10.0f32],
|
||||
[-4.0f32, 7.0f32],
|
||||
[-7.0f32, 9.0f32],
|
||||
[-9.0f32, 8.0f32],
|
||||
[-6.0f32, 5.0f32],
|
||||
[-7.0f32, 1.0f32],
|
||||
[-5.0f32, -3.0f32],
|
||||
[-8.0f32, -6.0f32],
|
||||
[-6.0f32, -8.0f32],
|
||||
[-4.0f32, -5.0f32],
|
||||
[0.0f32, -7.0f32],
|
||||
[4.0f32, -5.0f32],
|
||||
[6.0f32, -8.0f32],
|
||||
[8.0f32, -6.0f32],
|
||||
[5.0f32, -3.0f32],
|
||||
[7.0f32, 1.0f32],
|
||||
[6.0f32, 5.0f32],
|
||||
[9.0f32, 8.0f32],
|
||||
[7.0f32, 9.0f32],
|
||||
[4.0f32, 7.0f32],
|
||||
[1.25f32, 10.0f32],
|
||||
[2.5f32, 14.0f32],
|
||||
let polygon: &[[Precision; 2]; 23] = &[
|
||||
[-2.5, 14.0],
|
||||
[-1.25, 10.0],
|
||||
[-4.0, 7.0],
|
||||
[-7.0, 9.0],
|
||||
[-9.0, 8.0],
|
||||
[-6.0, 5.0],
|
||||
[-7.0, 1.0],
|
||||
[-5.0, -3.0],
|
||||
[-8.0, -6.0],
|
||||
[-6.0, -8.0],
|
||||
[-4.0, -5.0],
|
||||
[0.0, -7.0],
|
||||
[4.0, -5.0],
|
||||
[6.0, -8.0],
|
||||
[8.0, -6.0],
|
||||
[5.0, -3.0],
|
||||
[7.0, 1.0],
|
||||
[6.0, 5.0],
|
||||
[9.0, 8.0],
|
||||
[7.0, 9.0],
|
||||
[4.0, 7.0],
|
||||
[1.25, 10.0],
|
||||
[2.5, 14.0],
|
||||
];
|
||||
let mut turtle_path = PathBuilder::new();
|
||||
turtle_path.line_to(Vec2::new(1.0, 1.0));
|
148
src/turtle.rs
148
src/turtle.rs
@ -11,12 +11,10 @@ use bevy_tweening::{
|
||||
#[allow(unused_imports)]
|
||||
use crate::paths::{circle_star::circle_star, geometry_task::geometry_task};
|
||||
use crate::{
|
||||
animation_step::run_animation_step,
|
||||
datatypes::{angle::Angle, length::Length},
|
||||
primitives::{
|
||||
animation::{CircleAnimationLens, LineAnimationLens},
|
||||
bundles::{Turtle, TurtleDrawCircle, TurtleDrawLine},
|
||||
},
|
||||
turtle_shapes,
|
||||
primitives::bundles::{Turtle, TurtleDrawCircle, TurtleDrawLine},
|
||||
turtle_movement::TurtleStep,
|
||||
};
|
||||
|
||||
pub struct TurtlePlugin;
|
||||
@ -66,7 +64,7 @@ impl TurtleCommands {
|
||||
}
|
||||
|
||||
impl TurtleCommands {
|
||||
fn get_next(&mut self) -> Option<(Option<Tween<Transform>>, Option<TurtleGraphElement>)> {
|
||||
pub(crate) fn get_next(&mut self) -> Option<TurtleStep> {
|
||||
let index = self.state.index;
|
||||
let next_index = index + 1;
|
||||
|
||||
@ -86,11 +84,21 @@ impl TurtleCommands {
|
||||
}
|
||||
TurtleCommand::PenUp => {
|
||||
self.state.drawing = false;
|
||||
(None, None)
|
||||
|
||||
TurtleStep {
|
||||
turtle_animation: None,
|
||||
line_segment: None,
|
||||
line_animation: None,
|
||||
}
|
||||
}
|
||||
TurtleCommand::PenDown => {
|
||||
self.state.drawing = true;
|
||||
(None, None)
|
||||
|
||||
TurtleStep {
|
||||
turtle_animation: None,
|
||||
line_segment: None,
|
||||
line_animation: None,
|
||||
}
|
||||
}
|
||||
TurtleCommand::Circle { radius, angle } => {
|
||||
crate::turtle_movement::turtle_circle(&mut self.state, radius.0 as f32, *angle)
|
||||
@ -107,17 +115,8 @@ impl TurtleCommands {
|
||||
|
||||
#[derive(Inspectable, Default)]
|
||||
pub enum TurtleGraphElement {
|
||||
TurtleLine {
|
||||
start: Vec2,
|
||||
end: Vec2,
|
||||
},
|
||||
TurtleCircle {
|
||||
start: Vec2,
|
||||
end: Vec2,
|
||||
center: Vec2,
|
||||
radii: Vec2,
|
||||
angle: Angle<f32>,
|
||||
},
|
||||
TurtleLine(TurtleDrawLine),
|
||||
TurtleCircle(TurtleDrawCircle),
|
||||
#[default]
|
||||
Noop,
|
||||
}
|
||||
@ -159,17 +158,9 @@ fn setup(mut commands: Commands) {
|
||||
));
|
||||
commands.spawn_bundle(Camera2dBundle::default());
|
||||
let mut turtle_bundle = Turtle::default();
|
||||
turtle_bundle.set_commands(geometry_task());
|
||||
turtle_bundle.set_commands(circle_star());
|
||||
commands
|
||||
.spawn_bundle(turtle_bundle)
|
||||
.insert_bundle(GeometryBuilder::build_as(
|
||||
&turtle_shapes::turtle(),
|
||||
DrawMode::Outlined {
|
||||
fill_mode: FillMode::color(Color::MIDNIGHT_BLUE),
|
||||
outline_mode: StrokeMode::new(Color::BLACK, 1.0),
|
||||
},
|
||||
Transform::identity(),
|
||||
))
|
||||
.insert(animator)
|
||||
.insert(TurtleShape);
|
||||
}
|
||||
@ -182,117 +173,26 @@ fn draw_lines(
|
||||
) {
|
||||
for ev in query_event.iter() {
|
||||
let mut tcmd = tcmd.single_mut();
|
||||
loop {
|
||||
match tcmd.get_next() {
|
||||
Some((Some(turtle_animation), Some(graph_element_to_draw))) => {
|
||||
let mut turtle = turtle.single_mut();
|
||||
turtle.set_tweenable(turtle_animation);
|
||||
match graph_element_to_draw {
|
||||
TurtleGraphElement::TurtleLine { start, end } => {
|
||||
let line_animator = Animator::new(Tween::new(
|
||||
EaseFunction::QuadraticInOut,
|
||||
TweeningType::Once,
|
||||
Duration::from_millis(tcmd.state.speed),
|
||||
LineAnimationLens::new(start, end),
|
||||
));
|
||||
commands
|
||||
.spawn_bundle(TurtleDrawLine::new(start, end, tcmd.state.index))
|
||||
.insert(line_animator);
|
||||
}
|
||||
TurtleGraphElement::Noop => println!("No drawing!"),
|
||||
TurtleGraphElement::TurtleCircle {
|
||||
center,
|
||||
radii,
|
||||
angle,
|
||||
start,
|
||||
end,
|
||||
} => {
|
||||
let line_animator = Animator::new(Tween::new(
|
||||
EaseFunction::QuadraticInOut,
|
||||
TweeningType::Once,
|
||||
Duration::from_millis(tcmd.state.speed),
|
||||
CircleAnimationLens {
|
||||
start_pos: start,
|
||||
center,
|
||||
radii,
|
||||
start: Angle::degrees(0.),
|
||||
end: angle,
|
||||
},
|
||||
));
|
||||
commands
|
||||
.spawn_bundle(TurtleDrawCircle::new(
|
||||
center,
|
||||
radii,
|
||||
Angle::degrees(0.),
|
||||
tcmd.state.index,
|
||||
start,
|
||||
end,
|
||||
))
|
||||
.insert(line_animator);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Some((_, _)) => {
|
||||
println!("without animation");
|
||||
}
|
||||
None => {
|
||||
println!("nothing to draw");
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
run_animation_step(&mut commands, &mut tcmd, &mut turtle)
|
||||
}
|
||||
}
|
||||
|
||||
fn keypresses(
|
||||
mut commands: Commands,
|
||||
keys: Res<Input<KeyCode>>,
|
||||
mut qry: Query<&mut Animator<Transform>, With<TurtleShape>>,
|
||||
mut tcmd: Query<&mut TurtleCommands>,
|
||||
mut turtle: Query<&mut Animator<Transform>, With<TurtleShape>>,
|
||||
) {
|
||||
if keys.just_pressed(KeyCode::W) {
|
||||
let mut tcmd = tcmd.single_mut();
|
||||
tcmd.state = TurtleState {
|
||||
start: Vec2::ZERO,
|
||||
heading: Angle::degrees(0.),
|
||||
speed: 2000,
|
||||
speed: 500,
|
||||
index: 0,
|
||||
drawing: true,
|
||||
};
|
||||
if let Some((Some(turtle_animation), Some(graph_element_to_draw))) = tcmd.get_next() {
|
||||
let mut shap = qry.single_mut();
|
||||
shap.set_tweenable(turtle_animation);
|
||||
match graph_element_to_draw {
|
||||
TurtleGraphElement::TurtleLine { start, end } => {
|
||||
let line_animator = Animator::new(Tween::new(
|
||||
EaseFunction::QuadraticInOut,
|
||||
TweeningType::Once,
|
||||
Duration::from_millis(tcmd.state.speed),
|
||||
LineAnimationLens::new(start, end),
|
||||
));
|
||||
commands
|
||||
.spawn_bundle(TurtleDrawLine::new(start, end, tcmd.state.index))
|
||||
.insert(line_animator);
|
||||
}
|
||||
TurtleGraphElement::Noop => (),
|
||||
TurtleGraphElement::TurtleCircle {
|
||||
center,
|
||||
radii,
|
||||
angle,
|
||||
start,
|
||||
end,
|
||||
} => {
|
||||
commands.spawn_bundle(TurtleDrawCircle::new(
|
||||
center,
|
||||
radii,
|
||||
angle,
|
||||
tcmd.state.index,
|
||||
start,
|
||||
end,
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
run_animation_step(&mut commands, &mut tcmd, &mut turtle);
|
||||
}
|
||||
}
|
||||
|
@ -1,78 +1,89 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use bevy::prelude::{Quat, Transform, Vec2, Vec3};
|
||||
use bevy_prototype_lyon::prelude::Path;
|
||||
use bevy_tweening::{
|
||||
lens::{TransformPositionLens, TransformRotateZLens},
|
||||
EaseFunction, Tween, TweeningType,
|
||||
Animator, EaseFunction, Tween, TweeningType,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
datatypes::angle::Angle,
|
||||
primitives::animation::CircleMovementLens,
|
||||
turtle::{TurtleGraphElement, TurtleState},
|
||||
primitives::{
|
||||
animation::{CircleAnimationLens, CircleMovementLens, LineAnimationLens},
|
||||
bundles::{TurtleDrawCircle, TurtleDrawLine},
|
||||
},
|
||||
turtle::{Precision, TurtleGraphElement, TurtleState},
|
||||
};
|
||||
|
||||
pub fn turtle_turn(
|
||||
state: &mut TurtleState,
|
||||
angle_to_turn: Angle<f32>,
|
||||
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
|
||||
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(
|
||||
// Use a quadratic easing on both endpoints
|
||||
EaseFunction::QuadraticInOut,
|
||||
TweeningType::Once,
|
||||
// Animation time
|
||||
Duration::from_millis(state.speed),
|
||||
// Rotate the turtle
|
||||
TransformRotateZLens {
|
||||
start: start.to_radians().value(),
|
||||
end: end.to_radians().value(),
|
||||
},
|
||||
)
|
||||
.with_completed_event(state.index as u64);
|
||||
// Dont move and draw
|
||||
// Don't draw as the position does not change
|
||||
let line = TurtleGraphElement::Noop;
|
||||
// Update the state
|
||||
state.heading = end.limit_smaller_than_full_circle();
|
||||
(Some(animation), Some(line))
|
||||
TurtleStep {
|
||||
turtle_animation: Some(animation),
|
||||
line_segment: Some(line),
|
||||
line_animation: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn turtle_move(
|
||||
state: &mut TurtleState,
|
||||
length: f32,
|
||||
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
|
||||
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(
|
||||
// accelerate and decelerate
|
||||
EaseFunction::QuadraticInOut,
|
||||
TweeningType::Once,
|
||||
// later to be controlled by speed
|
||||
Duration::from_millis(state.speed),
|
||||
// set the start and end of the animation
|
||||
TransformPositionLens {
|
||||
start: start.extend(0.),
|
||||
end: end.extend(0.),
|
||||
},
|
||||
)
|
||||
.with_completed_event(state.index as u64);
|
||||
// The line for animating and drawing
|
||||
let line = if state.drawing {
|
||||
TurtleGraphElement::TurtleLine { start, end }
|
||||
TurtleGraphElement::TurtleLine(TurtleDrawLine::new(start, end, state.index))
|
||||
} else {
|
||||
TurtleGraphElement::Noop
|
||||
};
|
||||
let line_animator = Animator::new(Tween::new(
|
||||
EaseFunction::QuadraticInOut,
|
||||
TweeningType::Once,
|
||||
Duration::from_millis(state.speed),
|
||||
LineAnimationLens::new(start, end),
|
||||
));
|
||||
state.start = end;
|
||||
(Some(turtle_movement_animation), Some(line))
|
||||
TurtleStep {
|
||||
turtle_animation: Some(turtle_movement_animation),
|
||||
line_segment: Some(line),
|
||||
line_animation: Some(line_animator),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn turtle_circle(
|
||||
state: &mut TurtleState,
|
||||
radius: f32,
|
||||
angle: Angle<f32>,
|
||||
) -> (Option<Tween<Transform>>, Option<TurtleGraphElement>) {
|
||||
let radius_tuple = Vec2::ONE * radius.abs();
|
||||
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(
|
||||
@ -80,12 +91,9 @@ pub fn turtle_circle(
|
||||
)));
|
||||
|
||||
let turtle_movement_animation = Tween::new(
|
||||
// accelerate and decelerate
|
||||
EaseFunction::QuadraticInOut,
|
||||
TweeningType::Once,
|
||||
// later to be controlled by speed
|
||||
Duration::from_millis(state.speed),
|
||||
// set the start and end of the animation
|
||||
CircleMovementLens {
|
||||
start: Transform {
|
||||
translation: state.start.extend(0.),
|
||||
@ -97,23 +105,39 @@ pub fn turtle_circle(
|
||||
},
|
||||
)
|
||||
.with_completed_event(state.index as u64);
|
||||
// The line for animating and drawing
|
||||
let line = if state.drawing {
|
||||
TurtleGraphElement::TurtleCircle {
|
||||
center,
|
||||
radii: radius_tuple,
|
||||
angle,
|
||||
start: state.start,
|
||||
end: state.start,
|
||||
}
|
||||
} else {
|
||||
TurtleGraphElement::Noop
|
||||
};
|
||||
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,
|
||||
TweeningType::Once,
|
||||
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;
|
||||
(Some(turtle_movement_animation), Some(line))
|
||||
TurtleStep {
|
||||
turtle_animation: Some(turtle_movement_animation),
|
||||
line_segment: Some(line),
|
||||
line_animation: Some(line_animator),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user