🎮ArcadeLab

SES KOPYASI — ARCADE KAOS

by DriftBuilder15
708 lines22.4 KB
▶ Play
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>SES KOPYASI — ARCADE KAOS</title>
<style>
  * { margin:0; padding:0; box-sizing:border-box; -webkit-tap-highlight-color:transparent; }
  body {
    font-family: 'Segoe UI', system-ui, sans-serif;
    background: #0a0a0f; color: #fff; height: 100vh;
    overflow: hidden; display: flex; align-items: center; justify-content: center;
    user-select: none; transition: background 0.2s;
  }
  body.danger { animation: dangerPulse 0.5s infinite; }
  @keyframes dangerPulse {
    0%,100% { background: #0a0a0f; }
    50% { background: #2a0010; }
  }
  #game {
    width: 100%; max-width: 480px; height: 100vh; max-height: 900px;
    position: relative; display: flex; flex-direction: column;
    align-items: center; justify-content: center; padding: 20px;
  }

  /* MENÜ */
  #menu { text-align: center; animation: fadeIn 0.6s ease; }
  #menu h1 {
    font-size: 2.2rem; font-weight: 900;
    background: linear-gradient(90deg, #ff3366, #ffcc00, #00ff88);
    -webkit-background-clip: text; -webkit-text-fill-color: transparent;
    margin-bottom: 6px; letter-spacing: -1px;
  }
  #menu p { color: #888; margin-bottom: 18px; font-size: 0.85rem; letter-spacing: 2px; }
  .rules {
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 12px; padding: 14px; margin-bottom: 18px;
    text-align: left; font-size: 0.78rem; line-height: 1.7; color: #bbb;
  }
  .rules b { color: #ff3366; }
  .rules .key { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
  .best {
    background: rgba(255,255,255,0.05); padding: 10px 20px; border-radius: 12px;
    margin-bottom: 18px; display: inline-block; font-size: 0.9rem; color: #aaa;
  }
  .best span { color: #00ff88; font-weight: 700; }
  button {
    background: linear-gradient(135deg, #ff3366, #ffcc00);
    color: #000; border: none; padding: 18px 60px;
    font-size: 1.15rem; font-weight: 800; border-radius: 50px;
    cursor: pointer; transition: transform 0.15s; letter-spacing: 1px;
  }
  button:active { transform: scale(0.95); }

  /* OYUN ALANI */
  #arena { display: none; text-align: center; width: 100%; }
  #roundInfo {
    position: absolute; top: 12px; left: 0; right: 0;
    display: flex; justify-content: space-between;
    padding: 0 20px; font-size: 0.78rem; color: #666; font-weight: 600;
  }
  #roundInfo b { color: #fff; }
  #combo {
    position: absolute; top: 42px; left: 0; right: 0;
    text-align: center; font-size: 1.2rem; font-weight: 900;
    color: #ffcc00; opacity: 0; transition: all 0.2s;
    text-shadow: 0 0 20px currentColor;
  }
  #combo.show { opacity: 1; animation: comboPop 0.4s ease; }
  @keyframes comboPop { 0%{transform:scale(0.5)} 50%{transform:scale(1.4)} 100%{transform:scale(1)} }

  /* Sinyal alanı */
  #signalArea {
    position: relative; width: 260px; height: 260px;
    margin: 0 auto 25px;
  }
  .signal {
    position: absolute; inset: 0;
    border-radius: 50%; display: flex; align-items: center;
    justify-content: center; font-weight: 800;
    transition: all 0.12s; background: #1a1a24; color: #333;
  }
  .signal.active {
    animation: pulse 0.3s ease;
  }
  .signal.active.glow {
    box-shadow: 0 0 60px currentColor, 0 0 120px currentColor;
  }
  .signal .emoji { font-size: 3.8rem; display: block; margin-bottom: 4px; }
  .signal .label { font-size: 0.95rem; letter-spacing: 1px; }

  /* Çift sinyal modu */
  .signal.dual {
    width: 130px; height: 130px;
  }
  .signal.dual .emoji { font-size: 2.3rem; }
  .signal.dual .label { font-size: 0.65rem; letter-spacing: 0; }
  .signal.dual.pos-left { left: 0; top: 65px; right: auto; }
  .signal.dual.pos-right { right: 0; left: auto; top: 65px; }
  .signal.dual.pos-top { left: 65px; top: 0; bottom: auto; }
  .signal.dual.pos-bottom { left: 65px; bottom: 0; top: auto; }

  /* Sahte sinyal */
  .signal.ghost {
    opacity: 0.35;
    animation: ghostFlicker 0.15s infinite;
  }
  @keyframes ghostFlicker {
    0%,100% { opacity: 0.35; }
    50% { opacity: 0.7; }
  }

  /* Sinyal değişim uyarısı */
  .signal.swapping { animation: swapFlash 0.15s 3; }
  @keyframes swapFlash {
    0%,100% { transform: scale(1); }
    50% { transform: scale(1.05); filter: brightness(1.5); }
  }

  /* Sinyal zaman çubuğu (ring) */
  #ringTimer {
    position: absolute; inset: -8px;
    border-radius: 50%;
    background: conic-gradient(#00ff88 var(--p, 100%), transparent 0);
    z-index: -1;
    transition: --p 0.05s linear;
  }

  #hint {
    font-size: 0.95rem; color: #aaa; margin-bottom: 15px;
    min-height: 24px; font-weight: 700;
  }
  #hint.big { font-size: 1.3rem; animation: comboPop 0.3s; }

  #meter {
    width: 100%; height: 8px; background: #1a1a24; border-radius: 4px;
    overflow: hidden; margin-bottom: 12px;
  }
  #meterFill {
    height: 100%; width: 0%;
    background: linear-gradient(90deg, #00ff88, #ffaa00, #ff3366);
    transition: width 0.05s linear; border-radius: 4px;
  }

  #countdown {
    position: absolute; inset: 0;
    background: rgba(0,0,0,0.9);
    display: none; align-items: center; justify-content: center;
    font-size: 8rem; font-weight: 900; color: #ff3366; z-index: 10;
  }
  #countdown.show { display: flex; animation: pop 0.5s ease; }

  #result {
    position: absolute; inset: 0;
    background: rgba(0,0,0,0.96);
    display: none; flex-direction: column;
    align-items: center; justify-content: center;
    padding: 25px; text-align: center; z-index: 20;
  }
  #result.show { display: flex; animation: fadeIn 0.3s ease; }
  #result h2 { font-size: 1.9rem; margin-bottom: 8px; }
  #result .score { font-size: 4rem; font-weight: 900; color: #00ff88; margin: 15px 0; }
  #result .stats {
    display: flex; gap: 10px; margin-bottom: 25px; flex-wrap: wrap; justify-content: center;
  }
  #result .stats div {
    background: rgba(255,255,255,0.05); padding: 10px 14px;
    border-radius: 10px; font-size: 0.72rem; color: #888;
  }
  #result .stats b { color: #fff; display: block; font-size: 1.1rem; margin-top: 3px; }

  @keyframes fadeIn { from{opacity:0} to{opacity:1} }
  @keyframes pop { 0%{transform:scale(0.5);opacity:0} 50%{transform:scale(1.1)} 100%{transform:scale(1);opacity:1} }
  @keyframes pulse { 0%{transform:scale(1)} 50%{transform:scale(1.06)} 100%{transform:scale(1)} }
  @keyframes shake { 0%,100%{transform:translateX(0)} 25%{transform:translateX(-8px)} 75%{transform:translateX(8px)} }
  .shake { animation: shake 0.3s ease; }
</style>
</head>
<body>
<div id="game">

  <!-- MENÜ -->
  <div id="menu">
    <h1>SES KOPYASI</h1>
    <p>ARCADE KAOS</p>
    <div class="rules">
      <div><span class="key" style="background:#00ff88"></span><b style="color:#00ff88">YEŞİL</b> = kısa & sessiz (şıklat)</div>
      <div><span class="key" style="background:#00ccff"></span><b style="color:#00ccff">MAVİ</b> = kısa & orta (el çırp)</div>
      <div><span class="key" style="background:#ff3366"></span><b style="color:#ff3366">KIRMIZI</b> = uzun & yüksek (BAĞIR)</div>
      <div><span class="key" style="background:#ffcc00"></span><b style="color:#ffcc00">SARI</b> = uzun & sessiz (mırıldan)</div>
      <hr style="border:none; border-top:1px solid #222; margin:8px 0;">
      ⚡ Her turda süre <b>%8 kısalır</b><br>
      🔥 Combo x5 = x2 puan, x10 = x3 puan<br>
      👻 Sahte sinyal çıkabilir (yanıp söner)<br>
      🔄 Sinyal tur içinde rengini değiştirebilir<br>
      🎨 Aynı anda 2 sinyal gelebilir!
    </div>
    <div class="best">Rekor: <span id="bestScore">0</span></div>
    <br>
    <button onclick="startGame()">KAOSU BAŞLAT</button>
  </div>

  <!-- OYUN ALANI -->
  <div id="arena">
    <div id="roundInfo">
      <div>Tur <b id="roundNum">1</b></div>
      <div>Skor <b id="scoreNum">0</b></div>
      <div>Can <b id="lifeNum">❤❤❤</b></div>
    </div>
    <div id="combo"></div>

    <div id="signalArea">
      <div id="ringTimer"></div>
      <div class="signal" id="signal1">
        <div>
          <span class="emoji">🎤</span>
          <div class="label">HAZIR</div>
        </div>
      </div>
      <div class="signal" id="signal2" style="display:none;"></div>
    </div>

    <div id="hint">Hazır ol...</div>
    <div id="meter"><div id="meterFill"></div></div>
  </div>

  <!-- GERİ SAYIM -->
  <div id="countdown">3</div>

  <!-- SONUÇ -->
  <div id="result">
    <h2 id="resultTitle">OYUN BİTTİ</h2>
    <div class="score" id="finalScore">0</div>
    <div class="stats">
      <div>Tur<b id="statRound">1</b></div>
      <div>Maks Combo<b id="statCombo">0</b></div>
      <div>İsabet<b id="statAcc">0%</b></div>
    </div>
    <button onclick="startGame()">TEKRAR OYNA</button>
  </div>

</div>

<script>
// ==================== KONFİG ====================
const CONFIG = {
  baseWindow: 1300,       // ms
  windowDecay: 0.92,       // her turda %8 azalır
  minWindow: 450,
  tolerance: 0.2,
  maxLives: 3,
  dualChance: 0.2,         // çift sinyal şansı
  ghostChance: 0.15,       // sahte sinyal şansı
  swapChance: 0.25         // renk değiştirme şansı
};

const SIGNALS = {
  green:  { color:'#00ff88', emoji:'🟢', label:'KISA/SESSİZ', hint:'Şıklat!',   dB:'low',  dur:'short' },
  blue:   { color:'#00ccff', emoji:'🔵', label:'KISA/ORTA',   hint:'El çırp!',  dB:'mid',  dur:'short' },
  red:    { color:'#ff3366', emoji:'🔴', label:'UZUN/YÜKSEK', hint:'BAĞIR!',    dB:'high', dur:'long'  },
  yellow: { color:'#ffcc00', emoji:'🟡', label:'UZUN/SESSİZ', hint:'Mırıldan!', dB:'low',  dur:'long'  }
};

const DB_RANGES = {
  low:  { min: 0.00, max: 0.20 },
  mid:  { min: 0.20, max: 0.50 },
  high: { min: 0.50, max: 1.00 }
};
const DUR_RANGES = {
  short: { min: 0,   max: 280 },
  long:  { min: 280, max: 99999 }
};

// ==================== DURUM ====================
let audioCtx, analyser, micStream, dataArray;
let isPlaying = false;
let round = 1, score = 0, lives = CONFIG.maxLives;
let combo = 0, maxCombo = 0, hits = 0, attempts = 0;
let reactionWindow = CONFIG.baseWindow;
let currentSignals = [];   // aktif sinyaller
let roundTimeout = null;
let swapTimeout = null;
let ghostTimeout = null;
let rafId = null;
let listenStart = 0, listenEnd = 0;
let peakVolume = 0;
let soundDetected = false;
let silenceStart = 0;
let evaluated = false;

// ==================== SES ====================
async function initMic() {
  try {
    micStream = await navigator.mediaDevices.getUserMedia({ audio: true });
    audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    analyser = audioCtx.createAnalyser();
    analyser.fftSize = 512;
    analyser.smoothingTimeConstant = 0.25;
    const src = audioCtx.createMediaStreamSource(micStream);
    src.connect(analyser);
    dataArray = new Uint8Array(analyser.frequencyBinCount);
    return true;
  } catch(e) {
    alert('Mikrofon izni gerekli kanka! 🎤');
    return false;
  }
}

function getVolume() {
  if (!analyser) return 0;
  analyser.getByteTimeDomainData(dataArray);
  let sum = 0;
  for (let i = 0; i < dataArray.length; i++) {
    const v = (dataArray[i] - 128) / 128;
    sum += v * v;
  }
  return Math.sqrt(sum / dataArray.length);
}

// ==================== OYUN ====================
async function startGame() {
  document.getElementById('menu').style.display = 'none';
  document.getElementById('result').classList.remove('show');
  document.getElementById('arena').style.display = 'block';
  document.body.classList.remove('danger');

  if (!audioCtx) {
    const ok = await initMic();
    if (!ok) return;
  }
  if (audioCtx.state === 'suspended') await audioCtx.resume();

  round = 1; score = 0; lives = CONFIG.maxLives;
  combo = 0; maxCombo = 0; hits = 0; attempts = 0;
  reactionWindow = CONFIG.baseWindow;
  isPlaying = true;
  updateHUD();

  await countdown(3);
  nextRound();
}

function countdown(n) {
  return new Promise(resolve => {
    const el = document.getElementById('countdown');
    el.classList.add('show');
    let i = n;
    el.textContent = i;
    const iv = setInterval(() => {
      i--;
      if (i > 0) {
        el.textContent = i;
        el.style.animation = 'none';
        void el.offsetWidth;
        el.style.animation = 'pop 0.5s ease';
      } else {
        clearInterval(iv);
        el.classList.remove('show');
        resolve();
      }
    }, 700);
  });
}

function pickSignalKey() {
  const keys = Object.keys(SIGNALS);
  return keys[Math.floor(Math.random() * keys.length)];
}

function nextRound() {
  if (!isPlaying) return;
  if (lives <= 0) return endGame();

  // Temizle
  clearTimeout(roundTimeout);
  clearTimeout(swapTimeout);
  clearTimeout(ghostTimeout);
  cancelAnimationFrame(rafId);

  // Zorlaştırma
  if (round > 1) {
    reactionWindow = Math.max(CONFIG.minWindow, reactionWindow * CONFIG.windowDecay);
  }

  // Sinyalleri belirle
  currentSignals = [];
  const isDual = Math.random() < CONFIG.dualChance && round > 3;
  const isGhost = !isDual && Math.random() < CONFIG.ghostChance;

  if (isDual) {
    const k1 = pickSignalKey();
    let k2 = pickSignalKey();
    while (k2 === k1) k2 = pickSignalKey();
    currentSignals = [
      { key: k1, ...SIGNALS[k1], ghost: false, swap: false },
      { key: k2, ...SIGNALS[k2], ghost: false, swap: false }
    ];
    renderDual(currentSignals);
    document.getElementById('hint').textContent = '🎨 İKİSİNİ DE YAP!';
    document.getElementById('hint').style.color = '#ffcc00';
  } else {
    const k = pickSignalKey();
    const isSwap = Math.random() < CONFIG.swapChance && round > 5;
    currentSignals = [{
      key: k, ...SIGNALS[k],
      ghost: isGhost,
      swap: isSwap,
      swapTo: isSwap ? (() => { let n = pickSignalKey(); while(n === k) n = pickSignalKey(); return n; })() : null
    }];
    renderSingle(currentSignals[0]);
    document.getElementById('hint').textContent = '👉 ' + SIGNALS[k].hint;
    document.getElementById('hint').style.color = SIGNALS[k].color;
  }

  // Sahte sinyal kurulumu
  if (isGhost) {
    const el = document.getElementById('signal1');
    el.classList.add('ghost');
    ghostTimeout = setTimeout(() => {
      // Sahte sinyal kayboldu — puan cezası yok, ama refleks boşa gitti
      if (!evaluated) {
        showHint('👻 SAHTEYDİ!', '#888');
      }
    }, 400);
  }

  // Renk değiştirme tuzağı
  if (!isDual && currentSignals[0].swap) {
    swapTimeout = setTimeout(() => {
      if (!isPlaying || evaluated) return;
      const newKey = currentSignals[0].swapTo;
      currentSignals[0] = { key: newKey, ...SIGNALS[newKey], ghost: false, swap: false };
      const el = document.getElementById('signal1');
      el.classList.add('swapping');
      setTimeout(() => el.classList.remove('swapping'), 450);
      renderSingle(currentSignals[0]);
      showHint('🔄 DEĞİŞTİ!', '#ff3366');
    }, Math.max(250, reactionWindow * 0.35));
  }

  // Dinleme başlat
  soundDetected = false;
  evaluated = false;
  peakVolume = 0;
  listenStart = 0;
  listenEnd = 0;
  silenceStart = 0;

  animateRing(reactionWindow);
  meterLoop();

  // Zaman aşımı
  roundTimeout = setTimeout(() => {
    if (!soundDetected && !evaluated) {
      evaluated = true;
      fail('Çok yavaş! ⏰');
    }
  }, reactionWindow);
}

function renderSingle(sig) {
  const el1 = document.getElementById('signal1');
  const el2 = document.getElementById('signal2');
  el2.style.display = 'none';
  el2.className = 'signal';
  el1.className = 'signal active glow' + (sig.ghost ? ' ghost' : '');
  el1.style.color = sig.color;
  el1.style.background = sig.color + '22';
  el1.innerHTML = `
    <div>
      <span class="emoji">${sig.emoji}</span>
      <div class="label" style="color:${sig.color}">${sig.label}</div>
    </div>`;
}

function renderDual(sigs) {
  const el1 = document.getElementById('signal1');
  const el2 = document.getElementById('signal2');
  el1.className = 'signal active glow dual pos-left';
  el1.style.color = sigs[0].color;
  el1.style.background = sigs[0].color + '22';
  el1.innerHTML = `
    <div>
      <span class="emoji">${sigs[0].emoji}</span>
      <div class="label" style="color:${sigs[0].color}">${sigs[0].label}</div>
    </div>`;

  el2.style.display = 'flex';
  el2.className = 'signal active glow dual pos-right';
  el2.style.color = sigs[1].color;
  el2.style.background = sigs[1].color + '22';
  el2.innerHTML = `
    <div>
      <span class="emoji">${sigs[1].emoji}</span>
      <div class="label" style="color:${sigs[1].color}">${sigs[1].label}</div>
    </div>`;
}

function showHint(text, color) {
  const el = document.getElementById('hint');
  el.textContent = text;
  el.style.color = color;
  el.classList.add('big');
  setTimeout(() => el.classList.remove('big'), 300);
}

function animateRing(duration) {
  const ring = document.getElementById('ringTimer');
  const start = performance.now();
  const tick = () => {
    if (evaluated || !isPlaying) { ring.style.setProperty('--p', '0%'); return; }
    const p = Math.max(0, 100 - ((performance.now() - start) / duration) * 100);
    ring.style.setProperty('--p', p + '%');
    if (p > 0) requestAnimationFrame(tick);
  };
  requestAnimationFrame(tick);
}

function meterLoop() {
  if (!isPlaying || evaluated) return;
  const vol = getVolume();
  document.getElementById('meterFill').style.width = Math.min(100, vol * 200) + '%';

  if (vol > 0.05) {
    if (!soundDetected) {
      soundDetected = true;
      listenStart = performance.now();
      peakVolume = vol;
      waitForSilence();
      return;
    }
  }
  rafId = requestAnimationFrame(meterLoop);
}

function waitForSilence() {
  const check = () => {
    if (!isPlaying || evaluated) return;
    const vol = getVolume();
    if (vol > peakVolume) peakVolume = vol;
    document.getElementById('meterFill').style.width = Math.min(100, vol * 200) + '%';

    if (vol < 0.04) {
      if (silenceStart === 0) silenceStart = performance.now();
      if (performance.now() - silenceStart > 130) {
        listenEnd = silenceStart;
        evaluate();
        return;
      }
    } else {
      silenceStart = 0;
    }
    if (performance.now() - listenStart > 1800) {
      listenEnd = performance.now();
      evaluate();
      return;
    }
    requestAnimationFrame(check);
  };
  requestAnimationFrame(check);
}

function evaluate() {
  if (evaluated) return;
  evaluated = true;
  clearTimeout(roundTimeout);
  cancelAnimationFrame(rafId);

  attempts++;
  const duration = listenEnd - listenStart;
  const volume = peakVolume;

  // Hedef sinyal: eğer çiftse, daha uygun olanı seç (oyuncu dostu)
  let target = currentSignals[0];
  if (currentSignals.length === 2) {
    // Oyuncunun yaptığı sese en yakın sinyali seç
    target = currentSignals.reduce((best, s) => {
      const dbR = DB_RANGES[s.dB], duR = DUR_RANGES[s.dur];
      const dbOK = volume >= dbR.min && volume <= dbR.max;
      const duOK = duration >= duR.min && duration <= duR.max;
      const score = (dbOK?2:0) + (duOK?2:0);
      return score > best.score ? {...s, score} : best;
    }, {score:-1});
    if (!target.key) target = currentSignals[0];
  }

  const dbR = DB_RANGES[target.dB];
  const duR = DUR_RANGES[target.dur];
  const dbOK = volume >= dbR.min * (1 - CONFIG.tolerance) &&
               volume <= Math.min(1, dbR.max * (1 + CONFIG.tolerance));
  const duOK = duration >= duR.min * (1 - CONFIG.tolerance) &&
               duration <= duR.max * (1 + CONFIG.tolerance);

  if (dbOK && duOK) {
    hits++;
    combo++;
    maxCombo = Math.max(maxCombo, combo);

    // Puanlama
    let pts = 10;
    const reflexBonus = Math.max(0, Math.round((reactionWindow - duration) / 60));
    pts += reflexBonus;
    if (combo >= 10) pts *= 3;
    else if (combo >= 5) pts *= 2;

    score += pts;

    // Combo göster
    if (combo >= 5) {
      const comboEl = document.getElementById('combo');
      comboEl.textContent = `🔥 COMBO x${combo} ${combo >= 10 ? '(x3!)' : '(x2!)'}`;
      comboEl.classList.add('show');
      setTimeout(() => comboEl.classList.remove('show'), 700);
    }

    showHint(`✅ +${pts} ${reflexBonus > 100 ? '⚡' : ''}`, '#00ff88');
    updateHUD();

    setTimeout(() => {
      round++;
      updateHUD();
      nextRound();
    }, 450);
  } else {
    const reason = !dbOK
      ? `Ses yanlış (${volume < 0.15 ? 'çok sessiz' : volume < 0.4 ? 'orta' : 'yüksek'})`
      : `Süre yanlış (${duration < 280 ? 'kısa' : 'uzun'})`;
    fail(reason);
  }
}

function fail(reason) {
  evaluated = true;
  clearTimeout(roundTimeout);
  cancelAnimationFrame(rafId);

  combo = 0;
  lives--;
  updateHUD();
  hideCombo();

  const el = document.getElementById('signal1');
  el.classList.add('shake');
  setTimeout(() => el.classList.remove('shake'), 320);

  showHint('❌ ' + reason, '#ff3366');

  if (lives === 1) document.body.classList.add('danger');
  if (lives <= 0) {
    setTimeout(endGame, 700);
  } else {
    setTimeout(() => {
      round++;
      updateHUD();
      nextRound();
    }, 900);
  }
}

function hideCombo() {
  document.getElementById('combo').classList.remove('show');
}

function updateHUD() {
  document.getElementById('roundNum').textContent = round;
  document.getElementById('scoreNum').textContent = score;
  const lifeStr = '❤'.repeat(Math.max(0, lives)) || '💀';
  const lifeEl = document.getElementById('lifeNum');
  lifeEl.textContent = lifeStr;
  lifeEl.style.color = lives === 1 ? '#ff3366' : '#fff';
}

function endGame() {
  isPlaying = false;
  evaluated = true;
  clearTimeout(roundTimeout);
  clearTimeout(swapTimeout);
  clearTimeout(ghostTimeout);
  cancelAnimationFrame(rafId);
  document.body.classList.remove('danger');

  const best = Math.max(score, parseInt(localStorage.getItem('echoBest') || '0'));
  localStorage.setItem('echoBest', best);
  document.getElementById('bestScore').textContent = best;

  document.getElementById('finalScore').textContent = score;
  document.getElementById('statRound').textContent = round;
  document.getElementById('statCombo').textContent = maxCombo;
  document.getElementById('statAcc').textContent = attempts ? Math.round(hits/attempts*100) + '%' : '0%';

  let title = '😅 TEKRAR DENE';
  if (score > 250) title = '🔥 EFSANE!';
  else if (score > 120) title = '💪 İYİ!';
  else if (score > 50) title = '👍 FENA DEĞİL';
  document.getElementById('resultTitle').textContent = title;

  document.getElementById('result').classList.add('show');
  document.getElementById('arena').style.display = 'none';
}

// ==================== BAŞLAT ====================
window.addEventListener('load', () => {
  document.getElementById('bestScore').textContent = localStorage.getItem('echoBest') || '0';
});
</script>
</body>
</html>

Game Source: SES KOPYASI — ARCADE KAOS

Creator: DriftBuilder15

Libraries: none

Complexity: complex (708 lines, 22.4 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: ses-kopyasi-arcade-kaos-driftbuilder15" to link back to the original. Then publish at arcadelab.ai/publish.