onlinecodesimulator/sensor.js

130 lines
3.9 KiB
JavaScript

export class Sensor {
constructor(robot, offsetAngle, offsetDistance) {
this.robot = robot
this.value = null; // Last recorded value
this.offsetAngle = offsetAngle;
this.offsetDistance = offsetDistance;
this.hitX = null;
this.hitY = null;
this.hitObject = null;
}
updatePosition() {
const robotAngle = this.robot.angle * (Math.PI / 180);
const offsetAngleRad = this.offsetAngle * (Math.PI / 180);
this.startX = this.robot.x + this.offsetDistance * Math.cos(robotAngle + offsetAngleRad);
this.startY = this.robot.y + this.offsetDistance * Math.sin(robotAngle + offsetAngleRad);
}
read(robot, gameWorld) {
throw new Error("read() must be implemented in subclasses");
}
draw(ctx) {
// Default empty draw, can be overridden
}
}
export class RaycastSensor extends Sensor {
constructor(robot, offsetAngle, offsetDistance, angle, distance) {
super(robot, offsetAngle, offsetDistance); // Call the parent class constructor
this.angle = angle;
this.distance = distance;
this.range = 100;
}
updatePosition() {
const robotAngle = this.robot.angle * (Math.PI / 180);
const offsetAngleRad = this.offsetAngle * (Math.PI / 180);
this.startX = this.robot.x + this.offsetDistance * Math.cos(robotAngle + offsetAngleRad);
this.startY = this.robot.y + this.offsetDistance * Math.sin(robotAngle + offsetAngleRad);
const sensorAngle = robotAngle + (this.angle * (Math.PI / 180));
this.endX = this.startX + Math.cos(sensorAngle) * this.range;
this.endY = this.startY + Math.sin(sensorAngle) * this.range;
}
read(robot, gameWorld) {
//console.log(robot);
//console.log(gameWorld);
this.updatePosition();
const angleInRadians = (this.robot.direction + this.angle) * Math.PI / 180;
const x = this.robot.x + Math.cos(angleInRadians) * this.distance;
const y = this.robot.y + Math.sin(angleInRadians) * this.distance;
// Ensure gameWorld is available and properly passed to the sensor
let hitPos = gameWorld.rayCast(this.startX, this.startY, this.endX, this.endY);
if (hitPos != null) {
this.hitX = hitPos.x;
this.hitY = hitPos.y;
this.endX = this.hitX;
this.endY = this.hitY;
} else {
this.hitX = null;
this.hitY = null;
}
// console.log("Obstacle detected!");
// } else {
// console.log("Clear path!");
// }
}
draw(ctx) {
ctx.strokeStyle = "lime";
ctx.fillStyle = "green"
ctx.beginPath();
ctx.arc(this.startX, this.startY, 2, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
ctx.stroke();
if (this.hitX != null) {
ctx.strokeStyle = "red";
ctx.fillStyle = "red"
ctx.beginPath();
ctx.arc(this.hitX, this.hitY, 2, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
ctx.stroke();
}
ctx.strokeStyle = "yellow";
ctx.beginPath();
ctx.lineWidth = 2;
ctx.moveTo(this.startX, this.startY);
ctx.lineTo(this.endX, this.endY);
ctx.stroke();
}
}
export class FloorColorSensor extends Sensor {
constructor(robot, offsetAngle, offsetDistance) {
super(robot, offsetAngle, offsetDistance); // No angle offset, directly below robot
}
read(robot, gameWorld) {
this.value = gameWorld.getFloorColor(robot.x, robot.y);
return this.value;
}
draw(ctx) {
this.updatePosition();
ctx.strokeStyle = "purple";
ctx.fillStyle = "green"
ctx.beginPath();
ctx.arc(this.startX, this.startY, 2, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
ctx.stroke();
}
}