Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users

Dashboard
Notifications
Mark all as read
Q&A

Strange change of object lightness and colour in Nannou application

+5
−0

Building a Nannou App from their template. I want a circle to slowly fade in color and randomly change color when hitting the boundary of the window. But there is something strange going on when updating the colors.

My preamble looks like this:

use nannou::prelude::*;
use rand::Rng;

The model consists of a circle and a boundary.

struct Model {
     // so this is a window id called _window -- I guess.
     _window: window::Id,
    circle: Circle,
    boundary: Boundary,
}

The boundary is just the outline of the application window and the circle has a diameter, position, velocity and color.

struct Boundary {
    x_min: f32,
    x_max: f32,
    y_min: f32,
    y_max: f32,
}
struct Circle {
    d: f32, // diameter
    center: Point2,
    vel: Point2, 
    color: Hsl, 
}

Here is my model function:

fn model(app: &App) -> Model {
    let _window = app.new_window().size(512, 512).view(view).build().unwrap();
    // add the coordinates to a struct and add it to the model
    let circle = Circle {
        d: 50.0,
        center: pt2(-50.0, 167.0),
        vel: pt2(1.3, -0.9),
        color: hsl(154.1, 100.0, 85.0),
    };
    let boundary = Boundary {
        x_min: app.window_rect().x.start,
        x_max: app.window_rect().x.end,
        y_min: app.window_rect().y.start,
        y_max: app.window_rect().y.end,
    };
    Model {
        _window,
        circle,
        boundary,
    }
}

I want three things to happen:

  • The circle to bounce off of the boundary. (This works)
  • The lightness of the color of the circle to slowly reduce at every time step.(Not Working)
  • The color of the circle to randomly change whenever the circle hits the wall(seems to work for a split second)

This is how I update the model:

fn update(_app: &App, _model: &mut Model, _update: Update) {
    // move circle by velocity
    _model.circle.center.x += _model.circle.vel.x;
    _model.circle.center.y += _model.circle.vel.y;
    // update color
    _model.circle.update_color();
    // bounce of the wall
    _model.circle.bounce_wall(&_model.boundary);
}

I created the update_color and bounce_wall functions for my Circle:

impl Circle {
    fn update_color(&mut self) {
        let mut newlight = self.color.lightness - 0.1;
        if newlight < 0.0 {
            newlight = 0.0;
        }
        self.color = hsl(
            self.color.hue.to_positive_degrees(),
            self.color.saturation,
            newlight,
        );
    }
    fn bounce_wall(&mut self, boundary: &Boundary) {
        // all the random number stuff is stolen from
        // https://rust-lang-nursery.github.io/rust-cookbook/algorithms/randomness.html
        let mut rng = rand::thread_rng(); // rng = random number generator
        if self.center.x + 0.5 * self.d > boundary.x_max
            || self.center.x - 0.5 * self.d < boundary.x_min
        {
            self.color = hsl(rng.gen_range(0.0..360.0), rng.gen_range(0.0..100.0), 85.0);
            self.vel.x = -self.vel.x;
        }
        if self.center.y + 0.5 * self.d > boundary.y_max
            || self.center.y - 0.5 * self.d < boundary.y_min
        {
            self.color = hsl(rng.gen_range(0.0..360.0), rng.gen_range(0.0..100.0), 85.0);
            self.vel.y = -self.vel.y;
        }
    }
}

My view function looks like this:

fn view(app: &App, _model: &Model, frame: Frame) {
    let draw = app.draw();
    draw.background().color(GRAY);
    println!(
        "new color lightness is ({})",
        _model.circle.color.into_components().2
    );
    let ellipse = draw.ellipse();
    ellipse
        .color(_model.circle.color)
        .x_y(_model.circle.center.x, _model.circle.center.y)
        .w(_model.circle.d)
        .h(_model.circle.d);
    draw.to_frame(app, &frame).unwrap();
}

Here is what is happening that I do not understand:

  • The lightness of the circle that the view function prints to the command line does go down but the color of the circle does not change at all. Why?
  • When bouncing of a wall, the color of the circle visibly changes for a very brief moment to some random color but then goes back to the initial color. So it works but is reset somehow?
  • When I remove the random color changing from the bounce_wall() function, the color of the circle switches to black once lightness reaches 0. So only changing the color to black is permanent?

Edit: Thanks to comments by elgonzo the solution was quite easy.

hsl expects the first component (hue) to be in [0.0, 1.0] instead of [0.0, 360.0] and the third components (lightness) to be in [0.0, 1.0] instead of [0.0, 100.0].

So providing a lightness value that is slowly reducing from 1.0 is creating the effect I wanted.

Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

3 comment threads

Please post the answer as an answer (1 comment)
Post title (1 comment)
HSL values in range? (5 comments)

1 answer

+3
−0

Thanks to comments by elgonzo the solution was quite easy.

hsl expects the first component (hue) to be in [0.0, 1.0] instead of [0.0, 360.0] and the third components (lightness) to be in [0.0, 1.0] instead of [0.0, 100.0].

So providing a lightness value that is slowly reducing from 1.0 is creating the effect I wanted.

Why does this post require moderator attention?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »