diff --git "a/index.html" "b/index.html" --- "a/index.html" +++ "b/index.html" @@ -19,223 +19,2939 @@
- + if (b.dead) { bubbles.splice(i, 1); continue; } + b.draw(ctx); + } + + drawFgGrass(t); // v12: foreground grass — closest to the viewer, drawn on top + + // ambient day/night wash over the whole scene + if (light.washA > 0.005) { + ctx.fillStyle = `rgba(${light.washRGB[0]},${light.washRGB[1]},${light.washRGB[2]},${light.washA})`; + ctx.fillRect(0, 0, W, H); + } + + drawVignette(); + drawGrain(); // v8: mild film grain on top of everything + requestAnimationFrame(frame); +} + +function doResize() { + resize(); + buildRaySprites(); // v23: rebuild the pre-blurred beam sprites for the new size + buildFarSeaweedSprites(); // v5: rebuild ultra-far seaweed sprites for new size + buildVignette(); // v6: rebuild the static vignette layer + buildStaticLayer(); + buildRocksLayer(); // rocks drawn after grass so they sit in front of the plants + buildCausticTile(); // v25: caustic texture tile (built once) + if (!grainPattern) buildGrainTile(); // v8: grain tile is size-independent, build once +} +// ============ Player controls: keyboard + gamepad ============ +const keys = {}; // currently-held keyboard keys (lowercased) +let prevStartPressed = false; // edge-detect the gamepad Start button + +// Spawn a fresh player-controlled fish at the centre of the tank. +function spawnPlayerFish() { + if (playerFish) { // replace any existing one + const idx = fishes.indexOf(playerFish); + if (idx !== -1) fishes.splice(idx, 1); + } + playerFish = new Fish(); + playerFish.x = W / 2; + playerFish.y = H / 2; + playerFish.size = rand(25, 43); // ~20% larger than normal fish for visibility + playerFish.speed *= 1.5; // a touch faster than average for fun + playerFish.hue = (Math.random() * 360) | 0; // unique colour so it stands out + playerFish.saturation = 90; + playerFish.lightness = 55; + fishes.push(playerFish); + console.log('Player fish spawned! Steer with WASD or the left stick.'); +} + +// Keyboard: WASD steer, Shift speed up, Space slow down, F spawn. +document.addEventListener('keydown', (e) => { + const k = e.key.toLowerCase(); + keys[k] = true; + if (k === ' ') e.preventDefault(); // stop Space from scrolling the page + if (k === 'f' && !e.repeat) spawnPlayerFish(); +}); +document.addEventListener('keyup', (e) => { + keys[e.key.toLowerCase()] = false; +}); + +// Poll gamepad state each frame (Gamepad API requires polling). +function pollGamepad() { + const pads = navigator.getGamepads ? navigator.getGamepads() : null; + let startNow = false; + if (pads) { + for (const pad of pads) { + if (!pad || !pad.connected) continue; + // Xbox 360 layout: Start button is index [7]. + if (pad.buttons[7] && pad.buttons[7].pressed) startNow = true; + break; // only the first connected pad + } + } + if (startNow && !prevStartPressed) spawnPlayerFish(); // on-press only + prevStartPressed = startNow; +} +setInterval(pollGamepad, 10); + +// Combine keyboard + gamepad into one input vector for the player fish. +function getPlayerInput() { + let dx = 0, dy = 0, boost = 0, slow = 0; + // Keyboard: WASD steer, Shift speed up, Space slow down. + if (keys['a']) dx -= 1; + if (keys['d']) dx += 1; + if (keys['w']) dy -= 1; + if (keys['s']) dy += 1; + if (keys['shift']) boost = 1; + if (keys[' ']) slow = 1; + + // Gamepad: left stick steers, right stick down speeds up / up slows down. + const pads = navigator.getGamepads ? navigator.getGamepads() : null; + if (pads) { + for (const pad of pads) { + if (!pad || !pad.connected) continue; + const lx = Math.abs(pad.axes[0]) > GAMEPAD_DEADZONE ? pad.axes[0] : 0; + const ly = Math.abs(pad.axes[1]) > GAMEPAD_DEADZONE ? pad.axes[1] : 0; + dx += lx; + dy += ly; + if (pad.axes[3] > GAMEPAD_DEADZONE) boost = Math.max(boost, pad.axes[3]); // down → faster + if (pad.axes[3] < -GAMEPAD_DEADZONE) slow = Math.max(slow, -pad.axes[3]); // up → slower + break; // only the first connected pad + } + } + return { dx, dy, boost, slow }; +} + +// Fade out the controls help text 10s after load/refresh. +setTimeout(() => { + const el = document.getElementById('controls-help'); + if (el) el.style.opacity = '0'; +}, 10000); + +window.addEventListener("resize", doResize); +doResize(); +requestAnimationFrame(frame); +})(); +