-
Notifications
You must be signed in to change notification settings - Fork 0
/
car.js
116 lines (102 loc) · 4.35 KB
/
car.js
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
export default class Car {
constructor({ cvs, obstacles, speed, height, width, x, y, brain, inputAngles }) {
this.canvas = cvs.canvas
this.ctx = cvs.ctx
this.color = `rgb(${(Math.random() * 255).toFixed()},
${(Math.random() * 255).toFixed()},
${(Math.random() * 255).toFixed()})`
this.speed = speed
this.height = height
this.width = width
this.brain = brain
this.coord = { x: x, y: y, }
this.obstacles = obstacles
this.isDead = false
this.turnRate = 2
this.turnSpeed = 0
this.degrees = 0
this.score = 0
this.radius = Math.sqrt((this.height / 2) ** 2 + (this.width / 2) ** 2)
this.angle = Math.acos((this.width / 2) / this.radius) / (Math.PI / 180)
this.inputAngles = inputAngles
this.inputDistances = []
for (let i = 0; i < this.inputAngles.length; i++)
this.inputDistances.push(0)
}
getCoords(radius, degrees) {
let radians = degrees * Math.PI / 180
return {
x: this.coord.x + radius * Math.sin(radians),
y: this.coord.y - radius * Math.cos(radians),
}
}
draw() {
this.degrees += this.turnSpeed
this.ctx.beginPath()
let coordsBackRight = this.getCoords(this.radius, this.degrees - 90 - this.angle)
let coordsBackLeft = this.getCoords(this.radius, this.degrees - 90 + this.angle)
let coordsFrontLeft = this.getCoords(this.radius, this.degrees + 90 - this.angle)
let coordsFrontRight = this.getCoords(this.radius, this.degrees + 90 + this.angle)
this.ctx.moveTo(coordsBackRight.x, coordsBackRight.y) // back right
this.ctx.lineTo(coordsBackLeft.x, coordsBackLeft.y) // back left
this.ctx.lineTo(coordsFrontLeft.x, coordsFrontLeft.y) // front left
this.ctx.lineTo(coordsFrontRight.x, coordsFrontRight.y) // front right
this.ctx.fillStyle = this.color
this.ctx.fill()
}
coordHitObstacles(coord, obstacles) {
for (let i = 0; i < obstacles.squares.length; i++) {
if (obstacles.squares[i].x < coord.x && coord.x < obstacles.squares[i].x + obstacles.squares[i].width &&
obstacles.squares[i].y < coord.y && coord.y < obstacles.squares[i].y + obstacles.squares[i].height) {
return true
}
}
return false
}
dieIfHitObstacle(obstacles) {
if (this.coordHitObstacles(this.getCoords(this.radius, this.degrees + 90 - this.angle), obstacles) || // front left car coord
this.coordHitObstacles(this.getCoords(this.radius, this.degrees + 90 + this.angle), obstacles) // front right car coord
) {
this.isDead = true
}
}
drive() {
if (this.isDead) return
let radians = this.degrees * Math.PI / 180
this.coord.x += Math.cos(radians) * this.speed
this.coord.y += Math.sin(radians) * this.speed
}
drawDistances() {
for (let i = 0; i < this.inputDistances.length; i++) {
let lineEndCoords = this.getCoords(this.inputDistances[i], this.degrees + this.inputAngles[i])
this.ctx.beginPath()
this.ctx.moveTo(this.coord.x, this.coord.y)
this.ctx.lineTo(lineEndCoords.x, lineEndCoords.y)
this.ctx.stroke()
}
}
updateDistanceToObstacles(obstacles) {
for (let i = 0; i < this.inputDistances.length; i++) {
this.inputDistances[i] = 0
let distanceFound = false
while (!distanceFound) {
this.inputDistances[i] += 10
if (this.coordHitObstacles(this.getCoords(this.inputDistances[i], this.degrees + this.inputAngles[i]), obstacles)) {
while (this.coordHitObstacles(this.getCoords(this.inputDistances[i], this.degrees + this.inputAngles[i]), obstacles)) {
this.inputDistances[i] -= 1
}
distanceFound = true
}
}
}
}
useBrain() {
this.score++
const prediction = this.brain.getOutput(this.inputDistances)
if (prediction[0] < 0.5) {
this.turnSpeed = -this.turnRate
} else {
this.turnSpeed = this.turnRate
}
}
}