From a5a1be239254c9d0f780e980c7a23c3a449480fb Mon Sep 17 00:00:00 2001 From: Dietrich Date: Fri, 19 Aug 2022 22:30:28 +0200 Subject: [PATCH] circles partially working --- src/primitives.rs | 52 +++++++++++++++++++++++++++++++++++--- src/turtle.rs | 57 ++++++++++++++++++++++++++---------------- src/turtle_movement.rs | 28 ++++++++++++++------- 3 files changed, 103 insertions(+), 34 deletions(-) diff --git a/src/primitives.rs b/src/primitives.rs index 7f4bc33..557d7d3 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -1,4 +1,4 @@ -use bevy::prelude::{Bundle, Color, Component, Name, Transform, Vec2}; +use bevy::prelude::{Bundle, Color, Component, Name, Quat, Transform, Vec2}; use bevy_prototype_lyon::{ entity::ShapeBundle, prelude::{DrawMode, FillMode, GeometryBuilder, Path, PathBuilder, ShapePath, StrokeMode}, @@ -55,17 +55,49 @@ impl TurtleDrawLine { } pub(crate) struct CircleAnimationLens { - start: Vec2, - end: Vec2, + pub start_pos: Vec2, + pub center: Vec2, + pub radii: Vec2, + pub start: Angle, + pub end: Angle, } impl Lens for CircleAnimationLens { fn lerp(&mut self, target: &mut Path, ratio: f32) { - let line = shapes::Line(self.start, self.start + ((self.end - self.start) * ratio)); + let mut path_builder = PathBuilder::new(); + path_builder.move_to(self.start_pos); + // The center point of the radius, then the radii in x and y direction, then the angle that will be drawn, then the x_rotation ? + path_builder.arc( + self.center, + self.radii, + (self.start.0 + ((self.end.0 - self.start.0) * ratio)).to_radians(), + 0., + ); + let line = path_builder.build(); *target = ShapePath::build_as(&line); } } +pub(crate) struct CircleMovementLens { + pub center: Vec2, + pub start: Transform, + pub end: Angle, +} + +impl Lens for CircleMovementLens { + fn lerp(&mut self, target: &mut Transform, ratio: f32) { + let angle = self.end.0 * ratio; + let mut rotated = self.start; + + rotated.rotate_around( + self.center.extend(0.), + Quat::from_rotation_z(angle.to_radians()), + ); + + *target = rotated; + } +} + #[derive(Bundle)] pub(crate) struct TurtleDrawCircle { @@ -91,6 +123,18 @@ impl TurtleDrawCircle { path_builder.move_to(start); // The center point of the radius, then the radii in x and y direction, then the angle that will be drawn, then the x_rotation ? path_builder.arc(center, radii, angle.0.to_radians(), 0.); + + /* println!("The radiuses: {}", radii); + path_builder.move_to(Vec2::ZERO); + path_builder.line_to(center); + path_builder.line_to(Vec2::new(radii.x, 0.) + center); + path_builder.move_to(center); + path_builder.line_to(Vec2::new(0., radii.y) + center); + path_builder.move_to(center); + path_builder.line_to( + center + Vec2::new(radii.x.abs(), 0.).rotate(Vec2::from_angle(angle.0.to_radians())), + ); + path_builder.move_to(center); */ let line = path_builder.build(); println!("Draw Circle: {} {} {:?}", center, radii, angle); diff --git a/src/turtle.rs b/src/turtle.rs index e94abf9..6fdb9aa 100644 --- a/src/turtle.rs +++ b/src/turtle.rs @@ -9,7 +9,7 @@ use bevy_tweening::{ }; use crate::{ - primitives::{LineAnimationLens, TurtleDrawCircle, TurtleDrawLine}, + primitives::{CircleAnimationLens, LineAnimationLens, TurtleDrawCircle, TurtleDrawLine}, turtle_shapes, }; @@ -41,27 +41,29 @@ impl Default for Turtle { fill_color: Color::BLACK, }, commands: TurtleCommands::new(vec![ - TurtleCommand::Forward(Length(100.)), + TurtleCommand::Forward(Length(-100.)), TurtleCommand::Circle { radius: Length(150.), - angle: Angle(180.), + angle: Angle(30.), }, - TurtleCommand::Right(Angle(90.)), + TurtleCommand::Forward(Length(100.)), TurtleCommand::Circle { - radius: Length(15.), - angle: Angle(180.), + radius: Length(70.), + angle: Angle(60.), }, - TurtleCommand::Backward(Length(100.)), + TurtleCommand::Forward(Length(100.)), + TurtleCommand::Right(Angle(90.)), + //TurtleCommand::PenDown, + TurtleCommand::Circle { + radius: Length(30.), + angle: Angle(360. - 46.), + }, + /* TurtleCommand::Backward(Length(100.)), TurtleCommand::Right(Angle(90.)), TurtleCommand::Forward(Length(100.)), TurtleCommand::Right(Angle(45.)), //TurtleCommand::PenUp, TurtleCommand::Forward(Length(100.)), - //TurtleCommand::PenDown, - TurtleCommand::Circle { - radius: Length(-30.), - angle: Angle(90.), - }, TurtleCommand::Right(Angle(90.)), TurtleCommand::Forward(Length(50.)), TurtleCommand::Right(Angle(90.)), @@ -75,7 +77,7 @@ impl Default for Turtle { TurtleCommand::Left(Angle(120.)), TurtleCommand::Forward(Length(100.)), TurtleCommand::Right(Angle(150.)), - TurtleCommand::Forward(Length(100.)), + TurtleCommand::Forward(Length(100.)), */ ]), name: Name::new("Turtle"), } @@ -274,15 +276,28 @@ fn draw_lines( start, end, } => { - // let circle_animator = todo!(); - commands.spawn_bundle(TurtleDrawCircle::new( - center, - radii, - angle, - tcmd.state.index, - start, - end, + let line_animator = Animator::new(Tween::new( + EaseFunction::QuadraticInOut, + TweeningType::Once, + Duration::from_millis(500), + CircleAnimationLens { + start_pos: start, + center, + radii, + start: Angle(0.), + end: angle, + }, )); + commands + .spawn_bundle(TurtleDrawCircle::new( + center, + radii, + Angle(0.), + tcmd.state.index, + start, + end, + )) + .insert(line_animator); } } return; diff --git a/src/turtle_movement.rs b/src/turtle_movement.rs index b5a6c96..8ac54e4 100644 --- a/src/turtle_movement.rs +++ b/src/turtle_movement.rs @@ -1,12 +1,15 @@ use std::{f32::consts::PI, time::Duration}; -use bevy::prelude::{Transform, Vec2}; +use bevy::prelude::{Quat, Transform, Vec2, Vec3}; use bevy_tweening::{ - lens::{TransformPositionLens, TransformRotateZLens}, + lens::{TransformPositionLens, TransformRotateAxisLens, TransformRotateZLens}, EaseFunction, Tween, TweeningType, }; -use crate::turtle::{Angle, TurtleGraphElement, TurtleState}; +use crate::{ + primitives::{CircleAnimationLens, CircleMovementLens}, + turtle::{Angle, TurtleGraphElement, TurtleState}, +}; pub fn turtle_turn( state: &mut TurtleState, @@ -66,10 +69,12 @@ pub fn turtle_circle( angle: Angle, ) -> (Option>, Option) { let radius_tuple = Vec2::ONE * radius.abs(); - dbg!(state.start, radius_tuple); + let left_right = if radius >= 0. { 90f32 } else { -90. }; + println!("Heading: {}", state.heading); let center = state.start - + (Vec2::new(radius, 0.).rotate(Vec2::from_angle((state.heading + 90.).to_radians()))); - dbg!(center); + + (Vec2::new(radius.abs(), 0.) + .rotate(Vec2::from_angle(state.heading + left_right.to_radians()))); + let turtle_movement_animation = Tween::new( // accelerate and decelerate EaseFunction::QuadraticInOut, @@ -77,9 +82,14 @@ pub fn turtle_circle( // later to be controlled by speed Duration::from_millis(500), // set the start and end of the animation - TransformPositionLens { - start: center.extend(0.), - end: center.extend(0.), + CircleMovementLens { + start: Transform { + translation: state.start.extend(0.), + rotation: Quat::from_rotation_z(state.heading), + scale: Vec3::ONE, + }, + end: angle, + center, }, ) .with_completed_event(state.index as u64);