forward backward left right working

This commit is contained in:
Franz Dietrich 2022-08-08 14:23:56 +02:00
parent 2836b2926d
commit 92458b55e5
3 changed files with 164 additions and 90 deletions

View File

@ -1,5 +1,6 @@
mod debug; mod debug;
mod turtle; mod turtle;
mod turtle_movement;
mod turtle_shapes; mod turtle_shapes;
use bevy::{prelude::*, window::close_on_esc}; use bevy::{prelude::*, window::close_on_esc};

View File

@ -1,14 +1,14 @@
use std::{f32::consts::PI, time::Duration}; use std::time::Duration;
use bevy::prelude::*; use bevy::prelude::*;
use bevy_inspector_egui::{Inspectable, RegisterInspectable}; use bevy_inspector_egui::{Inspectable, RegisterInspectable};
use bevy_prototype_lyon::prelude::*; use bevy_prototype_lyon::{prelude::*, shapes::Line};
use bevy_tweening::{ use bevy_tweening::{
lens::{TransformPositionLens, TransformRotateZLens}, lens::TransformPositionLens, Animator, EaseFunction, Sequence, Tween, TweenCompleted,
Animator, EaseFunction, Sequence, Tween, TweeningPlugin, TweeningType, TweeningPlugin, TweeningType,
}; };
use crate::turtle_shapes; use crate::{turtle_movement::turtle_move, turtle_shapes};
pub struct TurtlePlugin; pub struct TurtlePlugin;
@ -17,6 +17,7 @@ impl Plugin for TurtlePlugin {
app.add_plugin(TweeningPlugin) app.add_plugin(TweeningPlugin)
.add_startup_system(setup) .add_startup_system(setup)
.add_system(keypresses) .add_system(keypresses)
.add_system(draw_lines)
.register_inspectable::<Colors>() .register_inspectable::<Colors>()
.register_inspectable::<TurtleCommands>(); .register_inspectable::<TurtleCommands>();
} }
@ -34,24 +35,29 @@ impl Default for Turtle {
color: Color::DARK_GRAY, color: Color::DARK_GRAY,
fill_color: Color::BLACK, fill_color: Color::BLACK,
}, },
commands: TurtleCommands(vec![ commands: TurtleCommands::new(vec![
TurtleCommand::Forward(Length(100.)), TurtleCommand::Forward(Length(100.)),
TurtleCommand::Left(Angle(90.)), TurtleCommand::Right(Angle(90.)),
TurtleCommand::Backward(Length(100.)),
TurtleCommand::Right(Angle(90.)),
TurtleCommand::Forward(Length(100.)), TurtleCommand::Forward(Length(100.)),
TurtleCommand::Left(Angle(90.)), TurtleCommand::Right(Angle(45.)),
TurtleCommand::Forward(Length(100.)), TurtleCommand::Forward(Length(100.)),
TurtleCommand::Left(Angle(90.)), TurtleCommand::Right(Angle(90.)),
TurtleCommand::Forward(Length(50.)),
TurtleCommand::Right(Angle(90.)),
TurtleCommand::Forward(Length(100.)), TurtleCommand::Forward(Length(100.)),
TurtleCommand::Left(Angle(90.)), TurtleCommand::Right(Angle(90.)),
]), /* TurtleCommand::Forward(Length(50.)),
shape: TurtleShape(GeometryBuilder::build_as( TurtleCommand::Right(Angle(45.)),
&turtle_shapes::turtle(), TurtleCommand::Forward(Length(100.)),
DrawMode::Outlined { TurtleCommand::Left(Angle(120.)),
fill_mode: FillMode::color(Color::MIDNIGHT_BLUE), TurtleCommand::Forward(Length(100.)),
outline_mode: StrokeMode::new(Color::BLACK, 1.0), TurtleCommand::Left(Angle(120.)),
}, TurtleCommand::Forward(Length(100.)),
Default::default(), TurtleCommand::Right(Angle(150.)),
)), */ TurtleCommand::Forward(Length(100.)),
]),
} }
} }
} }
@ -67,61 +73,60 @@ impl Turtle {
&self.colors &self.colors
} }
pub fn forward(&mut self) -> &mut Self { pub fn forward(&mut self) -> &mut Self {
self.commands.0.push(TurtleCommand::Forward(Length(100.0))); self.commands
.commands
.push(TurtleCommand::Forward(Length(100.0)));
self self
} }
} }
#[derive(Component, Inspectable)] #[derive(Component, Inspectable)]
pub struct TurtleCommands(Vec<TurtleCommand>); pub struct TurtleCommands {
commands: Vec<TurtleCommand>,
lines: Vec<TurtleGraphElement>,
}
impl TurtleCommands { impl TurtleCommands {
fn generate_tweenable(&self) -> Sequence<Transform> { fn new(commands: Vec<TurtleCommand>) -> Self {
let mut seq = Sequence::with_capacity(self.0.len()); Self {
commands,
lines: vec![],
}
}
}
impl TurtleCommands {
fn generate_tweenable(&mut self) -> Sequence<Transform> {
self.lines.clear();
let mut seq = Sequence::with_capacity(self.commands.len());
let mut pos = Vec2::ZERO; let mut pos = Vec2::ZERO;
let mut ori: f32 = 0.; let mut ori: f32 = 0.;
for op in &self.0 { for (index, op) in self.commands.iter().enumerate() {
match op { match op {
TurtleCommand::Forward(Length(x)) => { TurtleCommand::Forward(Length(x)) => {
println!("Adding Forward"); let (target, animation, line) = turtle_move(pos, ori, *x as f32, index as f32);
let start = pos; self.lines.push(line);
let end = pos + (Vec2::from_angle(ori) * *x as f32); seq = seq.then(animation);
seq = seq.then(Tween::new( pos = target;
// accelerate and decelerate }
EaseFunction::QuadraticInOut, TurtleCommand::Backward(Length(x)) => {
// Loop animation back and forth. let (target, animation, line) = turtle_move(pos, ori, -*x as f32, index as f32);
TweeningType::Once, self.lines.push(line);
// later to be controlled by speed seq = seq.then(animation);
Duration::from_secs(1), pos = target;
// set the start and end of the animation
TransformPositionLens {
start: start.extend(0.),
end: end.extend(0.),
},
));
pos = end;
} }
TurtleCommand::Backward(_) => todo!(),
TurtleCommand::Left(Angle(x)) => { TurtleCommand::Left(Angle(x)) => {
println!("Adding Left"); let (nori, tween, line) = crate::turtle_movement::turtle_turn(ori, *x as f32);
let start = ori; ori = nori;
let end = ori + (*x as f32 * PI / 180.); seq = seq.then(tween);
seq = seq.then(Tween::new( self.lines.push(line);
// Use a quadratic easing on both endpoints. }
EaseFunction::QuadraticInOut, TurtleCommand::Right(Angle(x)) => {
// Loop animation back and forth. let (nori, tween, line) = crate::turtle_movement::turtle_turn(ori, -*x as f32);
TweeningType::Once, ori = nori;
// Animation time (one way only; for ping-pong it takes 2 seconds seq = seq.then(tween);
// to come back to start). self.lines.push(line);
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, end },
));
ori = end % (2. * PI);
} }
TurtleCommand::Right(_) => todo!(),
TurtleCommand::PenUp => todo!(), TurtleCommand::PenUp => todo!(),
TurtleCommand::PenDown => todo!(), TurtleCommand::PenDown => todo!(),
TurtleCommand::Circle => todo!(), TurtleCommand::Circle => todo!(),
@ -132,6 +137,16 @@ impl TurtleCommands {
} }
} }
#[derive(Inspectable, Default)]
pub enum TurtleGraphElement {
TurtleLine {
start: Vec2,
end: Vec2,
},
#[default]
Noop,
}
#[derive(Clone, Component, Inspectable)] #[derive(Clone, Component, Inspectable)]
pub struct TurtleShape; pub struct TurtleShape;
@ -147,7 +162,7 @@ pub struct Length(f64);
pub struct Angle(f64); pub struct Angle(f64);
#[derive(Component, Inspectable, Default)] #[derive(Component, Inspectable, Default)]
enum TurtleCommand { pub enum TurtleCommand {
Forward(Length), Forward(Length),
Backward(Length), Backward(Length),
Left(Angle), Left(Angle),
@ -190,45 +205,43 @@ fn setup(mut commands: Commands) {
.insert(animator); .insert(animator);
} }
fn draw_lines(
mut commands: Commands,
tcmd: Query<&TurtleCommands>,
mut query_event: EventReader<TweenCompleted>,
) {
for ev in query_event.iter() {
let index = ev.user_data;
let tcmd = tcmd.get_single().unwrap();
let t = tcmd.lines.get(index as usize).unwrap();
match t {
TurtleGraphElement::TurtleLine { start, end } => {
commands.spawn_bundle(GeometryBuilder::build_as(
&Line(*start, *end),
DrawMode::Outlined {
fill_mode: FillMode::color(Color::MIDNIGHT_BLUE),
outline_mode: StrokeMode::new(Color::BLACK, 1.0),
},
Transform::identity(),
));
}
TurtleGraphElement::Noop => (),
}
}
}
/// The sprite is animated by changing its translation depending on the time that has passed since /// The sprite is animated by changing its translation depending on the time that has passed since
/// the last frame. /// the last frame.
fn keypresses( fn keypresses(
//time: Res<Time>, //time: Res<Time>,
keys: Res<Input<KeyCode>>, keys: Res<Input<KeyCode>>,
mut commands: Commands,
mut qry: Query<&mut Animator<Transform>>, mut qry: Query<&mut Animator<Transform>>,
tcmd: Query<&TurtleCommands>, mut tcmd: Query<&mut TurtleCommands>,
) { ) {
if keys.just_pressed(KeyCode::W) { if keys.just_pressed(KeyCode::W) {
let tcmd = tcmd.single(); let mut tcmd = tcmd.single_mut();
let c = tcmd.generate_tweenable(); let c = tcmd.generate_tweenable();
let mut shap = qry.single_mut(); let mut shap = qry.single_mut();
shap.set_tweenable(c); 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.),
},
))); */
} }
} }

60
src/turtle_movement.rs Normal file
View File

@ -0,0 +1,60 @@
use std::{f32::consts::PI, time::Duration};
use bevy::prelude::{Transform, Vec2};
use bevy_tweening::{
lens::{TransformPositionLens, TransformRotateZLens},
EaseFunction, Tween, TweeningType,
};
use crate::turtle::TurtleGraphElement;
pub fn turtle_turn(
orientation: f32,
angle_to_turn: f32,
) -> (f32, Tween<Transform>, TurtleGraphElement) {
let start = orientation;
let end = orientation + (angle_to_turn * PI / 180.);
let animation = 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_millis(500),
// 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, end },
);
let line = TurtleGraphElement::Noop;
let orientation = end % (2. * PI);
(orientation, animation, line)
}
pub fn turtle_move(
position: Vec2,
orientation: f32,
length: f32,
index: f32,
) -> (Vec2, Tween<Transform>, TurtleGraphElement) {
let start = position;
let end = position + (Vec2::from_angle(orientation) * length);
let turtle_movement_animation = Tween::new(
// accelerate and decelerate
EaseFunction::QuadraticInOut,
// Loop animation back and forth.
TweeningType::Once,
// later to be controlled by speed
Duration::from_millis(500),
// set the start and end of the animation
TransformPositionLens {
start: start.extend(0.),
end: end.extend(0.),
},
)
.with_completed_event(index as u64);
let line = TurtleGraphElement::TurtleLine { start, end };
(end, turtle_movement_animation, line)
}