Compare commits
2 Commits
28527e6113
...
b31ac29deb
| Author | SHA1 | Date | |
|---|---|---|---|
| b31ac29deb | |||
| 2199a7803f |
@ -19,3 +19,4 @@ crossbeam = "0.8"
|
|||||||
# For examples and testing
|
# For examples and testing
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
||||||
dialog = "*"
|
dialog = "*"
|
||||||
|
chrono = "0.4"
|
||||||
|
|||||||
56
turtle-lib/examples/bezier.rs
Normal file
56
turtle-lib/examples/bezier.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//! Cubic Bézier curve example
|
||||||
|
//! <https://en.wikipedia.org/wiki/B%C3%A9zier_curve>
|
||||||
|
|
||||||
|
use turtle_lib::{turtle_main, vec2};
|
||||||
|
|
||||||
|
struct CubicBezier {
|
||||||
|
point0: (f32, f32),
|
||||||
|
point1: (f32, f32),
|
||||||
|
point2: (f32, f32),
|
||||||
|
point3: (f32, f32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CubicBezier {
|
||||||
|
/// Returns the value of this curve at the given parameter t (0.0 to 1.0)
|
||||||
|
pub fn at(&self, t: f64) -> (f32, f32) {
|
||||||
|
let t = t as f32;
|
||||||
|
let mt = 1.0 - t; // (1 - t)
|
||||||
|
|
||||||
|
// Cubic Bézier formula from Wikipedia
|
||||||
|
let p0_weight = mt.powi(3);
|
||||||
|
let p1_weight = 3.0 * mt.powi(2) * t;
|
||||||
|
let p2_weight = 3.0 * mt * t.powi(2);
|
||||||
|
let p3_weight = t.powi(3);
|
||||||
|
|
||||||
|
(
|
||||||
|
self.point0.0 * p0_weight
|
||||||
|
+ self.point1.0 * p1_weight
|
||||||
|
+ self.point2.0 * p2_weight
|
||||||
|
+ self.point3.0 * p3_weight,
|
||||||
|
self.point0.1 * p0_weight
|
||||||
|
+ self.point1.1 * p1_weight
|
||||||
|
+ self.point2.1 * p2_weight
|
||||||
|
+ self.point3.1 * p3_weight,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turtle_main("Bézier Curve")]
|
||||||
|
fn draw(turtle: &mut TurtlePlan) {
|
||||||
|
let curve = CubicBezier {
|
||||||
|
point0: (-200.0, -100.0),
|
||||||
|
point1: (-100.0, 400.0),
|
||||||
|
point2: (100.0, -500.0),
|
||||||
|
point3: (300.0, 200.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
let start = curve.at(0.0);
|
||||||
|
turtle.pen_up().go_to(vec2(start.0, start.1)).pen_down();
|
||||||
|
|
||||||
|
let samples = 100;
|
||||||
|
for i in 0..samples {
|
||||||
|
let t = f64::from(i) / f64::from(samples);
|
||||||
|
let point = curve.at(t);
|
||||||
|
turtle.go_to(vec2(point.0, point.1));
|
||||||
|
}
|
||||||
|
}
|
||||||
91
turtle-lib/examples/clock.rs
Normal file
91
turtle-lib/examples/clock.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//! Animated clock example
|
||||||
|
//!
|
||||||
|
//! This example draws an animated clock that shows the current time.
|
||||||
|
//! The clock updates every second to reflect the actual time.
|
||||||
|
|
||||||
|
use chrono::{Local, Timelike};
|
||||||
|
use macroquad::prelude::{clear_background, is_key_pressed, next_frame, KeyCode, WHITE};
|
||||||
|
use turtle_lib::{create_turtle_plan, vec2, DirectionalMovement, Turnable, TurtleApp};
|
||||||
|
|
||||||
|
#[macroquad::main("Clock")]
|
||||||
|
async fn main() {
|
||||||
|
const HOURS: i32 = 12;
|
||||||
|
const MINUTES: f32 = 60.0;
|
||||||
|
const SECONDS: f32 = 60.0;
|
||||||
|
const FULL_CIRCLE: f32 = 360.0;
|
||||||
|
|
||||||
|
let mut app = TurtleApp::new();
|
||||||
|
let mut last_update = Local::now();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
clear_background(WHITE);
|
||||||
|
|
||||||
|
let now = Local::now();
|
||||||
|
|
||||||
|
// Only redraw when the time changes
|
||||||
|
if now.second() != last_update.second() {
|
||||||
|
let mut turtle = create_turtle_plan();
|
||||||
|
turtle.reset().set_speed(1100).left(90.0); // Instant mode for smooth updates
|
||||||
|
|
||||||
|
// Draw the clock circle and hour markers
|
||||||
|
for i in 1..=HOURS {
|
||||||
|
turtle
|
||||||
|
.pen_up()
|
||||||
|
.go_to(vec2(0.0, 0.0))
|
||||||
|
.right(FULL_CIRCLE / HOURS as f32)
|
||||||
|
.forward(205.0);
|
||||||
|
|
||||||
|
let pen_size = if (i) % 3 == 0 { 7.0 } else { 2.0 };
|
||||||
|
turtle
|
||||||
|
.set_pen_width(pen_size)
|
||||||
|
.pen_down()
|
||||||
|
.forward(10.0)
|
||||||
|
.right(90.0)
|
||||||
|
.write_text(format!("{i}"), 2 * pen_size as i32 + 10)
|
||||||
|
.left(90.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the hour hand
|
||||||
|
turtle
|
||||||
|
.pen_up()
|
||||||
|
.go_to(vec2(0.0, 0.0))
|
||||||
|
.set_heading(90.0)
|
||||||
|
.right(FULL_CIRCLE / HOURS as f32 * (now.hour() % 12) as f32)
|
||||||
|
.set_pen_width(5.0)
|
||||||
|
.pen_down()
|
||||||
|
.forward(120.0);
|
||||||
|
|
||||||
|
// Draw the minute hand
|
||||||
|
turtle
|
||||||
|
.pen_up()
|
||||||
|
.go_to(vec2(0.0, 0.0))
|
||||||
|
.set_heading(90.0)
|
||||||
|
.right(FULL_CIRCLE / MINUTES * now.minute() as f32)
|
||||||
|
.set_pen_width(3.0)
|
||||||
|
.pen_down()
|
||||||
|
.forward(150.0);
|
||||||
|
|
||||||
|
// Draw the second hand
|
||||||
|
turtle
|
||||||
|
.pen_up()
|
||||||
|
.go_to(vec2(0.0, 0.0))
|
||||||
|
.set_heading(90.0)
|
||||||
|
.right(FULL_CIRCLE / SECONDS * now.second() as f32)
|
||||||
|
.set_pen_width(1.0)
|
||||||
|
.pen_down()
|
||||||
|
.forward(180.0);
|
||||||
|
|
||||||
|
app = TurtleApp::new().with_commands(turtle.build());
|
||||||
|
last_update = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
app.update();
|
||||||
|
app.render();
|
||||||
|
|
||||||
|
if is_key_pressed(KeyCode::Escape) || is_key_pressed(KeyCode::Q) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_frame().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -368,7 +368,8 @@ impl TurtlePlan {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_heading(&mut self, heading: Precision) -> &mut Self {
|
pub fn set_heading(&mut self, heading: Precision) -> &mut Self {
|
||||||
self.queue.push(TurtleCommand::SetHeading(heading));
|
self.queue
|
||||||
|
.push(TurtleCommand::SetHeading(-heading.to_radians()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,7 +666,6 @@ impl TurtlePlan {
|
|||||||
/// .write_text("End", 16u16);
|
/// .write_text("End", 16u16);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
|
||||||
pub fn write_text<T>(&mut self, text: impl Into<String>, font_size: T) -> &mut Self
|
pub fn write_text<T>(&mut self, text: impl Into<String>, font_size: T) -> &mut Self
|
||||||
where
|
where
|
||||||
T: Into<FontSize>,
|
T: Into<FontSize>,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user