aboutsummaryrefslogtreecommitdiff
path: root/src/view/ship.ts
blob: 92590d353c8f4c14b7d14881bada7791eec0688e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import * as Controls from 'controls'
import * as Vec2 from 'model/vec2'
import * as Number from 'util/number'
import * as Screen from 'screen'
import * as Colors from 'view/colors'

export const radius: number = 30
export const fireDelay: number = 200
export const missileWidth: number = 10
export const missileHeight: number = 5

export interface State {
  pos: Vec2.Vec2,
  missiles: Array<Vec2.Vec2>,
  lastFired: number,
}

export function init(): State {
  return {
    pos: {
      x: Screen.width / 6,
      y: Screen.height / 2,
    },
    missiles: [],
    lastFired: 0,
  }
}

export function update(state: State, timestamp: number, delta: number) {
  move(state, delta)
  updateMissiles(state, timestamp, delta)
}

function move(state: State, delta: number) {
  let dir = controlsDir(Controls.current)

  if (!Vec2.equals(dir, Vec2.zero())) {
    let teta = Math.atan2(dir.y, dir.x)
    state.pos.x += Math.cos(teta) * delta / 3
    state.pos.y += Math.sin(teta) * delta / 3
  }

  state.pos.x = Number.clamp(state.pos.x, radius, Screen.width - radius)
  state.pos.y = Number.clamp(state.pos.y, radius, Screen.height - radius)
}

function controlsDir(c: Controls.Controls): Vec2.Vec2 {
  let dir = Vec2.zero()

  if (c.up && !c.down)
    dir.y = -1
  else if (c.down && !c.up)
    dir.y = 1

  if (c.right && !c.left)
    dir.x = 1
  else if (c.left && !c.right)
    dir.x = -1

  return dir
}

function updateMissiles(state: State, timestamp: number, delta: number) {
  if (Controls.current.space && state.lastFired + fireDelay < timestamp) {
    state.missiles.push({x: state.pos.x + radius, y: state.pos.y})
    state.lastFired = timestamp
  }

  state.missiles = state.missiles
    .map(missile => ({ ...missile, x: missile.x + delta}))
    .filter(missile => missile.x < Screen.width)
}

export function view(context: CanvasRenderingContext2D, state: State) {
  context.fillStyle = Colors.colors.red
  context.beginPath()
  context.moveTo(state.pos.x - radius, state.pos.y - radius)
  context.lineTo(state.pos.x + radius, state.pos.y)
  context.lineTo(state.pos.x - radius, state.pos.y + radius)
  context.closePath()
  context.fill()

  state.missiles.forEach(({x, y}) => {
    context.fillStyle = Colors.colors.red
    context.beginPath()
    context.rect(
      x - missileWidth / 2,
      y - missileHeight / 2,
      missileWidth,
      missileHeight
    )
    context.fill()
  })
}