RustX commited on
Commit
3b5f7bc
1 Parent(s): ccc43bb

Create car.js

Browse files
Files changed (1) hide show
  1. car.js +146 -0
car.js ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class Car{
2
+ constructor(x,y,width,height,controlType,maxSpeed=3){
3
+ this.x=x;
4
+ this.y=y;
5
+ this.width=width;
6
+ this.height=height;
7
+
8
+ this.speed=0;
9
+ this.acceleration=0.2;
10
+ this.maxSpeed=maxSpeed;
11
+ this.friction=0.05;
12
+ this.angle=0;
13
+
14
+ this.damaged=false;
15
+
16
+ this.useBrain=controlType=="AI";
17
+
18
+ if(controlType!="DUMMY"){
19
+ this.sensor=new Sensor();
20
+ this.brain=new NeuralNetwork(
21
+ [this.sensor.rayCount,6,4]
22
+ );
23
+ }
24
+ this.controls=new Controls(controlType);
25
+ }
26
+
27
+ update(roadBorders,traffic){
28
+ if(!this.damaged){
29
+ this.#move();
30
+ this.polygon=this.#createPolygon();
31
+ this.damaged=this.#assessDamage(roadBorders,traffic);
32
+ }
33
+ if(this.sensor){
34
+ this.sensor.update(this.x,this.y,this.angle,roadBorders,traffic);
35
+ const offsets=this.sensor.readings.map(
36
+ s=>s==null?0:1-s.offset
37
+ );
38
+ const outputs=NeuralNetwork.feedForward(offsets,this.brain);
39
+ if(this.useBrain){
40
+ this.controls.forward=outputs[0];
41
+ this.controls.left=outputs[1];
42
+ this.controls.right=outputs[2];
43
+ this.controls.reverse=outputs[3];
44
+ }
45
+ }
46
+ }
47
+
48
+ #assessDamage(roadBorders,traffic){
49
+ for(let i=0;i<roadBorders.length;i++){
50
+ if(polysIntersect(
51
+ [...this.polygon,this.polygon[0]],
52
+ roadBorders[i])
53
+ ){
54
+ return true;
55
+ }
56
+ }
57
+ for(let i=0;i<traffic.length;i++){
58
+ const poly=traffic[i].polygon;
59
+ if(polysIntersect(
60
+ [...this.polygon,this.polygon[0]],
61
+ [...poly,poly[0]])
62
+ ){
63
+ return true;
64
+ }
65
+ }
66
+ return false;
67
+ }
68
+
69
+ #createPolygon(){
70
+ const points=[];
71
+ const rad=Math.hypot(this.width,this.height)/2;
72
+ const alpha=Math.atan2(this.width,this.height);
73
+ points.push({
74
+ x:this.x-Math.sin(this.angle-alpha)*rad,
75
+ y:this.y-Math.cos(this.angle-alpha)*rad
76
+ });
77
+ points.push({
78
+ x:this.x-Math.sin(this.angle+alpha)*rad,
79
+ y:this.y-Math.cos(this.angle+alpha)*rad
80
+ });
81
+ points.push({
82
+ x:this.x-Math.sin(Math.PI+this.angle-alpha)*rad,
83
+ y:this.y-Math.cos(Math.PI+this.angle-alpha)*rad
84
+ });
85
+ points.push({
86
+ x:this.x-Math.sin(Math.PI+this.angle+alpha)*rad,
87
+ y:this.y-Math.cos(Math.PI+this.angle+alpha)*rad
88
+ });
89
+ return points;
90
+ }
91
+
92
+ #move(){
93
+ if(this.controls.forward){
94
+ this.speed+=this.acceleration;
95
+ }
96
+ if(this.controls.reverse){
97
+ this.speed-=this.acceleration;
98
+ }
99
+
100
+ if(this.speed!=0){
101
+ const flip=this.speed>0?1:-1;
102
+ if(this.controls.left){
103
+ this.angle+=0.03*flip;
104
+ }
105
+ if(this.controls.right){
106
+ this.angle-=0.03*flip;
107
+ }
108
+ }
109
+
110
+ if(this.speed>this.maxSpeed){
111
+ this.speed=this.maxSpeed;
112
+ }
113
+ if(this.speed<-this.maxSpeed/2){
114
+ this.speed=-this.maxSpeed/2;
115
+ }
116
+
117
+ if(this.speed>0){
118
+ this.speed-=this.friction;
119
+ }
120
+ if(this.speed<0){
121
+ this.speed+=this.friction;
122
+ }
123
+ if(Math.abs(this.speed)<this.friction){
124
+ this.speed=0;
125
+ }
126
+ this.x-=Math.sin(this.angle)*this.speed;
127
+ this.y-=Math.cos(this.angle)*this.speed;
128
+ }
129
+
130
+ draw(ctx,drawSensor=false){
131
+ if(this.damaged){
132
+ ctx.fillStyle="gray";
133
+ }else{
134
+ ctx.fillStyle="black";
135
+ }
136
+ ctx.beginPath();
137
+ ctx.moveTo(this.polygon[0].x,this.polygon[0].y);
138
+ for(let i=1;i<this.polygon.length;i++){
139
+ ctx.lineTo(this.polygon[i].x,this.polygon[i].y);
140
+ }
141
+ ctx.fill();
142
+ if(this.sensor && drawSensor){
143
+ this.sensor.draw(ctx);
144
+ }
145
+ }
146
+ }