diff --git a/classes/Car.js b/classes/Car.js index eb3fabe..c445356 100644 --- a/classes/Car.js +++ b/classes/Car.js @@ -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. diff --git a/classes/Obstacle.js b/classes/Obstacle.js index d33ad9e..34e5ce2 100644 --- a/classes/Obstacle.js +++ b/classes/Obstacle.js @@ -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]; } } \ No newline at end of file