diff --git a/src/lib.rs b/src/lib.rs index 2c50169..d0d4cbc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -552,7 +552,8 @@ fn bivector_exponential(bivector: &CGA) -> CGA { } struct Asteroid { - circle: CGA, + com_rotor: CGA, + verts: Vec::, vel: CGA, } @@ -569,28 +570,106 @@ fn circle_from_coords(x: f64, y: f64, r: f64) -> CGA { impl Asteroid { fn new() -> Asteroid { - let v = 0.; + let vec = 0.8*CGA::e1() + 0.0*CGA::e2(); + let vec_sqr = (&vec*&vec)[SCALAR]; + let scale = 1. / (1.-vec_sqr).sqrt(); + let com_rotor = scale * (CGA::new(1., SCALAR) + CGA::e5()*vec); + let tx_gen = CGA::e15(); + let ty_gen = CGA::e25(); + let v1_gen = -0.2*&tx_gen; + let v2_gen = 0.2*&tx_gen; + let v3_gen = 0.2*&ty_gen; + let v1_rot = bivector_exponential(&v1_gen); + let v2_rot = bivector_exponential(&v2_gen); + let v3_rot = bivector_exponential(&v3_gen); + + let origin = gen_hyperbolic_point(&CGA::zero()); + let v1 = &v1_rot * &origin * &v1_rot.Reverse(); + let v2 = &v2_rot * &origin * &v2_rot.Reverse(); + let v3 = &v3_rot * &origin * &v3_rot.Reverse(); + let verts = vec![v1, v2, v3]; + + let v = 1.; let (v_x, v_y) = (v * 1.0_f64.cos(), v*1.0_f64.sin()); - let vel = v_x*CGA::e15() + v_y*CGA::e25(); - let circle = circle_from_coords(0.5, 0., 0.4); - Asteroid { circle, vel } + let vel = v_x*CGA::e1() + v_y*CGA::e2(); + Asteroid { com_rotor, vel, verts } } - +/* fn _new_from_coords(x: f64, y: f64, r: f64, vel: CGA) -> Asteroid { - let circle = circle_from_coords(x, y, r); - Asteroid { circle, vel } + let (circle, verts) = circle_from_coords(x, y, r); + Asteroid { circle, vel, verts } } +*/ - fn update(&mut self, dt_s: f64) { - let vel = &self.vel; - let delta = vel * dt_s; + fn update(&mut self, dt_s: f64, boundary: &CGA) { + let vel = &self.vel*CGA::e5(); + let delta = &vel * dt_s; + let delta = self.fixed_to_world(&delta);//&self.com_rotor * delta * &self.com_rotor.Reverse(); let vel_rotor = bivector_exponential(&delta); - let circle = &vel_rotor*&self.circle*&vel_rotor.Reverse(); - self.circle = circle; + //let vel_rotor = &self.com_rotor.Reverse() * vel_rotor * &self.com_rotor; + let new_pos = &vel_rotor * &self.com_rotor; + let p1 = &new_pos * &self.verts[0] * &new_pos.Reverse(); + let p2 = &new_pos * &self.verts[1] * &new_pos.Reverse(); + let p3 = &new_pos * &self.verts[2] * &new_pos.Reverse(); + let circle = p1 ^ p2 ^ p3; + let intersect = circle_intersection(&circle, boundary); + match intersect { + CircleIntersection::None => { self.com_rotor = new_pos; } + CircleIntersection::TwoPoints(_,_) => { + self.reflect_off_boundary(); + } + } } fn draw(&self, context: &CanvasRenderingContext2d) { - draw_line(context, &self.circle); + let p1 = self.fixed_to_world(&self.verts[0]); + let p2 = self.fixed_to_world(&self.verts[1]); + let p3 = self.fixed_to_world(&self.verts[2]); + draw_point(context, &p1); + draw_point(context, &p2); + draw_point(context, &p3); + let circle = &p1 ^ &p2 ^ &p3; + draw_line(context, &circle); + //Construct and draw line pointing straight ahead, to help orient the player. + let origin = gen_hyperbolic_point(&CGA::zero()); + let com = self.fixed_to_world(&origin); + let delta_gen = self.fixed_to_world(&(&self.vel*CGA::e5())); + let dot = delta_gen | &com; + let line = CGA::e4() ^ com ^ dot; + draw_line(context, &line); + } + + fn fixed_to_world(&self, vec: &CGA) -> CGA { + &self.com_rotor*vec*&self.com_rotor.Reverse() + } + + fn get_circle(&self) -> CGA { + let p1 = self.fixed_to_world(&self.verts[0]); + let p2 = self.fixed_to_world(&self.verts[1]); + let p3 = self.fixed_to_world(&self.verts[2]); + p1 ^ p2 ^ p3 + } + + fn reflect_off_boundary(&mut self) { + let origin = gen_hyperbolic_point(&CGA::zero()); + let mut pos = self.fixed_to_world(&origin); + pos[E4] = 0.; + pos[E5] = 0.; + let norm = pos.norm(); + pos = pos * (1./ norm); + let norm_old = self.vel.norm(); + let vel = self.fixed_to_world(&self.vel); + let dot = &vel | &pos; + let vel_para_radial = dot * &pos; + let vel_perp_radial = &vel - &vel_para_radial; + let vel_tick = vel_perp_radial - vel_para_radial; + let mut vel_fixed = &self.com_rotor.Reverse()*vel_tick*&self.com_rotor; + vel_fixed[E4] = 0.; + vel_fixed[E5] = 0.; + let norm = vel_fixed.norm(); + vel_fixed = (1. / norm)*vel_fixed; + vel_fixed = norm_old * vel_fixed; + self.vel = vel_fixed; } } @@ -675,7 +754,8 @@ impl Game { self.context.set_stroke_style_str(RED); for asteroid in &self.asteroids { - if self.ship.intersects_circle(&asteroid.circle) { + let circle = asteroid.get_circle(); + if self.ship.intersects_circle(&circle) { intersects = true; } asteroid.draw(&self.context); @@ -699,7 +779,7 @@ impl Game { self.dt = dt_m; for asteroid in &mut self.asteroids { - asteroid.update(dt_s); + asteroid.update(dt_s, &self.boundary); } self.ship.update(dt_s, &self.keys, &self.boundary);