{"project":{"id":"CEQmBZ5","userId":"davidyarham@gmail.com","username":null,"userPicture":null,"name":"Voxel Road Hopper","thumbnail":"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","visible":true,"contributors":"","githubRepo":null,"forkedFrom":null,"isTemplate":false,"tags":"","files":{"folder":"","files":[{"name":"index.html","content":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Voxel Road Hopper</title>\n  <link rel=\"stylesheet\" href=\"css/styles.css\">\n  <script type=\"importmap\">\n    {\n      \"imports\": {\n        \"three\": \"https://unpkg.com/three@0.160.0/build/three.module.js\"\n      }\n    }\n  </script>\n</head>\n<body>\n  <div id=\"game-container\">\n    <canvas id=\"game-canvas\"></canvas>\n\n    <div id=\"hud\" class=\"hud\">\n      <div class=\"hud__score\" id=\"score\">0</div>\n      <button class=\"hud__mute\" id=\"mute-btn\" aria-label=\"Toggle sound\">&#128266;</button>\n    </div>\n\n    <div id=\"start-overlay\" class=\"overlay overlay--visible\">\n      <h1 class=\"overlay__title\">VOXEL ROAD<br>HOPPER</h1>\n      <p class=\"overlay__hint\">Arrow keys / WASD to hop &middot; Tap to go forward</p>\n      <button class=\"overlay__btn\" id=\"start-btn\">PLAY</button>\n    </div>\n\n    <div id=\"gameover-overlay\" class=\"overlay\">\n      <h2 class=\"overlay__title overlay__title--small\">GAME OVER</h2>\n      <div class=\"overlay__score-block\">\n        <div class=\"overlay__score-label\">SCORE</div>\n        <div class=\"overlay__score\" id=\"final-score\">0</div>\n        <div class=\"overlay__score-label\">BEST</div>\n        <div class=\"overlay__best\" id=\"best-score\">0</div>\n      </div>\n      <button class=\"overlay__btn\" id=\"retry-btn\">PLAY AGAIN</button>\n    </div>\n  </div>\n\n  <script type=\"module\" src=\"js/main.js\"></script>\n</body>\n</html>\n"},{"name":"README.md","content":"# Blnq Project\n"}],"folders":[{"folder":"css","files":[{"name":"styles.css","content":":root {\n  --color-bg: #6ec6e8;\n  --color-text: #ffffff;\n  --color-accent: #ff5a3c;\n  --color-overlay: rgba(20, 40, 60, 0.55);\n  --font-stack: 'Arial Black', 'Helvetica Neue', Arial, sans-serif;\n}\n\n* {\n  margin: 0;\n  padding: 0;\n  box-sizing: border-box;\n}\n\nhtml, body {\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n  background: var(--color-bg);\n  font-family: var(--font-stack);\n  touch-action: manipulation;\n  -webkit-user-select: none;\n  user-select: none;\n}\n\n#game-container {\n  position: relative;\n  width: 100%;\n  height: 100%;\n}\n\n#game-canvas {\n  display: block;\n  width: 100%;\n  height: 100%;\n}\n\n/* ---------- HUD ---------- */\n.hud {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-start;\n  padding: 18px 22px;\n  pointer-events: none;\n}\n\n.hud__score {\n  font-size: 56px;\n  font-weight: 900;\n  color: var(--color-text);\n  text-shadow: 0 3px 0 rgba(0, 0, 0, 0.35);\n  line-height: 1;\n}\n\n.hud__mute {\n  pointer-events: auto;\n  background: rgba(0, 0, 0, 0.25);\n  border: none;\n  border-radius: 10px;\n  font-size: 22px;\n  width: 46px;\n  height: 46px;\n  cursor: pointer;\n  color: var(--color-text);\n}\n\n.hud__mute:hover {\n  background: rgba(0, 0, 0, 0.4);\n}\n\n/* ---------- Overlays ---------- */\n.overlay {\n  position: absolute;\n  inset: 0;\n  display: none;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  gap: 26px;\n  background: var(--color-overlay);\n  text-align: center;\n  z-index: 10;\n}\n\n.overlay--visible {\n  display: flex;\n}\n\n.overlay__title {\n  font-size: clamp(40px, 8vw, 76px);\n  font-weight: 900;\n  color: var(--color-text);\n  letter-spacing: 2px;\n  text-shadow: 0 5px 0 rgba(0, 0, 0, 0.35);\n  line-height: 1.05;\n}\n\n.overlay__title--small {\n  font-size: clamp(34px, 6vw, 58px);\n}\n\n.overlay__hint {\n  font-family: Arial, sans-serif;\n  font-size: 16px;\n  color: var(--color-text);\n  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.3);\n}\n\n.overlay__btn {\n  font-family: var(--font-stack);\n  font-size: 24px;\n  font-weight: 900;\n  letter-spacing: 1px;\n  color: var(--color-text);\n  background: var(--color-accent);\n  border: none;\n  border-radius: 12px;\n  padding: 16px 44px;\n  cursor: pointer;\n  box-shadow: 0 6px 0 #c23a22;\n  transition: transform 0.08s ease, box-shadow 0.08s ease;\n}\n\n.overlay__btn:hover {\n  transform: translateY(2px);\n  box-shadow: 0 4px 0 #c23a22;\n}\n\n.overlay__btn:active {\n  transform: translateY(6px);\n  box-shadow: 0 0 0 #c23a22;\n}\n\n.overlay__score-block {\n  color: var(--color-text);\n}\n\n.overlay__score-label {\n  font-size: 16px;\n  letter-spacing: 3px;\n  opacity: 0.85;\n}\n\n.overlay__score {\n  font-size: 64px;\n  font-weight: 900;\n  text-shadow: 0 4px 0 rgba(0, 0, 0, 0.35);\n  margin-bottom: 14px;\n}\n\n.overlay__best {\n  font-size: 36px;\n  font-weight: 900;\n  text-shadow: 0 3px 0 rgba(0, 0, 0, 0.35);\n}\n"}],"folders":[]},{"folder":"js","files":[{"name":"audio.js","content":"// Tiny WebAudio synth — Crossy Road style plinks and effects, no assets.\nexport class AudioManager {\n  constructor() {\n    this.ctx = null;\n    this.muted = false;\n    this.master = null;\n  }\n\n  ensure() {\n    if (!this.ctx) {\n      const AC = window.AudioContext || window.webkitAudioContext;\n      this.ctx = new AC();\n      this.master = this.ctx.createGain();\n      this.master.gain.value = 0.5;\n      this.master.connect(this.ctx.destination);\n    }\n    if (this.ctx.state === 'suspended') this.ctx.resume();\n  }\n\n  toggleMute() {\n    this.muted = !this.muted;\n    if (this.master) this.master.gain.value = this.muted ? 0 : 0.5;\n    return this.muted;\n  }\n\n  tone({ freq = 440, dur = 0.1, type = 'square', vol = 0.3, slide = 0, delay = 0 }) {\n    if (!this.ctx || this.muted) return;\n    const t0 = this.ctx.currentTime + delay;\n    const osc = this.ctx.createOscillator();\n    const gain = this.ctx.createGain();\n    osc.type = type;\n    osc.frequency.setValueAtTime(freq, t0);\n    if (slide) osc.frequency.exponentialRampToValueAtTime(Math.max(30, freq + slide), t0 + dur);\n    gain.gain.setValueAtTime(vol, t0);\n    gain.gain.exponentialRampToValueAtTime(0.001, t0 + dur);\n    osc.connect(gain).connect(this.master);\n    osc.start(t0);\n    osc.stop(t0 + dur + 0.02);\n  }\n\n  noise({ dur = 0.3, vol = 0.3, delay = 0, lowpass = 1000 }) {\n    if (!this.ctx || this.muted) return;\n    const t0 = this.ctx.currentTime + delay;\n    const len = Math.floor(this.ctx.sampleRate * dur);\n    const buf = this.ctx.createBuffer(1, len, this.ctx.sampleRate);\n    const data = buf.getChannelData(0);\n    for (let i = 0; i < len; i++) data[i] = (Math.random() * 2 - 1) * (1 - i / len);\n    const src = this.ctx.createBufferSource();\n    src.buffer = buf;\n    const filter = this.ctx.createBiquadFilter();\n    filter.type = 'lowpass';\n    filter.frequency.value = lowpass;\n    const gain = this.ctx.createGain();\n    gain.gain.setValueAtTime(vol, t0);\n    gain.gain.exponentialRampToValueAtTime(0.001, t0 + dur);\n    src.connect(filter).connect(gain).connect(this.master);\n    src.start(t0);\n  }\n\n  // ---- game events ----\n  hop() {\n    this.tone({ freq: 660, dur: 0.07, type: 'square', vol: 0.18, slide: 240 });\n  }\n\n  scoreMilestone() {\n    this.tone({ freq: 880, dur: 0.08, vol: 0.2 });\n    this.tone({ freq: 1320, dur: 0.1, vol: 0.2, delay: 0.08 });\n  }\n\n  splash() {\n    this.noise({ dur: 0.45, vol: 0.5, lowpass: 800 });\n    this.tone({ freq: 300, dur: 0.3, type: 'sine', vol: 0.3, slide: -220 });\n  }\n\n  squash() {\n    this.noise({ dur: 0.2, vol: 0.6, lowpass: 500 });\n    this.tone({ freq: 160, dur: 0.25, type: 'sawtooth', vol: 0.35, slide: -120 });\n  }\n\n  trainWarning() {\n    this.tone({ freq: 740, dur: 0.12, vol: 0.15 });\n    this.tone({ freq: 740, dur: 0.12, vol: 0.15, delay: 0.2 });\n    this.tone({ freq: 740, dur: 0.12, vol: 0.15, delay: 0.4 });\n  }\n\n  trainPass() {\n    this.noise({ dur: 0.9, vol: 0.25, lowpass: 600 });\n  }\n\n  gameOver() {\n    this.tone({ freq: 440, dur: 0.15, type: 'square', vol: 0.25 });\n    this.tone({ freq: 330, dur: 0.15, type: 'square', vol: 0.25, delay: 0.15 });\n    this.tone({ freq: 220, dur: 0.3, type: 'square', vol: 0.25, delay: 0.3 });\n  }\n\n  start() {\n    this.tone({ freq: 523, dur: 0.09, vol: 0.2 });\n    this.tone({ freq: 659, dur: 0.09, vol: 0.2, delay: 0.09 });\n    this.tone({ freq: 784, dur: 0.12, vol: 0.2, delay: 0.18 });\n  }\n}\n"},{"name":"lanes.js","content":"// Lane generation — grass / road / rail / river strips, Crossy Road style.\n// World axes: player moves forward along -Z? No — we use +X as \"forward\" like\n// Crossy Road's diagonal view. Simpler: lanes advance along +Z is awkward for\n// the camera, so: forward = -Z, lanes are rows at integer z, tiles at integer x.\nimport * as THREE from 'three';\nimport {\n  box, mat,\n  createCar, createTruck, createTrain, createLog, createTree, createRock, createSignal,\n} from './models.js';\n\nexport const TILE = 1;\nexport const LANE_WIDTH = 30; // tiles wide (visual), playable area narrower\nexport const PLAY_MIN_X = -4;\nexport const PLAY_MAX_X = 4;\n\nconst GRASS_LIGHT = 0xbcec6a;\nconst GRASS_DARK = 0xaadd5c;\nconst ROAD = 0x4b5161;\nconst ROAD_LINE = 0xe3e6ec;\nconst RAIL_BED = 0x8b7b5e;\nconst WATER = 0x3fa8f0;\n\nlet laneIndexCounter = 0;\n\nfunction rand(min, max) { return min + Math.random() * (max - min); }\nfunction randInt(min, max) { return Math.floor(rand(min, max + 1)); }\nfunction pick(arr) { return arr[Math.floor(Math.random() * arr.length)]; }\n\n// ------------------------------------------------------------------ base strips\nfunction grassStrip(z, light) {\n  const m = box(LANE_WIDTH, 0.5, TILE, light ? GRASS_LIGHT : GRASS_DARK, 0, -0.25, z, false, true);\n  return m;\n}\n\nfunction roadStrip(z) {\n  return box(LANE_WIDTH, 0.5, TILE, ROAD, 0, -0.27, z, false, true);\n}\n\nfunction waterStrip(z) {\n  const m = box(LANE_WIDTH, 0.4, TILE, WATER, 0, -0.34, z, false, true);\n  return m;\n}\n\n// ------------------------------------------------------------------ Lane class\nexport class Lane {\n  constructor(type, z, scene, prevType) {\n    this.type = type;            // 'grass' | 'road' | 'rail' | 'river'\n    this.z = z;                  // world z of this row (negative going forward)\n    this.index = laneIndexCounter++;\n    this.group = new THREE.Group();\n    this.obstacles = new Set();  // static blockers (tree/rock) — tile x values\n    this.movers = [];            // {mesh, speed, dir, length} vehicles or logs\n    this.scene = scene;\n\n    this.build(prevType);\n    scene.add(this.group);\n  }\n\n  build(prevType) {\n    const z = this.z;\n    const g = this.group;\n\n    if (this.type === 'grass') {\n      g.add(grassStrip(z, Math.abs(Math.round(z)) % 2 === 0));\n      // trees & rocks outside + sparse inside playable area\n      const used = new Set();\n      // dense decoration outside playable bounds\n      for (let x = -Math.floor(LANE_WIDTH / 2) + 1; x < PLAY_MIN_X; x++) {\n        if (Math.random() < 0.45) this.addStatic(x, z, Math.random() < 0.85 ? createTree(randInt(1, 2)) : createRock(), used, false);\n      }\n      for (let x = PLAY_MAX_X + 1; x < Math.floor(LANE_WIDTH / 2); x++) {\n        if (Math.random() < 0.45) this.addStatic(x, z, Math.random() < 0.85 ? createTree(randInt(1, 2)) : createRock(), used, false);\n      }\n      // sparse blockers inside, never fully blocking\n      const insideCount = randInt(0, 3);\n      const candidates = [];\n      for (let x = PLAY_MIN_X; x <= PLAY_MAX_X; x++) candidates.push(x);\n      for (let i = 0; i < insideCount && candidates.length > 3; i++) {\n        const x = pick(candidates);\n        candidates.splice(candidates.indexOf(x), 1);\n        this.addStatic(x, z, Math.random() < 0.8 ? createTree(randInt(1, 2)) : createRock(), used, true);\n      }\n    } else if (this.type === 'road') {\n      g.add(roadStrip(z));\n      // dashed center line on the edge between consecutive road lanes (cosmetic)\n      if (prevType === 'road') {\n        for (let x = -14; x <= 14; x += 2) {\n          g.add(box(0.6, 0.02, 0.1, ROAD_LINE, x, -0.01, z - 0.5, false, false));\n        }\n      }\n      this.setupVehicles();\n    } else if (this.type === 'rail') {\n      g.add(roadStrip(z));\n      g.add(box(LANE_WIDTH, 0.04, 0.12, 0xc9cdd4, 0, 0.0, z - 0.22, false, false));\n      g.add(box(LANE_WIDTH, 0.04, 0.12, 0xc9cdd4, 0, 0.0, z + 0.22, false, false));\n      for (let x = -14; x <= 14; x++) {\n        g.add(box(0.7, 0.03, 0.22, RAIL_BED, x, -0.02, z, false, false));\n      }\n      this.setupTrain();\n    } else if (this.type === 'river') {\n      g.add(waterStrip(z));\n      this.setupLogs();\n    }\n  }\n\n  addStatic(x, z, mesh, used, isBlocker) {\n    if (used.has(x)) return;\n    used.add(x);\n    mesh.position.set(x, 0, z);\n    mesh.rotation.y = Math.floor(Math.random() * 4) * (Math.PI / 2);\n    this.group.add(mesh);\n    if (isBlocker || (x >= PLAY_MIN_X && x <= PLAY_MAX_X)) this.obstacles.add(x);\n  }\n\n  // ---------------------------------------------------------------- vehicles\n  setupVehicles() {\n    this.dir = Math.random() < 0.5 ? 1 : -1;\n    this.speed = rand(2.2, 4.6);\n    const isTruckLane = Math.random() < 0.25;\n    const count = isTruckLane ? randInt(1, 2) : randInt(2, 3);\n    const colorBase = randInt(0, 5);\n    const spacing = LANE_WIDTH / count;\n    for (let i = 0; i < count; i++) {\n      const mesh = isTruckLane ? createTruck() : createCar(colorBase + i);\n      mesh.rotation.y = this.dir === 1 ? Math.PI / 2 : -Math.PI / 2;\n      const x = -LANE_WIDTH / 2 + i * spacing + rand(0, spacing * 0.5);\n      mesh.position.set(x, 0, this.z);\n      this.group.add(mesh);\n      this.movers.push({ mesh, length: mesh.userData.length, half: mesh.userData.length / 2 });\n    }\n  }\n\n  // ---------------------------------------------------------------- train\n  setupTrain() {\n    this.dir = Math.random() < 0.5 ? 1 : -1;\n    this.speed = rand(14, 18);\n    this.trainTimer = rand(1.5, 5);   // seconds until train passes\n    this.trainActive = false;\n    this.warnTime = 1.1;              // signal blinks this long before train\n    const mesh = createTrain(randInt(3, 5));\n    mesh.rotation.y = this.dir === 1 ? Math.PI / 2 : -Math.PI / 2;\n    mesh.visible = false;\n    mesh.position.set(0, 0, this.z);\n    this.group.add(mesh);\n    this.train = { mesh, length: mesh.userData.length, half: mesh.userData.length / 2 };\n\n    const sig = createSignal();\n    sig.position.set(PLAY_MAX_X + 1.2, 0, this.z);\n    this.group.add(sig);\n    this.signal = sig;\n  }\n\n  // ---------------------------------------------------------------- logs\n  setupLogs() {\n    this.dir = Math.random() < 0.5 ? 1 : -1;\n    this.speed = rand(1.4, 2.6);\n    const count = randInt(2, 3);\n    const spacing = LANE_WIDTH / count;\n    for (let i = 0; i < count; i++) {\n      const tiles = randInt(2, 4);\n      const mesh = createLog(tiles);\n      mesh.position.set(-LANE_WIDTH / 2 + i * spacing + rand(0, spacing * 0.4), 0, this.z);\n      this.group.add(mesh);\n      mesh.rotation.y = Math.PI / 2; // logs float along x\n      this.movers.push({ mesh, length: mesh.userData.length, half: mesh.userData.length / 2 });\n    }\n  }\n\n  // ---------------------------------------------------------------- update\n  update(dt, game) {\n    const half = LANE_WIDTH / 2 + 3;\n    if (this.type === 'road' || this.type === 'river') {\n      for (const m of this.movers) {\n        m.mesh.position.x += this.speed * this.dir * dt;\n        if (this.dir === 1 && m.mesh.position.x > half) m.mesh.position.x = -half;\n        if (this.dir === -1 && m.mesh.position.x < -half) m.mesh.position.x = half;\n      }\n    } else if (this.type === 'rail') {\n      this.trainTimer -= dt;\n      const warning = this.trainTimer <= this.warnTime && this.trainTimer > 0;\n      if (this.signal) {\n        const blinkOn = warning && Math.floor(performance.now() / 180) % 2 === 0;\n        const l = this.signal.userData.lampLeft.material;\n        const r = this.signal.userData.lampRight.material;\n        l.color.setHex(blinkOn && Math.floor(performance.now() / 360) % 2 === 0 ? 0xff2222 : 0x550000);\n        r.color.setHex(blinkOn && Math.floor(performance.now() / 360) % 2 !== 0 ? 0xff2222 : 0x550000);\n        l.emissive = l.emissive || new THREE.Color(0x000000);\n      }\n      if (warning && !this.warned) {\n        this.warned = true;\n        game?.audio?.trainWarning();\n      }\n      if (this.trainTimer <= 0 && !this.trainActive) {\n        this.trainActive = true;\n        this.train.mesh.visible = true;\n        this.train.mesh.position.x = this.dir === 1 ? -half - this.train.half : half + this.train.half;\n        game?.audio?.trainPass();\n      }\n      if (this.trainActive) {\n        this.train.mesh.position.x += this.speed * this.dir * dt;\n        const off = this.dir === 1\n          ? this.train.mesh.position.x - this.train.half > half\n          : this.train.mesh.position.x + this.train.half < -half;\n        if (off) {\n          this.trainActive = false;\n          this.warned = false;\n          this.train.mesh.visible = false;\n          this.trainTimer = rand(3, 9);\n        }\n      }\n    }\n  }\n\n  // Vehicle collision check at player position (x, this lane).\n  hitsVehicle(px) {\n    if (this.type === 'road') {\n      for (const m of this.movers) {\n        if (Math.abs(m.mesh.position.x - px) < m.half * 0.78 + 0.3) return true;\n      }\n    } else if (this.type === 'rail' && this.trainActive) {\n      const t = this.train;\n      if (Math.abs(t.mesh.position.x - px) < t.half + 0.4) return true;\n    }\n    return false;\n  }\n\n  // Returns the log mover under px, or null (river lanes).\n  logAt(px) {\n    for (const m of this.movers) {\n      if (Math.abs(m.mesh.position.x - px) < m.half + 0.35) return m;\n    }\n    return null;\n  }\n\n  isBlocked(x) {\n    return this.obstacles.has(Math.round(x));\n  }\n\n  dispose() {\n    this.scene.remove(this.group);\n    this.group.traverse((o) => {\n      if (o.geometry) o.geometry.dispose();\n    });\n  }\n}\n\n// ------------------------------------------------------------------ generator\nexport class LaneGenerator {\n  constructor(scene) {\n    this.scene = scene;\n    this.lanes = new Map(); // row -> Lane (row 0 = start, increasing forward)\n    this.nextRow = 0;\n    this.prevType = 'grass';\n    this.runLeft = 0;\n    this.runType = 'grass';\n    laneIndexCounter = 0;\n  }\n\n  laneAt(row) { return this.lanes.get(row); }\n\n  ensure(upToRow) {\n    while (this.nextRow <= upToRow) {\n      this.generateNext();\n    }\n  }\n\n  generateNext() {\n    const row = this.nextRow++;\n    let type;\n    if (row < 4) {\n      type = 'grass';\n    } else {\n      if (this.runLeft <= 0) {\n        // choose a new run\n        const r = Math.random();\n        if (this.runType !== 'grass' && r < 0.38) {\n          this.runType = 'grass'; this.runLeft = randInt(1, 2);\n        } else if (r < 0.55) {\n          this.runType = 'road'; this.runLeft = randInt(1, 3);\n        } else if (r < 0.72) {\n          this.runType = 'river'; this.runLeft = randInt(1, 2);\n        } else if (r < 0.82) {\n          this.runType = 'rail'; this.runLeft = 1;\n        } else {\n          this.runType = 'grass'; this.runLeft = randInt(1, 2);\n        }\n      }\n      type = this.runType;\n      this.runLeft--;\n    }\n    const z = -row; // forward is -Z\n    const lane = new Lane(type, z, this.scene, this.prevType);\n    // start rows: clear the spawn tile\n    if (row <= 4) lane.obstacles.delete(0);\n    this.prevType = type;\n    this.lanes.set(row, lane);\n  }\n\n  // remove lanes far behind the player\n  cull(behindRow) {\n    for (const [row, lane] of this.lanes) {\n      if (row < behindRow) {\n        lane.dispose();\n        this.lanes.delete(row);\n      }\n    }\n  }\n\n  update(dt, game) {\n    for (const lane of this.lanes.values()) lane.update(dt, game);\n  }\n\n  reset() {\n    for (const lane of this.lanes.values()) lane.dispose();\n    this.lanes.clear();\n    this.nextRow = 0;\n    this.prevType = 'grass';\n    this.runLeft = 0;\n    this.runType = 'grass';\n  }\n}\n"},{"name":"main.js","content":"// Voxel Road Hopper — Crossy Road style endless hopper.\n// Orthographic ~isometric camera, flat-shaded voxel world, forward = -Z.\nimport * as THREE from 'three';\nimport { LaneGenerator } from './lanes.js';\nimport { Player } from './player.js';\nimport { AudioManager } from './audio.js';\n\nconst canvas = document.getElementById('game-canvas');\nconst scoreEl = document.getElementById('score');\nconst startOverlay = document.getElementById('start-overlay');\nconst gameoverOverlay = document.getElementById('gameover-overlay');\nconst finalScoreEl = document.getElementById('final-score');\nconst bestScoreEl = document.getElementById('best-score');\nconst startBtn = document.getElementById('start-btn');\nconst retryBtn = document.getElementById('retry-btn');\nconst muteBtn = document.getElementById('mute-btn');\n\n// ------------------------------------------------------------------ renderer\nconst renderer = new THREE.WebGLRenderer({ canvas, antialias: true });\nrenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\nrenderer.shadowMap.enabled = true;\nrenderer.shadowMap.type = THREE.PCFSoftShadowMap;\n\nconst scene = new THREE.Scene();\nscene.background = new THREE.Color(0x6ec6e8);\n\n// ------------------------------------------------------------------ camera\n// Crossy Road: orthographic, looking down at ~50°, rotated ~30° around Y\n// so the world reads as a diagonal isometric-ish view.\nconst camera = new THREE.OrthographicCamera(-1, 1, 1, -1, -100, 200);\nconst CAM_OFFSET = new THREE.Vector3(-5.2, 9.2, 6.6); // left-behind-above the player\nconst VIEW_SIZE = 5.4;\n\nfunction resize() {\n  const w = window.innerWidth;\n  const h = window.innerHeight;\n  renderer.setSize(w, h, false);\n  const aspect = w / h;\n  camera.left = -VIEW_SIZE * aspect;\n  camera.right = VIEW_SIZE * aspect;\n  camera.top = VIEW_SIZE;\n  camera.bottom = -VIEW_SIZE;\n  camera.updateProjectionMatrix();\n}\nwindow.addEventListener('resize', resize);\nresize();\n\n// ------------------------------------------------------------------ lights\nscene.add(new THREE.AmbientLight(0xffffff, 0.55));\nconst hemi = new THREE.HemisphereLight(0xcfeaff, 0x9ec96a, 0.35);\nscene.add(hemi);\n\nconst sun = new THREE.DirectionalLight(0xfff4e0, 1.15);\nsun.castShadow = true;\nsun.shadow.mapSize.set(2048, 2048);\nsun.shadow.camera.left = -14;\nsun.shadow.camera.right = 14;\nsun.shadow.camera.top = 14;\nsun.shadow.camera.bottom = -14;\nsun.shadow.camera.near = 1;\nsun.shadow.camera.far = 60;\nsun.shadow.bias = -0.0004;\nscene.add(sun);\nscene.add(sun.target);\n\n// ------------------------------------------------------------------ game state\nconst audio = new AudioManager();\nconst gen = new LaneGenerator(scene);\nconst player = new Player(scene);\n\n// static grass backdrop behind the start row (fills the void below/behind)\nimport { box, createTree } from './models.js';\nconst backdrop = new THREE.Group();\nfor (let r = 1; r <= 8; r++) {\n  backdrop.add(box(30, 0.5, 1, r % 2 ? 0xbcec6a : 0xaadd5c, 0, -0.25, r, false, true));\n  for (let x = -14; x <= 14; x++) {\n    const inPlay = x >= -4 && x <= 4;\n    if (Math.random() < (inPlay ? (r > 1 ? 0.18 : 0) : 0.4)) {\n      const t = createTree(1 + Math.floor(Math.random() * 2));\n      t.position.set(x, 0, r);\n      backdrop.add(t);\n    }\n  }\n}\nscene.add(backdrop);\n\nconst game = {\n  state: 'menu', // 'menu' | 'playing' | 'dead'\n  score: 0,\n  best: Number(localStorage.getItem('vrh-best') || 0),\n  audio,\n  camZ: 0,       // camera forward progress (world z, negative)\n  idleTimer: 0,  // eagle-style pressure: camera creeps forward\n};\n\nbestScoreEl.textContent = game.best;\n\ngen.ensure(18);\n\nfunction setScore(v) {\n  game.score = v;\n  scoreEl.textContent = v;\n}\n\nfunction startGame() {\n  gen.reset();\n  gen.ensure(18);\n  player.reset();\n  setScore(0);\n  game.state = 'playing';\n  game.camZ = 0;\n  game.idleTimer = 0;\n  startOverlay.classList.remove('overlay--visible');\n  gameoverOverlay.classList.remove('overlay--visible');\n  audio.ensure();\n  audio.start();\n}\n\nfunction endGame(type) {\n  if (game.state !== 'playing') return;\n  game.state = 'dead';\n  if (type === 'squash') { player.squash(); audio.squash(); }\n  else if (type === 'drown') { player.drown(); audio.splash(); }\n  else { player.vanish(); audio.splash(); }\n  audio.gameOver();\n  if (game.score > game.best) {\n    game.best = game.score;\n    localStorage.setItem('vrh-best', String(game.best));\n  }\n  finalScoreEl.textContent = game.score;\n  bestScoreEl.textContent = game.best;\n  setTimeout(() => gameoverOverlay.classList.add('overlay--visible'), 650);\n}\n\n// ------------------------------------------------------------------ input\nconst KEYMAP = {\n  ArrowUp: 'up', KeyW: 'up', w: 'up', W: 'up', ' ': 'up', Space: 'up',\n  ArrowDown: 'down', KeyS: 'down', s: 'down', S: 'down',\n  ArrowLeft: 'left', KeyA: 'left', a: 'left', A: 'left',\n  ArrowRight: 'right', KeyD: 'right', d: 'right', D: 'right',\n};\n\nfunction handleDir(dir) {\n  if (game.state === 'menu') { startGame(); return; }\n  if (game.state === 'dead') return;\n  const hopped = player.tryHop(dir, gen);\n  if (hopped) {\n    audio.ensure();\n    audio.hop();\n    game.idleTimer = 0;\n    if (player.row > game.score) {\n      setScore(player.row);\n      if (game.score % 25 === 0) audio.scoreMilestone();\n    }\n  }\n}\n\nwindow.addEventListener('keydown', (e) => {\n  const dir = KEYMAP[e.code] || KEYMAP[e.key];\n  if (!dir) return;\n  e.preventDefault();\n  handleDir(dir);\n});\n\n// tap / swipe\nlet touchStart = null;\ncanvas.addEventListener('pointerdown', (e) => { touchStart = { x: e.clientX, y: e.clientY, t: performance.now() }; });\ncanvas.addEventListener('pointerup', (e) => {\n  if (!touchStart) return;\n  const dx = e.clientX - touchStart.x;\n  const dy = e.clientY - touchStart.y;\n  const dist = Math.hypot(dx, dy);\n  let dir = 'up';\n  if (dist > 24) {\n    if (Math.abs(dx) > Math.abs(dy)) dir = dx > 0 ? 'right' : 'left';\n    else dir = dy > 0 ? 'down' : 'up';\n  }\n  touchStart = null;\n  handleDir(dir);\n});\n\nstartBtn.addEventListener('click', startGame);\nretryBtn.addEventListener('click', startGame);\nmuteBtn.addEventListener('click', () => {\n  audio.ensure();\n  const muted = audio.toggleMute();\n  muteBtn.innerHTML = muted ? '&#128263;' : '&#128266;';\n});\n\n// ------------------------------------------------------------------ loop\nconst clock = new THREE.Clock();\n\nfunction tick() {\n  requestAnimationFrame(tick);\n  const dt = Math.min(clock.getDelta(), 0.05);\n\n  gen.update(dt, game);\n\n  if (game.state === 'playing') {\n    const event = player.update(dt, gen);\n    if (event === 'drown') endGame('drown');\n    else if (event === 'offscreen') endGame('offscreen');\n\n    // vehicle / train collision\n    if (!player.dead) {\n      const lane = gen.laneAt(player.row);\n      if (lane && !player.hopping && lane.hitsVehicle(player.x)) {\n        endGame('squash');\n      } else if (lane && player.hopping) {\n        // mid-hop: check both rows roughly at current position\n        const zRow = Math.round(-player.mesh.position.z);\n        const l2 = gen.laneAt(zRow);\n        if (l2 && l2.hitsVehicle(player.mesh.position.x)) endGame('squash');\n      }\n    }\n\n    // keep world generated ahead, cull behind\n    gen.ensure(player.row + 16);\n    gen.cull(player.row - 10);\n\n    // camera pressure: slowly advance even if idle (the \"eagle\" mechanic, soft version)\n    game.idleTimer += dt;\n    const targetZ = -player.row;\n    game.camZ += (targetZ - game.camZ) * Math.min(1, dt * 4);\n    if (game.idleTimer > 3) game.camZ -= dt * 0.55; // creep forward when idle\n\n    // losing the camera = death (fell too far behind)\n    if (player.z > game.camZ + 5.5) {\n      endGame('offscreen');\n    }\n  }\n\n  // camera follow (also in menu/dead for nice framing)\n  const focusX = THREE.MathUtils.clamp(player.mesh.position.x * 0.4, -1.6, 1.6);\n  const focus = new THREE.Vector3(focusX, 0, game.camZ - 1.5);\n  camera.position.copy(focus).add(CAM_OFFSET);\n  camera.lookAt(focus);\n\n  // sun follows so shadows stay crisp near the player\n  sun.position.set(focus.x - 6, 14, focus.z + 6);\n  sun.target.position.set(focus.x, 0, focus.z);\n\n  renderer.render(scene, camera);\n}\n\ntick();\n"},{"name":"models.js","content":"// Voxel model builders — Crossy Road style blocky meshes.\n// Every model is built from BoxGeometry \"voxels\" with flat-shaded MeshLambertMaterial.\nimport * as THREE from 'three';\n\nconst matCache = new Map();\nexport function mat(color) {\n  if (!matCache.has(color)) {\n    matCache.set(color, new THREE.MeshLambertMaterial({ color }));\n  }\n  return matCache.get(color);\n}\n\nexport function box(w, h, d, color, x = 0, y = 0, z = 0, castShadow = true, receiveShadow = true) {\n  const m = new THREE.Mesh(new THREE.BoxGeometry(w, h, d), mat(color));\n  m.position.set(x, y, z);\n  m.castShadow = castShadow;\n  m.receiveShadow = receiveShadow;\n  return m;\n}\n\n// ---------------------------------------------------------------- Chicken\n// The iconic white chicken. Units: 1 tile = 1 world unit.\nexport function createChicken() {\n  const g = new THREE.Group();\n\n  const WHITE = 0xfdfdfd;\n  const DARK = 0x4a4a4a;\n  const RED = 0xe53b2c;\n  const ORANGE = 0xf2a000;\n\n  // body\n  g.add(box(0.52, 0.42, 0.66, WHITE, 0, 0.46, 0));\n  // head block\n  g.add(box(0.4, 0.5, 0.32, WHITE, 0, 0.86, -0.12));\n  // comb\n  g.add(box(0.12, 0.14, 0.22, RED, 0, 1.17, -0.12));\n  // beak\n  g.add(box(0.14, 0.12, 0.14, ORANGE, 0, 0.92, -0.34));\n  // wattle\n  g.add(box(0.1, 0.1, 0.08, RED, 0, 0.8, -0.3));\n  // eyes\n  g.add(box(0.05, 0.08, 0.08, DARK, 0.205, 0.96, -0.18));\n  g.add(box(0.05, 0.08, 0.08, DARK, -0.205, 0.96, -0.18));\n  // wings\n  g.add(box(0.08, 0.26, 0.4, 0xe8e8e8, 0.3, 0.5, 0.04));\n  g.add(box(0.08, 0.26, 0.4, 0xe8e8e8, -0.3, 0.5, 0.04));\n  // tail\n  g.add(box(0.3, 0.24, 0.12, 0xe8e8e8, 0, 0.62, 0.36));\n  // legs\n  g.add(box(0.07, 0.25, 0.07, ORANGE, 0.12, 0.13, 0.05));\n  g.add(box(0.07, 0.25, 0.07, ORANGE, -0.12, 0.13, 0.05));\n\n  return g;\n}\n\n// ---------------------------------------------------------------- Cars\nconst CAR_COLORS = [0xe8431f, 0x2f9be0, 0xf2b200, 0x8e4fd0, 0x39b54a, 0xff7ab8];\n\nexport function createCar(colorIndex = 0) {\n  const g = new THREE.Group();\n  const color = CAR_COLORS[colorIndex % CAR_COLORS.length];\n  const DARK = 0x2a2a2e;\n  const GLASS = 0xbfe6f5;\n\n  // chassis\n  g.add(box(0.95, 0.32, 1.7, color, 0, 0.36, 0));\n  // cabin\n  g.add(box(0.85, 0.32, 0.85, color, 0, 0.66, 0.06));\n  // windows (slightly inset)\n  g.add(box(0.87, 0.2, 0.6, GLASS, 0, 0.68, 0.06));\n  // wheels\n  const wy = 0.16;\n  g.add(box(0.18, 0.3, 0.3, DARK, 0.45, wy, -0.5));\n  g.add(box(0.18, 0.3, 0.3, DARK, -0.45, wy, -0.5));\n  g.add(box(0.18, 0.3, 0.3, DARK, 0.45, wy, 0.5));\n  g.add(box(0.18, 0.3, 0.3, DARK, -0.45, wy, 0.5));\n  // headlights\n  g.add(box(0.14, 0.1, 0.05, 0xfff6c9, 0.3, 0.36, -0.87));\n  g.add(box(0.14, 0.1, 0.05, 0xfff6c9, -0.3, 0.36, -0.87));\n\n  g.userData.length = 1.8;\n  return g;\n}\n\nexport function createTruck() {\n  const g = new THREE.Group();\n  const CAB = 0x2f9be0;\n  const BODY = 0xf4f4f4;\n  const DARK = 0x2a2a2e;\n\n  // cab\n  g.add(box(0.95, 0.6, 0.8, CAB, 0, 0.52, -1.0));\n  g.add(box(0.85, 0.22, 0.6, 0xbfe6f5, 0, 0.72, -1.0));\n  // cargo box\n  g.add(box(1.0, 0.85, 1.9, BODY, 0, 0.66, 0.45));\n  // chassis bar\n  g.add(box(0.8, 0.16, 2.9, DARK, 0, 0.18, 0));\n  // wheels\n  const wy = 0.16;\n  [-1.15, 0.0, 1.05].forEach((z) => {\n    g.add(box(0.18, 0.3, 0.32, DARK, 0.46, wy, z));\n    g.add(box(0.18, 0.3, 0.32, DARK, -0.46, wy, z));\n  });\n  // headlights\n  g.add(box(0.14, 0.1, 0.05, 0xfff6c9, 0.3, 0.42, -1.42));\n  g.add(box(0.14, 0.1, 0.05, 0xfff6c9, -0.3, 0.42, -1.42));\n\n  g.userData.length = 3.0;\n  return g;\n}\n\n// ---------------------------------------------------------------- Train\nexport function createTrain(carCount = 4) {\n  const g = new THREE.Group();\n  const BODY = 0xd6453a;\n  const DARK = 0x33333a;\n  const carLen = 2.4;\n  for (let i = 0; i < carCount; i++) {\n    const z = (i - (carCount - 1) / 2) * (carLen + 0.18);\n    g.add(box(0.95, 0.7, carLen, BODY, 0, 0.62, z));\n    g.add(box(0.99, 0.18, carLen, DARK, 0, 0.2, z));\n    g.add(box(0.97, 0.22, 0.7, 0xf0d9b5, 0, 0.84, z - 0.5));\n    g.add(box(0.97, 0.22, 0.7, 0xf0d9b5, 0, 0.84, z + 0.5));\n  }\n  g.userData.length = carCount * (carLen + 0.18);\n  return g;\n}\n\n// ---------------------------------------------------------------- Log\nexport function createLog(tiles = 2) {\n  const g = new THREE.Group();\n  const BROWN = 0x9a6433;\n  const len = tiles * 1.0 - 0.1;\n  g.add(box(0.8, 0.3, len, BROWN, 0, 0.0, 0));\n  // end caps (lighter)\n  g.add(box(0.7, 0.22, 0.06, 0xc89055, 0, 0.0, len / 2 + 0.01, false));\n  g.add(box(0.7, 0.22, 0.06, 0xc89055, 0, 0.0, -len / 2 - 0.01, false));\n  g.userData.length = len;\n  return g;\n}\n\n// ---------------------------------------------------------------- Tree\nexport function createTree(height = 1) {\n  const g = new THREE.Group();\n  const TRUNK = 0x8a5a2b;\n  const LEAF = 0x3eb24a;\n  const LEAF_DARK = 0x2f9c3c;\n\n  g.add(box(0.3, 0.5, 0.3, TRUNK, 0, 0.25, 0));\n  let y = 0.5;\n  const layers = 1 + height;\n  for (let i = 0; i < layers; i++) {\n    const s = 0.85 - i * 0.18;\n    const h = 0.42;\n    g.add(box(s, h, s, i % 2 ? LEAF_DARK : LEAF, 0, y + h / 2, 0));\n    y += h;\n  }\n  return g;\n}\n\n// ---------------------------------------------------------------- Rock\nexport function createRock() {\n  const g = new THREE.Group();\n  g.add(box(0.55, 0.4, 0.55, 0xb8bcc2, 0, 0.2, 0));\n  g.add(box(0.35, 0.25, 0.35, 0xcdd2d8, 0.08, 0.5, -0.05));\n  return g;\n}\n\n// ---------------------------------------------------------------- Lily pad (decor on river edges) / coin not in original — skip.\n\n// ---------------------------------------------------------------- Rail signal\nexport function createSignal() {\n  const g = new THREE.Group();\n  const POLE = 0x5b5b63;\n  g.add(box(0.12, 1.1, 0.12, POLE, 0, 0.55, 0));\n  g.add(box(0.5, 0.3, 0.12, 0x3a3a40, 0, 1.18, 0));\n  const left = box(0.16, 0.16, 0.06, 0x550000, -0.12, 1.18, -0.06, false);\n  const right = box(0.16, 0.16, 0.06, 0x550000, 0.12, 1.18, -0.06, false);\n  left.material = new THREE.MeshLambertMaterial({ color: 0x550000 });\n  right.material = new THREE.MeshLambertMaterial({ color: 0x550000 });\n  g.add(left, right);\n  g.userData.lampLeft = left;\n  g.userData.lampRight = right;\n  return g;\n}\n"},{"name":"player.js","content":"// Player — the hopping chicken. Grid moves with a squash-and-stretch hop arc.\nimport * as THREE from 'three';\nimport { createChicken } from './models.js';\nimport { PLAY_MIN_X, PLAY_MAX_X } from './lanes.js';\n\nconst HOP_TIME = 0.16;\nconst HOP_HEIGHT = 0.45;\n\nexport class Player {\n  constructor(scene) {\n    this.mesh = createChicken();\n    scene.add(this.mesh);\n    this.reset();\n  }\n\n  reset() {\n    this.row = 0;          // forward grid row (z = -row)\n    this.col = 0;          // sideways tile\n    this.x = 0;            // continuous x (drifts on logs)\n    this.hopping = false;\n    this.hopT = 0;\n    this.from = { x: 0, z: 0 };\n    this.to = { x: 0, z: 0 };\n    this.dead = false;\n    this.deathType = null;\n    this.onLog = null;     // log mover we're riding\n    this.logOffset = 0;\n    this.facing = 0;       // radians; 0 = forward (-Z)\n    this.mesh.visible = true;\n    this.mesh.scale.set(1, 1, 1);\n    this.mesh.position.set(0, 0, 0);\n    this.mesh.rotation.set(0, 0, 0);\n    this.queued = null;\n  }\n\n  get z() { return -this.row; }\n\n  // Attempt a hop. dir: 'up' | 'down' | 'left' | 'right'.\n  // Returns true if hop started.\n  tryHop(dir, gen) {\n    if (this.dead) return false;\n    if (this.hopping) { this.queued = dir; return false; }\n\n    let dRow = 0, dCol = 0, face = this.facing;\n    if (dir === 'up') { dRow = 1; face = 0; }\n    else if (dir === 'down') { dRow = -1; face = Math.PI; }\n    else if (dir === 'left') { dCol = -1; face = Math.PI / 2; }\n    else if (dir === 'right') { dCol = 1; face = -Math.PI / 2; }\n\n    const targetRow = this.row + dRow;\n    if (targetRow < 0) { this.facing = face; this.bump(); return false; }\n\n    // current x rounded for grid targeting (we may be drifting on a log)\n    const baseX = this.onLog ? this.x : this.col;\n    let targetX = Math.round(baseX) + dCol;\n    if (targetX < PLAY_MIN_X || targetX > PLAY_MAX_X) { this.facing = face; this.bump(); return false; }\n\n    const targetLane = gen.laneAt(targetRow);\n    if (!targetLane) return false;\n    if (targetLane.isBlocked(targetX)) { this.facing = face; this.bump(); return false; }\n\n    // start the hop\n    this.facing = face;\n    this.from.x = this.onLog ? this.x : this.col;\n    this.from.z = this.z;\n    this.row = targetRow;\n    this.col = targetX;\n    this.to.x = targetX;\n    this.to.z = -targetRow;\n    this.onLog = null;\n    this.hopping = true;\n    this.hopT = 0;\n    return true;\n  }\n\n  bump() {\n    // small refused-move wiggle\n    this.mesh.rotation.y = this.facing;\n  }\n\n  // dt update; gen = LaneGenerator. Returns event string or null:\n  // 'landed' | 'drown' | 'offscreen'\n  update(dt, gen) {\n    if (this.dead) return null;\n    let event = null;\n\n    if (this.hopping) {\n      this.hopT += dt / HOP_TIME;\n      const t = Math.min(this.hopT, 1);\n      const x = this.from.x + (this.to.x - this.from.x) * t;\n      const z = this.from.z + (this.to.z - this.from.z) * t;\n      const y = Math.sin(t * Math.PI) * HOP_HEIGHT;\n      this.x = x;\n      this.mesh.position.set(x, y, z);\n      // squash & stretch\n      const stretch = 1 + Math.sin(t * Math.PI) * 0.18;\n      this.mesh.scale.set(1 / Math.sqrt(stretch), stretch, 1 / Math.sqrt(stretch));\n\n      if (t >= 1) {\n        this.hopping = false;\n        this.mesh.scale.set(1, 1, 1);\n        this.mesh.position.y = 0;\n        event = 'landed';\n        // landing logic: river → must be on a log\n        const lane = gen.laneAt(this.row);\n        if (lane && lane.type === 'river') {\n          const log = lane.logAt(this.x);\n          if (log) {\n            this.onLog = log;\n            this.logOffset = this.x - log.mesh.position.x;\n            this.mesh.position.y = 0.18;\n          } else {\n            event = 'drown';\n          }\n        }\n        if (this.queued && event !== 'drown') {\n          const q = this.queued;\n          this.queued = null;\n          // small delay feel is fine — hop immediately\n          this.tryHop(q, gen);\n        } else {\n          this.queued = null;\n        }\n      }\n    } else if (this.onLog) {\n      // drift with the log\n      this.x = this.onLog.mesh.position.x + this.logOffset;\n      this.mesh.position.x = this.x;\n      this.mesh.position.y = 0.18;\n      if (this.x < PLAY_MIN_X - 1.2 || this.x > PLAY_MAX_X + 1.2) {\n        event = 'offscreen';\n      }\n    } else {\n      this.x = this.col;\n      this.mesh.position.set(this.x, 0, this.z);\n    }\n\n    // smooth facing rotation\n    const target = this.facing;\n    let diff = target - this.mesh.rotation.y;\n    while (diff > Math.PI) diff -= Math.PI * 2;\n    while (diff < -Math.PI) diff += Math.PI * 2;\n    this.mesh.rotation.y += diff * Math.min(1, dt * 18);\n\n    return event;\n  }\n\n  // death animations\n  squash() {\n    this.dead = true;\n    this.deathType = 'squash';\n    this.mesh.scale.set(1.6, 0.12, 1.6);\n    this.mesh.position.y = 0;\n  }\n\n  drown() {\n    this.dead = true;\n    this.deathType = 'drown';\n    this.mesh.position.y = -0.45;\n    this.mesh.scale.set(0.9, 0.5, 0.9);\n  }\n\n  vanish() {\n    this.dead = true;\n    this.deathType = 'offscreen';\n    this.mesh.visible = false;\n  }\n}\n"}],"folders":[]},{"folder":"other","files":[{"name":"main.sketch","content":""}],"folders":[]}]},"variants":null,"createdAt":"2026-06-10T12:08:47.058Z","updatedAt":"2026-06-10T12:08:55.385Z"}}