223 lines
7.7 KiB
Rust
223 lines
7.7 KiB
Rust
|
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<TurtleCommand>);
|
||
|
|
||
|
impl TurtleCommands {
|
||
|
fn generate_tweenable(&self) -> Sequence<Transform> {
|
||
|
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<Time>,
|
||
|
keys: Res<Input<KeyCode>>,
|
||
|
mut commands: Commands,
|
||
|
mut qry: Query<&mut Animator<Transform>>,
|
||
|
tcmd: Query<&TurtleCommands>,
|
||
|
) {
|
||
|
if keys.just_pressed(KeyCode::W) {
|
||
|
let tcmd = tcmd.single();
|
||
|
let c = tcmd.generate_tweenable();
|
||
|
let mut shap = qry.single_mut();
|
||
|
shap.set_tweenable(c);
|
||
|
/* commands
|
||
|
.spawn_bundle(Turtle::default())
|
||
|
.insert_bundle(GeometryBuilder::build_as(
|
||
|
&turtle_shapes::turtle(),
|
||
|
DrawMode::Outlined {
|
||
|
fill_mode: FillMode::color(Color::RED),
|
||
|
outline_mode: StrokeMode::new(Color::BLACK, 1.0),
|
||
|
},
|
||
|
Transform::from_translation(Vec3::new(-100., 0., 0.)),
|
||
|
))
|
||
|
.insert(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::new(-100., 0., 0.),
|
||
|
end: Vec3::new(-140., 40., 0.),
|
||
|
},
|
||
|
))); */
|
||
|
}
|
||
|
}
|