summaryrefslogtreecommitdiffstats
path: root/src/gates.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/gates.rs')
-rw-r--r--src/gates.rs185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/gates.rs b/src/gates.rs
new file mode 100644
index 0000000..c79297a
--- /dev/null
+++ b/src/gates.rs
@@ -0,0 +1,185 @@
+extern crate rand;
+extern crate std;
+
+use super::state;
+use super::constants;
+
+pub struct Gates {
+ x: f64,
+ y: f64,
+ v_x: f64,
+ v_y: f64,
+ a_x: f64,
+ a_y: f64,
+ target_x: f64,
+ target_y: f64,
+ health: f64,
+}
+
+pub struct GatesBullet {
+ real_x: f64,
+ real_y: f64,
+ d_x: f64,
+ d_y: f64,
+}
+
+impl GatesBullet {
+ pub fn new(x: i32, d_x: f64, y: i32, d_y: f64) -> GatesBullet {
+ GatesBullet { real_x: x as f64, real_y: y as f64, d_x: d_x, d_y: d_y }
+ }
+}
+
+impl state::Positioned for GatesBullet {
+ fn x(&self) -> i32 {
+ self.real_x.round() as i32
+ }
+ fn y(&self) -> i32 {
+ self.real_y.round() as i32
+ }
+ fn radius() -> u32 {
+ 10
+ }
+}
+
+impl state::Positioned for Gates {
+ fn x(&self) -> i32 {
+ self.x.round() as i32
+ }
+ fn y(&self) -> i32 {
+ self.y.round() as i32
+ }
+ fn radius() -> u32 {
+ 15
+ }
+}
+
+fn random_position() -> (f64, f64) {
+ (rand::random::<f64>() * (constants::X_DIM - 200) as f64 + 100., rand::random::<f64>() * 100.)
+}
+
+impl state::StraightBullet for GatesBullet {
+ fn real_x(&self) -> f64 {
+ self.real_x
+ }
+ fn real_y(&self) -> f64 {
+ self.real_y
+ }
+ fn set_real_x(&mut self, real_x: f64) {
+ self.real_x = real_x;
+ }
+ fn set_real_y(&mut self, real_y: f64) {
+ self.real_y = real_y;
+ }
+ fn d_x(&self) -> f64 {
+ self.d_x
+ }
+ fn d_y(&self) -> f64 {
+ self.d_y
+ }
+}
+
+fn random_bullet<T: state::Enemy<GatesBullet>>(enemy: &T) -> GatesBullet {
+ let multiplier = 2. + 2.*(1. - enemy.health());
+ let theta: f64 = rand::random::<f64>()*2.*std::f64::consts::PI/3. + std::f64::consts::PI/6.;
+ let dx = f64::cos(theta) * multiplier;
+ let dy = f64::sin(theta) * multiplier;
+ GatesBullet::new(enemy.x(), dx, enemy.y(), dy)
+}
+
+fn shorten(x: f64, y: f64, maxlen: f64) -> (f64, f64) {
+ let len = f64::sqrt(x*x + y*y);
+ if len > maxlen {
+ (x / len / 2., y / len / 2.)
+ } else {
+ (x, y)
+ }
+}
+
+impl state::Enemy<GatesBullet> for Gates {
+ fn new() -> Gates {
+ Gates { x: 200., y: 40., v_x: 0., v_y: 0., a_x: 0., a_y: 0., target_x: 200., target_y: 40., health: 1. }
+ }
+ fn act(&mut self, count: u64) -> Vec<GatesBullet> {
+ let max_accel = 0.25;
+ let max_velocity = 5.;
+ let dx = self.target_x - self.x;
+ let dy = self.target_y - self.y;
+ /* If we've arrived (close and stopped) */
+ if (dx*dx + dy*dy).sqrt() < max_velocity / max_accel && (self.v_x*self.v_x + self.v_y*self.v_y).sqrt() < 0.01 {
+ /* Then pick a new target */
+ let (x, y) = random_position();
+ self.target_x = x;
+ self.target_y = y;
+ }
+
+ let dx = self.target_x - self.x;
+ let dy = self.target_y - self.y;
+ /* If we're close */
+ if (dx*dx + dy*dy).sqrt() < max_velocity / max_accel {
+ /* Then slow down */
+ let (x, y) = shorten(-self.v_x, -self.v_y, max_accel);
+ self.a_x = x;
+ self.a_y = y;
+ } else {
+ /* Otherwise, speed up */
+ let (x, y) = shorten(dx, dy, max_accel);
+ self.a_x = x;
+ self.a_y = y;
+ }
+
+ /* If we're going too fast */
+ if (self.v_x*self.v_x + self.v_y*self.v_y).sqrt() > max_velocity {
+ /* Then don't go faster */
+ if self.v_x.signum() == self.a_x.signum() {
+ self.a_x = 0.;
+ }
+ if self.v_y.signum() == self.a_y.signum() {
+ self.a_y = 0.;
+ }
+ }
+
+ self.v_x += self.a_x;
+ self.x += self.v_x;
+ self.v_y += self.a_y;
+ self.y += self.v_y;
+ if count % 20 == 0 {
+ let num_bullets;
+ if self.health >= 0.8 {
+ num_bullets = 4;
+ } else if self.health >= 0.5 {
+ num_bullets = 5;
+ } else if self.health >= 0.3 {
+ num_bullets = 6;
+ } else if self.health >= 0.2 {
+ num_bullets = 7;
+ } else {
+ num_bullets = 8;
+ }
+ let mut result = Vec::new();
+ for _ in 0..num_bullets {
+ result.push(random_bullet(&*self));
+ }
+ result
+ } else {
+ Vec::new()
+ }
+ }
+ fn health(&self) -> f64 {
+ self.health
+ }
+ fn set_health(&mut self, health: f64) {
+ self.health = health;
+ }
+}
+
+impl state::Drawable for GatesBullet {
+ fn center() -> (u32, u32) {
+ (20, 20)
+ }
+}
+
+impl state::Drawable for Gates {
+ fn center() -> (u32, u32) {
+ (16, 23)
+ }
+}