Moved out objects from game module
[kaka/rust-sdl-test.git] / src / core / object / boll.rs
diff --git a/src/core/object/boll.rs b/src/core/object/boll.rs
new file mode 100644 (file)
index 0000000..adae989
--- /dev/null
@@ -0,0 +1,59 @@
+use core::level::{Level, IntersectResult::Intersection};
+use core::object::{Object, Objects, ObjectState};
+use core::render::Renderer;
+use geometry::{Point, ToAngle};
+use sdl2::rect::Rect;
+use sprites::SpriteManager;
+use time::Duration;
+
+////////// BOLL ////////////////////////////////////////////////////////////////
+
+pub struct Boll {
+    pos: Point<f64>,
+    vel: Point<f64>,
+    bounces: u8,
+}
+
+impl Boll {
+    pub fn new(pos: Point<f64>, vel: Point<f64>, bounces: u8) -> Self {
+       Boll { pos, vel, bounces }
+    }
+}
+
+impl Object for Boll {
+
+    fn update(&mut self, objects: &mut Objects, lvl: &Level, _dt: Duration) -> ObjectState {
+       self.vel += lvl.gravity;
+       self.pos += self.vel;
+
+       if let Intersection(wall, pos) = lvl.intersect_walls(self.pos - self.vel, self.pos) {
+           if self.bounces == 0 {
+               return ObjectState::Dead
+           }
+           self.bounces -= 1;
+           let mut a = wall.normal().mirror(self.vel.to_angle()); // TODO interpolera normalen mellan närliggande väggdelar? bollarna studsar väldigt "kantigt" nu
+           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
+           self.vel = Point::from(a) * self.vel.length() * 0.35;
+
+           // create another boll
+           use rand::distributions::{Distribution, Normal};
+           let mut rng = rand::thread_rng();
+           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?
+           use rand::Rng;
+           objects.push(Box::new(Boll {
+               vel: Point::from(a) * Normal::new(1.0, 0.25).sample(&mut rng) * self.vel.length() * rng.gen_range(0.25, 1.0),
+               ..*self
+           }));
+       }
+
+       ObjectState::Alive
+    }
+
+    fn render(&self, renderer: &mut Renderer, _sprites: &SpriteManager) {
+        let block = _sprites.get("block");
+       let size = 4 + self.bounces * 6;
+        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));
+       // renderer.canvas().set_draw_color((0, self.bounces * 100, 255));
+       // renderer.canvas().draw_point((self.pos.x as i32, self.pos.y as i32)).unwrap();
+    }
+}