onlinecodesimulator/sensor.js

140 lines
4.4 KiB
JavaScript

export class Sensor {
constructor(robot, offsetAngle, offsetDistance) {
this.type = "base";
this.robot = robot
this.value = null; // Last recorded value
this.offsetAngle = offsetAngle;
this.offsetDistance = offsetDistance;
this.hitX = null;
this.hitY = null;
this.hitObject = null;
this.angle = 0;
this.hitpoint = {x: null, y: null};
}
updatePosition() {
const robotAngle = this.robot.body.angle;
const offsetAngleRad = this.offsetAngle * (Math.PI / 180);
this.startX = this.robot.body.position.x + this.offsetDistance * Math.cos(robotAngle + offsetAngleRad);
this.startY = this.robot.body.position.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, range) {
super(robot, offsetAngle, offsetDistance); // Call the parent class constructor
this.type = "line";
this.angle = angle;
this.distance = null;
this.range = range;
}
updatePosition() {
const robotAngle = this.robot.body.angle;
const offsetAngleRad = this.offsetAngle * (Math.PI / 180);
this.startX = this.robot.body.position.x + this.offsetDistance * Math.cos(robotAngle + offsetAngleRad);
this.startY = this.robot.body.position.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.range;
const y = this.robot.y + Math.sin(angleInRadians) * this.range;
// Ensure gameWorld is available and properly passed to the sensor
let hitPos = gameWorld.rayCast(this.startX, this.startY, this.endX, this.endY, [this.robot.body]);
if (hitPos != null) {
this.hitX = hitPos.x;
this.hitY = hitPos.y;
this.endX = this.hitX;
this.endY = this.hitY;
this.hitpoint = {x: this.hitX, y: this.hitY};
this.distance = Math.sqrt(Math.pow(this.hitX - this.startX, 2) + Math.pow(this.hitY - this.startY, 2));
} else {
this.hitX = null;
this.hitY = null;
this.hitpoint = {x: this.hitX, y: this.hitY};
this.distance = Math.sqrt(Math.pow(this.endX - this.startX, 2) + Math.pow(this.endY - this.startY, 2));
}
// 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
this.type = "color";
}
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();
}
}