SOURCE

console 命令行工具 X clear

                    
>
console
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Phigros Web</title>
<style>
  * { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
  body { overflow: hidden; background: #050510; touch-action: none; font-family: sans-serif; }
  
  #game {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    background: radial-gradient(circle at center, #12122b 0%, #050510 100%);
    z-index: 1;
  }
  
  #score-board {
    position: absolute; top: 20px; left: 20px; color: #fff; font-size: 18px; 
    font-weight: bold; letter-spacing: 2px; z-index: 10;
  }
  
  #combo-board {
    position: absolute; top: 30%; left: 50%; transform: translateX(-50%);
    color: #fff; font-size: 50px; font-weight: 900; font-style: italic;
    text-shadow: 0 0 20px #0ff; z-index: 6; pointer-events: none;
  }
  
  #judge-line {
    position: absolute; bottom: 20vh; left: 0; width: 100%; height: 4px;
    background: #fff; box-shadow: 0 0 12px #0ff, 0 0 24px #0ff;
    z-index: 5; pointer-events: none;
  }
  
  .note {
    position: absolute; width: 80px; height: 14px; margin-left: -40px; margin-top: -7px;
    background: linear-gradient(90deg, #00e5ff, #007bff);
    border-radius: 7px; box-shadow: 0 0 15px rgba(0, 229, 255, 0.8);
    pointer-events: none; z-index: 2;
  }
  .note::after {
    content: ''; position: absolute; top: 50%; left: 10%; right: 10%; height: 2px;
    background: #fff; transform: translateY(-50%);
  }
  
  .hit-effect {
    position: absolute; width: 120px; height: 12px; margin-left: -60px; margin-top: -6px;
    background: #fff; box-shadow: 0 0 20px #fff, 0 0 40px #0ff;
    pointer-events: none; z-index: 20; animation: hitAnim 0.2s ease-out forwards;
  }
  @keyframes hitAnim {
    0% { transform: scaleX(0.5) scaleY(2); opacity: 1; }
    100% { transform: scaleX(1.5) scaleY(0.1); opacity: 0; }
  }
  
  .judge-text {
    position: absolute; color: #fff; font-weight: 900; font-size: 18px; font-style: italic;
    pointer-events: none; z-index: 25; transform: translate(-50%, -50%);
    animation: textFade 0.4s ease-out forwards;
  }
  .judge-text.perfect { color: #ffd700; text-shadow: 0 0 10px #ffd700; }
  .judge-text.good { color: #00e5ff; text-shadow: 0 0 10px #00e5ff; }
  @keyframes textFade {
    0% { opacity: 1; transform: translate(-50%, -50%) scale(0.8); }
    50% { opacity: 1; transform: translate(-50%, -60%) scale(1.1); }
    100% { opacity: 0; transform: translate(-50%, -80%) scale(1); }
  }
  
  #start-screen {
    position: absolute; inset: 0; background: rgba(0,0,0,0.85); z-index: 100;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
  }
  #start-screen h2 { color: #fff; letter-spacing: 4px; margin-bottom: 20px; }
  #start-btn {
    padding: 15px 50px; font-size: 20px; border: 2px solid #0ff; border-radius: 30px;
    background: transparent; color: #0ff; font-weight: bold; cursor: pointer;
    box-shadow: 0 0 15px #0ff, inset 0 0 15px #0ff;
  }
  
  #over {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    background: rgba(0, 0, 0, 0.85); color: #fff;
    display: none; flex-direction: column; align-items: center; justify-content: center; z-index: 30;
  }
  #over h2 { font-size: 32px; font-weight: 300; letter-spacing: 4px; margin-bottom: 15px; }
  #over p { font-size: 16px; color: #aaa; margin-bottom: 30px; }
  #over span { color: #fff; font-size: 36px; font-weight: bold; display: block; margin-top: 5px; }
  #over button {
    padding: 10px 30px; font-size: 16px; border-radius: 5px; border: 1px solid #fff;
    background: transparent; color: #fff; font-weight: bold; cursor: pointer;
  }
</style>
</head>
<body>

<div id="game">
  <div id="score-board">SCORE: <span id="score-val">0</span></div>
  <div id="judge-line"></div>
  <div id="combo-board" class="hide">0</div>
  
  <div id="start-screen">
    <h2>PHIGROS WEB</h2>
    <button id="start-btn">START</button>
  </div>
</div>

<div id="over">
  <h2>GAME OVER</h2>
  <p>最终得分 <span id="final-score">0</span></p>
  <button onclick="location.reload()">RESTART</button>
</div>

<script>
  const game = document.getElementById('game');
  const scoreVal = document.getElementById('score-val');
  const comboBoard = document.getElementById('combo-board');
  const overScreen = document.getElementById('over');
  const finalScoreEl = document.getElementById('final-score');
  const judgeLineEl = document.getElementById('judge-line');
  const startScreen = document.getElementById('start-screen');
  const startBtn = document.getElementById('start-btn');

  let score = 0, combo = 0, timeLeft = 30, isOver = false;
  let notes = [];
  let judgeY = 0;
  let speed = 7; 
  let gameRunning = false;

  startBtn.addEventListener('click', () => {
      startScreen.style.display = 'none';
      gameRunning = true;
      
      let rect = judgeLineEl.getBoundingClientRect();
      judgeY = rect.top > 100 ? rect.top : (window.innerHeight || 800) * 0.8;

      spawnNote();
      gameLoop();
      
      setInterval(() => {
          if (isOver) return;
          timeLeft--;
          if (timeLeft <= 0) gameOver();
      }, 1000);
  });

  function spawnNote() {
      if (isOver || !gameRunning) return;
      const note = document.createElement('div');
      note.className = 'note';
      
      const x = Math.random() * (window.innerWidth - 120) + 60;
      note.style.left = x + 'px';
      note.style.top = '-30px'; 
      
      notes.push({ el: note, x: x, y: -30, isHit: false });
      game.appendChild(note);

      let rate = Math.max(350, 650 - (30 - timeLeft) * 8);
      setTimeout(spawnNote, Math.random() * 150 + rate);
  }

  function gameLoop() {
      if (isOver || !gameRunning) return;
      let rect = judgeLineEl.getBoundingClientRect();
      if(rect.top > 0) judgeY = rect.top;

      for (let i = notes.length - 1; i >= 0; i--) {
          let n = notes[i];
          if (n.isHit) continue;
          
          n.y += speed;
          n.el.style.top = n.y + 'px';
          
          if (n.y > judgeY + 100) {
              n.el.remove();
              notes.splice(i, 1);
              combo = 0; 
              updateUI();
          }
      }
      requestAnimationFrame(gameLoop);
  }

  game.addEventListener('pointerdown', (e) => {
      if (isOver || !gameRunning) return;
      const clickX = e.clientX;
      
      let closestDist = Infinity;
      let closestIndex = -1;
      
      for (let i = 0; i < notes.length; i++) {
          let n = notes[i];
          if (n.isHit) continue;
          
          if (Math.abs(n.y - judgeY) < 80 && Math.abs(n.x - clickX) < 60) {
              let dist = Math.abs(n.y - judgeY);
              if (dist < closestDist) {
                  closestDist = dist;
                  closestIndex = i;
              }
          }
      }
      
      if (closestIndex !== -1) {
          let n = notes[closestIndex];
          n.isHit = true;
          n.el.remove(); 
          notes.splice(closestIndex, 1);
          
          let judgeType = closestDist < 40 ? 'PERFECT' : 'GOOD';
          combo++;
          score += (judgeType === 'PERFECT' ? 100 : 50) + combo * 2;
          updateUI();
          
          showHitEffect(n.x, judgeY);
          showJudgeText(n.x, judgeY, judgeType);
      }
  });

  function showHitEffect(x, y) {
      const effect = document.createElement('div');
      effect.className = 'hit-effect';
      effect.style.left = x + 'px';
      effect.style.top = y + 'px';
      game.appendChild(effect);
      setTimeout(() => effect.remove(), 200);
  }

  function showJudgeText(x, y, text) {
      const t = document.createElement('div');
      t.className = `judge-text ${text.toLowerCase()}`;
      t.innerText = text;
      t.style.left = x + 'px';
      t.style.top = (y - 40) + 'px';
      game.appendChild(t);
      setTimeout(() => t.remove(), 400);
  }

  function updateUI() {
      scoreVal.innerText = score;
      if (combo > 0) {
          comboBoard.classList.remove('hide');
          comboBoard.innerText = combo;
      } else {
          comboBoard.classList.add('hide');
      }
  }

  function gameOver() {
      isOver = true;
      finalScoreEl.innerText = score;
      overScreen.style.display = 'flex';
  }
</script>
</body>
</html>