diff options
Diffstat (limited to 'static/games/stallman-shooter/gates.js')
| -rw-r--r-- | static/games/stallman-shooter/gates.js | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/static/games/stallman-shooter/gates.js b/static/games/stallman-shooter/gates.js new file mode 100644 index 0000000..c307f1e --- /dev/null +++ b/static/games/stallman-shooter/gates.js @@ -0,0 +1,143 @@ +import * as constants from '/static/games/stallman-shooter/constants.js'; + +export class Gates { + constructor() { + this.x = 200; + this.y = 40; + this.v_x = 0; + this.v_y = 0; + this.a_x = 0; + this.a_y = 0; + this.target_x = 200; + this.target_y = 40; + this.health = 1; + } + + radius() { + return 30; + } + + choose_position() { + const [x, y] = random_position(); + this.target_x = x; + this.target_y = y; + } + + act(count) { + const max_accel = (1 - this.health) * 0.75 + 0.25; + const max_velocity = (1 - this.health) * 5 + 5; + let dx = this.target_x - this.x; + let dy = this.target_y - this.y; + /* If we've arrived (close and stopped) */ + if (Math.sqrt(dx * dx + dy * dy) < max_velocity / max_accel && Math.sqrt(this.v_x * this.v_x + this.v_y * this.v_y) < 0.01) { + /* Then pick a new target */ + this.choose_position(); + + } + + dx = this.target_x - this.x; + dy = this.target_y - this.y; + /* if we're close */ + if (Math.sqrt(dx * dx + dy * dy) < max_velocity / max_accel) { + /* Then slow down */ + const [x, y] = shorten(-this.v_x, -this.v_y, max_accel); + this.a_x = x; + this.a_y = y; + } else { + /* Otherwise, speed up */ + const [x, y] = shorten(dx, dy, max_accel); + this.a_x = x; + this.a_y = y; + } + + /* If we're going too fast */ + if (Math.sqrt(this.v_x * this.v_x + this.v_y * this.v_y) > max_velocity) { + /* Then don't go faster */ + if (Math.sign(this.v_x) == Math.sign(this.a_x)) { + this.a_x = 0; + } + if (Math.sign(this.v_y) == Math.sign(this.a_y)) { + this.a_y = 0; + } + } + + this.v_x += this.a_x; + this.x += this.v_x; + this.v_y += this.a_y; + this.y += this.v_y; + if (count % 20 === 0) { + let num_bullets; + if (this.health >= 0.8) { + num_bullets = 5; + } else if (this.health >= 0.7) { + num_bullets = 6; + } else if (this.health >= 0.5) { + num_bullets = 7; + } else if (this.health >= 0.4) { + num_bullets = 8; + } else if (this.health >= 0.3) { + num_bullets = 9; + } else if (this.health >= 0.2) { + num_bullets = 10; + } else { + num_bullets = 11; + } + const result = []; + for (let i = 0; i < num_bullets; i++) { + result.push(random_bullet(this)); + } + return result; + } else { + return []; + } + } + + injure(damage) { + this.health -= damage; + } + + center() { + return [16, 23]; + } +} + +export class GatesBullet { + constructor(x, d_x, y, d_y) { + this.x = x; + this.y = y; + this.d_x = d_x; + this.d_y = d_y; + } + + radius() { + return 10; + } + + center() { + return [20, 20]; + } +} + +function random_position() { + return [ + Math.random() * (constants.x_dim - 200) + 100, + Math.random() * 100, + ]; +} + +function random_bullet(enemy) { + const multiplier = 2 + 3 * (1 - enemy.health); + const theta = Math.random() * 2 * Math.PI / 3 + Math.PI / 6; + const dx = Math.cos(theta) * multiplier; + const dy = Math.sin(theta) * multiplier; + return new GatesBullet(enemy.x, dx, enemy.y, dy); +} + +function shorten(x, y, maxlen) { + const len = Math.sqrt(x * x + y * y); + if (len > maxlen) { + return [x / len / 2, y / len / 2]; + } else { + return [x, y]; + } +} |
