const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
let car = {
x: 400,
y: 300,
width: 40,
height: 20,
speed: 0,
angle: 0,
maxSpeed: 5,
accel: 0.2,
friction: 0.05,
turnSpeed: 0.04
};
let keys = {};
document.addEventListener("keydown", (e) => keys[e.key] = true);
document.addEventListener("keyup", (e) => keys[e.key] = false);
function update() {
if (keys["ArrowUp"]) car.speed += car.accel;
if (keys["ArrowDown"]) car.speed -= car.accel;
car.speed *= (1 - car.friction);
car.speed = Math.max(Math.min(car.speed, car.maxSpeed), -car.maxSpeed);
if (keys["ArrowLeft"]) car.angle -= car.turnSpeed * car.speed;
if (keys["ArrowRight"]) car.angle += car.turnSpeed * car.speed;
car.x += Math.cos(car.angle) * car.speed;
car.y += Math.sin(car.angle) * car.speed;
}
function drawCar() {
ctx.save();
ctx.translate(car.x, car.y);
ctx.rotate(car.angle);
ctx.fillStyle = "red";
ctx.fillRect(-car.width / 2, -car.height / 2, car.width, car.height);
ctx.restore();
}
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
update();
drawCar();
requestAnimationFrame(gameLoop);
}
gameLoop();
let lap = 0;
let currentCheckpoint = 0;
const checkpoints = [
{ x: 200, y: 100 },
{ x: 600, y: 100 },
{ x: 600, y: 500 },
{ x: 200, y: 500 }
];
function checkLapProgress() {
const cp = checkpoints[currentCheckpoint];
const dx = car.x - cp.x;
const dy = car.y - cp.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
currentCheckpoint++;
if (currentCheckpoint >= checkpoints.length) {
lap++;
currentCheckpoint = 0;
console.log("Lap completed! Total laps:", lap);
}
}
}
checkLapProgress();
drawCheckpoints();
drawLapCounter();
function drawCheckpoints() {
for (let i = 0; i < checkpoints.length; i++) {
ctx.fillStyle = (i === currentCheckpoint) ? "lime" : "yellow";
ctx.beginPath();
ctx.arc(checkpoints[i].x, checkpoints[i].y, 10, 0, Math.PI * 2);
ctx.fill();
}
}
function drawLapCounter() {
ctx.fillStyle = "white";
ctx.font = "20px Arial";
ctx.fillText("Lap: " + lap, 10, 30);
}
const walls = [
{ x: 100, y: 100, width: 20, height: 400 }, // Left wall
{ x: 100, y: 100, width: 600, height: 20 }, // Top wall
{ x: 680, y: 100, width: 20, height: 400 }, // Right wall
{ x: 100, y: 480, width: 600, height: 20 } // Bottom wall
];
function checkWallCollision() {
for (let wall of walls) {
if (
car.x > wall.x &&
car.x < wall.x + wall.width &&
car.y > wall.y &&
car.y < wall.y + wall.height
) {
car.speed = 0;
}
}
}
function drawWalls() {
ctx.fillStyle = "gray";
for (let wall of walls) {
ctx.fillRect(wall.x, wall.y, wall.width, wall.height);
}
}
drawWalls();
checkWallCollision();
if (keys["Shift"]) {
car.speed += 0.5;
car.speed = Math.min(car.speed, car.maxSpeed * 2); // Nitro limit
}
let aiCar = {
x: 420,
y: 320,
width: 40,
height: 20,
speed: 0,
angle: 0,
maxSpeed: 2.5,
targetCheckpoint: 0
};
function updateAICar() {
const target = checkpoints[aiCar.targetCheckpoint];
const dx = target.x - aiCar.x;
const dy = target.y - aiCar.y;
const targetAngle = Math.atan2(dy, dx);
let angleDiff = targetAngle - aiCar.angle;
angleDiff = Math.atan2(Math.sin(angleDiff), Math.cos(angleDiff)); // Normalize
if (angleDiff > 0.05) aiCar.angle += 0.03;
else if (angleDiff < -0.05) aiCar.angle -= 0.03;
aiCar.speed = aiCar.maxSpeed;
aiCar.x += Math.cos(aiCar.angle) * aiCar.speed;
aiCar.y += Math.sin(aiCar.angle) * aiCar.speed;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 30) {
aiCar.targetCheckpoint++;
if (aiCar.targetCheckpoint >= checkpoints.length) {
aiCar.targetCheckpoint = 0;
}
}
}
function drawAICar() {
ctx.save();
ctx.translate(aiCar.x, aiCar.y);
ctx.rotate(aiCar.angle);
ctx.fillStyle = "blue";
ctx.fillRect(-aiCar.width / 2, -aiCar.height / 2, aiCar.width, aiCar.height);
ctx.restore();
}
updateAICar();
drawAICar();