Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions classes/Car.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,30 @@ export class Car {
ctx.restore();
}

/**
* Returns the world coordinates of the car's four corners
* accounting for its current rotation.
* @returns {{x:number, y:number}[]} Array of 4 corner points
*/
getCorners() {
const w2 = this.width / 2;
const h2 = this.height / 2;
const sin = Math.sin(this.angle);
const cos = Math.cos(this.angle);

const local = [
{ x: -w2, y: -h2 },
{ x: w2, y: -h2 },
{ x: w2, y: h2 },
{ x: -w2, y: h2 }
];

return local.map(p => ({
x: this.x + p.x * cos - p.y * sin,
y: this.y + p.x * sin + p.y * cos
}));
}

/**
* Creates a deep clone of this car, including its neural network.
* Used during evolution to preserve elite behavior.
Expand Down
49 changes: 42 additions & 7 deletions classes/Obstacle.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,48 @@ export class Obstacle {
* @returns True if the obstacle collides with the car, false otherwise
*/
collidesWith(car) {
//const y = car.y ?? ctx.canvas.height * 0.8; // fixed y draw position
return (
this.y + this.height / 2 > car.y - car.height / 2 &&
this.y - this.height / 2 < car.y + car.height / 2 &&
this.x + this.width / 2 > car.x - car.width / 2 &&
this.x - this.width / 2 < car.x + car.width / 2
);
const carCorners = car.getCorners();
const obsCorners = this.getCorners();

const axes = [
{ x: Math.cos(car.angle), y: Math.sin(car.angle) }, // car width axis
{ x: -Math.sin(car.angle), y: Math.cos(car.angle) }, // car height axis
{ x: 1, y: 0 },
{ x: 0, y: 1 }
];

for (const axis of axes) {
const [cMin, cMax] = this.project(carCorners, axis);
const [oMin, oMax] = this.project(obsCorners, axis);
if (cMax < oMin || oMax < cMin) {
return false; // Separated along this axis
}
}
return true;
}

getCorners() {
const x1 = this.x - this.width / 2;
const x2 = this.x + this.width / 2;
const y1 = this.y - this.height / 2;
const y2 = this.y + this.height / 2;
return [
{ x: x1, y: y1 },
{ x: x2, y: y1 },
{ x: x2, y: y2 },
{ x: x1, y: y2 }
];
}

project(points, axis) {
let min = points[0].x * axis.x + points[0].y * axis.y;
let max = min;
for (const p of points.slice(1)) {
const val = p.x * axis.x + p.y * axis.y;
if (val < min) min = val;
if (val > max) max = val;
}
return [min, max];
}
}