add a threaded clock example
This commit is contained in:
parent
284fcdcb6d
commit
9fda96e439
114
turtle-lib/examples/clock_threaded.rs
Normal file
114
turtle-lib/examples/clock_threaded.rs
Normal file
@ -0,0 +1,114 @@
|
||||
//! Animated clock example using threading
|
||||
//!
|
||||
//! This example demonstrates how to use turtle command channels for animated updates.
|
||||
//! A separate thread generates the clock drawing commands every second while the main
|
||||
//! thread handles rendering via the Macroquad game loop.
|
||||
|
||||
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 (Threaded)")]
|
||||
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 turtle_tx = app.create_turtle_channel(10);
|
||||
|
||||
// Spawn a thread that generates clock commands every second
|
||||
std::thread::spawn(move || {
|
||||
let mut last_second = -1i32;
|
||||
|
||||
loop {
|
||||
let now = Local::now();
|
||||
let current_second = now.second() as i32;
|
||||
|
||||
// Only generate commands when the time changes
|
||||
if current_second != last_second {
|
||||
let mut turtle = create_turtle_plan();
|
||||
turtle.reset().set_speed(1100).left(90.0);
|
||||
|
||||
// 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)
|
||||
.pen_up()
|
||||
.backward(pen_size.max(4.0) + (i / 10) as f32 * 4.0)
|
||||
.pen_down()
|
||||
.write_text(format!("{i}"), 2 * pen_size as i32 + 14)
|
||||
.pen_up()
|
||||
.forward(pen_size.max(4.0) + (i / 10) as f32 * 4.0)
|
||||
.pen_down()
|
||||
.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(7.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);
|
||||
|
||||
// Send the command queue to the main thread
|
||||
let _ = turtle_tx.send(turtle.build());
|
||||
last_second = current_second;
|
||||
}
|
||||
|
||||
// Sleep briefly to avoid busy-waiting (update ~10 times per second)
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
}
|
||||
});
|
||||
|
||||
// Main render loop
|
||||
loop {
|
||||
clear_background(WHITE);
|
||||
|
||||
// Process any pending commands from the worker thread
|
||||
app.process_commands();
|
||||
|
||||
app.update();
|
||||
app.render();
|
||||
|
||||
if is_key_pressed(KeyCode::Escape) || is_key_pressed(KeyCode::Q) {
|
||||
break;
|
||||
}
|
||||
|
||||
next_frame().await;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user