Moved out objects from game module
[kaka/rust-sdl-test.git] / src / core / object / boll.rs
1 use core::level::{Level, IntersectResult::Intersection};
2 use core::object::{Object, Objects, ObjectState};
3 use core::render::Renderer;
4 use geometry::{Point, ToAngle};
5 use sdl2::rect::Rect;
6 use sprites::SpriteManager;
7 use time::Duration;
8
9 ////////// BOLL ////////////////////////////////////////////////////////////////
10
11 pub struct Boll {
12     pos: Point<f64>,
13     vel: Point<f64>,
14     bounces: u8,
15 }
16
17 impl Boll {
18     pub fn new(pos: Point<f64>, vel: Point<f64>, bounces: u8) -> Self {
19         Boll { pos, vel, bounces }
20     }
21 }
22
23 impl Object for Boll {
24
25     fn update(&mut self, objects: &mut Objects, lvl: &Level, _dt: Duration) -> ObjectState {
26         self.vel += lvl.gravity;
27         self.pos += self.vel;
28
29         if let Intersection(wall, pos) = lvl.intersect_walls(self.pos - self.vel, self.pos) {
30             if self.bounces == 0 {
31                 return ObjectState::Dead
32             }
33             self.bounces -= 1;
34             let mut a = wall.normal().mirror(self.vel.to_angle()); // TODO interpolera normalen mellan närliggande väggdelar? bollarna studsar väldigt "kantigt" nu
35             self.pos = pos + Point::from(wall.normal()) * 0.1; // får bollen att inte åka igenom väggen av misstag p.g.a nedan slumpvinkel
36             self.vel = Point::from(a) * self.vel.length() * 0.35;
37
38             // create another boll
39             use rand::distributions::{Distribution, Normal};
40             let mut rng = rand::thread_rng();
41             a += Normal::new(0.0, 0.1).sample(&mut rng).radians(); // TODO slumpen kan ge en vinkel som är under tangenten. vinkel-metoder på väggen istället kanske?
42             use rand::Rng;
43             objects.push(Box::new(Boll {
44                 vel: Point::from(a) * Normal::new(1.0, 0.25).sample(&mut rng) * self.vel.length() * rng.gen_range(0.25, 1.0),
45                 ..*self
46             }));
47         }
48
49         ObjectState::Alive
50     }
51
52     fn render(&self, renderer: &mut Renderer, _sprites: &SpriteManager) {
53         let block = _sprites.get("block");
54         let size = 4 + self.bounces * 6;
55         renderer.blit(block, None, Rect::new(self.pos.x as i32 - size as i32 / 2, self.pos.y as i32 - size as i32 / 2, size as u32, size as u32));
56         // renderer.canvas().set_draw_color((0, self.bounces * 100, 255));
57         // renderer.canvas().draw_point((self.pos.x as i32, self.pos.y as i32)).unwrap();
58     }
59 }