Bounce bolls off of walls in a proper angle
authorTomas Wenström <tomas.wenstrom@gmail.com>
Mon, 8 Feb 2021 16:45:40 +0000 (17:45 +0100)
committerTomas Wenström <tomas.wenstrom@gmail.com>
Mon, 8 Feb 2021 16:45:40 +0000 (17:45 +0100)
src/common/geometry.rs
src/core/game.rs
src/core/level/mod.rs

index e46f23e..ebf122a 100644 (file)
@@ -173,16 +173,21 @@ pub struct Radians(pub f64);
 
 impl Degrees {
     #[allow(dead_code)]
-    fn to_radians(&self) -> Radians {
+    pub fn to_radians(&self) -> Radians {
        Radians(self.0.to_radians())
     }
 }
 
 impl Radians {
     #[allow(dead_code)]
-    fn to_degrees(&self) -> Degrees {
+    pub fn to_degrees(&self) -> Degrees {
        Degrees(self.0.to_degrees())
     }
+
+    /// Returns the reflection of the incident when mirrored along this angle.
+    pub fn mirror(&self, incidence: Radians) -> Radians {
+       Radians((std::f64::consts::PI + self.0 * 2.0 - incidence.0) % std::f64::consts::TAU)
+    }
 }
 
 ////////// INTERSECTION ////////////////////////////////////////////////////////
index b0d9968..39af2e1 100644 (file)
@@ -275,15 +275,19 @@ impl Object for Boll {
            if self.bounces == 0 {
                return Dead
            }
-           self.pos = pos;
-           self.vel *= -0.25;
-           self.pos += self.vel;
            self.bounces -= 1;
+           let mut a = wall.normal().mirror(self.vel.to_radians()); // TODO interpolera normalen mellan närliggande väggdelar? bollarna studsar väldigt "kantigt" nu
+           self.pos = pos;
+           self.vel = Point::from(a) * self.vel.length() * 0.35;
+           self.pos += self.vel; // TODO det här kan få bollen att åka igenom en närliggande vägg utan att kollisionstestas, men behövs just nu för att inte kollidera med samma vägg bakifrån
+
+           // create another boll
            use rand::distributions::{Distribution, Normal};
            let mut rng = rand::thread_rng();
-           let a = Radians(self.vel.to_radians().0 + Normal::new(0.0, 0.75).sample(&mut rng));
+           a.0 += Normal::new(0.0, 0.1).sample(&mut rng); // 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(),
+               vel: Point::from(a) * Normal::new(1.0, 0.25).sample(&mut rng) * self.vel.length() * rng.gen_range(0.25, 1.0),
                ..*self
            }));
        }
index 84d4fad..cccd253 100644 (file)
@@ -1,4 +1,4 @@
-use common::{Point, Dimension, Intersection, supercover_line};
+use common::{Point, Dimension, Intersection, Radians, supercover_line};
 use core::render::Renderer;
 use sprites::SpriteManager;
 use std::rc::Rc;
@@ -89,6 +89,15 @@ impl Level {
        // walls
        for wall in &self.walls {
            for e in &wall.edges {
+               let c = (e.p1 + e.p2) / 2.0;
+               let mut rad = (e.p2 - e.p1).to_radians();
+               rad.0 += std::f64::consts::FRAC_PI_2;
+
+               renderer.draw_line(
+                   <(i32, i32)>::from(c.to_i32()),
+                   <(i32, i32)>::from((c + Point::from(rad) * 10.0).to_i32()),
+                   (255, 128, 0));
+
                renderer.draw_line(
                    <(i32, i32)>::from(e.p1.to_i32()),
                    <(i32, i32)>::from(e.p2.to_i32()),
@@ -238,4 +247,10 @@ impl<'a> Wall<'a> {
            edge,
        }
     }
+
+    pub fn normal(&self) -> Radians {
+       let mut rad = (self.edge.p2 - self.edge.p1).to_radians();
+       rad.0 += std::f64::consts::FRAC_PI_2;
+       rad
+    }
 }