JSFiddle - React, Tailwind, and code Playground
by Ben Gillbanks
HTML
<canvas id="game" width="900" height="600"></canvas>
CSS
html, body {
margin: 0;
padding: 0;
background: #1b1b1b;
overflow: hidden;
font-family: sans-serif;
}
canvas {
display: block;
margin: 0 auto;
background: #5c9452;
image-rendering: pixelated;
image-rendering: crisp-edges;
}
JavaScript
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
const keys = {};
window.addEventListener("keydown", (event) => {
keys[event.key.toLowerCase()] = true;
});
window.addEventListener("keyup", (event) => {
keys[event.key.toLowerCase()] = false;
});
const track = {
x: 60,
y: 60,
width: canvas.width - 120,
height: canvas.height - 120
};
const car = {
x: canvas.width * 0.5,
y: canvas.height * 0.5,
angle: -Math.PI * 0.5,
vx: 0,
vy: 0,
radius: 18,
acceleration: 700,
reverseAcceleration: 400,
maxSpeed: 320,
drag: 0.985,
grip: 0.05,
steerRate: 2.8,
steerSpeed: 140,
bounce: 0.35,
width: 26,
length: 40,
stackHeight: 10,
lean: 0,
pitch: 0
};
let lastTime = 0;
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
function lerp(from, to, amount) {
return from + (to - from) * amount;
}
function dot(ax, ay, bx, by) {
return ax * bx + ay * by;
}
function length(x, y) {
return Math.hypot(x, y);
}
function update(delta) {
handleInput(delta);
applyCarPhysics(delta);
moveCar(delta);
handleWallCollisions();
updateVisualEffects(delta);
}
function handleInput(delta) {
const forwardX = Math.cos(car.angle);
const forwardY = Math.sin(car.angle);
const forwardSpeed = dot(car.vx, car.vy, forwardX, forwardY);
let throttle = 0;
if (keys["arrowup"] || keys["w"]) throttle += 1;
if (keys["arrowdown"] || keys["s"]) throttle -= 1;
let steer = 0;
if (keys["arrowleft"] || keys["a"]) steer -= 1;
if (keys["arrowright"] || keys["d"]) steer += 1;
if (throttle > 0) {
car.vx += forwardX * car.acceleration * delta;
car.vy += forwardY * car.acceleration * delta;
} else if (throttle < 0) {
car.vx -= forwardX * car.reverseAcceleration * delta;
car.vy -= forwardY * car.reverseAcceleration * delta;
}
const speedFactor = clamp(Math.abs(forwardSpeed) / car.steerSpeed, 0, 1);
const...