← Rally results

Rally

Gemma 4 12b · typescript

Initial view of Rally

Reviews & generation details

Reviews

No human review yet. Unreviewed does not mean unsuccessful.

Generation context

Imported historical artifact. Its exact original instructions and lineage are not known.

Generation prompt · exact text unavailable

See the current prompt for reference. It may differ from the instructions used to generate this artifact.

Inspect original source 18,467 bytes · SHA-256 438cdf511991
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rally Pro 3D</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.min.js"></script>
<style>
/* ── css: layout ── */
#game-canvas {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    z-index: -1;
}

#ui-layer {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    color: white;
    user-select: none;
}

#hud {
    position: absolute;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0, 0, 0, 0.6);
    padding: 15px 30px;
    border-radius: 50px;
    display: flex;
    gap: 40px;
    align-items: center;
    border: 2px solid rgba(255, 255, 255, 0.3);
}

#hud .speedometer {
    font-size: 2rem;
    font-weight: bold;
}

#hud .stats {
    display: flex;
    gap: 15px;
    font-size: 1.2rem;
}

#minimap-container {
    position: absolute;
    top: 20px;
    right: 20px;
    background: rgba(0, 0, 0, 0.5);
    padding: 10px;
    border-radius: 10px;
    border: 2px solid white;
}

#minimap {
    width: 150px;
    height: 150px;
    background: #333;
}

#overlay, #pause-menu, #finish-screen {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background: rgba(0, 0, 0, 0.7);
}

#overlay.hidden { display: none; }
#pause-menu.hidden { display: none; }
#finish-screen.hidden { display: none; }

button {
    padding: 15px 40px;
    font-size: 1.5rem;
    background: #e74c3c;
    color: white;
    border: none;
    border-radius: 10px;
    cursor: pointer;
}

button:hover { background: #c0392b; }

#overlay h1 { font-size: 5rem; }
</style>
</head>
<body>
<div id="ui-layer">
    <div id="hud">
        <div class="speedometer">
            <span id="speed-val">0</span> <span class="unit">KM/H</span>
        </div>
        <div class="stats">
            <div>LAP <span id="lap-current">1</span> / 3</div>
            <div>TIME <span id="timer">0.00</span></div>
            <div>BEST <span id="best-lap">-</span></div>
        </div>
    </div>
    <div id="minimap-container">
        <canvas id="minimap"></canvas>
    </div>
    <div id="overlay" class="hidden">
        <h1 id="overlay-text">READY?</h1>
    </div>
    <div id="pause-menu" class="hidden">
        <h2>PAUSED</h2>
        <button id="btn-resume">RESUME</button>
        <button id="btn-restart">RESTART</button>
    </div>
    <div id="finish-screen" class="hidden">
        <h1>RACE FINISHED!</h1>
        <p>Final Time: <span id="final-time">-</span></p>
        <p>Best Lap: <span id="best-lap-final">-</span></p>
        <button id="btn-next-race">NEXT RACE</button>
    </div>
</div>
<canvas id="game-canvas"></canvas>
<script>
(function () {
'use strict';
var __mods = {};
var __cache = {};
var __map = {"src/main.ts":{"./physics":"src/physics.ts","./audio":"src/audio.ts"}};
function __require(id) {
  if (__cache[id]) return __cache[id].exports;
  var module = __cache[id] = { exports: {} };
  var factory = __mods[id];
  if (!factory) throw new Error("Module not found: " + id);
  factory(module.exports, function (spec) {
    var target = (__map[id] && __map[id][spec]) || spec;
    return __require(target);
  }, module);
  return module.exports;
}

// ── module: src/main.ts ──
__mods["src/main.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const physics_1 = require("./physics");
const audio_1 = require("./audio");
class Game {
    constructor() {
        this.trackPoints = [];
        this.checkpoints = [];
        this.currentLap = 1;
        this.totalLaps = 3;
        this.lastCheckpointIndex = -1;
        this.bestLap = Infinity;
        this.timer = 0;
        this.isPaused = false;
        this.isStarted = false;
        this.countdown = 3;
        this.inputState = {};
        this.cameraMode = 'chase';
        const THREE = window.THREE;
        this.scene = new THREE.Scene();
        const skyColor = new THREE.Color(0x87ceeb);
        this.scene.background = skyColor;
        this.scene.fog = new THREE.Fog(skyColor, 20, 150);
        this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const canvas = document.getElementById('game-canvas');
        this.renderer = new THREE.WebGLRenderer({ canvas: canvas });
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
        this.audio = new audio_1.AudioEngine();
        // Lighting
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
        this.scene.add(ambientLight);
        const sun = new THREE.PointLight(0xffffff, 1.5);
        sun.position.set(50, 50, 50);
        this.scene.add(sun);
        // Ground & Environment
        this.createEnvironment();
        this.createTrack();
        // Car
        this.physics = new physics_1.CarPhysics(new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, 1));
        this.carModel = this.createCarModel();
        this.scene.add(this.carModel);
        // Controls
        this.initInputs();
        // UI
        this.updateUI();
        this.setupGameLoop();
    }
    createEnvironment() {
        const THREE = window.THREE;
        const groundGeo = new THREE.PlaneGeometry(2000, 2000);
        const groundMat = new THREE.MeshStandardMaterial({ color: 0x3a5f0b });
        const ground = new THREE.Mesh(groundGeo, groundMat);
        ground.rotation.x = -Math.PI / 2;
        this.scene.add(ground);
        for (let i = 0; i < 100; i++) {
            const tree = new THREE.Group();
            const trunk = new THREE.Mesh(new THREE.CylinderGeometry(0.5, 0.7, 4), new THREE.MeshStandardMaterial({ color: 0x4b3621 }));
            trunk.position.y = 2;
            const leaves = new THREE.Mesh(new THREE.SphereGeometry(2, 8, 8), new THREE.MeshStandardMaterial({ color: 0x0a5d00 }));
            leaves.position.y = 4;
            tree.add(trunk);
            tree.add(leaves);
            tree.position.set(Math.random() * 400 - 200, 0, Math.random() * 400 - 200);
            if (Math.abs(tree.position.x) > 50 || Math.abs(tree.position.z) > 50) {
                this.scene.add(tree);
            }
        }
    }
    createTrack() {
        const THREE = window.THREE;
        const pts = [
            new THREE.Vector3(0, 0, 0),
            new THREE.Vector3(100, 20, 50),
            new THREE.Vector3(150, 40, 150),
            new THREE.Vector3(50, 30, 200),
            new THREE.Vector3(-50, 20, 150),
            new THREE.Vector3(-100, 10, 50),
            new THREE.Vector3(-50, 0, -50),
            new THREE.Vector3(0, 0, 0)
        ];
        this.trackPoints = pts;
        const curve = new THREE.CatmullRomCurve3(pts);
        const geometry = new THREE.TubeGeometry(curve, 64, 8, 8, false);
        const material = new THREE.MeshStandardMaterial({ color: 0x333333 });
        const road = new THREE.Mesh(geometry, material);
        road.position.y = 2;
        this.scene.add(road);
        for (let i = 0; i < pts.length - 1; i++) {
            const cp = new THREE.Vector3().lerpVectors(pts[i], pts[i + 1], 0.5);
            this.checkpoints.push({ pos: cp, id: i });
        }
    }
    createCarModel() {
        const THREE = window.THREE;
        const car = new THREE.Group();
        const body = new THREE.Mesh(new THREE.BoxGeometry(2, 1, 4), new THREE.MeshStandardMaterial({ color: 0xff0000 }));
        body.position.y = 0.6;
        car.add(body);
        const cabin = new THREE.Mesh(new THREE.BoxGeometry(1.5, 0.8, 2), new THREE.MeshStandardMaterial({ color: 0x333333 }));
        cabin.position.y = 1.4;
        cabin.position.z = -0.2;
        car.add(cabin);
        const spoiler = new THREE.Mesh(new THREE.BoxGeometry(2, 0.2, 0.5), new THREE.MeshStandardMaterial({ color: 0x111111 }));
        spoiler.position.set(0, 1.4, 1.8);
        car.add(spoiler);
        const wheelGeo = new THREE.CylinderGeometry(0.5, 0.5, 0.4, 8);
        const wheelMat = new THREE.MeshStandardMaterial({ color: 0x111111 });
        const wheels = [];
        const positions = [
            [1, 0.5, 1.2], [-1, 0.5, 1.2],
            [1, 0.5, -1.2], [-1, 0.5, -1.2]
        ];
        positions.forEach(p => {
            const w = new THREE.Mesh(wheelGeo, wheelMat);
            w.rotation.z = Math.PI / 2;
            w.position.set(p[0], p[1], p[2]);
            car.add(w);
            wheels.push(w);
        });
        return car;
    }
    initInputs() {
        window.addEventListener('keydown', (e) => {
            this.inputState[e.code] = true;
            if (e.code === 'KeyR')
                this.restart();
            if (e.code === 'KeyP')
                this.togglePause();
            if (e.code === 'KeyC')
                this.toggleCamera();
        });
        window.addEventListener('keyup', (e) => {
            this.inputState[e.code] = false;
        });
    }
    togglePause() {
        this.isPaused = !this.isPaused;
        const pm = document.getElementById('pause-menu');
        if (pm)
            pm.classList.toggle('hidden', !this.isPaused);
    }
    toggleCamera() {
        this.cameraMode = this.cameraMode === 'chase' ? 'cinematic' : 'chase';
    }
    setupGameLoop() {
        const loop = () => {
            if (!this.isPaused) {
                this.update();
            }
            this.renderer.render(this.scene, this.camera);
            requestAnimationFrame(loop);
        };
        requestAnimationFrame(loop);
    }
    update() {
        const THREE = window.THREE;
        if (!this.isStarted) {
            this.countdown--;
            const overlayText = document.getElementById('overlay-text');
            if (overlayText) {
                overlayText.innerText = this.countdown > 0 ? this.countdown.toString() : "GO!";
            }
            if (this.countdown <= 0) {
                this.isStarted = true;
                const overlay = document.getElementById('overlay');
                if (overlay)
                    overlay.classList.add('hidden');
                this.audio.playBeep();
            }
            return;
        }
        const input = {
            gas: this.inputState['ArrowUp'] || this.inputState['KeyW'] ? 1 : 0,
            brake: this.inputState['ArrowDown'] || this.inputState['KeyS'] ? 1 : 0,
            steer: this.inputState['ArrowLeft'] ? -1 : (this.inputState['ArrowRight'] || this.inputState['KeyD'] ? 1 : 0)
        };
        const grip = 1.0;
        this.physics.update(input, grip);
        this.carModel.position.copy(this.physics.position);
        this.carModel.rotation.y = this.physics.rotation;
        this.carModel.rotation.z = -input.steer * (Math.min(this.physics.speed, 100) / 100) * 0.5;
        const camOffset = new THREE.Vector3(0, 5, -12);
        camOffset.applyAxisAngle(new THREE.Vector3(0, 1, 0), this.physics.rotation);
        const targetCamPos = new THREE.Vector3();
        targetCamPos.copy(this.carModel.position);
        targetCamPos.add(camOffset);
        const currentPos = this.camera.position;
        this.camera.position.x = currentPos.x + (targetCamPos.x - currentPos.x) * 0.1;
        this.camera.position.y = currentPos.y + (targetCamPos.y - currentPos.y) * 0.1;
        this.camera.position.z = currentPos.z + (targetCamPos.z - currentPos.z) * 0.1;
        this.camera.lookAt(this.carModel.position);
        this.timer += 1 / 60;
        this.checkpoints.forEach((cp, idx) => {
            if (this.physics.position.distanceTo(cp.pos) < 25) {
                if (idx === this.lastCheckpointIndex + 1) {
                    this.lastCheckpointIndex = idx;
                    if (idx === this.checkpoints.length - 1) {
                        this.completeLap();
                    }
                }
            }
        });
        this.audio.playEngine(this.physics.speed);
        this.updateUI();
    }
    completeLap() {
        if (this.currentLap < this.totalLaps) {
            this.currentLap++;
            this.lastCheckpointIndex = -1;
            if (this.timer < this.bestLap)
                this.bestLap = this.timer;
        }
        else {
            this.endRace();
        }
    }
    endRace() {
        const fs = document.getElementById('finish-screen');
        if (fs)
            fs.classList.remove('hidden');
        const ft = document.getElementById('final-time');
        if (ft)
            ft.innerText = this.timer.toFixed(2);
        const blf = document.getElementById('best-lap-final');
        if (blf)
            blf.innerText = this.bestLap === Infinity ? "-" : this.bestLap.toFixed(2);
    }
    updateUI() {
        const speedEl = document.getElementById('speed-val');
        if (speedEl)
            speedEl.innerText = Math.floor(this.physics.speed * 2.5).toString();
        const lapEl = document.getElementById('lap-current');
        if (lapEl)
            lapEl.innerText = this.currentLap.toString();
        const timerEl = document.getElementById('timer');
        if (timerEl)
            timerEl.innerText = this.timer.toFixed(2);
        const bestEl = document.getElementById('best-lap');
        if (bestEl)
            bestEl.innerText = this.bestLap === Infinity ? "-" : this.bestLap.toFixed(2);
    }
    restart() {
        location.reload();
    }
}
new Game();
};

// ── types: src/globals.d.ts ──
__mods["src/globals.d.ts"] = function (exports) {};

// ── module: src/audio.ts ──
__mods["src/audio.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AudioEngine = void 0;
class AudioEngine {
    constructor() {
        this.engineObj = null;
        this.ctx = new window.AudioContext || new window.webkitAudioContext();
    }
    // Simple synth for engine sound
    createOscillator(freq, volume) {
        const osc = this.ctx.createOscillator();
        const gain = this.ctx.createGain();
        osc.type = 'sawtooth';
        osc.frequency.setValueAtTime(freq, this.ctx.currentTime);
        gain.gain.setValueAtTime(volume, this.ctx.currentTime);
        osc.connect(gain);
        gain.connect(this.ctx.destination);
        osc.start();
        return { osc, gain };
    }
    playEngine(speed) {
        if (!this.engineObj) {
            this.engineObj = this.createOscillator(100, 0.1);
        }
        const freq = 100 + speed * 2;
        this.engineObj.osc.frequency.setTargetAtTime(freq, this.ctx.currentTime, 0.1);
    }
    playBeep() {
        const osc = this.ctx.createOscillator();
        const gain = this.ctx.createGain();
        osc.type = 'sine';
        osc.frequency.setValueAtTime(880, this.ctx.currentTime);
        gain.gain.setValueAtTime(0.1, this.ctx.currentTime);
        gain.gain.exponentialRampToValueAtTime(0.01, this.ctx.currentTime + 0.5);
        osc.connect(gain);
        gain.connect(this.ctx.destination);
        osc.start();
        osc.stop(this.ctx.currentTime + 0.5);
    }
    playCrash() {
        const osc = this.ctx.createOscillator();
        const gain = this.ctx.createGain();
        osc.type = 'square';
        osc.frequency.setValueAtTime(150, this.ctx.currentTime);
        osc.frequency.exponentialRampToValueAtTime(40, this.ctx.currentTime + 0.3);
        gain.gain.setValueAtTime(0.2, this.ctx.currentTime);
        gain.gain.linearRampToValueAtTime(0, this.ctx.currentTime + 0.3);
        osc.connect(gain);
        gain.connect(this.ctx.destination);
        osc.start();
        osc.stop(this.ctx.currentTime + 0.3);
    }
}
exports.AudioEngine = AudioEngine;
};

// ── module: src/physics.ts ──
__mods["src/physics.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CarPhysics = void 0;
class CarPhysics {
    constructor(position, direction) {
        this.position = position;
        this.direction = direction;
        this.speed = 0;
        this.acceleration = 0;
        this.steering = 0;
        this.drift = 0;
        this.rotation = 0;
        this.maxSpeed = 150;
        this.accelRate = 0.4;
        this.friction = 0.98;
        this.turnSensitivity = 2.5;
    }
    update(input, surfaceGrip) {
        // Acceleration/Braking
        const targetAccel = input.gas * 0.8 - input.brake * 0.5;
        this.acceleration += targetAccel;
        this.acceleration *= 0.9;
        const force = (this.acceleration * surfaceGrip);
        this.speed += force;
        this.speed *= this.friction;
        if (Math.abs(this.speed) < 1 && Math.abs(this.acceleration) < 0.1) {
            this.speed *= 0.9;
        }
        if (this.speed > this.maxSpeed * surfaceGrip) {
            this.speed = this.maxSpeed * surfaceGrip;
        }
        // Steering
        const steerAmount = input.steer * this.turnSensitivity * (Math.min(Math.abs(this.speed), 100) / 50);
        this.rotation += steerAmount * (this.speed / 50);
        // Drifting calculation
        const driftFactor = (Math.abs(input.steer) > 0.7 && this.speed > 60) ? 0.9 : 1;
        this.drift = (1 - driftFactor) * surfaceGrip;
        // Update direction vector based on rotation
        const forwardX = Math.sin(this.rotation);
        const forwardZ = Math.cos(this.rotation);
        // Apply drift (sideways velocity component)
        const sidewaysX = -Math.cos(this.rotation);
        const sidewaysZ = Math.sin(this.rotation);
        this.position.x += forwardX * this.speed * 0.01;
        this.position.z += forwardZ * this.speed * 0.01;
        this.position.x += sidewaysX * (this.drift * 5);
        this.position.z += sidewaysZ * (this.drift * 5);
    }
}
exports.CarPhysics = CarPhysics;
};

// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>
<!-- agent-meta {"model":"google/gemma-4-12b","provider":"lmstudio","persona":"typescript","sessionId":"12dd928b-3bff-4464-9a81-121738201870","tokensIn":1527210,"tokensOut":51219,"tokensTotal":1578429,"turns":42,"toolCalls":41,"failedToolCalls":3,"timestamp":"2026-07-31T04:00:48.402Z"} -->