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}