summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hogenson <rhogenson@posteo.net>2018-08-18 00:49:15 -0400
committerRaymond Hogenson <rhogenson@posteo.net>2018-08-18 00:49:15 -0400
commit804206beeb82671552ccd9b689b303a1251fade0 (patch)
treeb513f1cc70be614fd130a63949a2bc574c998f60
parentdaa61a51eb97f868a56a52fc61b560832dde353b (diff)
downloadstallman-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.
-rw-r--r--src/state.rs75
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