squares/
squares.rs

1/*!
2 * This example uses the draw methods on simple::Window to display some rectangles bouncing around
3 * on screen. You can click anywhere to add a new rectangle.
4 */
5
6extern crate rand;
7use rand::random;
8
9extern crate simple;
10use simple::{Event, Rect, Window};
11
12static SCREEN_WIDTH: u16 = 1280;
13static SCREEN_HEIGHT: u16 = 720;
14
15/// Return an f32 in the interval [0, upper_bound]
16/// Used to generate random positions for Square.
17fn rand_up_to(upper_bound: f32) -> f32 {
18    random::<f32>().abs() * upper_bound
19}
20
21/// Square is our game object. It has a position, movement vector, and color.
22#[derive(Debug, Copy, Clone)]
23struct Square {
24    x: f32,
25    y: f32,
26    speed_x: f32,
27    speed_y: f32,
28    color: (u8, u8, u8, u8),
29}
30
31impl Square {
32    /// Generate a Square with random speed and color starting at the point you specify
33    fn new_at_position(x: f32, y: f32) -> Self {
34        // generate a random angle and then use that angle to calculate the initial speed_x and
35        // speed_y. We do this because it simplifies bouncing logic later in the update function.
36        // The multiplication here is because random::<f32> appears to generate a value between 0
37        // and 1, so we have to expand that range to [0, 2*PI] to get a full distribution of
38        // possible angles.
39        let angle: f32 = rand_up_to(3.141592 * 2.0);
40
41        Square {
42            x: x,
43            y: y,
44            speed_x: angle.sin() * 8.0,
45            speed_y: angle.cos() * 8.0,
46            color: (random(), random(), random(), 255), // color is totally random
47        }
48    }
49
50    /// Generate a totally random new Square
51    fn new() -> Self {
52        Square::new_at_position(
53            rand_up_to(SCREEN_WIDTH as f32),
54            rand_up_to(SCREEN_HEIGHT as f32),
55        )
56    }
57
58    /// Move the Square the distance it needs to travel for one frame.
59    fn update(&mut self) {
60        self.x += self.speed_x;
61        self.y += self.speed_y;
62
63        if self.x < 0.0 || self.x > SCREEN_WIDTH as f32 {
64            self.speed_x *= -1f32;
65        }
66        if self.y < 0.0 || self.y > SCREEN_HEIGHT as f32 {
67            self.speed_y *= -1f32;
68        }
69    }
70
71    /// Blit a square representing this object onto the Window.
72    fn draw(&self, app: &mut Window) {
73        app.set_color(self.color.0, self.color.1, self.color.2, self.color.3);
74        app.fill_rect(Rect::new(self.x as i32 - 32, self.y as i32 - 32, 64, 64));
75    }
76}
77
78fn main() {
79    // Create an application
80    let mut app = Window::new("Squares", SCREEN_WIDTH, SCREEN_HEIGHT);
81
82    // Create some objects to live in the application
83    let mut squares = vec![Square::new(), Square::new(), Square::new()];
84
85    // Run the game loop
86    while app.next_frame() {
87        // event handling
88        while app.has_event() {
89            match app.next_event() {
90                // If the user clicks, we add a new Square at the position of the mouse event.
91                Event::Mouse {
92                    is_down: true,
93                    mouse_x,
94                    mouse_y,
95                    ..
96                } => squares.push(Square::new_at_position(mouse_x as f32, mouse_y as f32)),
97
98                _ => (),
99            }
100        }
101
102        app.clear();
103
104        // update and draw
105        for square in squares.iter_mut() {
106            square.update();
107            square.draw(&mut app);
108        }
109    }
110}