summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hogenson <rhogenson@posteo.net>2018-08-18 08:37:19 -0400
committerRaymond Hogenson <rhogenson@posteo.net>2018-08-18 08:37:19 -0400
commit950e60067ce036e831e81afeec180a63511f9e65 (patch)
tree7736409a9eec7332009d579e4dde7fd35ec83f09
parent8b239f55d1c08584f7ba8a735657d4ef6c915626 (diff)
downloadstallman-shooter-950e60067ce036e831e81afeec180a63511f9e65.tar.zst
Tune enemy movement logic
Now the logic is straightforward and not so fragile when we add some new complexity. Next step I think is to make it all based around traits or some kind of generics, and then we can plug in new enemies. Ideally we'll just have the game represented as a list of phases, where a phase is just an object, and the player will progress through them in order. Because it has to be a concrete object, I think we can embed a function pointer into a struct to get most of the functionality that we want.
-rw-r--r--src/state.rs64
1 files changed, 36 insertions, 28 deletions
diff --git a/src/state.rs b/src/state.rs
index e2ca280..da53054 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -15,12 +15,6 @@ pub struct EBullet {
d_y: f64,
}
-enum EnemyStatus {
- Accel,
- Travel,
- Decel,
-}
-
pub struct Enemy {
pub x: f64,
pub y: f64,
@@ -92,30 +86,36 @@ impl Enemy {
Enemy { x: 200., y: 40., v_x: 0., v_y: 0., a_x: 0., a_y: 0., radius: 30, health: STARTING_HEALTH, target_x: x, target_y: y }
}
pub fn act(&mut self, count: u64) -> Vec<EBullet> {
- let dx = self.target_x - self.x as f64;
- let dy = self.target_y - self.y as f64;
- let vec_x = self.target_x - self.x;
- let vec_y = self.target_y - self.y;
- let (x, y) = shorten(vec_x, vec_y, 0.25);
- self.a_x = x;
- self.a_y = y;
+ 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;
+ }
- /* Except that if we're really close, we actually should just slow down */
- if f64::sqrt(dx*dx + dy*dy) < 100. {
- let (x, y) = shorten(-self.v_x, -self.v_y, 0.25);
+ 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;
- /* And, if we're close and we managed to slow down, we'll pick a new target */
- if f64::sqrt(self.v_x*self.v_x + self.v_y*self.v_y) < 0.1 {
- let (x, y) = random_position();
- self.target_x = x;
- self.target_y = y;
- }
}
- /* Close enough */
- /* If we're too fast, don't go faster */
- if f64::sqrt(self.v_x*self.v_x + self.v_y*self.v_y) > 10. {
+ /* 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.;
}
@@ -184,13 +184,21 @@ pub trait Positioned {
d <= self.radius() as f64
}
fn overlaps<T: Positioned>(&self, other: &T) -> bool {
- let dist = dist(self.x(), self.y(), other.x(), other.y());
- dist < (self.radius() + other.radius()) as f64
+ let sx = self.x();
+ let ox = other.x();
+ let sy = self.y();
+ let oy = other.y();
+ let threshold = self.radius() + other.radius();
+ if (sx - ox).abs() as u32 >= threshold || (sy - oy).abs() as u32 >= threshold {
+ return false;
+ }
+ let dist = dist(sx, sy, ox, oy);
+ dist < threshold as f64
}
fn outside(&self) -> bool {
let x = self.x();
let y = self.y();
- x < 0 || x as u32 > constants::X_DIM || y < 0 || y as u32 > constants::Y_DIM
+ x < 0 || x > constants::X_DIM as i32 || y < 0 || y > constants::Y_DIM as i32
}
}