mirror of https://github.com/dirtbags/tanks.git
167 lines
4.5 KiB
JavaScript
167 lines
4.5 KiB
JavaScript
|
const craterPoints = 7
|
||
|
const craterAngle = Math.PI / craterPoints
|
||
|
|
||
|
export class Tank {
|
||
|
constructor(ctx, color, sensors) {
|
||
|
this.ctx = ctx
|
||
|
this.color = color
|
||
|
|
||
|
// Do all the yucky math up front
|
||
|
this.maxlen = 0
|
||
|
this.sensors = []
|
||
|
for (let i in sensors) {
|
||
|
let s = sensors[i]
|
||
|
|
||
|
if (! s) {
|
||
|
this.sensors[i] = [0,0,0,0]
|
||
|
} else {
|
||
|
// r, angle, width, turret
|
||
|
this.sensors[i] = [
|
||
|
s[0], // Center angle
|
||
|
s[1] - s[2]/2, // Left border angle
|
||
|
s[1] + s[2]/2, // Right border angle
|
||
|
s[3]?1:0, // On turret?
|
||
|
]
|
||
|
if (s[0] > this.maxlen) {
|
||
|
this.maxlen = s[0]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.set_state(0, 0, 0, 0, 0)
|
||
|
}
|
||
|
|
||
|
// Set up our state, for later interleaved draw requests
|
||
|
set_state(x, y, rotation, turret, flags, sensor_state) {
|
||
|
this.x = x
|
||
|
this.y = y
|
||
|
this.rotation = rotation
|
||
|
this.turret = turret
|
||
|
if (flags & 1) {
|
||
|
this.fire = 5
|
||
|
}
|
||
|
this.led = flags & 2
|
||
|
this.dead = flags & 4
|
||
|
this.sensor_state = sensor_state
|
||
|
}
|
||
|
|
||
|
draw_crater() {
|
||
|
if (!this.dead) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
this.ctx.save()
|
||
|
this.ctx.translate(this.x, this.y)
|
||
|
this.ctx.rotate(this.rotation)
|
||
|
|
||
|
if (this.fire == 5) {
|
||
|
this.ctx.save()
|
||
|
this.ctx.rotate(this.turret)
|
||
|
// one frame of cannon fire
|
||
|
this.draw_cannon()
|
||
|
this.fire = 0
|
||
|
this.ctx.restore()
|
||
|
}
|
||
|
|
||
|
this.ctx.lineWidth = 2
|
||
|
this.ctx.strokeStyle = `rgb(from ${this.color} r g b / 50%)`
|
||
|
this.ctx.fillStyle = `rgb(from ${this.color} r g b / 20%)`
|
||
|
this.ctx.beginPath()
|
||
|
this.ctx.moveTo(12, 0)
|
||
|
for (let i = 0; i < craterPoints; i += 1) {
|
||
|
this.ctx.rotate(craterAngle)
|
||
|
this.ctx.lineTo(6, 0)
|
||
|
this.ctx.rotate(craterAngle)
|
||
|
this.ctx.lineTo(12, 0)
|
||
|
}
|
||
|
this.ctx.closePath()
|
||
|
this.ctx.stroke()
|
||
|
this.ctx.fill()
|
||
|
|
||
|
this.ctx.restore()
|
||
|
}
|
||
|
|
||
|
draw_sensors() {
|
||
|
if (this.dead) {
|
||
|
return
|
||
|
}
|
||
|
this.ctx.save()
|
||
|
this.ctx.translate(this.x, this.y)
|
||
|
this.ctx.rotate(this.rotation)
|
||
|
|
||
|
this.ctx.lineWidth = 1
|
||
|
for (let i in this.sensors) {
|
||
|
var s = this.sensors[i]
|
||
|
var adj = this.turret * s[3]
|
||
|
|
||
|
if (this.sensor_state & (1 << i)) {
|
||
|
// Sensor is triggered
|
||
|
this.ctx.strokeStyle = "#000"
|
||
|
} else {
|
||
|
this.ctx.strokeStyle = `rgb(from ${this.color} r g b / 40%)`
|
||
|
}
|
||
|
this.ctx.beginPath()
|
||
|
this.ctx.moveTo(0, 0)
|
||
|
this.ctx.arc(0, 0, s[0], s[1] + adj, s[2] + adj, false)
|
||
|
this.ctx.closePath()
|
||
|
this.ctx.stroke()
|
||
|
}
|
||
|
|
||
|
this.ctx.restore()
|
||
|
}
|
||
|
|
||
|
draw_tank() {
|
||
|
if (this.dead) {
|
||
|
return
|
||
|
}
|
||
|
this.ctx.save()
|
||
|
this.ctx.translate(this.x, this.y)
|
||
|
this.ctx.rotate(this.rotation)
|
||
|
|
||
|
this.ctx.fillStyle = this.color
|
||
|
this.ctx.fillRect(-5, -4, 10, 8)
|
||
|
this.ctx.fillStyle = "#777"
|
||
|
this.ctx.fillRect(-7, -9, 15, 5)
|
||
|
this.ctx.fillRect(-7, 4, 15, 5)
|
||
|
this.ctx.rotate(this.turret)
|
||
|
if (this.fire) {
|
||
|
this.draw_cannon()
|
||
|
this.fire -= 1
|
||
|
} else {
|
||
|
if (this.led) {
|
||
|
this.ctx.fillStyle = "#f00"
|
||
|
} else {
|
||
|
this.ctx.fillStyle = "#000"
|
||
|
}
|
||
|
this.ctx.fillRect(0, -1, 10, 2)
|
||
|
}
|
||
|
|
||
|
this.ctx.restore()
|
||
|
}
|
||
|
|
||
|
draw_cannon() {
|
||
|
this.ctx.fillStyle = ("hsl(0, 100%, 100%, " + this.fire/5 + ")")
|
||
|
this.ctx.fillRect(0, -1, 45, 2)
|
||
|
}
|
||
|
|
||
|
draw_wrap_sensors() {
|
||
|
let width = this.ctx.canvas.width
|
||
|
let height = this.ctx.canvas.height
|
||
|
let orig_x = this.x
|
||
|
let orig_y = this.y
|
||
|
for (let x = this.x - width; x < width + this.maxlen; x += width) {
|
||
|
for (let y = this.y - height; y < height + this.maxlen; y += height) {
|
||
|
if ((-this.maxlen < x) && (x < width + this.maxlen) &&
|
||
|
(-this.maxlen < y) && (y < height + this.maxlen)) {
|
||
|
this.x = x
|
||
|
this.y = y
|
||
|
this.draw_sensors()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
this.x = orig_x
|
||
|
this.y = orig_y
|
||
|
}
|
||
|
}
|
||
|
|