CoolFace
Apppublic

SingerkoneRKM/meaing_attack

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
index.html204 linesDownload Raw Back to root
1<!doctype html>2<html lang="en">3<head>4<meta charset="utf-8" />5<meta name="viewport" content="width=device-width,initial-scale=1" />6<title>Word Attack — Vocabulary Battle</title>7 8<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>9 10<style>11:root{12  --bg:#05050f;--panel:rgba(0,0,0,.45);--accent:#b71c1c;13  --text:#f5f5f5;--muted:#bfc6cc;14}15html,body{margin:0;height:100%;background:var(--bg);color:var(--text);font-family:Inter,system-ui;overflow:hidden}16button{background:var(--accent);border:0;color:#fff;padding:8px 12px;border-radius:8px;font-weight:600;cursor:pointer}17button.secondary{background:transparent;border:1px solid rgba(255,255,255,.08)}18.ui{position:fixed;left:12px;right:12px;top:12px;display:flex;justify-content:space-between;z-index:10}19.panel{background:var(--panel);padding:8px 12px;border-radius:8px;display:flex;gap:12px;align-items:center}20#questionBox{position:fixed;top:84px;left:50%;transform:translateX(-50%);21background:rgba(255,255,255,.05);padding:8px 16px;border-radius:8px;font-weight:700}22canvas{width:100vw;height:100vh}23.overlay{position:fixed;inset:0;background:rgba(0,0,0,.7);24display:flex;align-items:center;justify-content:center;opacity:0;pointer-events:none}25.overlay.show{opacity:1;pointer-events:auto}26.overlay-panel{background:#000;padding:24px;border-radius:12px;text-align:center}27</style>28</head>29 30<body>31 32<div class="ui">33  <div class="panel">34    <div>Score: <span id="score">0</span></div>35    <div>Lives: <span id="lives">3</span></div>36  </div>37  <div class="panel">38    <label>39      <input type="file" id="fileInput" accept=".xlsx" hidden>40      <span style="cursor:pointer">Upload Excel</span>41    </label>42    <button id="startBtn">Start</button>43    <button id="pauseBtn" class="secondary">Pause</button>44  </div>45</div>46 47<div id="questionBox">Word: <span id="currentWord">—</span></div>48<canvas id="game"></canvas>49 50<div id="overlay" class="overlay">51  <div class="overlay-panel">52    <h1>GAME OVER</h1>53    <p>Final Score: <span id="finalScore"></span></p>54    <button id="restartBtn">Restart</button>55  </div>56</div>57 58<script>59/* ---------------- CONFIG ---------------- */60const CONFIG = { lives:3, options:4 };61 62/* ---------------- DATA ---------------- */63const FALLBACK = [64 ['vivid','bright'],['fragile','easily broken'],65 ['orbit','path around a body'],['gravity','pulling force']66];67let pairs=[...FALLBACK], currentIndex=-1;68 69/* ---------------- STATE ---------------- */70let score=0,lives=CONFIG.lives,state='stopped';71let options=[], lasers=[], stars=[];72const canvas=document.getElementById('game');73const ctx=canvas.getContext('2d');74resize(); window.addEventListener('resize',resize);75 76/* ---------------- UI ---------------- */77const scoreEl=scoreSpan=document.getElementById('score');78const livesEl=document.getElementById('lives');79const wordEl=document.getElementById('currentWord');80const overlay=document.getElementById('overlay');81const finalScore=document.getElementById('finalScore');82 83/* ---------------- HELPERS ---------------- */84function resize(){85  canvas.width=window.innerWidth;86  canvas.height=window.innerHeight;87}88function rand(a,b){return a+Math.random()*(b-a);}89 90/* ---------------- STARS ---------------- */91for(let i=0;i<100;i++)stars.push({x:Math.random()*canvas.width,y:Math.random()*canvas.height,s:Math.random()*2});92 93/* ---------------- GAME FLOW ---------------- */94function nextRound(){95  currentIndex=Math.floor(Math.random()*pairs.length);96  const [word,correct]=pairs[currentIndex];97  wordEl.textContent=word;98  options=[];99  ctx.font='16px Inter, Arial';100 101  const pool=new Set([correct]);102  while(pool.size<CONFIG.options){103    pool.add(pairs[Math.floor(Math.random()*pairs.length)][1]);104  }105  [...pool].sort(()=>Math.random()-0.5).forEach(t=>{106    options.push({107      text:t,isCorrect:t===correct,108      x:rand(120,canvas.width-120),109      y:rand(-120,-40),110      vy:rand(40,80),111      w:Math.max(140,ctx.measureText(t).width+30),112      h:32,resolved:false113    });114  });115}116 117/* ---------------- INPUT ---------------- */118canvas.addEventListener('click',e=>{119  if(state!=='running')return;120  const r=canvas.getBoundingClientRect();121  const mx=e.clientX-r.left,my=e.clientY-r.top;122  const hit=options.find(o=>123    mx>o.x-o.w/2&&mx<o.x+o.w/2&&124    my>o.y-o.h/2&&my<o.y+o.h/2125  );126  if(!hit||hit.resolved)return;127  hit.resolved=true;128  lasers.push({sx:canvas.width/2,sy:canvas.height-60,tx:hit.x,ty:hit.y,a:0});129 130  if(hit.isCorrect){131    score+=20;scoreEl.textContent=score;132    setTimeout(nextRound,250);133  }else{134    lives--;livesEl.textContent=lives;135    options=options.filter(o=>o!==hit);136    if(lives<=0)gameOver();137  }138});139 140/* ---------------- LOOP ---------------- */141function loop(){142  requestAnimationFrame(loop);143  if(state!=='running')return;144  ctx.fillStyle='#03030a';ctx.fillRect(0,0,canvas.width,canvas.height);145 146  stars.forEach(s=>{s.y+=s.s;if(s.y>canvas.height)s.y=0;147    ctx.fillStyle='#fff';ctx.fillRect(s.x,s.y,2,2);});148 149  ctx.font='16px Inter, Arial';150  options.forEach(o=>{151    o.y+=o.vy*0.016;152    ctx.fillStyle='rgba(255,255,255,.06)';153    ctx.fillRect(o.x-o.w/2,o.y-o.h/2,o.w,o.h);154    ctx.fillStyle='#fff';ctx.textAlign='center';ctx.textBaseline='middle';155    ctx.fillText(o.text,o.x,o.y);156    if(o.isCorrect&&o.y>canvas.height){157      lives--;livesEl.textContent=lives;158      nextRound();159    }160  });161 162  lasers.forEach(l=>{163    l.a+=0.1;164    ctx.strokeStyle='rgba(255,80,80,.8)';165    ctx.lineWidth=4;166    ctx.beginPath();ctx.moveTo(l.sx,l.sy);ctx.lineTo(l.tx,l.ty);ctx.stroke();167  });168  lasers=lasers.filter(l=>l.a<1);169}170loop();171 172/* ---------------- CONTROL ---------------- */173function start(){174  score=0;lives=CONFIG.lives;175  scoreEl.textContent=score;livesEl.textContent=lives;176  overlay.classList.remove('show');177  state='running';nextRound();178}179function gameOver(){180  state='stopped';181  finalScore.textContent=score;182  overlay.classList.add('show');183}184 185document.getElementById('startBtn').onclick=start;186document.getElementById('restartBtn').onclick=start;187document.getElementById('pauseBtn').onclick=()=>state=state==='running'?'paused':'running';188 189/* ---------------- EXCEL ---------------- */190document.getElementById('fileInput').onchange=e=>{191  const f=e.target.files[0];if(!f)return;192  const r=new FileReader();193  r.onload=ev=>{194    const wb=XLSX.read(new Uint8Array(ev.target.result),{type:'array'});195    const rows=XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]],{header:1});196    pairs=rows.filter(r=>r[0]&&r[1]).map(r=>[String(r[0]),String(r[1])]);197    alert(`Loaded ${pairs.length} words`);198  };199  r.readAsArrayBuffer(f);200};201</script>202</body>203</html>204