diff options
Diffstat (limited to 'src/gates.rs')
| -rw-r--r-- | src/gates.rs | 185 |
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) + } +} |
