use std::{f32::consts::PI, time::Duration}; use bevy::prelude::*; use bevy_prototype_lyon::{entity::ShapeBundle, prelude::*}; use bevy_tweening::{ lens::{TransformPositionLens, TransformRotateXLens, TransformRotateZLens, TransformScaleLens}, Animator, EaseFunction, Lens, Sequence, Tween, Tweenable, TweeningPlugin, TweeningType, }; use crate::turtle_shapes; pub struct TurtlePlugin; impl Plugin for TurtlePlugin { fn build(&self, app: &mut bevy::prelude::App) { app.add_plugin(TweeningPlugin) .add_startup_system(setup) .add_system(keypresses); } } #[derive(Bundle)] pub struct Turtle { colors: Colors, commands: TurtleCommands, } impl Default for Turtle { fn default() -> Self { Self { colors: Colors { color: Color::DARK_GRAY, fill_color: Color::BLACK, }, commands: TurtleCommands(vec![ TurtleCommand::Forward(Length(100.)), TurtleCommand::Left(Angle(90.)), ]), /* shape: TurtleShape(GeometryBuilder::build_as( &turtle_shapes::turtle(), DrawMode::Outlined { fill_mode: FillMode::color(Color::MIDNIGHT_BLUE), outline_mode: StrokeMode::new(Color::BLACK, 1.0), }, Default::default(), )), */ } } } impl Turtle { pub fn set_color(&mut self, color: Color) { self.colors.color = color; } pub fn set_fill_color(&mut self, color: Color) { self.colors.fill_color = color; } pub fn get_colors(&self) -> &Colors { &self.colors } pub fn forward(&mut self) -> &mut Self { self.commands.0.push(TurtleCommand::Forward(Length(100.0))); self } } #[derive(Component)] pub struct TurtleCommands(Vec); impl TurtleCommands { fn generate_tweenable(&self) -> Sequence { let mut seq = Sequence::with_capacity(self.0.len()); for op in &self.0 { match op { TurtleCommand::Forward(Length(x)) => { println!("Adding Forward"); seq = seq.then(Tween::new( // Use a quadratic easing on both endpoints. EaseFunction::QuadraticInOut, // Loop animation back and forth. TweeningType::Once, // Animation time (one way only; for ping-pong it takes 2 seconds // to come back to start). Duration::from_secs(1), // The lens gives access to the Transform component of the Entity, // for the Animator to animate it. It also contains the start and // end values respectively associated with the progress ratios 0. and 1. TransformPositionLens { start: Vec3::ZERO, end: Vec3::new(*x as f32, 40., 0.), }, )); } TurtleCommand::Backward(_) => todo!(), TurtleCommand::Left(Angle(x)) => { println!("Adding Left"); seq = seq.then(Tween::new( // Use a quadratic easing on both endpoints. EaseFunction::QuadraticInOut, // Loop animation back and forth. TweeningType::Once, // Animation time (one way only; for ping-pong it takes 2 seconds // to come back to start). Duration::from_secs(1), // The lens gives access to the Transform component of the Entity, // for the Animator to animate it. It also contains the start and // end values respectively associated with the progress ratios 0. and 1. TransformRotateZLens { start: *x as f32 * (PI / 180.), end: -*x as f32 * (PI / 180.), }, )); } TurtleCommand::Right(_) => todo!(), TurtleCommand::PenUp => todo!(), TurtleCommand::PenDown => todo!(), TurtleCommand::Circle => todo!(), } } seq } } #[derive(Clone, Component)] pub struct TurtleShape; #[derive(Clone, Component)] pub struct Colors { color: Color, fill_color: Color, } pub struct Length(f64); pub struct Angle(f64); #[derive(Component)] enum TurtleCommand { Forward(Length), Backward(Length), Left(Angle), Right(Angle), PenUp, PenDown, Circle, } struct TurtleMoveLens { start: Vec3, end: Vec3, } fn setup(mut commands: Commands) { let animator = Animator::new(Tween::new( // Use a quadratic easing on both endpoints. EaseFunction::QuadraticInOut, // Loop animation back and forth. TweeningType::PingPong, // Animation time (one way only; for ping-pong it takes 2 seconds // to come back to start). Duration::from_secs(1), // The lens gives access to the Transform component of the Entity, // for the Animator to animate it. It also contains the start and // end values respectively associated with the progress ratios 0. and 1. TransformPositionLens { start: Vec3::ZERO, end: Vec3::new(40., 40., 0.), }, )); commands.spawn_bundle(Camera2dBundle::default()); commands .spawn_bundle(Turtle::default()) .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), }, Default::default(), )) .insert(animator); } /// The sprite is animated by changing its translation depending on the time that has passed since /// the last frame. fn keypresses( //time: Res