Guest User

7K roguelike

a guest
Jun 24th, 2025
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 6.28 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.   <meta charset="UTF-8">
  5.   <title>8K (7K) Roguelike (ignore 800mb browser)</title>
  6.   <style>
  7.       html, body {
  8.           margin: 0;
  9.           padding: 0;
  10.           height: 100%;
  11.           width: 100%;
  12.           overflow: hidden;
  13.       }
  14.  
  15.       body {
  16.           background: #000;
  17.       }
  18.  
  19.       canvas {
  20.           display: block;
  21.           position: fixed;
  22.           top: 0;
  23.           left: 0;
  24.           width: 100vw;
  25.           height: 100vh;
  26.       }
  27.  
  28.       #hud {
  29.           position: fixed;
  30.           top: 8px;
  31.           left: 8px;
  32.           color: #fff;
  33.           font: 20px monospace;
  34.           z-index: 10;
  35.       }
  36.   </style>
  37. </head>
  38. <body>
  39. <div id="hud"></div>
  40. <canvas id="c"></canvas>
  41. <script>
  42.   const W = 48, H = 32, TS = 24, GOLD_COUNT = 10, ENEMY_COUNT = 5;
  43.   const canvas = /** @type HTMLCanvasElement */ document.getElementById("c");
  44.   const ctx = canvas.getContext("2d");
  45.   const hud = document.getElementById("hud");
  46.  
  47.   function resize() {
  48.     canvas.width = W * TS;
  49.     canvas.height = H * TS;
  50.   }
  51.  
  52.   resize();
  53.  
  54.   let map = [];
  55.   for (let y = 0; y < H; y++) {
  56.    map[y] = [];
  57.    for (let x = 0; x < W; x++)
  58.      map[y][x] = Math.random() < 0.45 ? 1 : 0;
  59.  }
  60.  for (let k = 0; k < 4; k++) {
  61.    let m2 = [];
  62.    for (let y = 0; y < H; y++) {
  63.      m2[y] = [];
  64.      for (let x = 0; x < W; x++) {
  65.        let cnt = 0;
  66.        for (let dy = -1; dy <= 1; dy++)
  67.          for (let dx = -1; dx <= 1; dx++)
  68.            if (map[y + dy]?.[x + dx]) cnt++;
  69.        m2[y][x] = cnt >= 5 ? 1 : 0;
  70.       }
  71.     }
  72.     map = m2;
  73.   }
  74.  
  75.   function randomFloor(exclude = []) {
  76.     let x, y;
  77.     do {
  78.       x = 1 + Math.floor(Math.random() * (W - 2));
  79.       y = 1 + Math.floor(Math.random() * (H - 2));
  80.     } while (map[y][x] !== 0 || exclude.some(e => e.x === x && e.y === y));
  81.     return { x, y };
  82.   }
  83.  
  84.   let { x: px, y: py } = randomFloor();
  85.   let hp = 10;
  86.  
  87.   let exit;
  88.   do {
  89.     exit = randomFloor([{ x: px, y: py }]);
  90.   } while (Math.abs(exit.x - px) + Math.abs(exit.y - py) < W / 2);
  91.  
  92.  let golds = [];
  93.  for (let i = 0; i < GOLD_COUNT; i++) {
  94.    golds.push(randomFloor([{ x: px, y: py }, exit, ...golds]));
  95.  }
  96.  
  97.  let enemies = [];
  98.  for (let i = 0; i < ENEMY_COUNT; i++) {
  99.    enemies.push(randomFloor([{ x: px, y: py }, exit, ...golds, ...enemies]));
  100.  }
  101.  
  102.  const AudioContext = window.AudioContext;
  103.  const audioCtx = new AudioContext();
  104.  let drumGain, drumInterval, baseTempo = 1200, fastTempo = 300;
  105.  let isFast = false;
  106.  let drumHigh = false;
  107.  
  108.  function startSoundtrack() {
  109.    drumGain = audioCtx.createGain();
  110.    drumGain.gain.value = 1;
  111.    drumGain.connect(audioCtx.destination);
  112.  
  113.    scheduleDrum(baseTempo);
  114.  }
  115.  
  116.  function playDrum() {
  117.    drumHigh = !drumHigh;
  118.    let osc = audioCtx.createOscillator();
  119.    osc.type = "triangle";
  120.    let startFreq = drumHigh ? 260 : 180;
  121.    osc.frequency.setValueAtTime(startFreq, audioCtx.currentTime);
  122.    osc.frequency.exponentialRampToValueAtTime(60, audioCtx.currentTime + 0.3);
  123.    let gain = audioCtx.createGain();
  124.    gain.gain.setValueAtTime(1, audioCtx.currentTime);
  125.    gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.3);
  126.    osc.connect(gain).connect(audioCtx.destination);
  127.    osc.start();
  128.    osc.stop(audioCtx.currentTime + 0.3);
  129.  }
  130.  
  131.  function scheduleDrum(tempo) {
  132.    if (drumInterval) clearInterval(drumInterval);
  133.    drumInterval = setInterval(playDrum, tempo);
  134.  }
  135.  
  136.  window.addEventListener("keydown", function once() {
  137.    if (audioCtx.state === "suspended") audioCtx.resume();
  138.    startSoundtrack();
  139.    window.removeEventListener("keydown", once);
  140.  });
  141.  
  142.  function updateSoundtrack() {
  143.    let adjacent = enemies.some(en => isAdjacent({ x: px, y: py }, en));
  144.     if (adjacent && !isFast) {
  145.      isFast = true;
  146.       scheduleDrum(fastTempo);
  147.     } else if (!adjacent && isFast) {
  148.      isFast = false;
  149.       scheduleDrum(baseTempo);
  150.     }
  151.   }
  152.  
  153.   function draw() {
  154.     ctx.clearRect(0, 0, canvas.width, canvas.height);
  155.     for (let y = 0; y < H; y++)
  156.      for (let x = 0; x < W; x++) {
  157.        ctx.fillStyle = map[y][x] ? "#444" : "#111";
  158.        ctx.fillRect(x * TS, y * TS, TS, TS);
  159.      }
  160.    for (const g of golds) {
  161.      ctx.fillStyle = "#ff0";
  162.      ctx.fillRect(g.x * TS + 6, g.y * TS + 6, TS - 12, TS - 12);
  163.    }
  164.    ctx.fillStyle = "#0f0";
  165.    ctx.fillRect(exit.x * TS + 6, exit.y * TS + 6, TS - 12, TS - 12);
  166.    for (const e of enemies) {
  167.      ctx.fillStyle = "#f00";
  168.      ctx.fillRect(e.x * TS + 6, e.y * TS + 6, TS - 12, TS - 12);
  169.    }
  170.    ctx.fillStyle = "#fff";
  171.    ctx.fillRect(px * TS + 4, py * TS + 4, TS - 8, TS - 8);
  172.    hud.textContent = `HP: ${hp}  Gold: ${GOLD_COUNT - golds.length}`;
  173.  }
  174.  
  175.  draw();
  176.  
  177.  function moveEnemies() {
  178.    for (const e of enemies) {
  179.      let dx = px - e.x, dy = py - e.y;
  180.      let nx = e.x, ny = e.y;
  181.      if (Math.abs(dx) > Math.abs(dy)) nx += Math.sign(dx);
  182.       else if (dy !== 0) ny += Math.sign(dy);
  183.       if (map[ny]?.[nx] === 0 && !enemies.some(en => en.x === nx && en.y === ny) && !(nx === px && ny === py))
  184.        e.x = nx, e.y = ny;
  185.     }
  186.   }
  187.  
  188.   function isAdjacent(a, b) {
  189.     return (Math.abs(a.x - b.x) + Math.abs(a.y - b.y)) === 1;
  190.   }
  191.  
  192.   window.addEventListener("keydown", e => {
  193.     if (hp <= 0) return;
  194.    let dx = 0, dy = 0;
  195.    if (e.key === "ArrowUp") dy = -1;
  196.    if (e.key === "ArrowDown") dy = 1;
  197.    if (e.key === "ArrowLeft") dx = -1;
  198.    if (e.key === "ArrowRight") dx = 1;
  199.    if (dx === 0 && dy === 0) return;
  200.    let nx = px + dx, ny = py + dy;
  201.    if (map[ny]?.[nx] === 0) {
  202.      let idx = enemies.findIndex(en => en.x === nx && en.y === ny);
  203.       if (idx !== -1) {
  204.         enemies.splice(idx, 1);
  205.       } else {
  206.         px = nx;
  207.         py = ny;
  208.         golds = golds.filter(g => !(g.x === px && g.y === py));
  209.         if (px === exit.x && py === exit.y && golds.length === 0) {
  210.          hud.textContent = "You win!";
  211.           return;
  212.         }
  213.       }
  214.       let dmg = enemies.filter(en => isAdjacent({ x: px, y: py }, en)).length;
  215.       if (dmg > 0) hp -= dmg;
  216.       if (hp <= 0) {
  217.        hud.textContent = "Game Over";
  218.        draw();
  219.        return;
  220.      }
  221.      moveEnemies();
  222.      draw();
  223.      updateSoundtrack();
  224.    }
  225.  });
  226. </script>
  227. </body>
  228. </html>
Advertisement
Add Comment
Please, Sign In to add comment