add a macro for simpler first examples.

This commit is contained in:
2025-10-12 16:13:25 +02:00
parent 453e8e39bd
commit cef63ca32a
26 changed files with 902 additions and 453 deletions
+1
View File
@@ -9,6 +9,7 @@ macroquad = "0.4"
tween = "2.1.0"
lyon = "1.0"
tracing = { version = "0.1", features = ["log"], default-features = false }
turtle-lib-macroquad-macros = { path = "../turtle-lib-macroquad-macros" }
[dev-dependencies]
# For examples and testing
+62 -5
View File
@@ -22,17 +22,74 @@ The main turtle graphics library built on Macroquad with Lyon tessellation.
- Frame-rate independent animation
- Live fill preview during circle/arc drawing
## Quick Start
### Using the `turtle_main` Macro (Recommended for Beginners)
The easiest way to create turtle programs is with the `turtle_main` macro:
```rust
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[turtle_main("My First Drawing")]
fn my_drawing(turtle: &mut TurtlePlan) {
turtle.set_pen_color(RED);
turtle.forward(100.0);
turtle.right(90.0);
turtle.forward(100.0);
}
```
The macro automatically handles:
- Window creation and setup
- Turtle initialization
- Rendering loop
- Quit handling (ESC or Q keys)
### Manual Setup (For Advanced Use)
For more control over the application loop:
```rust
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[macroquad::main("Turtle")]
async fn main() {
let mut turtle = create_turtle();
turtle.forward(100.0).right(90.0);
let mut app = TurtleApp::new().with_commands(turtle.build());
loop {
clear_background(WHITE);
app.update();
app.render();
next_frame().await;
}
}
```
## Quick Examples
All examples now use the `turtle_main` macro for simplicity:
```bash
# Run from this directory
cargo run --example square # Basic square drawing
cargo run --example yinyang # Multi-contour fills with holes
cargo run --example fill_advanced # Self-intersecting fills
cargo run --example koch # Recursive fractals
cargo run --example fill_demo # Multiple independent fills
cargo run --example hello_turtle # Minimal 10-line example
cargo run --example macro_demo # Simple square with macro
cargo run --example square # Basic square drawing
cargo run --example shapes # Different turtle shapes
cargo run --example yinyang # Multi-contour fills with holes
cargo run --example koch # Recursive fractals
cargo run --example fill_demo # Fill with holes (donut)
cargo run --example cheese_macro # Cheese example using macro
cargo run --example fill_advanced # Complex shapes (manual setup)
```
Most examples use `turtle_main` for simplicity. A few keep manual setup for custom UI or logging.
## Architecture Highlights
### Rendering Pipeline
@@ -0,0 +1,66 @@
//! Cheese example using the turtle_main macro
//!
//! This is a simplified version of cheese.rs that demonstrates how the
//! turtle_main macro reduces boilerplate code.
use turtle_lib_macroquad::*;
#[turtle_main("Cheese with Holes - Using Macro")]
fn draw_cheese(turtle: &mut TurtlePlan) {
// Set fill color to yellow (cheese color!)
turtle.set_pen_color(ORANGE);
turtle.set_pen_width(3.0);
turtle.set_fill_color(YELLOW);
println!("=== Starting cheese fill ===");
turtle.begin_fill();
// Draw outer boundary (large square)
println!("Drawing outer square boundary...");
for _ in 0..4 {
turtle.forward(400.0);
turtle.right(90.0);
}
// Close outer contour and start drawing holes
println!("Closing outer contour with pen_up");
turtle.pen_up();
// Draw triangular hole in the middle
println!("Drawing triangular hole...");
turtle.go_to(vec2(200.0, 120.0));
turtle.pen_down(); // Start new contour for hole
for _ in 0..3 {
turtle.forward(160.0);
turtle.right(120.0);
}
println!("Closing triangle contour with pen_up");
turtle.pen_up(); // Close triangle hole contour
// Draw circular hole (top-left) using circle_left
println!("Drawing circular hole (top-left) with circle_left...");
turtle.go_to(vec2(100.0, 100.0));
turtle.pen_down(); // Start new contour for hole
turtle.circle_left(30.0, 360.0, 36); // radius=30, full circle, 36 steps
println!("Closing circle contour with pen_up");
turtle.pen_up(); // Close circle hole contour
// Draw circular hole (bottom-right) using circle_right
println!("Drawing circular hole (bottom-right) with circle_right...");
turtle.go_to(vec2(280.0, 280.0));
turtle.pen_down(); // Start new contour for hole
turtle.circle_right(40.0, 360.0, 36); // radius=40, full circle, 36 steps
println!("Closing circle contour with pen_up");
turtle.pen_up(); // Close circle hole contour
// End fill - Lyon will automatically create holes!
println!("Calling end_fill - Lyon should create holes now!");
turtle.end_fill();
// Set animation speed
turtle.set_speed(300);
println!("Building and executing turtle plan...");
}
+20 -37
View File
@@ -1,46 +1,29 @@
//! Test circle_left and circle_right commands
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[macroquad::main("Circle Test")]
async fn main() {
// Create a turtle plan
let mut plan = create_turtle();
plan.shape(ShapeType::Turtle);
#[turtle_main("Circle Test")]
fn draw(turtle: &mut TurtlePlan) {
turtle.shape(ShapeType::Turtle);
// Draw some circles
plan.set_pen_color(RED);
plan.set_pen_width(0.5);
plan.left(90.0);
plan.set_speed(999);
plan.circle_left(100.0, 540.0, 72); // partial circle to the left
turtle.set_pen_color(RED);
turtle.set_pen_width(0.5);
turtle.left(90.0);
turtle.set_speed(999);
turtle.circle_left(100.0, 540.0, 72); // partial circle to the left
plan.forward(150.0);
plan.set_speed(100);
plan.set_pen_color(BLUE);
plan.circle_right(50.0, 270.0, 72); // partial circle to the right
// Set animation speed
plan.set_speed(20);
plan.forward(150.0);
plan.circle_left(50.0, 180.0, 12);
plan.circle_right(50.0, 180.0, 12);
turtle.forward(150.0);
turtle.set_speed(100);
turtle.set_pen_color(BLUE);
turtle.circle_right(50.0, 270.0, 72); // partial circle to the right
// Set animation speed
turtle.set_speed(20);
turtle.forward(150.0);
turtle.circle_left(50.0, 180.0, 12);
turtle.circle_right(50.0, 180.0, 12);
plan.set_speed(700);
plan.set_pen_color(GREEN);
plan.circle_left(50.0, 180.0, 36); // Half circle to the left
// Create turtle app with animation (speed = 100 pixels/sec)
let mut app = TurtleApp::new().with_commands(plan.build());
// Main loop
loop {
clear_background(WHITE);
// Update and render
app.update();
app.render();
next_frame().await
}
turtle.set_speed(700);
turtle.set_pen_color(GREEN);
turtle.circle_left(50.0, 180.0, 36); // Half circle to the left
}
@@ -1,31 +1,13 @@
//! Test circle_left and circle_right commands
//! Test direction and movement commands
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[macroquad::main("Circle Test")]
async fn main() {
// Create a turtle plan
let mut plan = create_turtle();
#[turtle_main("Direction Test")]
fn draw(turtle: &mut TurtlePlan) {
// Set animation speed
plan.set_speed(50);
plan.right(45.0);
plan.forward(100.0);
plan.right(45.0);
plan.forward(100.0);
// Create turtle app with animation (speed = 100 pixels/sec)
let mut app = TurtleApp::new().with_commands(plan.build());
// Main loop
loop {
clear_background(WHITE);
// Update and render
app.update();
app.render();
next_frame().await
}
turtle.set_speed(50);
turtle.right(45.0);
turtle.forward(100.0);
turtle.right(45.0);
turtle.forward(100.0);
}
@@ -1,4 +1,6 @@
//! Advanced fill example with multiple holes and complex shapes
//!
//! This example uses manual setup to demonstrate custom window size and UI elements.
use macroquad::{miniquad::window::set_window_size, prelude::*};
use turtle_lib_macroquad::*;
+20 -32
View File
@@ -1,55 +1,43 @@
//! Fill demonstration with holes
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[macroquad::main("Fill Demo")]
async fn main() {
let mut t = create_turtle();
#[turtle_main("Fill Demo")]
fn draw(turtle: &mut TurtlePlan) {
// Example from requirements: circle with hole (like a donut)
t.set_pen_color(BLUE);
t.set_pen_width(3.0);
t.right(90.0);
turtle.set_pen_color(BLUE);
turtle.set_pen_width(3.0);
turtle.right(90.0);
// Set fill color and begin fill
t.set_fill_color(RED);
t.begin_fill();
turtle.set_fill_color(RED);
turtle.begin_fill();
// Outer circle
t.circle_right(150.0, 360.0, 72);
turtle.circle_right(150.0, 360.0, 72);
// Move to start of inner circle (hole)
// pen_up doesn't matter for fill - vertices still recorded!
t.pen_up();
t.forward(50.0);
t.pen_down();
turtle.pen_up();
turtle.forward(50.0);
turtle.pen_down();
// Inner circle (creates a hole)
t.circle_right(150.0, 360.0, 72);
turtle.circle_right(150.0, 360.0, 72);
t.end_fill();
turtle.end_fill();
// Draw a square with no fill
t.pen_up();
t.forward(100.0);
t.pen_down();
t.set_pen_color(GREEN);
turtle.pen_up();
turtle.forward(100.0);
turtle.pen_down();
turtle.set_pen_color(GREEN);
for _ in 0..4 {
t.forward(100.0);
t.right(90.0);
turtle.forward(100.0);
turtle.right(90.0);
}
// Set animation speed
t.set_speed(100);
let mut app = TurtleApp::new().with_commands(t.build());
loop {
clear_background(WHITE);
app.update();
app.render();
next_frame().await
}
turtle.set_speed(100);
}
@@ -1,12 +1,9 @@
//! Example matching the original requirements exactly
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[macroquad::main("Fill Example - Original Requirements")]
async fn main() {
let mut turtle = create_turtle();
#[turtle_main("Fill Example - Original Requirements")]
fn draw(turtle: &mut TurtlePlan) {
turtle.right(90.0);
turtle.set_pen_width(3.0);
turtle.set_speed(900);
@@ -37,30 +34,4 @@ async fn main() {
// Set speed for animation
turtle.set_speed(200);
let mut app = TurtleApp::new().with_commands(turtle.build());
loop {
clear_background(WHITE);
app.update();
app.render();
// Instructions
draw_text(
"Fill Example - Circle filled with red, square not filled",
10.0,
20.0,
20.0,
BLACK,
);
draw_text(
"Mouse: drag to pan, scroll to zoom",
10.0,
40.0,
16.0,
DARKGRAY,
);
next_frame().await
}
}
@@ -0,0 +1,14 @@
//! Minimal turtle example - just 10 lines!
//!
//! This is the simplest possible turtle program using the macro.
use turtle_lib_macroquad::*;
#[turtle_main("Hello Turtle")]
fn hello() {
turtle.set_pen_color(BLUE);
for _ in 0..4 {
turtle.forward(100.0);
turtle.right(90.0);
}
}
+19 -32
View File
@@ -1,50 +1,37 @@
//! Koch snowflake fractal example
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
fn koch(depth: u32, plan: &mut TurtlePlan, distance: f32) {
fn koch(depth: u32, turtle: &mut TurtlePlan, distance: f32) {
if depth == 0 {
plan.forward(distance);
turtle.forward(distance);
} else {
let new_distance = distance / 3.0;
koch(depth - 1, plan, new_distance);
plan.left(60.0);
koch(depth - 1, plan, new_distance);
plan.right(120.0);
koch(depth - 1, plan, new_distance);
plan.left(60.0);
koch(depth - 1, plan, new_distance);
koch(depth - 1, turtle, new_distance);
turtle.left(60.0);
koch(depth - 1, turtle, new_distance);
turtle.right(120.0);
koch(depth - 1, turtle, new_distance);
turtle.left(60.0);
koch(depth - 1, turtle, new_distance);
}
}
#[macroquad::main("Koch Snowflake")]
async fn main() {
let mut plan = create_turtle();
#[turtle_main("Koch Snowflake")]
fn draw(turtle: &mut TurtlePlan) {
// Position turtle
plan.set_speed(1001);
plan.pen_up();
plan.backward(150.0);
turtle.set_speed(1001);
turtle.pen_up();
turtle.backward(150.0);
plan.pen_down();
turtle.pen_down();
// Draw Koch snowflake (triangle of Koch curves)
for _ in 0..3 {
koch(4, &mut plan, 300.0);
plan.right(120.0);
plan.set_speed(1200);
koch(4, turtle, 300.0);
turtle.right(120.0);
turtle.set_speed(1200);
}
plan.hide(); // Hide turtle when done
// Create app with animation
let mut app = TurtleApp::new().with_commands(plan.build());
loop {
clear_background(WHITE);
app.update();
app.render();
next_frame().await
}
turtle.hide(); // Hide turtle when done
}
@@ -17,6 +17,8 @@
//! RUST_LOG=turtle_lib_macroquad::tessellation=debug cargo run --example logging_example
//! RUST_LOG=turtle_lib_macroquad::execution=debug cargo run --example logging_example
//! ```
//!
//! Note: This example uses manual setup to demonstrate custom initialization logic.
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
@@ -27,11 +29,10 @@ async fn main() {
// This will respect the RUST_LOG environment variable
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| {
// Default to showing info-level logs if RUST_LOG is not set
tracing_subscriber::EnvFilter::new("turtle_lib_macroquad=info")
}),
tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
// Default to showing info-level logs if RUST_LOG is not set
tracing_subscriber::EnvFilter::new("turtle_lib_macroquad=info")
}),
)
.with_target(true) // Show which module the log came from
.with_thread_ids(false)
@@ -40,7 +41,9 @@ async fn main() {
.init();
tracing::info!("Starting turtle graphics example with logging enabled");
tracing::info!("Try running with: RUST_LOG=turtle_lib_macroquad=debug cargo run --example logging_example");
tracing::info!(
"Try running with: RUST_LOG=turtle_lib_macroquad=debug cargo run --example logging_example"
);
// Create a turtle plan with fill operations to see detailed logging
let mut t = create_turtle();
@@ -0,0 +1,17 @@
//! Simple demo of the turtle_main macro
//!
//! This example shows how the turtle_main macro simplifies turtle programs
//! by automatically handling window setup, turtle creation, and the render loop.
use turtle_lib_macroquad::*;
#[turtle_main("Macro Demo - Simple Square")]
fn draw_square(turtle: &mut TurtlePlan) {
turtle.set_pen_color(BLUE);
turtle.set_pen_width(3.0);
for _ in 0..4 {
turtle.forward(150.0);
turtle.right(90.0);
}
}
@@ -0,0 +1,17 @@
//! Demo of the turtle_main macro with inline code
//!
//! This example shows that you can write your turtle code directly
//! in the function body without taking a turtle parameter.
use turtle_lib_macroquad::*;
#[turtle_main("Macro Demo - Inline Spiral")]
fn draw_spiral() {
turtle.set_pen_color(RED);
turtle.set_pen_width(2.0);
for i in 0..36 {
turtle.forward(i as f32 * 3.0);
turtle.right(25.0);
}
}
@@ -0,0 +1,57 @@
//! Comprehensive macro example showing various turtle features
//!
//! This example demonstrates:
//! - Colors and pen settings
//! - Fills
//! - Circles
//! - Animation speed
use turtle_lib_macroquad::*;
#[turtle_main("Turtle Macro - Full Demo")]
fn full_demo(turtle: &mut TurtlePlan) {
// Draw a colorful flower
turtle.set_speed(200);
// Center the drawing
turtle.pen_up();
turtle.go_to(vec2(200.0, 300.0));
turtle.pen_down();
// Draw petals
for i in 0..8 {
let hue = i as f32 / 8.0;
let color = Color::from_rgba(
((hue * 360.0).to_radians().sin() * 127.0 + 128.0) as u8,
((hue * 360.0 + 120.0).to_radians().sin() * 127.0 + 128.0) as u8,
((hue * 360.0 + 240.0).to_radians().sin() * 127.0 + 128.0) as u8,
255,
);
turtle.set_fill_color(color);
turtle.set_pen_color(color);
turtle.begin_fill();
// Draw a petal using circles
turtle.circle_left(50.0, 180.0, 20);
turtle.left(90.0);
turtle.circle_left(50.0, 180.0, 20);
turtle.left(90.0);
turtle.end_fill();
// Move to next petal position
turtle.right(45.0);
}
// Draw center circle
turtle.pen_up();
turtle.go_to(vec2(200.0, 300.0));
turtle.pen_down();
turtle.set_fill_color(YELLOW);
turtle.set_pen_color(ORANGE);
turtle.set_pen_width(2.0);
turtle.begin_fill();
turtle.circle_left(20.0, 360.0, 36);
turtle.end_fill();
}
+36 -53
View File
@@ -1,74 +1,57 @@
//! Nikolaus example - draws a house-like figure
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
fn nikolausquadrat(plan: &mut TurtlePlan, groesse: f32) {
plan.forward(groesse);
plan.left(90.0);
plan.forward(groesse);
plan.left(90.0);
plan.forward(groesse);
plan.left(90.0);
plan.forward(groesse);
plan.left(90.0);
fn nikolausquadrat(turtle: &mut TurtlePlan, groesse: f32) {
turtle.forward(groesse);
turtle.left(90.0);
turtle.forward(groesse);
turtle.left(90.0);
turtle.forward(groesse);
turtle.left(90.0);
turtle.forward(groesse);
turtle.left(90.0);
}
fn nikolausdiag(plan: &mut TurtlePlan, groesse: f32) {
fn nikolausdiag(turtle: &mut TurtlePlan, groesse: f32) {
let quadrat = groesse * groesse;
let diag = (quadrat + quadrat).sqrt();
plan.left(45.0);
plan.forward(diag);
plan.left(45.0);
nikolausdach2(plan, groesse);
plan.left(45.0);
plan.forward(diag);
plan.left(45.0);
turtle.left(45.0);
turtle.forward(diag);
turtle.left(45.0);
nikolausdach2(turtle, groesse);
turtle.left(45.0);
turtle.forward(diag);
turtle.left(45.0);
}
fn nikolausdach2(plan: &mut TurtlePlan, groesse: f32) {
fn nikolausdach2(turtle: &mut TurtlePlan, groesse: f32) {
let quadrat = groesse * groesse;
let diag = (quadrat + quadrat).sqrt();
plan.left(45.0);
plan.forward(diag / 2.0);
plan.left(90.0);
plan.forward(diag / 2.0);
plan.left(45.0);
turtle.left(45.0);
turtle.forward(diag / 2.0);
turtle.left(90.0);
turtle.forward(diag / 2.0);
turtle.left(45.0);
}
fn nikolaus(plan: &mut TurtlePlan, groesse: f32) {
nikolausquadrat(plan, groesse);
nikolausdiag(plan, groesse);
fn nikolaus(turtle: &mut TurtlePlan, groesse: f32) {
nikolausquadrat(turtle, groesse);
nikolausdiag(turtle, groesse);
}
#[macroquad::main("Nikolaus")]
async fn main() {
// Create a turtle plan
let mut plan = create_turtle();
plan.shape(ShapeType::Turtle);
#[turtle_main("Nikolaus")]
fn draw(turtle: &mut TurtlePlan) {
turtle.shape(ShapeType::Turtle);
// Position the turtle (pen up, move, pen down)
plan.pen_up();
plan.backward(80.0);
plan.left(90.0);
plan.forward(50.0);
plan.right(90.0);
plan.pen_down();
turtle.pen_up();
turtle.backward(80.0);
turtle.left(90.0);
turtle.forward(50.0);
turtle.right(90.0);
turtle.pen_down();
nikolaus(&mut plan, 100.0);
// Create turtle app with animation
let mut app = TurtleApp::new().with_commands(plan.build());
// Main loop
loop {
clear_background(WHITE);
// Update and render
app.update();
app.render();
next_frame().await
}
nikolaus(turtle, 100.0);
}
+16 -34
View File
@@ -1,50 +1,32 @@
//! Example demonstrating different turtle shapes
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[macroquad::main("Turtle Shapes")]
async fn main() {
// Create a turtle plan that demonstrates different shapes
let mut plan = create_turtle();
#[turtle_main("Turtle Shapes")]
fn draw(turtle: &mut TurtlePlan) {
// Start with triangle (default)
plan.forward(100.0);
plan.right(90.0);
turtle.forward(100.0);
turtle.right(90.0);
// Change to turtle shape
plan.shape(ShapeType::Turtle);
plan.forward(100.0);
plan.right(90.0);
turtle.shape(ShapeType::Turtle);
turtle.forward(100.0);
turtle.right(90.0);
// Change to circle
plan.shape(ShapeType::Circle);
plan.forward(100.0);
plan.right(90.0);
turtle.shape(ShapeType::Circle);
turtle.forward(100.0);
turtle.right(90.0);
// Change to square
plan.shape(ShapeType::Square);
plan.forward(100.0);
plan.right(90.0);
turtle.shape(ShapeType::Square);
turtle.forward(100.0);
turtle.right(90.0);
// Change to arrow
plan.shape(ShapeType::Arrow);
plan.forward(100.0);
turtle.shape(ShapeType::Arrow);
turtle.forward(100.0);
// Set animation speed
plan.set_speed(50);
// Create turtle app with animation (speed = 100 pixels/sec for slower animation)
let mut app = TurtleApp::new().with_commands(plan.build());
// Main loop
loop {
clear_background(WHITE);
// Update and render
app.update();
app.render();
next_frame().await
}
turtle.set_speed(50);
}
+5 -22
View File
@@ -1,33 +1,16 @@
//! Simple square example demonstrating basic turtle graphics
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[macroquad::main("Turtle Square")]
async fn main() {
// Create a turtle plan
let mut plan = create_turtle();
plan.shape(ShapeType::Turtle);
#[turtle_main("Turtle Square")]
fn draw(turtle: &mut TurtlePlan) {
turtle.shape(ShapeType::Turtle);
// Draw a square
for _ in 0..4 {
plan.forward(100.0).right(90.0);
turtle.forward(100.0).right(90.0);
}
// Set animation speed
plan.set_speed(50);
// Create turtle app with animation
let mut app = TurtleApp::new().with_commands(plan.build());
// Main loop
loop {
clear_background(WHITE);
// Update and render
app.update();
app.render();
next_frame().await
}
turtle.set_speed(50);
}
+11 -28
View File
@@ -1,38 +1,21 @@
//! Simple square example demonstrating basic turtle graphics
//! Star pattern example demonstrating complex turtle patterns
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[macroquad::main("Turtle Square")]
async fn main() {
// Create a turtle plan
let mut plan = create_turtle();
plan.shape(ShapeType::Turtle);
plan.set_speed(1500);
plan.set_pen_width(0.5);
#[turtle_main("Star Pattern")]
fn draw(turtle: &mut TurtlePlan) {
turtle.shape(ShapeType::Turtle);
turtle.set_speed(1500);
turtle.set_pen_width(0.5);
// Draw a 5-pointed star pattern repeatedly
for _i in 0..50000 {
plan.forward(200.0);
plan.circle_left(10.0, 72.0, 1000);
plan.circle_right(5.0, 360.0, 1000);
plan.circle_left(10.0, 72.0, 1000);
turtle.forward(200.0);
turtle.circle_left(10.0, 72.0, 1000);
turtle.circle_right(5.0, 360.0, 1000);
turtle.circle_left(10.0, 72.0, 1000);
}
// Set animation speed
plan.set_speed(300);
// Create turtle app with animation (speed = 100 pixels/sec)
let mut app = TurtleApp::new().with_commands(plan.build());
// Main loop
loop {
clear_background(WHITE);
// Update and render
app.update();
app.render();
next_frame().await
}
turtle.set_speed(300);
}
+23 -40
View File
@@ -1,47 +1,30 @@
//! Simple square example demonstrating basic turtle graphics
//! Yin-Yang symbol example demonstrating multi-contour fills
use macroquad::prelude::*;
use turtle_lib_macroquad::*;
#[macroquad::main("Turtle Square")]
async fn main() {
// Create a turtle plan
let mut t = create_turtle();
t.set_speed(900);
#[turtle_main("Yin-Yang")]
fn draw(turtle: &mut TurtlePlan) {
turtle.set_speed(900);
t.circle_left(90.0, 180.0, 36);
t.begin_fill();
t.circle_left(90.0, 180.0, 36);
t.circle_left(45.0, 180.0, 26);
t.circle_right(45.0, 180.0, 26);
t.pen_up();
t.right(90.0);
t.forward(37.0);
t.left(90.0);
t.pen_down();
t.circle_right(8.0, 360.0, 12);
t.pen_up();
t.right(90.0);
t.forward(90.0);
t.left(90.0);
t.pen_down();
t.circle_right(8.0, 360.0, 12);
t.end_fill();
turtle.circle_left(90.0, 180.0, 36);
turtle.begin_fill();
turtle.circle_left(90.0, 180.0, 36);
turtle.circle_left(45.0, 180.0, 26);
turtle.circle_right(45.0, 180.0, 26);
turtle.pen_up();
turtle.right(90.0);
turtle.forward(37.0);
turtle.left(90.0);
turtle.pen_down();
turtle.circle_right(8.0, 360.0, 12);
turtle.pen_up();
turtle.right(90.0);
turtle.forward(90.0);
turtle.left(90.0);
turtle.pen_down();
turtle.circle_right(8.0, 360.0, 12);
turtle.end_fill();
// Set animation speed
t.set_speed(1000);
// Create turtle app with animation (speed = 100 pixels/sec)
let mut app = TurtleApp::new().with_commands(t.build());
// Main loop
loop {
clear_background(WHITE);
// Update and render
app.update();
app.render();
next_frame().await
}
turtle.set_speed(1000);
}
+31 -1
View File
@@ -3,7 +3,29 @@
//! This library provides a turtle graphics API for creating drawings and animations
//! using the Macroquad game framework.
//!
//! # Example
//! # Quick Start with `turtle_main` Macro
//!
//! The easiest way to create a turtle program is using the `turtle_main` macro:
//!
//! ```no_run
//! use macroquad::prelude::*;
//! use turtle_lib_macroquad::*;
//!
//! #[turtle_main("My Drawing")]
//! fn draw(turtle: &mut TurtlePlan) {
//! turtle.set_pen_color(RED);
//! turtle.forward(100.0);
//! turtle.right(90.0);
//! turtle.forward(100.0);
//! }
//! ```
//!
//! The macro automatically handles window setup, rendering loop, and quit handling.
//!
//! # Manual Setup Example
//!
//! For more control, you can set up the application manually:
//!
//! ```no_run
//! use macroquad::prelude::*;
//! use turtle_lib_macroquad::*;
@@ -43,6 +65,14 @@ pub use shapes::{ShapeType, TurtleShape};
pub use state::{DrawCommand, TurtleState, TurtleWorld};
pub use tweening::TweenController;
// Re-export the turtle_main macro
pub use turtle_lib_macroquad_macros::turtle_main;
// Re-export common macroquad types and colors for convenience
pub use macroquad::prelude::{
vec2, BLACK, BLUE, DARKGRAY, GOLD, GREEN, ORANGE, PURPLE, RED, WHITE, YELLOW,
};
use macroquad::prelude::*;
/// Main turtle application struct