diff options
| author | Raymond Hogenson <rhogenson@posteo.net> | 2018-08-18 00:49:15 -0400 |
|---|---|---|
| committer | Raymond Hogenson <rhogenson@posteo.net> | 2018-08-18 00:49:15 -0400 |
| commit | 804206beeb82671552ccd9b689b303a1251fade0 (patch) | |
| tree | b513f1cc70be614fd130a63949a2bc574c998f60 /src/state.rs | |
| parent | daa61a51eb97f868a56a52fc61b560832dde353b (diff) | |
| download | stallman-shooter-804206beeb82671552ccd9b689b303a1251fade0.tar.zst | |
Finalize the new movement scheme
Ok it's pretty fucking cool. Tracking acceleration has always looked
good, no matter what. There's some pretty advanced logic going on here,
and it's worth it.
Diffstat (limited to 'src/state.rs')
| -rw-r--r-- | src/state.rs | 75 |
1 files changed, 55 insertions, 20 deletions
diff --git a/src/state.rs b/src/state.rs index 74ac73b..e2ca280 100644 --- a/src/state.rs +++ b/src/state.rs @@ -15,10 +15,15 @@ pub struct EBullet { d_y: f64, } +enum EnemyStatus { + Accel, + Travel, + Decel, +} + pub struct Enemy { - pub x: i32, - pub y: i32, - action_count: u64, + pub x: f64, + pub y: f64, v_x: f64, v_y: f64, a_x: f64, @@ -65,34 +70,64 @@ fn random_bullet(enemy: &Enemy) -> EBullet { 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; - EBullet::new(enemy.x, dx, enemy.y, dy) + EBullet::new(enemy.x.round() as i32, dx, enemy.y.round() as i32, dy) } fn random_position() -> (f64, f64) { - (rand::random() * (constants::X_DIM - 200) as f64 + 100., rand::random() * 200) + (rand::random::<f64>() * (constants::X_DIM - 200) as f64 + 100., rand::random::<f64>() * 100.) +} + +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 Enemy { pub fn new() -> Enemy { - Enemy { x: 200, y: 40, action_count: 1, v_x: 0., v_y: 0., a_x: 0., a_y: 0., radius: 30, health: STARTING_HEALTH, target_x: 200, target_y: 400 } + let (x, y) = random_position(); + 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; - let dy = self.target_y - self.y; - /* Made it; pick a new destination */ - if f64::sqrt(dx*dx + dy*dy) < 10 { - let (self.target_x, self.target_y) = random_position(); + 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; + + /* 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); + 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 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.; + } } - let vec_x = self.target_x - self.real_x; - let vec_y = self.target_y - self.real_y; - let len = f64::sqrt(vec_x*vec_x + vec_y*vec_y); - self.a_x = vec_x / len / 2.; - self.a_y = vec_y / len / 2.; self.v_x += self.a_x; - self.x = (self.x as f64 + self.v_x).round() as i32; + self.x += self.v_x; self.v_y += self.a_y; - self.y = (self.y as f64 + self.v_y).round() as i32; + self.y += self.v_y; if count % 20 == 0 { let num_bullets; if self.health >= 80 { @@ -185,10 +220,10 @@ impl Positioned for PBullet { impl Positioned for Enemy { fn x(&self) -> i32 { - self.x + self.x.round() as i32 } fn y(&self) -> i32 { - self.y + self.y.round() as i32 } fn radius(&self) -> u32 { self.radius |
