90 lines
2.0 KiB
JavaScript
90 lines
2.0 KiB
JavaScript
export class LineFollowerSim {
|
|
constructor(canvas, updateBoxFn) {
|
|
this.canvas = canvas;
|
|
this.ctx = canvas.getContext("2d");
|
|
|
|
this.box = {
|
|
x: 250,
|
|
y: 150,
|
|
width: 40,
|
|
height: 20,
|
|
speed: 0.4,
|
|
dir: 0
|
|
};
|
|
|
|
this.lineX = 250;
|
|
this.lineTargetX = 250;
|
|
this.lineWidth = 12;
|
|
|
|
this.updateBox = updateBoxFn || this.defaultUpdateBox.bind(this);
|
|
this.loop = this.loop.bind(this);
|
|
}
|
|
|
|
updateLine() {
|
|
if (Math.random() < 0.02) {
|
|
this.lineTargetX = 250 + (Math.random() - 0.5) * 200;
|
|
}
|
|
|
|
this.lineX += (this.lineTargetX - this.lineX) * 0.005;
|
|
}
|
|
|
|
defaultUpdateBox() {
|
|
const leftSensor = this.box.x - this.box.width / 2;
|
|
const rightSensor = this.box.x + this.box.width / 2;
|
|
|
|
const onLine = x => x >= this.lineX - this.lineWidth / 2 && x <= this.lineX + this.lineWidth / 2;
|
|
|
|
const leftOnLine = onLine(leftSensor);
|
|
const rightOnLine = onLine(rightSensor);
|
|
|
|
if (leftOnLine && !rightOnLine) {
|
|
this.box.dir = -1;
|
|
} else if (rightOnLine && !leftOnLine) {
|
|
this.box.dir = 1;
|
|
} else {
|
|
//this.box.dir = 0;
|
|
}
|
|
|
|
this.box.x += this.box.dir * this.box.speed;
|
|
}
|
|
|
|
draw() {
|
|
const ctx = this.ctx;
|
|
const { x, y, width, height } = this.box;
|
|
|
|
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
|
|
// Line
|
|
ctx.beginPath();
|
|
ctx.moveTo(this.lineX, 0);
|
|
ctx.lineTo(this.lineX, this.canvas.height);
|
|
ctx.strokeStyle = "blue";
|
|
ctx.lineWidth = this.lineWidth;
|
|
ctx.stroke();
|
|
|
|
// Box
|
|
ctx.fillStyle = "red";
|
|
ctx.fillRect(x - width / 2, y - height / 2, width, height);
|
|
|
|
// Sensors
|
|
ctx.fillStyle = "black";
|
|
ctx.beginPath();
|
|
ctx.arc(x - width / 2, y - height / 2, 3, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
ctx.beginPath();
|
|
ctx.arc(x + width / 2, y - height / 2, 3, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
}
|
|
|
|
loop() {
|
|
this.updateLine();
|
|
this.updateBox();
|
|
this.draw();
|
|
requestAnimationFrame(this.loop);
|
|
}
|
|
|
|
start() {
|
|
this.loop();
|
|
}
|
|
}
|