Skip to content

Commit

Permalink
Add tutorials via Rustdoc (#351)
Browse files Browse the repository at this point in the history
Create a series of numbered tutorials that are written in Rustdoc comments, so they are checked in CI and cargo test automatically. These tutorials should allow users to be walked through Quicksilver step-by-step rather than just reading the examples and the API docs.
  • Loading branch information
ryanisaacg committed Sep 13, 2018
1 parent 63f51c1 commit f3cbb8e
Show file tree
Hide file tree
Showing 18 changed files with 927 additions and 28 deletions.
8 changes: 4 additions & 4 deletions Cargo.toml
Expand Up @@ -52,10 +52,6 @@ rodio = { version = "0.8", optional = true }
stdweb = "0.4.9"
webgl_stdweb = "0.2"

[[example]]
name = "basic"
required-features = []

[[example]]
name = "draw-geometry"
required-features = []
Expand Down Expand Up @@ -87,3 +83,7 @@ required-features = ["complex_shapes"]
[[example]]
name = "stopwatch"
required-features = []

[[example]]
name = "camera"
required-features = []
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -63,8 +63,6 @@ fn main() {
Run this with `cargo run` or, if you have the wasm32 toolchain installed, you can build for the web
(instructions below).

You should see a red square in the top-left, and a green circle with a blue rectangle inside it
on the bottom-right.

## Building and Deploying a Quicksilver application

Expand All @@ -87,6 +85,9 @@ files produced (found at "target/wasm32-unknown-unknown/release") and any assets

If you want to test your application locally, use `cargo +nightly web start --target wasm32-unknown-unknown` and open your favorite browser to the port it provides.

## Learning Quicksilver

Currently there isn't a book-like tutorial for Quicksilver, but there

## Optional Features

Expand Down
22 changes: 0 additions & 22 deletions examples/basic.rs

This file was deleted.

66 changes: 66 additions & 0 deletions examples/camera.rs
@@ -0,0 +1,66 @@
// Demonstrate adding a View to the draw-geometry example
// The camera can be controlled with the arrow keys
extern crate quicksilver;

use quicksilver::{
Result,
geom::{Circle, Line, Rectangle, Shape, Transform, Triangle, Vector},
graphics::{Background::Col, Color, View},
input::{Key},
lifecycle::{Settings, State, Window, run},
};

struct Camera {
view: Rectangle
}

impl State for Camera {
// Initialize the struct
fn new() -> Result<Camera> {
Ok(Camera {
view: Rectangle::new_sized((800, 600))
})
}

fn update(&mut self, window: &mut Window) -> Result<()> {
if window.keyboard()[Key::Left].is_down() {
self.view = self.view.translate((-4, 0));
}
if window.keyboard()[Key::Right].is_down() {
self.view = self.view.translate((4, 0));
}
if window.keyboard()[Key::Down].is_down() {
self.view = self.view.translate((0, 4));
}
if window.keyboard()[Key::Up].is_down() {
self.view = self.view.translate((0, -4));
}
window.set_view(View::new(self.view));
Ok(())
}

fn draw(&mut self, window: &mut Window) -> Result<()> {
window.clear(Color::WHITE)?;
window.draw(&Rectangle::new((100, 100), (32, 32)), Col(Color::BLUE));
window.draw_ex(&Rectangle::new((400, 300), (32, 32)), Col(Color::BLUE), Transform::rotate(45), 10);
window.draw(&Circle::new((400, 300), 100), Col(Color::GREEN));
window.draw_ex(
&Line::new((50, 80),(600, 450)).with_thickness(2.0),
Col(Color::RED),
Transform::IDENTITY,
5
);
window.draw_ex(
&Triangle::new((500, 50), (450, 100), (650, 150)),
Col(Color::RED),
Transform::rotate(45) * Transform::scale((0.5, 0.5)),
0
);
Ok(())
}
}

fn main() {
run::<Camera>("Camera", Vector::new(800, 600), Settings::default());
}

19 changes: 19 additions & 0 deletions examples/draw-geometry.rs
@@ -1,4 +1,5 @@
// Draw some multi-colored geometry to the screen
// This is a good place to get a feel for the basic structure of a Quicksilver app
extern crate quicksilver;

use quicksilver::{
Expand All @@ -8,35 +9,53 @@ use quicksilver::{
lifecycle::{Settings, State, Window, run},
};

// A unit struct that we're going to use to run the Quicksilver functions
// If we wanted to store persistent state, we would put it in here.
struct DrawGeometry;

impl State for DrawGeometry {
// Initialize the struct
fn new() -> Result<DrawGeometry> {
Ok(DrawGeometry)
}

fn draw(&mut self, window: &mut Window) -> Result<()> {
// Remove any lingering artifacts from the previous frame
window.clear(Color::WHITE)?;
// Draw a rectangle with a top-left corner at (100, 100) and a width and height of 32 with
// a blue background
window.draw(&Rectangle::new((100, 100), (32, 32)), Col(Color::BLUE));
// Draw another rectangle, rotated by 45 degrees, with a z-height of 10
window.draw_ex(&Rectangle::new((400, 300), (32, 32)), Col(Color::BLUE), Transform::rotate(45), 10);
// Draw a circle with its center at (400, 300) and a radius of 100, with a background of
// green
window.draw(&Circle::new((400, 300), 100), Col(Color::GREEN));
// Draw a line with a thickness of 2 pixels, a red background,
// and a z-height of 5
window.draw_ex(
&Line::new((50, 80),(600, 450)).with_thickness(2.0),
Col(Color::RED),
Transform::IDENTITY,
5
);
// Draw a triangle with a red background, rotated by 45 degrees, and scaled down to half
// its size
window.draw_ex(
&Triangle::new((500, 50), (450, 100), (650, 150)),
Col(Color::RED),
Transform::rotate(45) * Transform::scale((0.5, 0.5)),
0
);
// We completed with no errors
Ok(())
}
}

// The main isn't that important in Quicksilver: it just serves as an entrypoint into the event
// loop
fn main() {
// Run with DrawGeometry as the event handler, with a window title of 'Draw Geometry' and a
// size of (800, 600)
run::<DrawGeometry>("Draw Geometry", Vector::new(800, 600), Settings::default());
}

2 changes: 2 additions & 0 deletions src/lib.rs
Expand Up @@ -128,6 +128,8 @@ pub mod sound;
pub use error::QuicksilverError as Error;
pub use file::load_file;

pub mod tutorials;

/// A Result that returns either success or a Quicksilver Error
pub type Result<T> = ::std::result::Result<T, Error>;
/// Types that represents a "future" computation, used to load assets
Expand Down
81 changes: 81 additions & 0 deletions src/tutorials/_01_basic.rs
@@ -0,0 +1,81 @@
//! Our first tutorial is simple: Just create a blank window.
//!
//! Here's the full source:
//!
//! ```no_run
//! extern crate quicksilver;
//!
//! use quicksilver::{
//! Result,
//! geom::Vector,
//! lifecycle::{State, run}
//! };
//!
//! struct Screen;
//!
//! impl State for Screen {
//! fn new() -> Result<Screen> {
//! Ok(Screen)
//! }
//! }
//!
//! fn main() {
//! run::<Screen>("Hello World", Vector::new(800, 600), Default::default());
//! }
//! ```
//! Let's start with importing what we need from Quicksilver:
//! ```no_run
//! extern crate quicksilver;
//!
//! use quicksilver::{
//! Result,
//! geom::Vector,
//! lifecycle::{State, run}
//! };
//! ```
//!
//! Quicksilver has its own `Result` type, which is just the same as `std::result::Result<T, quicksilver::Error>`.
//! We use `Vector` for anything 2-dimensional: position, speed, or size, for example.
//! `State` is the trait that defines how we handle the core loop of Quicksilver
//! `run` is the function that kicks off the core loop.
//!
//! Next we declare our `State` handler:
//! ```no_run
//! struct Screen;
//! ```
//! It's a unit struct (a struct with no fields) because we don't need to store anything.
//!
//! Now we implement `State` for our handler:
//!
//! ```no_run
//! # use quicksilver::{
//! # Result,
//! # geom::Vector,
//! # lifecycle::{State, run}
//! # };
//! # struct Screen;
//! impl State for Screen {
//! fn new() -> Result<Screen> {
//! Ok(Screen)
//! }
//! }
//! ```
//! All we have to do is implement the `new` function, and Quicksilver will take care of all the other functions.
//! The other functions we could override are `draw`, `update`, and `event`, which will be covered in later tutorials.
//! ```no_run
//! # use quicksilver::{
//! # Result,
//! # geom::Vector,
//! # lifecycle::{State, run}
//! # };
//! # struct Screen;
//! # impl State for Screen {
//! # fn new() -> Result<Screen> {
//! # Ok(Screen)
//! # }
//! # }
//! fn main() {
//! run::<Screen>("Hello World", Vector::new(800, 600), Default::default());
//! }
//! ```
//! Lastly, we create a main that calls `run`, starting the event loop and showing our window

0 comments on commit f3cbb8e

Please sign in to comment.