| 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 | } |