use std::{f32::consts::PI, time::Duration}; use bevy::prelude::{Quat, Transform, Vec2, Vec3}; use bevy_tweening::{ lens::{TransformPositionLens, TransformRotateAxisLens, TransformRotateZLens}, EaseFunction, Tween, TweeningType, }; use crate::{ datatypes::angle::Angle, primitives::{CircleAnimationLens, CircleMovementLens}, turtle::{TurtleGraphElement, TurtleState}, }; pub fn turtle_turn( state: &mut TurtleState, angle_to_turn: Angle, ) -> (Option>, Option) { 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 let line = TurtleGraphElement::Noop; // Update the state state.heading = end.limit_smaller_than_full_circle(); (Some(animation), Some(line)) } pub fn turtle_move( state: &mut TurtleState, length: f32, ) -> (Option>, Option) { 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 } } else { TurtleGraphElement::Noop }; state.start = end; (Some(turtle_movement_animation), Some(line)) } pub fn turtle_circle( state: &mut TurtleState, radius: f32, angle: Angle, ) -> (Option>, Option) { let radius_tuple = 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( ((state.heading + left_right).to_radians()).value(), ))); 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.), rotation: Quat::from_rotation_z(state.heading.to_radians().value()), scale: Vec3::ONE, }, end: angle, center, }, ) .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(), )); state.start = end_pos; state.heading = state.heading + angle; (Some(turtle_movement_animation), Some(line)) }