By Sunjay Varma
Link to slides: slides.com/sunjay/tour-of-turtle
RustConf 2018
Link to slides: slides.com/sunjay/tour-of-turtle
@sunjay03
@sunjay03
Online Tutorials/Websites
Podcasts/YouTube Channels
Even more resources listed here:
@sunjay03
My goal with turtle is to create the resources and community we need in order to make Rust a language that anyone can learn.
@sunjay03
@sunjay03
Pen
Turtle Legs?
Turtle Shell
Turtle
@sunjay03
@sunjay03
Source code for these images can be found in the examples/ directory in the turtle GitHub repo
Movement & Rotation:
Speed, Position, & Heading:
Pen Control:
Shape Filling & Turtle Visibility:
See the complete list in the documentation: docs.rs/turtle
@sunjay03
TO Square
REPEAT 4 [ FD 100 RT 90 ]
END
TO Flower
SETPC [255 000 255] SETPENSIZE [4 4]
CS HT REPEAT 36 [ PU FD 4 PD Square LT 10 ]
SETPENCOLOR [0 0 0] SETPENSIZE [1 1] PU HOME PD
END
Flower
"flower.lgo" from:
vlado.fmf.uni-lj.si/educa/logo/ferdoe.htm
The Turtle Robot
The Logo Programming Language
@sunjay03
Fun fact: My mom introduced me to Logo when I was 12 and I used it to draw a lot of pretty neat pictures back in the day.
The Python turtle Module
The Rust turtle Crate
import turtle
for i in xrange(4):
turtle.forward(200)
turtle.right(90)
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
for _ in 0..4 {
turtle.forward(200.0);
turtle.right(90.0);
}
}
Modifies "global mutable state" in the turtle module
Creates a new turtle explicitly
The "mut" on the variable above lets us modify the position and rotation of the turtle here
@sunjay03
Tells you exactly how to fix the error
Image from: examples/heart.rs in turtle GitHub repo
@sunjay03
extern crate turtle;
use turtle::{Turtle, Color};
fn main() {
let mut turtle = Turtle::new();
turtle.drawing_mut().set_background_color("#112244");
turtle.wait_for_click();
turtle.pen_up();
turtle.backward(160.0);
turtle.right(90.);
turtle.forward(110.);
turtle.pen_down();
turtle.set_speed("faster");
dragon(&mut turtle, -90., 11, 0., 255.);
turtle.hide();
}
/// Draw the dragon curve by simulating folding a strip of paper
fn dragon(
turtle: &mut Turtle,
fold_direction: f64,
num_folds: usize,
color_start: f64,
color_end: f64
) {
let color_mid = (color_start + color_end) * 0.5;
if num_folds == 0 {
// mapping a color number 0-255 to an rgb gradient.
turtle.set_pen_color(Color {
red: ((color_mid - 128.).abs() * 2.).floor(),
green: color_mid,
blue: 160.,
alpha: 1.,
});
return turtle.forward(10.);
}
// draw a left to right strip (which has a left turn in the middle)
dragon(turtle, -90., num_folds - 1, color_start, color_mid);
turtle.right(fold_direction);
// draw a right to left strip (which has a right turn in the middle)
dragon(turtle, 90., num_folds - 1, color_mid, color_end);
}
This code only gives instructions to the turtle and ignores the window, events, etc.
There is no event loop, window management, or rendering code here.
Code from examples/dragon.rs in turtle GitHub repo
Contributed by @exoticorn
@sunjay03
"Manish asked himself: Is that an event loop?"
User interacts with your application
Application renders your drawings on the screen...
Event loop quickly switches back and forth between these
...and runs your program as fast as possible
Hmm...
*click*
*type*
*click*
Wow! Sunjay is SO cool!
@sunjay03
main thread
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
for _ in 0..4 {
turtle.forward(200.0);
turtle.right(90.0);
}
}
background thread
spawns new thread
waits for the window to be closed before ending the main thread
opens window
starts drawing & handling events
sends drawing command messages
@sunjay03
share state without blocking each other for too long
@sunjay03
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
for _ in 0..4 {
turtle.forward(200.0);
turtle.right(90.0);
}
}
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
let mut i = 0;
while turtle.is_window_open() {
turtle.render();
if i < 4 {
turtle.forward(200.0);
turtle.right(90.0);
i += 1;
}
}
}
manually managing the event loop
@sunjay03
main thread
extern crate turtle;
use turtle::Turtle;
fn main() {
let mut turtle = Turtle::new();
for _ in 0..4 {
turtle.forward(200.0);
turtle.right(90.0);
}
}
background thread
opens window
starts drawing & handling events
@sunjay03
spawns new thread
waits for the window to be closed before ending the main thread
sends drawing command messages
share state without blocking each other for too long
process
process
between processes
keep state in sync between both processes
main thread #2
#1
#1
The PR that saved the day: github.com/sunjay/turtle/pull/31
@sunjay03
@sunjay03
@sunjay03
@sunjay03
@sunjay03
@sunjay03
Image from examples/maze in turtle GitHub repo
@sunjay03
Tips to make your crates accessible to a wider audience
Image from: github.com/sunjay/turtle/pull/39
@sunjay03
Docs · Audience · Examples · Guide
.
.
Level of experience
You don't need to be doing this...
.
.
Level of experience
.
.
Level of experience
...in order to do this
.
.
Level of experience
@sunjay03
@sunjay03
cargo test
Runs all of the tests in a Rust project
--features test
Required by turtle to avoid lots of problems
#[cfg(all(test, not(feature = "test")))]
compile_error!("Make sure you run tests with `cargo test --features test`");
@sunjay03
@sunjay03
@sunjay03
Links to websites that explain concepts so that we don't have to explain them ourselves
@sunjay03
Help people get around your documentation quickly
@sunjay03
@sunjay03
@sunjay03
@sunjay03
For demonstrating a specific method:
For full examples of using your crate:
cargo run --example circle
These examples are tested automatically
@sunjay03
@sunjay03
Read the full guidelines here:
Please go try turtle out!
@sunjay03
Thank you everyone who contributes code and everyone who opens issues!
@sunjay03
Link to slides: slides.com/sunjay/tour-of-turtle