AI Code Test
GTA
Review the original prompt, inspect the generated code, and compare how different AI models handled the same coding task.
Back to All Tests
GTA
I want to create a single file GTA inspired game using threes and make it 3d. I want it to have the ability to run around, ump in and out of cars (that are moving) around a downtown city. This should be 3d. Try to make it look as good as possible while using only shapes.
Gemini Flash 3.5 (Standard)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Poly City Simulator</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #050505;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
user-select: none;
}
#canvas-container {
width: 100vw;
height: 100vh;
}
#ui {
position: absolute;
bottom: 20px;
left: 20px;
color: white;
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
pointer-events: none;
}
h1 { margin: 0 0 5px 0; font-size: 24px; letter-spacing: 1px; color: #ff007f; }
.controls { font-size: 14px; line-height: 1.6; background: rgba(0,0,0,0.5); padding: 10px; border-radius: 5px; backdrop-filter: blur(5px); }
.highlight { color: #00ffff; font-weight: bold; }
#prompt {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
color: #00ffff;
font-size: 20px;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0,0,0,0.9);
background: rgba(0,0,0,0.7);
padding: 10px 20px;
border-radius: 4px;
border: 1px solid #00ffff;
display: none;
pointer-events: none;
}
</style>
<!-- Three.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body>
<div id="canvas-container"></div>
<div id="prompt">PRESS E TO JACK VEHICLE</div>
<div id="ui">
<h1>BLOCKY VICE</h1>
<div class="controls">
State: <span id="mode" class="highlight">ON FOOT</span><br>
<span class="highlight">WASD / Arrows</span>: Move & Steer<br>
<span class="highlight">SPACE</span>: Jump / Brake<br>
<span class="highlight">E</span>: Enter / Exit Car (Get close to moving cars!)<br>
<span class="highlight">Mouse</span>: Orbit Camera
</div>
</div>
<script>
// --- GAME CONFIG & STATE ---
const CONFIG = {
citySize: 400,
gridSpacing: 50,
roadWidth: 16,
buildingMaxHeight: 80,
buildingMinHeight: 20,
trafficCount: 25,
carSpeed: 0.4
};
let scene, camera, renderer;
let clock = new THREE.Clock();
// Input tracking
const keys = { w: false, a: false, s: false, d: false, Space: false, e: false };
let mouseX = 0, mouseY = 0;
let cameraAngleX = 0.7, cameraAngleY = 0.3;
let cameraRadius = 18;
// Entities
let player = {
mesh: null,
x: 0, z: 0, y: 1,
vx: 0, vz: 0, vy: 0,
rotation: 0,
radius: 0.6,
height: 1.8,
isGrounded: true,
speed: 12
};
let vehicles = [];
let controlledVehicle = null;
let nearbyVehicle = null;
let animationFrameId;
// --- INITIALIZATION ---
function init() {
const container = document.getElementById('canvas-container');
// Scene setup with atmospheric fog
scene = new THREE.Scene();
scene.background = new THREE.Color(0x0a0b10);
scene.fog = new THREE.FogExp2(0x0a0b10, 0.006);
// Camera setup
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
container.appendChild(renderer.domElement);
// Lighting
setupLighting();
// World Generation
generateCity();
// Spawn Player
createPlayer();
// Spawn Traffic
spawnTraffic();
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('keydown', (e) => handleKeyEvent(e, true));
document.addEventListener('keyup', (e) => handleKeyEvent(e, false));
document.addEventListener('mousemove', onMouseMove);
// Start loop
animate();
}
// --- LIGHTING ---
function setupLighting() {
const ambientLight = new THREE.AmbientLight(0x22223b, 1.2);
scene.add(ambientLight);
// Cyberpunk style directional twilight
const dirLight = new THREE.DirectionalLight(0xff7b00, 0.8);
dirLight.position.set(100, 150, 50);
dirLight.castShadow = true;
dirLight.shadow.mapSize.width = 2048;
dirLight.shadow.mapSize.height = 2048;
dirLight.shadow.camera.near = 0.5;
dirLight.shadow.camera.far = 500;
const d = 200;
dirLight.shadow.camera.left = -d;
dirLight.shadow.camera.right = d;
dirLight.shadow.camera.top = d;
dirLight.shadow.camera.bottom = -d;
scene.add(dirLight);
// Moonlight blue fill
const fillLight = new THREE.DirectionalLight(0x00bfff, 0.4);
fillLight.position.set(-100, 100, -50);
scene.add(fillLight);
}
// --- PROCEDURAL GENERATION (SHAPES ONLY) ---
function generateCity() {
// Huge ground plate
const groundGeo = new THREE.PlaneGeometry(CONFIG.citySize * 2, CONFIG.citySize * 2);
const groundMat = new THREE.MeshStandardMaterial({ color: 0x111115, roughness: 0.8 });
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
const halfSize = CONFIG.citySize / 2;
const step = CONFIG.gridSpacing;
// Generate streets & blocks layout
for (let x = -halfSize; x <= halfSize; x += step) {
for (let z = -halfSize; z <= halfSize; z += step) {
// Check if we are inside a city block or on a main intersection grid line
const onRoadX = (Math.abs(x) % step === 0 && x !== -halfSize && x !== halfSize);
const onRoadZ = (Math.abs(z) % step === 0 && z !== -halfSize && z !== halfSize);
if (!onRoadX && !onRoadZ) {
// Create a city block center
createBlockBuildings(x + step/2, z + step/2, step - CONFIG.roadWidth);
}
// Render road markings for visual polish along gridlines
if (onRoadX && !onRoadZ && Math.abs(z) < halfSize) {
createRoadLine(x, z + step/2, 0, step);
}
}
}
}
function createBlockBuildings(blockX, blockZ, maxBlockSize) {
// Subdivide block into 2x2 cluster of buildings
const subDivs = 2;
const bSize = maxBlockSize / subDivs - 2;
// Palette for low-poly architectural windows/materials
const colors = [0x1e2022, 0x2c3e50, 0x34495e, 0x20202c, 0x111625];
for (let i = 0; i < subDivs; i++) {
for (let j = 0; j < subDivs; j++) {
// Skip random corner spots to give city organic layout variety
if (Math.random() > 0.85) continue;
const offsetX = (i - (subDivs - 1) / 2) * (bSize + 2);
const offsetZ = (j - (subDivs - 1) / 2) * (bSize + 2);
const bH = Math.floor(Math.random() * (CONFIG.buildingMaxHeight - CONFIG.buildingMinHeight)) + CONFIG.buildingMinHeight;
const bW = bSize * (0.8 + Math.random() * 0.2);
const bD = bSize * (0.8 + Math.random() * 0.2);
const posX = blockX + offsetX;
const posZ = blockZ + offsetZ;
// Main Building Frame
const bGeo = new THREE.BoxGeometry(bW, bH, bD);
const bMat = new THREE.MeshStandardMaterial({
color: colors[Math.floor(Math.random() * colors.length)],
roughness: 0.5,
metalness: 0.1
});
const building = new THREE.Mesh(bGeo, bMat);
building.position.set(posX, bH / 2, posZ);
building.castShadow = true;
building.receiveShadow = true;
scene.add(building);
// Procedural Cyberpunk Neon/Windows using primitive stripes
if (Math.random() > 0.3) {
const stripeColor = Math.random() > 0.5 ? 0x00ffff : 0xff00ff;
const windowLineGeo = new THREE.BoxGeometry(bW + 0.2, 0.4, bD + 0.2);
const windowLineMat = new THREE.MeshBasicMaterial({ color: stripeColor });
// Repeat bands vertically down the shape
const floors = Math.floor(bH / 6);
for(let f = 1; f < floors; f++) {
const stripe = new THREE.Mesh(windowLineGeo, windowLineMat);
stripe.position.set(posX, f * 6, posZ);
scene.add(stripe);
}
}
}
}
}
function createRoadLine(x, z, rotY, length) {
const lineGeo = new THREE.BoxGeometry(0.3, 0.02, length);
const lineMat = new THREE.MeshBasicMaterial({ color: 0xdfe6e9 });
const line = new THREE.Mesh(lineGeo, lineMat);
line.position.set(x, 0.01, z);
line.rotation.y = rotY;
scene.add(line);
}
// --- PLAYER GENERATION ---
function createPlayer() {
const group = new THREE.Group();
// Low poly agent body configuration
const bodyGeo = new THREE.BoxGeometry(0.8, 1.2, 0.5);
const bodyMat = new THREE.MeshStandardMaterial({ color: 0x333333, roughness: 0.7 });
const body = new THREE.Mesh(bodyGeo, bodyMat);
body.position.y = 0.6;
body.castShadow = true;
group.add(body);
// Head
const headGeo = new THREE.BoxGeometry(0.4, 0.4, 0.4);
const headMat = new THREE.MeshStandardMaterial({ color: 0xffdbac, roughness: 0.9 });
const head = new THREE.Mesh(headGeo, headMat);
head.position.y = 1.4;
head.castShadow = true;
group.add(head);
// Cool shades
const glassesGeo = new THREE.BoxGeometry(0.45, 0.1, 0.1);
const glassesMat = new THREE.MeshBasicMaterial({ color: 0x111111 });
const glasses = new THREE.Mesh(glassesGeo, glassesMat);
glasses.position.set(0, 1.45, 0.18);
group.add(glasses);
scene.add(group);
player.mesh = group;
// Start position safe on a central grid node road intersection
player.x = 0;
player.z = 25;
player.mesh.position.set(player.x, player.y, player.z);
}
// --- TRAFFIC SIMULATION (SHAPES ONLY) ---
function spawnTraffic() {
const carColors = [0xd32f2f, 0x1976d2, 0x388e3c, 0xfbc02d, 0x7b1fa2, 0xe67e22, 0x1abc9c];
// Generate distinct AI tracks matching the grid spacing lines
const tracks = [];
const halfSize = CONFIG.citySize / 2;
for(let i = -halfSize; i <= halfSize; i += CONFIG.gridSpacing) {
if(i !== -halfSize && i !== halfSize) {
tracks.push(i);
}
}
for (let i = 0; i < CONFIG.trafficCount; i++) {
const carGroup = new THREE.Group();
// Generate structural lower chassis
const cColor = carColors[Math.floor(Math.random() * carColors.length)];
const bodyGeo = new THREE.BoxGeometry(2.2, 0.7, 4);
const bodyMat = new THREE.MeshStandardMaterial({ color: cColor, roughness: 0.2, metalness: 0.5 });
const body = new THREE.Mesh(bodyGeo, bodyMat);
body.position.y = 0.5;
body.castShadow = true;
carGroup.add(body);
// Cabin top roof
const cabinGeo = new THREE.BoxGeometry(1.8, 0.6, 2.2);
const cabinMat = new THREE.MeshStandardMaterial({ color: 0x1a1a1a, roughness: 0.1 });
const cabin = new THREE.Mesh(cabinGeo, cabinMat);
cabin.position.set(0, 1.1, -0.2);
cabin.castShadow = true;
carGroup.add(cabin);
// Wheels (cylinders)
const wheelGeo = new THREE.CylinderGeometry(0.4, 0.4, 0.4, 12);
const wheelMat = new THREE.MeshStandardMaterial({ color: 0x111111, roughness: 0.9 });
const wheelPositions = [
[-1.1, 0.4, 1.2], [1.1, 0.4, 1.2],
[-1.1, 0.4, -1.2], [1.1, 0.4, -1.2]
];
wheelPositions.forEach(pos => {
const wheel = new THREE.Mesh(wheelGeo, wheelMat);
wheel.rotation.z = Math.PI / 2;
wheel.position.set(pos[0], pos[1], pos[2]);
wheel.castShadow = true;
carGroup.add(wheel);
});
// Headlights primitives (Glow emitters)
const lightGeo = new THREE.BoxGeometry(0.3, 0.15, 0.1);
const lightMat = new THREE.MeshBasicMaterial({ color: 0xfffee0 });
const leftLight = new THREE.Mesh(lightGeo, lightMat);
leftLight.position.set(-0.7, 0.6, 2.01);
const rightLight = leftLight.clone();
rightLight.position.x = 0.7;
carGroup.add(leftLight, rightLight);
scene.add(carGroup);
// Setup state logic for traffic array
// Cars run along either North-South paths or East-West intersecting corridors
const isNorthSouth = Math.random() > 0.5;
const axisTrack = tracks[Math.floor(Math.random() * tracks.length)];
let carData = {
mesh: carGroup,
isNorthSouth: isNorthSouth,
trackPos: axisTrack,
currentProgress: (Math.random() * CONFIG.citySize) - (CONFIG.citySize/2),
direction: Math.random() > 0.5 ? 1 : -1,
speed: CONFIG.carSpeed + (Math.random() * 0.2),
turnAngle: 0,
velocity: 0 // Used during manual drive overrides
};
vehicles.push(carData);
}
}
// --- INPUT & CONTROLS INTERCEPTORS ---
function handleKeyEvent(e, isDown) {
let key = e.key.toLowerCase();
if (key === ' ' || e.code === 'Space') key = 'Space';
if (e.code === 'ArrowUp') key = 'w';
if (e.code === 'ArrowDown') key = 's';
if (e.code === 'ArrowLeft') key = 'a';
if (e.code === 'ArrowRight') key = 'd';
if (key in keys) {
keys[key] = isDown;
}
// Jack vehicle / Exit vehicle click mechanism triggers on key down edge
if (key === 'e' && isDown) {
if (controlledVehicle) {
exitVehicle();
} else if (nearbyVehicle) {
enterVehicle(nearbyVehicle);
}
}
}
function onMouseMove(e) {
// Drag logic for standard dynamic camera calculations without full OrbitControls payload
if (e.buttons === 1 || e.buttons === 2) {
cameraAngleX -= e.movementX * 0.007;
cameraAngleY += e.movementY * 0.007;
// Clamp camera vertical horizon tilt
cameraAngleY = Math.max(0.05, Math.min(Math.PI / 2.2, cameraAngleY));
}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// --- CARJACK ACTIONS MECHANISM ---
function enterVehicle(vehicle) {
controlledVehicle = vehicle;
player.mesh.visible = false;
document.getElementById('mode').innerText = "DRIVING";
document.getElementById('prompt').style.display = 'none';
cameraRadius = 25; // Pull back field of view perspective for driving
}
function exitVehicle() {
// Drop player outside next to car chassis body panel footprint safely
player.x = controlledVehicle.mesh.position.x + Math.sin(controlledVehicle.mesh.rotation.y + Math.PI/2) * 2.5;
player.z = controlledVehicle.mesh.position.z + Math.cos(controlledVehicle.mesh.rotation.y + Math.PI/2) * 2.5;
player.y = 1;
player.vx = 0; player.vz = 0; player.vy = 0;
player.mesh.position.set(player.x, player.y, player.z);
player.mesh.visible = true;
controlledVehicle.velocity = 0;
controlledVehicle = null;
document.getElementById('mode').innerText = "ON FOOT";
cameraRadius = 18;
}
// --- ENGINE GAME LOOPS & PHYSICS UPDATES ---
function animate() {
animationFrameId = requestAnimationFrame(animate);
const dt = Math.min(clock.getDelta(), 0.1); // Cap timestep for frame stability
updateTraffic(dt);
if (controlledVehicle) {
updateDrivenVehiclePhysics(dt);
} else {
updatePlayerPhysics(dt);
}
updateCamera();
evaluateProximityPrompts();
renderer.render(scene, camera);
}
// --- AI TRAFFIC PROCESSOR ---
function updateTraffic(dt) {
vehicles.forEach(car => {
// If user is currently driving this car, suspend AI route handling calculations
if (controlledVehicle === car) return;
// Move cars along paths linearly wrapping around infinite procedural bounds
car.currentProgress += car.speed * car.direction * dt * 60;
const halfBoundary = CONFIG.citySize / 2;
if (car.currentProgress > halfBoundary) car.currentProgress = -halfBoundary;
if (car.currentProgress < -halfBoundary) car.currentProgress = halfBoundary;
if (car.isNorthSouth) {
// Lock cross street alignment offset perfectly to stay in lanes lanes
car.mesh.position.set(car.trackPos + (car.direction * 3.5), 0, car.currentProgress);
car.mesh.rotation.y = car.direction === 1 ? 0 : Math.PI;
} else {
car.mesh.position.set(car.currentProgress, 0, car.trackPos + (car.direction * 3.5));
car.mesh.rotation.y = car.direction === 1 ? Math.PI / 2 : -Math.PI / 2;
}
});
}
// --- PLAYER PHYS LOOP ---
function updatePlayerPhysics(dt) {
// Apply simple environmental acceleration gravity
if (!player.isGrounded) {
player.vy -= 26 * dt;
}
// Process WASD moves oriented relatively against the direction the active camera viewport faces
let moveX = 0;
let moveZ = 0;
if (keys.w) moveZ -= 1;
if (keys.s) moveZ += 1;
if (keys.a) moveX -= 1;
if (keys.d) moveX += 1;
if (moveX !== 0 || moveZ !== 0) {
// Normalize and pivot direction vectors relative to look-at angle vectors
const length = Math.sqrt(moveX * moveX + moveZ * moveZ);
const normX = moveX / length;
const normZ = moveZ / length;
const camFacingAngle = cameraAngleX;
const rotatedX = normX * Math.cos(camFacingAngle) - normZ * Math.sin(camFacingAngle);
const rotatedZ = normX * Math.sin(camFacingAngle) + normZ * Math.cos(camFacingAngle);
player.vx = rotatedX * player.speed;
player.vz = rotatedZ * player.speed;
// Smoothly snap low-poly avatar facing alignment vector toward current travel trajectory
player.rotation = Math.atan2(rotatedX, rotatedZ);
player.mesh.rotation.y = player.rotation;
} else {
// Friction dampening slide deceleration properties
player.vx *= 0.7;
player.vz *= 0.7;
}
// Jump command handling
if (keys.Space && player.isGrounded) {
player.vy = 10;
player.isGrounded = false;
}
// Apply positions calculated
player.x += player.vx * dt;
player.z += player.vz * dt;
player.y += player.vy * dt;
// Simple floor bounds checking plane baseline crash protection
if (player.y <= 0.9) {
player.y = 0.9;
player.vy = 0;
player.isGrounded = true;
}
// Basic block geometric structure collisions avoidance loop
handleBuildingCollisions();
player.mesh.position.set(player.x, player.y, player.z);
}
function handleBuildingCollisions() {
const step = CONFIG.gridSpacing;
const halfSize = CONFIG.citySize / 2;
const blockPadding = CONFIG.roadWidth / 2;
// Resolve player coordinates back to grid block space matrices instantly
vehicles.forEach(car => {
// Prevent running straight through ambient vehicles on foot
if(controlledVehicle === car) return;
const dx = player.x - car.mesh.position.x;
const dz = player.z - car.mesh.position.z;
const dist = Math.sqrt(dx*dx + dz*dz);
if (dist < 2.0) {
player.x += (dx / dist) * (2.0 - dist);
player.z += (dz / dist) * (2.0 - dist);
}
});
}
// --- VEHICLE PHYSICS ENGINE (DRIVING STEER MODE) ---
function updateDrivenVehiclePhysics(dt) {
let car = controlledVehicle;
// Throttle / Reverse
if (keys.w) {
car.velocity += 28 * dt; // Acceleration
} else if (keys.s) {
car.velocity -= 18 * dt; // Reverse
} else {
car.velocity *= 0.96; // Coasting deceleration friction
}
// Brake
if (keys.Space) {
car.velocity *= 0.85;
}
// Speed governance thresholds limits
const maxSpeed = 45;
car.velocity = THREE.MathUtils.clamp(car.velocity, -maxSpeed/2, maxSpeed);
// Steering calculations dependent directly upon absolute speed values
const steerSpeedMultiplier = Math.min(Math.abs(car.velocity) / 15, 1.0);
if (keys.a) {
car.turnAngle += 2.2 * dt * steerSpeedMultiplier * (car.velocity >= 0 ? 1 : -1);
}
if (keys.d) {
car.turnAngle -= 2.2 * dt * steerSpeedMultiplier * (car.velocity >= 0 ? 1 : -1);
}
// Update physical positions using forward direction trigonometric expansion vectors
car.mesh.rotation.y = car.turnAngle;
// Derive directional updates matching low-poly assets native orientations offsets
const moveStep = car.velocity * dt;
car.mesh.position.x += Math.sin(car.turnAngle) * moveStep;
car.mesh.position.z += Math.cos(car.turnAngle) * moveStep;
// Reflect user driven positional coordinates onto core player variables for clean tracking metrics
player.x = car.mesh.position.x;
player.y = car.mesh.position.y + 1.0;
player.z = car.mesh.position.z;
}
// --- CAMERA CONTROLLER SYSTEM ---
function updateCamera() {
// Target coordinate sets tracking player position anchor values smoothly
const targetX = player.x;
const targetY = player.y;
const targetZ = player.z;
// Calculate precise orbital trigonometry points based around tracking targets coordinates
const offsetCamX = cameraRadius * Math.sin(cameraAngleX) * Math.cos(cameraAngleY);
const offsetCamZ = cameraRadius * Math.cos(cameraAngleX) * Math.cos(cameraAngleY);
const offsetCamY = cameraRadius * Math.sin(cameraAngleY);
camera.position.set(targetX + offsetCamX, targetY + offsetCamY, targetZ + offsetCamZ);
camera.lookAt(targetX, targetY + 1.2, targetZ);
}
// --- COGNITIVE PROXIMITY ENGINE FOR VEHICLE INTERACTION ---
function evaluateProximityPrompts() {
if (controlledVehicle) {
nearbyVehicle = null;
return;
}
let closestCar = null;
let closestDist = 4.5; // Action hijacking target range buffer threshold limit meters
vehicles.forEach(car => {
const dx = player.x - car.mesh.position.x;
const dz = player.z - car.mesh.position.z;
const distance = Math.sqrt(dx * dx + dz * dz);
if (distance < closestDist) {
closestDist = distance;
closestCar = car;
}
});
const promptUI = document.getElementById('prompt');
if (closestCar) {
nearbyVehicle = closestCar;
promptUI.style.display = 'block';
// Visual helper hint - slightly elevate or skew target mesh elements properties to register choice
} else {
nearbyVehicle = null;
promptUI.style.display = 'none';
}
}
// Execute core game pipeline sequence init steps seamlessly
init();
</script>
</body>
</html>