Now that we have two functions generating nice, smooth wave movements, let's use them to control our little circle.
If we put these values directly in the ellipse's .x_y()-method we would not see much movement. That's because the sine waves generate values between -1.0 and 1.0 and the coordinates expect a pixel position.
But how wide is our window ? To get a precise idea of this, we can use a handy method called [window_rect](https://docs.rs/nannou/latest/nannou/app/struct.App.html# method.window_rect) which is available in the app variable.
This will give us the boundary of the window as a handy Rect. This is a struct that responds to tons of useful methods that we can use to define the minimum and maximum values of our x and y coordinates respectively to constrain the movements of our circle.
The minimum x value is thus available as:
#![allow(dead_code)]externcrate nannou;
use nannou::prelude::*;
fnmain() {
nannou::app(model).event(event).simple_window(view).run();
}
fnmodel(_app: &App) -> Model {
Model {}
}
structModel {}
fnevent(_app: &App, _model: &mut Model, _event: Event) {}
fnview(app: &App, _model: &Model, _frame: Frame) {
let boundary = app.window_rect();
boundary.left();
}
Using these values, we can map our sine and slowersine values to ranges of values that are within the boundary of our window. To do this, we will use the map_range function available in nannou.
The map_range function takes 5 arguments: val, in_min, in_max, out_min, out_max. The val here is our sinewaves which has a minimum value of -1.0 and a maximum value of 1.0. For the x-coordinate, we then map it to a range of values between the leftmost point and the rightmost point.
#![allow(unused_imports)]externcrate nannou;
use nannou::prelude::*;
fnmain() {
nannou::app(model)
.event(event)
.simple_window(view)
.run();
}
fnmodel(_app: &App) -> Model {
Model {}
}
structModel {}
fnevent(_app: &App, _model: &mut Model, _event: Event) {
}
fnview(app: &App, _model: &Model, frame: Frame) {
let draw = app.draw();
let sine = app.time.sin();
let slowersine = (app.time / 2.0).sin();
let boundary = app.window_rect();
let x = map_range(sine, -1.0, 1.0, boundary.left(), boundary.right());
let y = map_range(slowersine, -1.0, 1.0, boundary.bottom(), boundary.top());
draw.background().color(PLUM);
draw.ellipse().color(STEELBLUE).x_y(x, y);
draw.to_frame(app, &frame).unwrap();
}
And then the same for the y value but using the slowersine variable.
#![allow(unused_imports)]externcrate nannou;
use nannou::prelude::*;
structModel{}
fnmain() {
nannou::app(model)
.event(event)
.simple_window(view)
.run();
}
fnmodel(_app: &App) -> Model {
Model {}
}
fnevent(_app: &App, _model: &mut Model, _event: Event) {
}
fnview(app: &App, _model: &Model, frame: Frame) {
let draw = app.draw();
let sine = app.time.sin();
let slowersine = (app.time / 2.0).sin();
let boundary = app.window_rect();
let x = map_range(sine, -1.0, 1.0, boundary.left(), boundary.right());
let y = map_range(slowersine, -1.0, 1.0, boundary.bottom(), boundary.top());
draw.background().color(PLUM);
draw.ellipse().color(STEELBLUE).x_y(x, y);
draw.to_frame(app, &frame).unwrap();
}
The only thing left to do now is to put this into the arguments of our circle-drawing function.
#![allow(unused_imports)]externcrate nannou;
use nannou::prelude::*;
structModel{}
fnmain() {
nannou::app(model)
.event(event)
.simple_window(view)
.run();
}
fnmodel(_app: &App) -> Model {
Model {}
}
fnevent(_app: &App, _model: &mut Model, _event: Event) {
}
fnview(app: &App, _model: &Model, frame: Frame) {
let draw = app.draw();
let sine = app.time.sin();
let slowersine = (app.time / 2.0).sin();
let boundary = app.window_rect();
let x = map_range(sine, -1.0, 1.0, boundary.left(), boundary.right());
let y = map_range(slowersine, -1.0, 1.0, boundary.bottom(), boundary.top());
draw.background().color(PLUM);
draw.ellipse().color(STEELBLUE).x_y(x, y);
draw.to_frame(app, &frame).unwrap();
}
Your updated view-function should now look something like this:
#![allow(unused_imports)]externcrate nannou;
use nannou::prelude::*;
structModel{}
fnmain() {
nannou::app(model)
.event(event)
.simple_window(view)
.run();
}
fnmodel(_app: &App) -> Model {
Model {}
}
fnevent(_app: &App, _model: &mut Model, _event: Event) {
}
fnview(app: &App, _model: &Model, frame: Frame) {
// Prepare to draw.let draw = app.draw();
// Generate sine wave data based on the time of the applet sine = app.time.sin();
let slowersine = (app.time / 2.0).sin();
// Get boundary of the window (to constrain the movements of our circle)let boundary = app.window_rect();
// Map the sine wave functions to ranges between the boundaries of the windowlet x = map_range(sine, -1.0, 1.0, boundary.left(), boundary.right());
let y = map_range(slowersine, -1.0, 1.0, boundary.bottom(), boundary.top());
// Clear the background to purple.
draw.background().color(PLUM);
// Draw a blue ellipse at the x/y coordinates 0.0, 0.0
draw.ellipse().color(STEELBLUE).x_y(x, y);
draw.to_frame(app, &frame).unwrap();
}