add two threading examples
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
//! Example: Game Logic in Separate Thread
|
||||
//!
|
||||
//! This example demonstrates how to run game logic in a separate thread
|
||||
//! while keeping the render loop responsive on the main thread.
|
||||
//!
|
||||
//! The main thread handles rendering and animation, while game logic
|
||||
//! threads can perform blocking operations (like fetching data) and
|
||||
//! send turtle commands via channels.
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use turtle_lib::*;
|
||||
|
||||
#[macroquad::main("Game Logic Threading")]
|
||||
async fn main() {
|
||||
let mut app = TurtleApp::new();
|
||||
|
||||
// Create two turtles and get their command senders
|
||||
let turtle1_tx = app.create_turtle_channel(100);
|
||||
let turtle2_tx = app.create_turtle_channel(100);
|
||||
|
||||
// Spawn first game logic thread
|
||||
let _thread1 = thread::spawn({
|
||||
let tx = turtle1_tx.clone();
|
||||
move || {
|
||||
// Simulate some blocking work (e.g., network request, calculation)
|
||||
println!("Thread 1: Starting work...");
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
|
||||
// Now send turtle commands
|
||||
let mut plan = create_turtle_plan();
|
||||
plan.set_pen_color(BLUE)
|
||||
.forward(100.0)
|
||||
.right(90.0)
|
||||
.forward(100.0)
|
||||
.right(90.0)
|
||||
.forward(100.0)
|
||||
.right(90.0)
|
||||
.forward(100.0);
|
||||
|
||||
tx.send(plan.build())
|
||||
.expect("Failed to send commands for turtle 1");
|
||||
println!("Thread 1: Commands sent!");
|
||||
|
||||
// Send more commands in a loop
|
||||
for i in 0..10 {
|
||||
thread::sleep(Duration::from_millis(300));
|
||||
let mut step = create_turtle_plan();
|
||||
step.right(36.0).forward(50.0);
|
||||
let _ = tx.try_send(step.build());
|
||||
println!("Thread 1: Step {} sent", i + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Spawn second game logic thread
|
||||
let _thread2 = thread::spawn({
|
||||
let tx = turtle2_tx.clone();
|
||||
move || {
|
||||
// Different timing than thread1
|
||||
println!("Thread 2: Starting work...");
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
|
||||
// Draw a circle with turtle2
|
||||
let mut plan = create_turtle_plan();
|
||||
plan.set_pen_color(RED).circle_left(75.0, 360.0, 72);
|
||||
|
||||
tx.send(plan.build())
|
||||
.expect("Failed to send commands for turtle 2");
|
||||
println!("Thread 2: Circle sent!");
|
||||
}
|
||||
});
|
||||
|
||||
// Main render loop
|
||||
let mut frame_count = 0;
|
||||
loop {
|
||||
// Check for quit
|
||||
if macroquad::prelude::is_key_pressed(macroquad::prelude::KeyCode::Escape)
|
||||
|| macroquad::prelude::is_key_pressed(macroquad::prelude::KeyCode::Q)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear background
|
||||
macroquad::prelude::clear_background(WHITE);
|
||||
|
||||
// Process incoming commands from game logic threads
|
||||
// This drains all pending commands from turtle channels
|
||||
app.process_commands();
|
||||
|
||||
// Update animation state (tweening, etc.)
|
||||
app.update();
|
||||
|
||||
// Render the turtles
|
||||
app.render();
|
||||
|
||||
frame_count += 1;
|
||||
if frame_count % 60 == 0 {
|
||||
println!("Rendered {} frames", frame_count);
|
||||
}
|
||||
|
||||
macroquad::prelude::next_frame().await;
|
||||
}
|
||||
|
||||
println!("Finished!");
|
||||
}
|
||||
Reference in New Issue
Block a user