1use crate::dimensions::Dimensions;
2use crate::position::Position;
3use crate::vector::Vector;
4
5pub struct Ball {
7 position: Position,
8 velocity: Vector,
9 power: u16,
10 game_dimensions: Dimensions,
11}
12
13impl Ball {
14 pub fn new(position: Position, game_dimensions: Dimensions, power: u16) -> Ball {
18 Ball {
19 position,
20 velocity: Vector::new(0., 1.),
21 power,
22 game_dimensions,
23 }
24 }
25
26 pub fn x(&self) -> u16 {
28 self.position.x()
29 }
30
31 pub fn y(&self) -> u16 {
33 self.position.y()
34 }
35
36 pub fn power(&self) -> u16 {
38 self.power
39 }
40
41 pub fn update_dimensions(&mut self, dimensions: Dimensions) {
43 self.game_dimensions = dimensions;
44 if self.x() >= self.game_dimensions.width() {
45 self.position = Position::new(self.game_dimensions.width() - 1, self.y())
46 }
47 if self.y() >= self.game_dimensions.height() {
48 self.position = Position::new(self.x(), self.game_dimensions.height() - 1)
49 }
50 }
51
52 pub fn tick(&mut self) {
54 let mut new_position = &self.position + &self.velocity;
55
56 if new_position.x() >= self.game_dimensions.width() {
57 new_position = Position::new(self.game_dimensions.width() - 1, new_position.y())
58 }
59 if new_position.y() >= self.game_dimensions.height() {
60 new_position = Position::new(new_position.x(), self.game_dimensions.height())
61 }
62 if new_position.y() >= self.game_dimensions.height() - 1 {
63 self.velocity = Vector::new(0., 0.)
64 }
65 self.position = new_position
66 }
67
68 pub fn bounce(&mut self, normal: Vector) {
70 self.velocity -= 2. * self.velocity.dot(&normal) * normal;
71 self.velocity.normalise()
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn bounce_works() {
81 let mut ball = Ball::new(Position::new(0, 0), Dimensions::new(100, 100), 1);
82
83 ball.bounce(Vector::new(0., -1.));
86 assert_eq!(ball.velocity, Vector::new(0., -1.));
87 }
88}