From 8065e2645a936275c7d69c6068d80ece598d6e57 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tomas=20Wenstr=C3=B6m?= Date: Mon, 8 Feb 2021 17:45:40 +0100 Subject: [PATCH] Bounce bolls off of walls in a proper angle --- src/common/geometry.rs | 9 +++++++-- src/core/game.rs | 14 +++++++++----- src/core/level/mod.rs | 17 ++++++++++++++++- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/common/geometry.rs b/src/common/geometry.rs index e46f23e..ebf122a 100644 --- a/src/common/geometry.rs +++ b/src/common/geometry.rs @@ -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 //////////////////////////////////////////////////////// diff --git a/src/core/game.rs b/src/core/game.rs index b0d9968..39af2e1 100644 --- a/src/core/game.rs +++ b/src/core/game.rs @@ -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 })); } diff --git a/src/core/level/mod.rs b/src/core/level/mod.rs index 84d4fad..cccd253 100644 --- a/src/core/level/mod.rs +++ b/src/core/level/mod.rs @@ -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 + } } -- 2.11.0