diff --git a/5. Traffic simulation/car.js b/5. Traffic simulation/car.js new file mode 100644 index 0000000..abdbe7b --- /dev/null +++ b/5. Traffic simulation/car.js @@ -0,0 +1,125 @@ +class Car{ + constructor(x,y,width,height,controlType,maxSpeed=3){ + this.x=x; + this.y=y; + this.width=width; + this.height=height; + + this.speed=0; + this.acceleration=0.2; + this.maxSpeed=maxSpeed; + this.friction=0.05; + this.angle=0; + this.damaged=false; + + if(controlType!="DUMMY"){ + this.sensor=new Sensor(this); + } + this.controls=new Controls(controlType); + } + + update(roadBorders,traffic){ + if(!this.damaged){ + this.#move(); + this.polygon=this.#createPolygon(); + this.damaged=this.#assessDamage(roadBorders,traffic); + } + if(this.sensor){ + this.sensor.update(roadBorders,traffic); + } + } + + #assessDamage(roadBorders,traffic){ + for(let i=0;ithis.maxSpeed){ + this.speed=this.maxSpeed; + } + if(this.speed<-this.maxSpeed/2){ + this.speed=-this.maxSpeed/2; + } + + if(this.speed>0){ + this.speed-=this.friction; + } + if(this.speed<0){ + this.speed+=this.friction; + } + if(Math.abs(this.speed)0?1:-1; + if(this.controls.left){ + this.angle+=0.03*flip; + } + if(this.controls.right){ + this.angle-=0.03*flip; + } + } + + this.x-=Math.sin(this.angle)*this.speed; + this.y-=Math.cos(this.angle)*this.speed; + } + + draw(ctx,color){ + if(this.damaged){ + ctx.fillStyle="gray"; + }else{ + ctx.fillStyle=color; + } + ctx.beginPath(); + ctx.moveTo(this.polygon[0].x,this.polygon[0].y); + for(let i=1;i{ + switch(event.key){ + case "ArrowLeft": + this.left=true; + break; + case "ArrowRight": + this.right=true; + break; + case "ArrowUp": + this.forward=true; + break; + case "ArrowDown": + this.reverse=true; + break; + } + } + document.onkeyup=(event)=>{ + switch(event.key){ + case "ArrowLeft": + this.left=false; + break; + case "ArrowRight": + this.right=false; + break; + case "ArrowUp": + this.forward=false; + break; + case "ArrowDown": + this.reverse=false; + break; + } + } + } +} \ No newline at end of file diff --git a/5. Traffic simulation/index.html b/5. Traffic simulation/index.html new file mode 100644 index 0000000..08ead52 --- /dev/null +++ b/5. Traffic simulation/index.html @@ -0,0 +1,15 @@ + + + Self-driving car - No libraries + + + + + + + + + + + + \ No newline at end of file diff --git a/5. Traffic simulation/main.js b/5. Traffic simulation/main.js new file mode 100644 index 0000000..9aea346 --- /dev/null +++ b/5. Traffic simulation/main.js @@ -0,0 +1,32 @@ +const canvas=document.getElementById("myCanvas"); +canvas.width=200; + +const ctx = canvas.getContext("2d"); +const road=new Road(canvas.width/2,canvas.width*0.9); +const car=new Car(road.getLaneCenter(1),100,30,50,"KEYS"); +const traffic=[ + new Car(road.getLaneCenter(1),-100,30,50,"DUMMY",2) +]; + +animate(); + +function animate(){ + for(let i=0;i{ + ctx.beginPath(); + ctx.moveTo(border[0].x,border[0].y); + ctx.lineTo(border[1].x,border[1].y); + ctx.stroke(); + }); + } +} \ No newline at end of file diff --git a/5. Traffic simulation/sensor.js b/5. Traffic simulation/sensor.js new file mode 100644 index 0000000..7ab6bef --- /dev/null +++ b/5. Traffic simulation/sensor.js @@ -0,0 +1,119 @@ +class Sensor{ + constructor(car){ + this.car=car; + this.rayCount=5; + this.rayLength=150; + this.raySpread=Math.PI/2; + + this.rays=[]; + this.readings=[]; + } + + update(roadBorders,traffic){ + this.#castRays(); + this.readings=[]; + for(let i=0;ie.offset); + const minOffset=Math.min(...offsets); + return touches.find(e=>e.offset==minOffset); + } + } + + #castRays(){ + this.rays=[]; + for(let i=0;i=0 && t<=1 && u>=0 && u<=1){ + return { + x:lerp(A.x,B.x,t), + y:lerp(A.y,B.y,t), + offset:t + } + } + } + + return null; +} + +function polysIntersect(poly1, poly2){ + for(let i=0;i