Preview

Code ยท 5.4 KiB
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <meta name="theme-color" content="#101216">
  <meta name="description" content="Snake in a haunted hollow. Collect potions and avoid the ghosts.">
  <title>Hollow Snake</title>
  <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Ctext y='32' font-size='32'%3E๐Ÿ%3C/text%3E%3C/svg%3E">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="world" aria-hidden="true"><div class="arch arch-left"></div><div class="arch arch-right"></div><div class="mist"></div></div>
  <main>
    <header>
      <h1>Hollow Snake</h1>
      <nav aria-label="Game options">
        <button id="music" class="icon-button" aria-pressed="false" aria-label="Background music" title="Turn music on"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M11 5 6 9H3v6h3l5 4z"/><path class="sound-muted" d="m16 9 6 6m0-6-6 6"/><g class="sound-waves"><path d="M15 8a6 6 0 0 1 0 8M18 5a10 10 0 0 1 0 14"/></g></svg></button>
        <button id="settings" class="icon-button" aria-label="Settings" title="Settings" aria-haspopup="dialog"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m9 3-.6 2.4-2 .9L4 5.6 2 9l1.8 1.7v2.6L2 15l2 3.4 2.4-.7 2 .9L9 21h6l.6-2.4 2-.9 2.4.7 2-3.4-1.8-1.7v-2.6L22 9l-2-3.4-2.4.7-2-.9L15 3z"/><circle cx="12" cy="12" r="3"/></svg></button>
        <button id="help" aria-haspopup="dialog" aria-label="How to play">Help</button>
      </nav>
    </header>
    <section class="game-panel" aria-label="Snake game">
      <div class="scorebar">
        <div class="scores"><span>Potions <strong id="score">0</strong></span><span>Best <strong id="best">0</strong></span></div>
        <button id="pause" aria-label="Pause game" disabled>Pause</button>
      </div>
      <div class="board-shell">
        <canvas id="board" width="660" height="660" tabindex="0" aria-label="Snake board. Use arrow keys or W A S D to steer. Space pauses."></canvas>
        <div class="overlay" id="overlay"><div class="start-card">
          <h2 id="overlay-title">Into the hollow</h2>
          <p id="overlay-copy">Collect potions. Avoid the ghosts.</p>
          <button id="start" class="primary">Play</button>
        </div></div>
      </div>
      <div class="board-footer"><span id="state-label">Ready</span><span id="difficulty-label">Haunted</span></div>
    </section>
    <div class="touch-controls" aria-label="Direction controls"><button data-direction="up" aria-label="Move up">โ†‘</button><div><button data-direction="left" aria-label="Move left">โ†</button><button data-direction="down" aria-label="Move down">โ†“</button><button data-direction="right" aria-label="Move right">โ†’</button></div></div>
    <p class="keyboard-hint">Arrow keys or WASD to move ยท Space to pause</p>
  </main>
  <dialog id="settings-dialog" aria-labelledby="settings-title">
    <div class="dialog-heading"><h2 id="settings-title">Settings</h2><button id="close-settings" aria-label="Close settings">ร—</button></div>
    <label class="field-label" for="difficulty">Difficulty</label>
    <select id="difficulty"><option value="cozy">Cozy โ€” slow</option><option value="haunted" selected>Haunted โ€” normal</option><option value="cursed">Cursed โ€” fast</option></select>
    <fieldset><legend>Obstacles</legend><div class="obstacle-options">
      <label><input type="checkbox" value="ghost" checked>Ghosts</label>
      <label><input type="checkbox" value="pumpkin" checked>Pumpkins</label>
      <label><input type="checkbox" value="candle" checked>Candles</label>
    </div></fieldset>
    <div class="setting-row"><label for="snake-color">Snake color</label><input id="snake-color" type="color" value="#b6ff54" aria-label="Snake color"></div>
    <div class="setting-row"><label for="atmosphere">Background mist</label><input id="atmosphere" type="checkbox" role="switch" checked></div>
    <div class="setting-row"><label for="volume">Music volume</label><input type="range" id="volume" min="0" max="100" value="35"></div>
    <p class="settings-note" id="settings-note">Difficulty and obstacles apply to your next game.</p>
    <div class="dialog-actions"><button id="restart">New game</button><button id="settings-done" class="primary">Done</button></div>
  </dialog>
  <dialog id="help-dialog" aria-labelledby="help-title">
    <div class="dialog-heading"><h2 id="help-title">How to play</h2><button id="close-help" aria-label="Close instructions">ร—</button></div>
    <p>Use the arrow keys, WASD, a swipe, or the on-screen arrows to steer.</p>
    <p>Collect bright pink potions to grow. Avoid walls, your tail, and the spooky obstacles.</p>
    <p>Press Space or P to pause. Opening a menu or leaving the tab also pauses the game.</p>
    <p>Personal bests are saved on this device for each difficulty and obstacle selection.</p>
    <div class="music-credit"><p>Music: <a href="https://opengameart.org/content/8-bit-haunted-house-theme" target="_blank" rel="noopener">8-bit Haunted House Theme</a> by Wolfgang_. Free to use under CC0.</p><p id="audio-status" role="status">Music is off.</p></div>
    <button id="help-done" class="primary">Got it</button>
  </dialog>
  <audio id="soundtrack" loop preload="none" src="assets/hauntedcastle.mp3"></audio>
  <div id="announcement" class="sr-only" role="status" aria-live="polite"></div>
  <script type="module" src="app.js"></script>
</body>
</html>

Files