107 lines
3.3 KiB
Rust
107 lines
3.3 KiB
Rust
//! 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!");
|
|
}
|