DGHKLMNOPQRSTUVWXYZ
1
nama_lengkapasal_schoolnipM2 LinkM3 Link
2
Musalim Djaka Sasmita, S.Pd.SD N 6 WONOGIRI199001312022211004Buka LinkBuka Link
3
Rekyan Pandhiga Dewi, S.Pd.SDN 7 Wonogiri199505212019022002Buka LinkBuka Link
4
Dwi Purnama Utami, S.Pd.SDSD N 1 Giritirto197307262022212008Buka LinkBuka Link
5
Catur Rahmadani, S.Pd.SDSD Negeri 1 Wonogiri198206272022212021Buka LinkBuka Link
6
RATRI CAHYANINGRUM, S.PdSD Negeri 1 Giripurwo198901162022212004Buka LinkBuka Link
7
MEILANI ANDITA IFANI, S.Pd.SD NEGERI 3 POKOH KIDUL199705202023212019Buka LinkBuka Link
8
Riyanto, S.Pd.SDSD Negeri 7 Wonogiri198406222022211004Buka LinkBuka Link
9
Nunung Nurhiqmah, S.Psi., M.Pd.SD Negeri 1 Wonogiri198211202008012008Buka LinkBuka Link
10
Sekti Sumarni,S PdSD N 2 Pokoh Kidul197010011997032007Buka LinkBuka Link
11
Sri Wahyuni,S.Pd.AUDSD N 4 Wonoboyo196806162008012014Buka LinkBuka Link
12
ANGGIT HASTUTI, S. Pd. SDSDN 6 WONOGIRI198411172022212020Buka LinkBuka Link
13
ENDANG DWI ANJARI, S.Pd AUDSD NEGERI 3 WONOKERTO19750422 200801 2007Buka LinkBuka Link
14
Sri Harumi, S. E.SD Negeri 2 Wonoboyo197702092022212007Buka LinkBuka Link
15
Noniek Dian Pratiwi,S.PdSD Negeri 2 Wonoboyo198305832022212016Buka LinkBuka Link
16
HERIKA YUTI KURNIA, S.Pd.SDSD Negeri 6 Wonogiri19850405 201001 2 024Buka LinkBuka Link
17
INTAN LISTIA PUTRI PRIYADI,S.PdSD NEGERI 1 PELEM199505082023212024Buka LinkBuka Link
18
Tulus Wijayanti S.PdSD NEGERI 2 BULUSULUR199510032025212106Buka LinkBuka Link
19
Indah RahmawatiSD Negeri SelopukangBuka LinkBuka Link
20
Yenni Roosita, S.PdSD Negeri 1 Wonogiri197912312014062012Buka Link
<!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Roda Keberuntungan: Matematika Bilangan 1 - 10</title> <!-- Tailwind CSS CDN --> <script src="https://cdn.tailwindcss.com"></script> <!-- Google Fonts --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&display=swap" rel="stylesheet"> <!-- Canvas Confetti CDN --> <script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.6.0/dist/confetti.browser.min.js"></script> <style> body { font-family: 'Fredoka', cursive, sans-serif; background: linear-gradient(135deg, #a8ff78 0%, #78ffd6 100%); touch-action: manipulation; } .custom-shadow { box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1); } .btn-bounce { transition: transform 0.15s ease, box-shadow 0.15s ease; } .btn-bounce:active { transform: scale(0.95); } .wheel-container { position: relative; width: 320px; height: 320px; margin: 0 auto; } @media (min-width: 640px) { .wheel-container { width: 380px; height: 380px; } } /* Pointer Marker */ .wheel-pointer { position: absolute; top: -15px; left: 50%; transform: translateX(-50%); width: 0; height: 0; border-left: 18px solid transparent; border-right: 18px solid transparent; border-top: 32px solid #ef4444; z-index: 20; filter: drop-shadow(0px 4px 4px rgba(0,0,0,0.3)); } .glass-card { background: rgba(255, 255, 255, 0.88); backdrop-filter: blur(12px); border: 2px solid rgba(255, 255, 255, 0.6); } @keyframes pulse-glow { 0%, 100% { box-shadow: 0 0 15px rgba(234, 179, 8, 0.6); } 50% { box-shadow: 0 0 30px rgba(234, 179, 8, 0.9); } } .active-player-glow { animation: pulse-glow 2s infinite; } </style> </head> <body class="min-h-screen flex flex-col justify-between items-center p-2 sm:p-4 text-slate-800 antialiased selection:bg-amber-300"> <header class="w-full max-w-4xl flex justify-between items-center mb-2 sm:mb-4 px-2"> <div class="flex items-center gap-2"> <span class="text-3xl sm:text-4xl animate-bounce">🎡</span> <div> <h1 class="text-xl sm:text-3xl font-bold text-emerald-800 drop-shadow-sm leading-tight">RODA ANGKA AJAIB</h1> <p class="text-xs sm:text-sm text-emerald-700 font-semibold">Matematika Kelas 1 SD (Bilangan 1 - 10)</p> </div> </div> <button id="bgmToggleBtn" onclick="toggleBGM()" class="glass-card px-3 py-2 rounded-full flex items-center gap-2 font-bold text-xs sm:text-sm text-slate-700 hover:bg-white shadow transition-all"> <span id="bgmIcon">🔇</span> <span id="bgmLabel">Musik: OFF</span> </button> </header> <!-- MAIN CONTAINER --> <main class="w-full max-w-4xl flex-grow flex flex-col justify-center items-center"> <!-- SCREEN 1: SETUP SCREEN --> <div id="setupScreen" class="w-full glass-card rounded-3xl p-4 sm:p-8 custom-shadow text-center max-w-lg transition-all duration-300"> <div class="mb-6"> <div class="inline-block bg-amber-100 text-amber-800 text-sm font-bold px-4 py-1.5 rounded-full mb-2"> 🎮 Persiapan Permainan </div> <h2 class="text-2xl sm:text-3xl font-extrabold text-slate-800">Pilih Jumlah Pemain</h2> <p class="text-slate-600 text-xs sm:text-sm mt-1">Siapa saja yang akan ikut bermain?</p> </div> <!-- Player Count Selector --> <div class="flex justify-center gap-3 mb-6"> <button onclick="setPlayerCount(1)" id="btnCount1" class="player-count-btn w-12 h-12 rounded-2xl font-bold text-lg bg-emerald-500 text-white shadow-md btn-bounce">1</button> <button onclick="setPlayerCount(2)" id="btnCount2" class="player-count-btn w-12 h-12 rounded-2xl font-bold text-lg bg-white text-slate-700 border-2 border-slate-200 shadow-sm hover:border-emerald-400 btn-bounce">2</button> <button onclick="setPlayerCount(3)" id="btnCount3" class="player-count-btn w-12 h-12 rounded-2xl font-bold text-lg bg-white text-slate-700 border-2 border-slate-200 shadow-sm hover:border-emerald-400 btn-bounce">3</button> <button onclick="setPlayerCount(4)" id="btnCount4" class="player-count-btn w-12 h-12 rounded-2xl font-bold text-lg bg-white text-slate-700 border-2 border-slate-200 shadow-sm hover:border-emerald-400 btn-bounce">4</button> </div> <!-- Player Input List --> <div id="playerInputs" class="space-y-3 mb-8 text-left"> <!-- Dynamic Inputs Populated by JS --> </div> <button onclick="startGame()" class="w-full py-4 bg-gradient-to-r from-emerald-500 to-teal-600 hover:from-emerald-600 hover:to-teal-700 text-white font-extrabold text-xl rounded-2xl shadow-lg shadow-emerald-500/30 btn-bounce flex items-center justify-center gap-2"> <span>MULAI PETUALANGAN</span> <span class="text-2xl">🚀</span> </button> </div> <!-- SCREEN 2: MAIN GAMEPLAY --> <div id="gameScreen" class="w-full hidden flex-col items-center gap-4 transition-all duration-300"> <!-- Scoreboard Row --> <div id="scoreboard" class="w-full grid grid-cols-2 sm:grid-cols-4 gap-2 sm:gap-3"> <!-- Dynamic Player Score Cards --> </div> <!-- Question Progress Header --> <div class="w-full glass-card rounded-2xl px-4 py-2 flex justify-between items-center"> <div class="flex items-center gap-2 font-bold text-emerald-800 text-sm sm:text-base"> <span>📝 Pertanyaan</span> <span id="questionCounter" class="bg-emerald-200 text-emerald-900 px-2 py-0.5 rounded-full text-xs">Soal 1 / 10</span> </div> <div id="turnBadge" class="bg-amber-400 text-amber-950 font-bold px-3 py-1 rounded-full text-xs sm:text-sm flex items-center gap-1 shadow-sm"> <span id="turnAvatar">🐰</span> <span id="turnName">Giliran Pemain 1</span> </div> </div> <!-- Wheel Section / Question Section Container --> <div class="w-full grid grid-cols-1 lg:grid-cols-12 gap-4 items-center"> <!-- Wheel Column (Left/Top) --> <div id="wheelBox" class="lg:col-span-5 glass-card rounded-3xl p-4 flex flex-col items-center justify-center custom-shadow"> <div class="wheel-container"> <div class="wheel-pointer"></div> <canvas id="wheelCanvas" width="380" height="380" class="w-full h-full rounded-full cursor-pointer"></canvas> </div> <button id="spinBtn" onclick="spinWheel()" class="mt-4 px-8 py-3.5 bg-gradient-to-r from-amber-400 to-amber-500 hover:from-amber-500 hover:to-amber-600 text-amber-950 font-extrabold text-xl rounded-2xl shadow-lg shadow-amber-500/40 btn-bounce flex items-center gap-2"> <span>PUTAR RODA</span> <span class="text-2xl">🎯</span> </button> <p id="spinMessage" class="text-xs font-semibold text-slate-500 mt-2 text-center h-4">Putar roda untuk mendapatkan poin!</p> </div> <!-- Question Column (Right/Bottom) --> <div id="questionBox" class="lg:col-span-7 glass-card rounded-3xl p-4 sm:p-6 custom-shadow flex flex-col justify-between min-h-[380px]"> <!-- Question Placeholder State --> <div id="questionPlaceholder" class="flex-grow flex flex-col justify-center items-center text-center p-6 text-slate-500"> <div class="text-6xl mb-3 animate-pulse">🎡</div> <h3 class="text-xl font-bold text-slate-700 mb-1">Roda Belum Diputar!</h3> <p class="text-xs sm:text-sm max-w-xs">Tekan tombol <span class="font-bold text-amber-600">PUTAR RODA</span> untuk memilih nilai poin dan menampilkan soal matematika.</p> </div> <!-- Question Active Content State --> <div id="questionContent" class="hidden flex-col flex-grow"> <!-- Points Awarded Alert Banner --> <div id="sliceAlert" class="bg-amber-100 border border-amber-300 text-amber-900 rounded-xl p-2.5 mb-3 text-center text-xs sm:text-sm font-bold flex items-center justify-center gap-2"> <span id="sliceIcon">⭐</span> <span id="sliceText">Nilai Soal Ini: 100 Poin</span> </div> <!-- Question Title/Text --> <h3 id="questionText" class="text-base sm:text-lg font-bold text-slate-800 mb-3 text-center sm:text-left"> Berapa jumlah benda di bawah ini? </h3> <!-- Question Visual / SVG Illustration Box --> <div id="visualBox" class="bg-white/90 border-2 border-emerald-100 rounded-2xl p-3 sm:p-4 mb-4 flex justify-center items-center min-h-[140px] shadow-inner"> <!-- Dynamic SVG Illustration rendered via JS --> </div> <!-- Answer Options Grid --> <div id="optionsGrid" class="grid grid-cols-1 sm:grid-cols-3 gap-2 sm:gap-3 mt-auto"> <!-- Dynamic Option Buttons --> </div> </div> </div> </div> </div> <!-- SCREEN 3: GAME OVER / VICTORY SCREEN --> <div id="victoryScreen" class="w-full hidden glass-card rounded-3xl p-6 sm:p-10 custom-shadow text-center max-w-2xl transition-all duration-300"> <div class="text-5xl sm:text-6xl mb-2 animate-bounce">🏆</div> <h2 class="text-2xl sm:text-4xl font-extrabold text-amber-600 mb-1">PERMAINAN SELESAI!</h2> <p class="text-slate-600 text-xs sm:text-base font-semibold mb-6">Luar biasa! Kalian semua adalah Bintang Matematika Hari Ini!</p> <!-- Leaderboard / Podium --> <div id="leaderboardList" class="space-y-3 mb-8 text-left max-w-md mx-auto"> <!-- Dynamic Leaderboard Items --> </div> <button onclick="resetGame()" class="px-8 py-4 bg-gradient-to-r from-emerald-500 to-teal-600 hover:from-emerald-600 hover:to-teal-700 text-white font-extrabold text-lg sm:text-xl rounded-2xl shadow-lg shadow-emerald-500/30 btn-bounce flex items-center justify-center gap-2 mx-auto"> <span>MAIN LAGI</span> <span class="text-2xl">🔄</span> </button> </div> </main> <!-- FOOTER --> <footer class="mt-4 text-center text-xs font-semibold text-emerald-800/80"> Game Edukasi Matematika Kelas 1 SD • Pembelajaran Interaktif Bilangan 1 - 10 </footer> <script> /* ========================================================================== AUDIO SYSTEM (Synthesized using Web Audio API for 100% reliability) ========================================================================== */ let audioCtx = null; let isBgmPlaying = false; let bgmInterval = null; function initAudio() { if (!audioCtx) { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } if (audioCtx.state === 'suspended') { audioCtx.resume(); } } // Play Tone helper function playTone(freq, type, duration, startTime = 0, vol = 0.1) { if (!audioCtx) return; try { const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.type = type; osc.frequency.setValueAtTime(freq, audioCtx.currentTime + startTime); gain.gain.setValueAtTime(vol, audioCtx.currentTime + startTime); gain.gain.exponentialRampToValueAtTime(0.0001, audioCtx.currentTime + startTime + duration); osc.connect(gain); gain.connect(audioCtx.destination); osc.start(audioCtx.currentTime + startTime); osc.stop(audioCtx.currentTime + startTime + duration); } catch (e) { console.log("Audio play error", e); } } // Sound Effects function playPopSFX() { initAudio(); playTone(600, 'sine', 0.08, 0, 0.15); } function playTickSFX() { initAudio(); playTone(800, 'triangle', 0.03, 0, 0.1); } function playCorrectSFX() { initAudio(); const now = 0; playTone(523.25, 'sine', 0.12, now, 0.2); // C5 playTone(659.25, 'sine', 0.12, now + 0.1, 0.2); // E5 playTone(783.99, 'sine', 0.12, now + 0.2, 0.2); // G5 playTone(1046.50, 'triangle', 0.3, now + 0.3, 0.25); // C6 } function playWrongSFX() { initAudio(); playTone(280, 'sawtooth', 0.15, 0, 0.15); playTone(220, 'sawtooth', 0.25, 0.12, 0.15); } function playFanfareSFX() { initAudio(); const notes = [523.25, 659.25, 783.99, 1046.50, 880, 1046.50]; const times = [0, 0.15, 0.3, 0.45, 0.6, 0.75]; notes.forEach((note, idx) => { playTone(note, 'triangle', 0.25, times[idx], 0.2); }); } // Background Music Loop Synthesizer function toggleBGM() { initAudio(); isBgmPlaying = !isBgmPlaying; const bgmIcon = document.getElementById('bgmIcon'); const bgmLabel = document.getElementById('bgmLabel'); if (isBgmPlaying) { bgmIcon.textContent = "🔊"; bgmLabel.textContent = "Musik: ON"; startBGM(); } else { bgmIcon.textContent = "🔇"; bgmLabel.textContent = "Musik: OFF"; stopBGM(); } } function startBGM() { if (bgmInterval) clearInterval(bgmInterval); const notes = [261.63, 329.63, 392.00, 329.63, 261.63, 392.00, 329.63, 349.23]; let step = 0; bgmInterval = setInterval(() => { if (isBgmPlaying && audioCtx) { playTone(notes[step % notes.length], 'sine', 0.25, 0, 0.03); step++; } }, 350); } function stopBGM() { if (bgmInterval) { clearInterval(bgmInterval); bgmInterval = null; } } /* ========================================================================== GAME STATE & DATA ========================================================================== */ const AVATARS = [ { name: "Kelinci", emoji: "🐰", color: "bg-pink-100 text-pink-700 border-pink-300" }, { name: "Kucing", emoji: "🐱", color: "bg-amber-100 text-amber-700 border-amber-300" }, { name: "Beruang", emoji: "🐻", color: "bg-emerald-100 text-emerald-700 border-emerald-300" }, { name: "Panda", emoji: "🐼", color: "bg-sky-100 text-sky-700 border-sky-300" } ]; const WHEEL_SLICES = [ { label: "100 POIN", value: 100, color: "#f59e0b", textColor: "#ffffff", icon: "⭐" }, { label: "200 POIN", value: 200, color: "#10b981", textColor: "#ffffff", icon: "🌟" }, { label: "ZONK", value: 0, color: "#ef4444", textColor: "#ffffff", icon: "💥" }, { label: "300 POIN", value: 300, color: "#3b82f6", textColor: "#ffffff", icon: "💎" }, { label: "DUA KALI", value: "DOUBLE", color: "#8b5cf6", textColor: "#ffffff", icon: "🚀" }, { label: "500 POIN", value: 500, color: "#ec4899", textColor: "#ffffff", icon: "👑" }, { label: "150 POIN", value: 150, color: "#06b6d4", textColor: "#ffffff", icon: "🎈" }, { label: "ZONK", value: 0, color: "#ef4444", textColor: "#ffffff", icon: "💥" } ]; // 10 MATHEMATICS QUESTIONS FOR GRADE 1 SD (Numbers 1-10) const QUESTIONS = [ { id: 1, title: "Mengenal Jumlah Benda", question: "Ada berapa buah apel merah segar pada piring di bawah ini?", type: "apples", count: 4, options: [3, 4, 5], answer: 4, explanation: "Mari hitung bersama: 1, 2, 3, 4! Ada 4 apel merah." }, { id: 2, title: "Membandingkan Banyak Benda", question: "Kelompok balon manakah yang jumlahnya LEBIH BANYAK?", type: "compare_balloons", leftCount: 3, rightCount: 6, options: ["Balon Biru (3)", "Balon Kuning (6)", "Sama Banyak"], answer: "Balon Kuning (6)", explanation: "Balon Kuning berjumlah 6, sedangkan Balon Biru ada 3. 6 lebih banyak dari 3!" }, { id: 3, title: "Urutan Angka Maju", question: "Berapa angka yang hilang pada batu pijakan di bawah?", type: "stepping_stones", sequence: [5, 6, "?", 8], options: [4, 7, 9], answer: 7, explanation: "Urutan menghitung maju: 5, 6, 7, 8. Angka yang hilang adalah 7." }, { id: 4, title: "Penjumlahan Bergambar", question: "2 Bintang + 3 Bintang = ... Berapa total semua bintang?", type: "add_stars", left: 2, right: 3, options: [4, 5, 6], answer: 5, explanation: "2 bintang ditambah 3 bintang menjadi 5 bintang!" }, { id: 5, title: "Hitung Mundur Roket", question: "Roket siap meluncur! Hitung mundur: 10, 9, 8, [ ? ], 6. Angka berapa yang hilang?", type: "rocket_countdown", options: [5, 7, 8], answer: 7, explanation: "Dalam hitungan mundur dari 10: 10, 9, 8, 7, 6! Jawabannya 7." }, { id: 6, title: "Pengurangan Bergambar", question: "Ada 5 donat lezat. 2 donat telah dimakan (❌). Berapa sisa donat di piring?", type: "donuts_subtraction", total: 5, eaten: 2, options: [3, 2, 4], answer: 3, explanation: "5 dikurangi 2 (5 - 2) adalah 3 donat." }, { id: 7, title: "Pasangan Bilangan (Number Bond)", question: "Angka 8 terdiri dari pasangan 5 dan angka berapa?", type: "number_bond", total: 8, part1: 5, options: [2, 3, 4], answer: 3, explanation: "5 + 3 = 8. Jadi pasangan angka 5 agar menjadi 8 adalah 3." }, { id: 8, title: "Membaca Kata Bilangan", question: "Manakah lambang angka yang sesuai dengan kata di bawah ini?", type: "word_number", word: "TUJUH", options: [6, 7, 9], answer: 7, explanation: "Kata 'TUJUH' ditulis dengan angka 7." }, { id: 9, title: "Soal Cerita Penjumlahan", question: "Budi punya 4 pensil. Ibu memberi Budi 4 pensil lagi. Berapa total pensil Budi?", type: "pencils_story", options: [7, 8, 10], answer: 8, explanation: "4 pensil + 4 pensil = 8 pensil." }, { id: 10, title: "Soal Cerita Pengurangan", question: "10 ekor burung hinggap di ranting. 4 ekor terbang. Berapa burung tersisa?", type: "birds_story", options: [5, 6, 7], answer: 6, explanation: "10 burung dikurangi 4 burung yang terbang (10 - 4) = 6 burung tersisa." } ]; // State Variables let playerCount = 1; let players = []; let currentPlayerIdx = 0; let currentQuestionIdx = 0; let currentSliceResult = null; let isSpinning = false; let wheelRotation = 0; /* ========================================================================== SETUP SCREEN LOGIC ========================================================================== */ window.onload = function() { setPlayerCount(1); initWheelCanvas(); }; function setPlayerCount(count) { playPopSFX(); playerCount = count; // Highlight Buttons for (let i = 1; i <= 4; i++) { const btn = document.getElementById(`btnCount${i}`); if (i === count) { btn.className = "player-count-btn w-12 h-12 rounded-2xl font-bold text-lg bg-emerald-500 text-white shadow-md btn-bounce"; } else { btn.className = "player-count-btn w-12 h-12 rounded-2xl font-bold text-lg bg-white text-slate-700 border-2 border-slate-200 shadow-sm hover:border-emerald-400 btn-bounce"; } } // Render Player Input Fields const inputsContainer = document.getElementById('playerInputs'); inputsContainer.innerHTML = ''; for (let i = 0; i < playerCount; i++) { const avatar = AVATARS[i]; const div = document.createElement('div'); div.className = "flex items-center gap-3 bg-white p-2.5 rounded-2xl border border-slate-200 shadow-sm"; div.innerHTML = ` <span class="text-2xl p-2 rounded-xl ${avatar.color}">${avatar.emoji}</span> <input type="text" id="playerNameInput_${i}" value="Pemain ${i+1}" class="w-full bg-slate-50 border border-slate-200 rounded-xl px-3 py-2 text-sm font-bold text-slate-700 focus:outline-none focus:border-emerald-500" placeholder="Nama Pemain ${i+1}" maxLength="12"> `; inputsContainer.appendChild(div); } } function startGame() { playPopSFX(); players = []; for (let i = 0; i < playerCount; i++) { const nameInput = document.getElementById(`playerNameInput_${i}`); const name = nameInput ? (nameInput.value.trim() || `Pemain ${i+1}`) : `Pemain ${i+1}`; players.push({ id: i, name: name, avatar: AVATARS[i], score: 0 }); } currentPlayerIdx = 0; currentQuestionIdx = 0; document.getElementById('setupScreen').classList.add('hidden'); document.getElementById('gameScreen').classList.remove('hidden'); document.getElementById('gameScreen').classList.add('flex'); updateScoreboard(); updateTurnHeader(); resetQuestionBox(); drawWheel(); } function updateScoreboard() { const container = document.getElementById('scoreboard'); container.innerHTML = ''; players.forEach((p, idx) => { const isActive = idx === currentPlayerIdx; const card = document.createElement('div'); card.className = `glass-card p-3 rounded-2xl flex items-center justify-between transition-all ${ isActive ? 'border-2 border-amber-400 active-player-glow bg-amber-50/90' : 'opacity-85' }`; card.innerHTML = ` <div class="flex items-center gap-2 overflow-hidden"> <span class="text-2xl sm:text-3xl p-1.5 rounded-xl ${p.avatar.color} shrink-0">${p.avatar.emoji}</span> <div class="truncate"> <h4 class="font-bold text-xs sm:text-sm text-slate-800 truncate">${p.name}</h4> <p class="text-[10px] sm:text-xs text-slate-500 font-semibold">${isActive ? ' Turn Now' : 'Pemain'}</p> </div> </div> <div class="text-right ml-1 shrink-0"> <span class="text-xs sm:text-sm font-bold text-amber-600">⭐ ${p.score}</span> </div> `; container.appendChild(card); }); } function updateTurnHeader() { const curP = players[currentPlayerIdx]; document.getElementById('questionCounter').textContent = `Soal ${currentQuestionIdx + 1} / ${QUESTIONS.length}`; document.getElementById('turnAvatar').textContent = curP.avatar.emoji; document.getElementById('turnName').textContent = `Giliran ${curP.name}`; } /* ========================================================================== WHEEL OF FORTUNE CANVAS & SPINNING ========================================================================== */ let canvas, ctx; function initWheelCanvas() { canvas = document.getElementById('wheelCanvas'); ctx = canvas.getContext('2d'); drawWheel(); } function drawWheel() { if (!ctx) return; const numSlices = WHEEL_SLICES.length; const centerX = canvas.width / 2; const centerY = canvas.height / 2; const radius = canvas.width / 2 - 10; const sliceAngle = (2 * Math.PI) / numSlices; ctx.clearRect(0, 0, canvas.width, canvas.height); // Save context for rotation ctx.save(); ctx.translate(centerX, centerY); ctx.rotate(wheelRotation); // Draw Slices for (let i = 0; i < numSlices; i++) { const angle = i * sliceAngle; const slice = WHEEL_SLICES[i]; ctx.beginPath(); ctx.moveTo(0, 0); ctx.arc(0, 0, radius, angle, angle + sliceAngle); ctx.closePath(); ctx.fillStyle = slice.color; ctx.fill(); ctx.lineWidth = 4; ctx.strokeStyle = "#ffffff"; ctx.stroke(); // Slice Text & Icon ctx.save(); ctx.rotate(angle + sliceAngle / 2); ctx.textAlign = "right"; ctx.fillStyle = slice.textColor; ctx.font = "bold 16px Fredoka, sans-serif"; ctx.fillText(`${slice.icon} ${slice.label}`, radius - 20, 6); ctx.restore(); } // Draw Center Hub ctx.beginPath(); ctx.arc(0, 0, 35, 0, 2 * Math.PI); ctx.fillStyle = "#ffffff"; ctx.fill(); ctx.lineWidth = 5; ctx.strokeStyle = "#f59e0b"; ctx.stroke(); // Center Star ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.font = "22px sans-serif"; ctx.fillText("⭐", 0, 0); ctx.restore(); } function spinWheel() { if (isSpinning) return; initAudio(); isSpinning = true; const spinBtn = document.getElementById('spinBtn'); spinBtn.disabled = true; spinBtn.classList.add('opacity-50', 'cursor-not-allowed'); document.getElementById('spinMessage').textContent = "Roda sedang berputar..."; // Physics calculation const randomExtraSpins = 5 + Math.floor(Math.random() * 4); // 5 to 8 full spins const randomSliceIndex = Math.floor(Math.random() * WHEEL_SLICES.length); const sliceAngle = (2 * Math.PI) / WHEEL_SLICES.length; // Calculate target rotation so marker (top 12 o'clock / -PI/2) aligns with chosen slice // Slice 0 starts at angle 0. const targetSliceAngle = (2 * Math.PI) - (randomSliceIndex * sliceAngle) - (sliceAngle / 2) - (Math.PI / 2); const totalRotationNeeded = wheelRotation + (randomExtraSpins * 2 * Math.PI) + (targetSliceAngle - (wheelRotation % (2 * Math.PI))); const duration = 4000; // 4 seconds spin const startTime = performance.now(); let lastTickSlice = -1; function animateSpin(now) { const elapsed = now - startTime; const progress = Math.min(elapsed / duration, 1); // Ease Out Cubic ease curve const easeOut = 1 - Math.pow(1 - progress, 3); wheelRotation = easeOut * totalRotationNeeded; // Sound tick on passing slices const currentSliceTick = Math.floor((wheelRotation % (2 * Math.PI)) / sliceAngle); if (currentSliceTick !== lastTickSlice) { playTickSFX(); lastTickSlice = currentSliceTick; } drawWheel(); if (progress < 1) { requestAnimationFrame(animateSpin); } else { isSpinning = false; currentSliceResult = WHEEL_SLICES[randomSliceIndex]; handleWheelStop(); } } requestAnimationFrame(animateSpin); } function handleWheelStop() { const spinBtn = document.getElementById('spinBtn'); spinBtn.disabled = false; spinBtn.classList.remove('opacity-50', 'cursor-not-allowed'); playPopSFX(); // Check if ZONK if (currentSliceResult.value === 0) { document.getElementById('spinMessage').textContent = "Aduh! Roda mendarat di ZONK!"; showZonkModal(); } else { let textVal = typeof currentSliceResult.value === 'number' ? `${currentSliceResult.value} Poin` : "Poin Ganda (x2)!"; document.getElementById('spinMessage').textContent = `Mendarat di ${currentSliceResult.label}! Jawab soal di bawah.`; // Show Question Box displayQuestion(currentSliceResult); } } function showZonkModal() { const questionPlaceholder = document.getElementById('questionPlaceholder'); const questionContent = document.getElementById('questionContent'); questionContent.classList.add('hidden'); questionPlaceholder.classList.remove('hidden'); questionPlaceholder.innerHTML = ` <div class="text-6xl mb-2 animate-bounce">💥</div> <h3 class="text-2xl font-extrabold text-red-600 mb-1">ZONK!</h3> <p class="text-xs sm:text-sm text-slate-600 mb-4 max-w-xs">Sayang sekali! Kamu tidak mendapatkan poin di giliran ini.</p> <button onclick="nextTurn(false)" class="px-6 py-2.5 bg-red-500 hover:
21
Radian Dwi Anggorowati, S.PdSD Negeri 2 Wonoharjo-Buka LinkBuka Link
22
PARAMITA AYU HAPSARI, S.Pd.SDSD Negeri 2 Wonoboyo198609252022212004Buka LinkBuka Link
23
Wahyu Agus Riyanto, S. Pd.SD Negeri Selopukang198008142022211002Buka LinkBuka Link
24
DJUMADI. S. PdSD Negeri Selopukang196808072008011012Buka Link
BERTINDAK SEBAGAI PEMBUAT GAME PROFESIONAL. Buatkan game edukasi model lompat karakter untuk materi agama islam. Terdiri dari 10 soal. Dapat dimainkan oleh 1-4 orang. Disertai ilustrasi, music efek, dan music latar yang sesuai
25
Sri Wahyuni, S.PdSD Negeri 1 Wonogiri198106222021212004Buka Link
<!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Roda Angka Ajaib - Matematika Kelas 1 SD</title> <!-- Tailwind CSS --> <script src="https://cdn.tailwindcss.com"></script> <!-- FontAwesome Icons --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <!-- Google Fonts for Child-friendly Typography --> <link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600;700&family=Quicksand:wght@500;700&display=swap" rel="stylesheet"> <script> tailwind.config = { theme: { extend: { fontFamily: { fredoka: ['Fredoka', 'sans-serif'], quicksand: ['Quicksand', 'sans-serif'] }, colors: { gameYellow: '#FFD166', gamePink: '#EF476F', gameBlue: '#118AB2', gameGreen: '#06D6A0', gamePurple: '#8338EC' } } } } </script> <style> body { font-family: 'Quicksand', sans-serif; background: linear-gradient(135deg, #A8EDEA 0%, #FED6E3 100%); min-height: 100vh; user-select: none; } h1, h2, h3, .font-title { font-family: 'Fredoka', cursive; } .bounce-gentle { animation: bounceGentle 2s infinite; } @keyframes bounceGentle { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } } .pulse-slow { animation: pulseSlow 1.5s infinite alternate; } @keyframes pulseSlow { from { transform: scale(1); } to { transform: scale(1.05); } } /* Glassmorphism Card Style */ .glass-card { background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(10px); border: 4px solid rgba(255, 255, 255, 0.9); box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.05); } /* Wheel Pointer Arrow */ .wheel-pointer { width: 0; height: 0; border-left: 20px solid transparent; border-right: 20px solid transparent; border-top: 35px solid #EF476F; filter: drop-shadow(0px 4px 4px rgba(0,0,0,0.3)); } /* Confetti Canvas */ #confettiCanvas { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 100; } </style> </head> <body class="flex flex-col min-h-screen text-slate-800"> <canvas id="confettiCanvas"></canvas> <!-- Top Bar Navigation & Sound Controls --> <header class="w-full bg-white/80 backdrop-blur-md border-b-4 border-gameYellow px-4 py-3 flex justify-between items-center z-10 shadow-sm"> <div class="flex items-center space-x-3"> <div class="bg-gameYellow text-slate-900 w-10 h-10 rounded-2xl flex items-center justify-center font-title text-2xl shadow-md"> 🎡 </div> <div> <h1 class="text-xl md:text-2xl font-bold text-slate-800 leading-tight">Roda Angka Ajaib</h1> <p class="text-xs font-semibold text-slate-500 hidden sm:block">Matematika Kelas 1 SD • Bilangan 1 - 10</p> </div> </div> <div class="flex items-center space-x-2 sm:space-x-4"> <!-- Audio Toggles --> <button id="bgmToggle" class="bg-indigo-100 hover:bg-indigo-200 text-indigo-700 px-3 py-2 rounded-xl text-sm font-bold transition flex items-center space-x-2"> <i id="bgmIcon" class="fas fa-music text-indigo-600"></i> <span class="hidden md:inline">Musik</span> </button> <button id="sfxToggle" class="bg-emerald-100 hover:bg-emerald-200 text-emerald-700 px-3 py-2 rounded-xl text-sm font-bold transition flex items-center space-x-2"> <i id="sfxIcon" class="fas fa-volume-up text-emerald-600"></i> <span class="hidden md:inline">Efek Suara</span> </button> <button id="resetGameBtn" class="bg-rose-100 hover:bg-rose-200 text-rose-700 px-3 py-2 rounded-xl text-sm font-bold transition flex items-center space-x-1"> <i class="fas fa-redo"></i> <span class="hidden md:inline">Ulang</span> </button> </div> </header> <!-- MAIN CONTAINER --> <main class="flex-1 max-w-6xl w-full mx-auto p-4 flex flex-col justify-center items-center relative"> <!-- SCREEN 1: GAME SETUP --> <section id="setupScreen" class="w-full max-w-lg glass-card rounded-3xl p-6 sm:p-8 text-center my-auto transition-all duration-300"> <div class="inline-block p-4 bg-yellow-100 rounded-full mb-3 text-4xl bounce-gentle"> 🐰 </div> <h2 class="text-2xl sm:text-3xl font-bold text-slate-800 mb-2">Selamat Datang!</h2> <p class="text-slate-600 mb-6 text-sm sm:text-base">Halo teman-teman! Si Kiki ingin mengajak kamu bermain Roda Keberuntungan sambil belajar berhitung 1-10.</p> <!-- Number of Players Selector --> <div class="mb-6"> <label class="block text-sm font-bold text-slate-700 mb-3 uppercase tracking-wider">Pilih Jumlah Pemain</label> <div class="grid grid-cols-4 gap-2 sm:gap-3"> <button class="player-count-btn bg-slate-100 hover:bg-gameYellow border-2 border-slate-300 text-slate-700 font-bold py-3 rounded-2xl text-lg transition active shadow-sm" data-players="1">1</button> <button class="player-count-btn bg-gameYellow border-2 border-yellow-500 text-slate-900 font-bold py-3 rounded-2xl text-lg transition active shadow-sm" data-players="2">2</button> <button class="player-count-btn bg-slate-100 hover:bg-gameYellow border-2 border-slate-300 text-slate-700 font-bold py-3 rounded-2xl text-lg transition active shadow-sm" data-players="3">3</button> <button class="player-count-btn bg-slate-100 hover:bg-gameYellow border-2 border-slate-300 text-slate-700 font-bold py-3 rounded-2xl text-lg transition active shadow-sm" data-players="4">4</button> </div> </div> <!-- Player Names Inputs --> <div id="playerInputsContainer" class="space-y-3 mb-8 text-left"> <!-- Dynamic player name inputs inserted here --> </div> <button id="startGameBtn" class="w-full bg-gameGreen hover:bg-emerald-500 text-white font-title text-xl py-4 rounded-2xl shadow-lg hover:shadow-xl transition transform hover:-translate-y-1 active:translate-y-0 flex items-center justify-center space-x-3"> <span>Mulai Permainan</span> <i class="fas fa-arrow-right"></i> </button> </section> <!-- SCREEN 2: MAIN GAME PLAYBOARD --> <section id="gameScreen" class="w-full grid grid-cols-1 lg:grid-cols-12 gap-6 items-center hidden my-auto"> <!-- Left Side: Player Leaderboard / Scoreboards --> <div class="lg:col-span-4 order-2 lg:order-1 flex flex-col space-y-4"> <div class="glass-card rounded-3xl p-4 sm:p-5"> <div class="flex justify-between items-center mb-4"> <h3 class="font-title text-lg text-slate-700 flex items-center space-x-2"> <i class="fas fa-users text-indigo-500"></i> <span>Papan Skor Pemain</span> </h3> <span id="questionProgress" class="bg-indigo-100 text-indigo-700 font-bold px-3 py-1 rounded-full text-xs">Soal 1 / 10</span> </div> <div id="scoreboardList" class="space-y-3"> <!-- Dynamic Player Score Cards Here --> </div> </div> <!-- Mascot Greeting Box --> <div class="glass-card rounded-3xl p-4 flex items-center space-x-4 border-l-8 border-l-gameYellow"> <div class="text-4xl bg-yellow-100 p-2 rounded-2xl">🐰</div> <div> <div id="mascotName" class="text-xs font-bold text-amber-600 uppercase">Si Kiki</div> <div id="mascotSpeech" class="text-xs sm:text-sm text-slate-700 font-semibold">Putar rodanya dan jawab soalnya ya!</div> </div> </div> </div> <!-- Right Side: Interactive Wheel Canvas & Spin Controls --> <div class="lg:col-span-8 order-1 lg:order-2 flex flex-col items-center justify-center relative"> <div class="relative flex flex-col items-center justify-center p-2"> <!-- Wheel Pointer --> <div class="wheel-pointer z-20 -mb-4"></div> <!-- Canvas Wheel --> <div class="relative p-3 bg-white/90 rounded-full shadow-2xl border-8 border-yellow-300"> <canvas id="wheelCanvas" width="420" height="420" class="w-[300px] h-[300px] sm:w-[380px] sm:h-[380px] md:w-[420px] md:h-[420px] max-w-full h-auto cursor-pointer"></canvas> <!-- Center Wheel Pin --> <div id="centerSpinBtn" class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-16 h-16 sm:w-20 sm:h-20 bg-white rounded-full border-4 border-amber-400 shadow-lg flex items-center justify-center font-title font-bold text-slate-800 text-sm sm:text-base text-center cursor-pointer hover:scale-105 active:scale-95 transition"> PUTAR! </div> </div> </div> <!-- Big Spin Button for Mobile/Ease --> <button id="spinBtn" class="mt-6 bg-gamePink hover:bg-rose-600 text-white font-title text-2xl px-10 py-4 rounded-2xl shadow-xl transition transform hover:scale-105 active:scale-95 flex items-center space-x-3 pulse-slow"> <i class="fas fa-sync-alt"></i> <span>PUTAR RODA!</span> </button> </div> </section> </main> <!-- MODAL: QUESTION CARD --> <div id="questionModal" class="fixed inset-0 bg-slate-900/60 backdrop-blur-md flex items-center justify-center p-4 z-50 opacity-0 pointer-events-none transition-all duration-300"> <div class="bg-white rounded-3xl max-w-xl w-full p-6 sm:p-8 shadow-2xl transform scale-90 transition-all duration-300 border-4 border-yellow-300 relative"> <!-- Turn Indicator Banner --> <div class="flex justify-between items-center mb-4 border-b border-slate-100 pb-3"> <div class="flex items-center space-x-2"> <span id="modalPlayerAvatar" class="text-2xl">👦</span> <span id="modalPlayerName" class="font-title text-lg text-slate-800">Giliran Budi</span> </div> <div class="bg-emerald-100 text-emerald-800 px-3 py-1 rounded-full text-xs font-bold" id="modalRewardText"> Hadiah: +50 Poin </div> </div> <!-- Question Visual Illustration Container --> <div id="questionIllustration" class="w-full h-40 bg-slate-50 rounded-2xl flex items-center justify-center mb-4 p-2 border-2 border-indigo-50 relative overflow-hidden"> <!-- SVG illustration dynamically injected --> </div> <!-- Question Text --> <h3 id="questionText" class="text-lg sm:text-xl font-bold text-slate-800 text-center mb-6 leading-snug"> Berapa jumlah apel merah pada gambar? </h3> <!-- Answer Options Grid --> <div id="optionsContainer" class="grid grid-cols-1 sm:grid-cols-3 gap-3 mb-4"> <!-- Answer choice buttons inserted here --> </div> <!-- Feedback Message --> <div id="modalFeedback" class="hidden text-center p-3 rounded-xl font-bold text-sm mb-2"></div> </div> </div> <!-- MODAL: GAME OVER / VICTORY PODIUM --> <div id="victoryModal" class="fixed inset-0 bg-slate-900/80 backdrop-blur-lg flex items-center justify-center p-4 z-50 opacity-0 pointer-events-none transition-all duration-300"> <div class="glass-card rounded-3xl max-w-md w-full p-6 sm:p-8 text-center transform scale-90 transition-all duration-300 relative border-4 border-yellow-400"> <div class="text-5xl mb-2 bounce-gentle">👑</div> <h2 class="text-3xl font-title font-bold text-slate-800 mb-1">Permainan Selesai!</h2> <p class="text-slate-600 text-sm mb-6">Hebat sekali semuanya! Berikut adalah pemenang permainan ini:</p> <!-- Winner Announcement --> <div id="winnerBox" class="bg-gradient-to-r from-amber-100 via-yellow-200 to-amber-100 p-4 rounded-2xl border-2 border-amber-300 mb-6"> <div id="winnerAvatar" class="text-4xl mb-1">🏆</div> <div id="winnerName" class="font-title text-2xl font-bold text-amber-900">Budi</div> <div id="winnerScore" class="text-amber-800 font-bold text-sm">Total Skor: 250 Poin</div> </div> <!-- Full Ranking List --> <div id="finalRankings" class="space-y-2 mb-6 text-left"> <!-- Final scores list injected here --> </div> <button id="playAgainBtn" class="w-full bg-gameGreen hover:bg-emerald-500 text-white font-title text-lg py-3 rounded-2xl shadow-lg transition transform hover:-translate-y-1"> Main Lagi <i class="fas fa-redo ml-2"></i> </button> </div> </div> <script> // Web Audio API Synthesizer (Zero External File Dependencies) class SoundEngine { constructor() { this.ctx = null; this.bgmEnabled = true; this.sfxEnabled = true; this.bgmInterval = null; this.bgmStep = 0; } init() { if (!this.ctx) { const AudioContext = window.AudioContext || window.webkitAudioContext; this.ctx = new AudioContext(); } if (this.ctx.state === 'suspended') { this.ctx.resume(); } } playTone(freq, type = 'sine', duration = 0.1, gainVal = 0.1) { if (!this.sfxEnabled) return; this.init(); try { const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.type = type; osc.frequency.setValueAtTime(freq, this.ctx.currentTime); gain.gain.setValueAtTime(gainVal, this.ctx.currentTime); gain.gain.exponentialRampToValueAtTime(0.0001, this.ctx.currentTime + duration); osc.connect(gain); gain.connect(this.ctx.destination); osc.start(); osc.stop(this.ctx.currentTime + duration); } catch (e) { console.error(e); } } playTick() { this.playTone(600, 'triangle', 0.03, 0.15); } playCorrect() { if (!this.sfxEnabled) return; this.init(); const now = this.ctx.currentTime; const notes = [523.25, 659.25, 783.99, 1046.50]; // C5, E5, G5, C6 notes.forEach((freq, idx) => { const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.type = 'sine'; osc.frequency.setValueAtTime(freq, now + idx * 0.08); gain.gain.setValueAtTime(0.15, now + idx * 0.08); gain.gain.exponentialRampToValueAtTime(0.001, now + idx * 0.08 + 0.25); osc.connect(gain); gain.connect(this.ctx.destination); osc.start(now + idx * 0.08); osc.stop(now + idx * 0.08 + 0.25); }); } playWrong() { if (!this.sfxEnabled) return; this.init(); const now = this.ctx.currentTime; const notes = [220, 196]; // A3, G3 notes.forEach((freq, idx) => { const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.type = 'sawtooth'; osc.frequency.setValueAtTime(freq, now + idx * 0.15); gain.gain.setValueAtTime(0.12, now + idx * 0.15); gain.gain.exponentialRampToValueAtTime(0.001, now + idx * 0.15 + 0.3); osc.connect(gain); gain.connect(this.ctx.destination); osc.start(now + idx * 0.15); osc.stop(now + idx * 0.15 + 0.3); }); } playZonk() { if (!this.sfxEnabled) return; this.init(); const now = this.ctx.currentTime; const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.type = 'sawtooth'; osc.frequency.setValueAtTime(300, now); osc.frequency.exponentialRampToValueAtTime(80, now + 0.4); gain.gain.setValueAtTime(0.2, now); gain.gain.exponentialRampToValueAtTime(0.001, now + 0.4); osc.connect(gain); gain.connect(this.ctx.destination); osc.start(); osc.stop(now + 0.4); } playFanfare() { if (!this.sfxEnabled) return; this.init(); const now = this.ctx.currentTime; const arpeggio = [523.25, 659.25, 783.99, 1046.50, 783.99, 1046.50]; arpeggio.forEach((freq, idx) => { const osc = this.ctx.createOscillator(); const gain = this.ctx.createGain(); osc.type = 'triangle'; osc.frequency.setValueAtTime(freq, now + idx * 0.12); gain.gain.setValueAtTime(0.2, now + idx * 0.12); gain.gain.exponentialRampToValueAtTime(0.001, now + idx * 0.12 + 0.35); osc.connect(gain); gain.connect(this.ctx.destination); osc.start(now + idx * 0.12); osc.stop(now + idx * 0.12 + 0.35); }); } startBGM() { if (this.bgmInterval) return; this.init(); // Playful cheerful melody sequence const melody = [ 261.63, 329.63, 392.00, 329.63, 349.23, 392.00, 440.00, 392.00, 349.23, 329.63, 293.66, 329.63, 261.63, 293.66, 329.63, 261.63 ]; this.bgmStep = 0; this.bgmInterval = setInterval(() => { if (!this.bgmEnabled) return; const freq = melody[this.bgmStep % melody.length]; this.playTone(freq, 'sine', 0.12, 0.03); this.bgmStep++; }, 300); } stopBGM() { if (this.bgmInterval) { clearInterval(this.bgmInterval); this.bgmInterval = null; } } } const audio = new SoundEngine(); // QUESTION BANK (10 Questions for Grade 1 SD: Numbers 1-10) const questionsData = [ { id: 1, text: "Berapa jumlah apel merah pada pohon ini?", options: ["3 Apel", "4 Apel", "5 Apel"], correct: 1, renderSVG: () => ` <svg viewBox="0 0 200 120" class="h-full mx-auto"> <!-- Tree trunk & crown --> <rect x="90" y="60" width="20" height="50" fill="#8B5A2B" rx="4"/> <circle cx="100" cy="50" r="45" fill="#2ECC71"/> <circle cx="75" cy="45" r="30" fill="#27AE60"/> <circle cx="125" cy="45" r="30" fill="#27AE60"/> <!-- 4 Red Apples --> <circle cx="80" cy="35" r="9" fill="#E74C3C"/> <circle cx="120" cy="40" r="9" fill="#E74C3C"/> <circle cx="90" cy="65" r="9" fill="#E74C3C"/> <circle cx="110" cy="60" r="9" fill="#E74C3C"/> </svg> ` }, { id: 2, text: "Angka berapakah nama bilangan di bawah ini?", options: ["Enam", "Tujuh", "Delapan"], correct: 1, renderSVG: () => ` <svg viewBox="0 0 200 120" class="h-full mx-auto"> <text x="100" y="90" font-family="'Fredoka', sans-serif" font-size="90" font-weight="bold" fill="#8338EC" text-anchor="middle">7</text> </svg> ` }, { id: 3, text: "Berapakah angka selanjutnya pada gerbong kereta: 1, 2, 3, 4, ... ?", options: ["5", "6", "7"], correct: 0, renderSVG: () => ` <svg viewBox="0 0 300 100" class="h-full mx-auto"> <!-- Train engine & carriages --> <rect x="10" y="30" width="40" height="40" fill="#EF476F" rx="5"/> <rect x="60" y="30" width="40" height="40" fill="#FFD166" rx="5"/> <text x="80" y="58" font-size="22" font-weight="bold" text-anchor="middle" fill="#333">1</text> <rect x="110" y="30" width="40" height="40" fill="#06D6A0" rx="5"/> <text x="130" y="58" font-size="22" font-weight="bold" text-anchor="middle" fill="#333">2</text> <rect x="160" y="30" width="40" height="40" fill="#118AB2" rx="5"/> <text x="180" y="58" font-size="22" font-weight="bold" text-anchor="middle" fill="#fff">3</text> <rect x="210" y="30" width="40" height="40" fill="#8338EC" rx="5"/> <text x="230" y="58" font-size="22" font-weight="bold" text-anchor="middle" fill="#fff">4</text> <rect x="260" y="30" width="35" height="40" fill="#E2E8F0" stroke="#94A3B8" stroke-dasharray="4" rx="5"/> <text x="277" y="58" font-size="22" font-weight="bold" text-anchor="middle" fill="#64748B">?</text> </svg> ` }, { id: 4, text: "Manakah kelompok bintang yang LEBIH BANYAK?", options: ["Kelompok A (3 Bintang)", "Kelompok B (6 Bintang)", "Sama Banyak"], correct: 1, renderSVG: () => ` <svg viewBox="0 0 260 120" class="h-full mx-auto"> <!-- Box A --> <rect x="10" y="10" width="110" height="100" fill="#FFF5F5" stroke="#EF476F" stroke-width="3" rx="10"/> <text x="65" y="30" font-weight="bold" text-anchor="middle" fill="#EF476F">Kelompok A</text> <text x="35" y="65" font-size="20">⭐</text><text x="65" y="65" font-size="20">⭐</text><text x="95" y="65" font-size="20">⭐</text> <!-- Box B --> <rect x="140" y="10" width="110" height="100" fill="#F0FDF4" stroke="#06D6A0" stroke-width="3" rx="10"/> <text x="195" y="30" font-weight="bold" text-anchor="middle" fill="#06D6A0">Kelompok B</text> <text x="160" y="60" font-size="18">⭐</text><text x="195" y="60" font-size="18">⭐</text><text x="230" y="60" font-size="18">⭐</text> <text x="160" y="90" font-size="18">⭐</text><text x="195" y="90" font-size="18">⭐</text><text x="230" y="90" font-size="18">⭐</text> </svg> ` }, { id: 5, text: "Berapa jumlah semua mobil? (2 Mobil Biru + 3 Mobil Merah)", options: ["4 Mobil", "5 Mobil", "6 Mobil"], correct: 1, renderSVG: () => ` <svg viewBox="0 0 250 100" class="h-full mx-auto"> <!-- Blue Cars --> <text x="30" y="55" font-size="30">🚗</text> <text x="70" y="55" font-size="30">🚗</text> <text x="115" y="55" font-size="24" font-weight="bold" fill="#64748B">+</text> <!-- Red Cars --> <text x="140" y="55" font-size="30">🏎️</text> <text x="175" y="55" font-size="30">🏎️</text> <text x="210" y="55" font-size="30">🏎️</text> </svg> ` }, { id: 6, text: "Berapa jumlah jari pada satu tangan manusia?", options: ["5 Jari", "8 Jari", "10 Jari"], correct: 0, renderSVG: () => ` <svg viewBox="0 0 200 120" class="h-full mx-auto"> <text x="100" y="75" font-size="70" text-anchor="middle">🖐️</text> </svg> ` }, { id: 7, text: "Ada 8 balon, lalu 3 balon meletus (8 - 3). Berapa balon yang tersisa?", options: ["4 Balon", "5 Balon", "6 Balon"], correct: 1, renderSVG: () => ` <svg viewBox="0 0 260 110" class="h-full mx-auto"> <!-- 5 Intact Balloons --> <text x="20" y="50" font-size="26">🎈</text> <text x="50" y="50" font-size="26">🎈</text> <text x="80" y="50" font-size="26">🎈</text> <text x="110" y="50" font-size="26">🎈</text> <text x="140" y="50" font-size="26">🎈</text> <!-- 3 Popped Balloons --> <text x="180" y="50" font-size="22">💥</text> <text x="205" y="50" font-size="22">💥</text> <text x="230" y="50" font-size="22">💥</text> </svg> ` }, { id: 8, text: "Isi titik-titik dengan tanda yang tepat: 6 ... 4", options: ["Kurang Dari (<)", "Lebih Besar Dari (>)", "Sama Dengan (=)"], correct: 1, renderSVG: () => ` <svg viewBox="0 0 240 110" class="h-full mx-auto"> <!-- Scale / Balance balance illustration --> <circle cx="60" cy="50" r="30" fill="#118AB2"/> <text x="60" y="60" font-size="30" font-weight="bold" fill="#fff" text-anchor="middle">6</text> <rect x="105" y="45" width="30" height="30" rx="5" fill="#E2E8F0"/> <text x="120" y="67" font-size="22" font-weight="bold" fill="#64748B" text-anchor="middle">?</text> <circle cx="180" cy="50" r="25" fill="#EF476F"/> <text x="180" y="58" font-size="26" font-weight="bold" fill="#fff" text-anchor="middle">4</text> </svg> ` }, { id: 9, text: "Ani punya 4 kue, lalu dibelikan lagi 4 kue oleh Ibu. Berapa total kue Ani?", options: ["6 Kue", "7 Kue", "8 Kue"], correct: 2, renderSVG: () => ` <svg viewBox="0 0 240 100" class="h-full mx-auto"> <!-- Plate 1 --> <ellipse cx="60" cy="60" rx="45" ry="20" fill="#E2E8F0"/> <text x="35" y="55" font-size="20">🍪🍪</text> <text x="35" y="70" font-size="20">🍪🍪</text> <text x="120" y="60" font-size="24" font-weight="bold" fill="#64748B" text-anchor="middle">+</text> <!-- Plate 2 --> <ellipse cx="180" cy="60" rx="45" ry="20" fill="#E2E8F0"/> <text x="155" y="55" font-size="20">🍪🍪</text> <text x="155" y="70" font-size="20">🍪🍪</text> </svg> ` }, { id: 10, text: "Hitung mundur peluncuran roket: 10, 9, 8, 7, ... ?", options: ["6", "5", "4"], correct: 0, renderSVG: () => ` <svg viewBox="0 0 200 110" class="h-full mx-auto"> <text x="60" y="75" font-size="60">🚀</text> <text x="140" y="70" font-size="45" font-weight="bold" fill="#EF476F" font-family="'Fredoka', sans-serif">?</text> </svg> ` } ]; // GAME STATE MANAGEMENT const wheelSlices = [ { label: "10 POIN", value: 10, color: "#EF476F", type: "score" }, { label: "50 POIN", value: 50, color: "#118AB2", type: "score" }, { label: "2X POIN", value: "2X", color: "#8338EC", type: "double" }, { label: "20 POIN", value: 20, color: "#06D6A0", type: "score" }, { label: "ZONK!", value: 0, color: "#333333", type: "zonk" }, { label: "100 POIN", value: 100, color: "#FFD166", type: "score" }, { label: "30 POIN", value: 30, color: "#F78C6B", type: "score" }, { label: "BONUS 40", value: 40, color: "#06D6A0", type: "score" } ]; const avatarIcons = ["👦", "👧", "🦊", "🐼"]; const avatarColors = ["#118AB2", "#EF476F", "#F78C6B", "#8338EC"]; let players = []; let currentTurnIndex = 0; let currentQuestionIndex = 0; let isSpinning = false; let currentRotation = 0; let pendingSliceResult = null; // DOM ELEMENTS const setupScreen = document.getElementById('setupScreen'); const gameScreen = document.getElementById('gameScreen'); const playerInputsContainer = document.getElementById('playerInputsContainer'); const scoreboardList = document.getElementById('scoreboardList'); const questionProgress = document.getElementById('questionProgress'); const mascotSpeech = document.getElementById('mascotSpeech'); const wheelCanvas = document.getElementById('wheelCanvas'); const ctx = wheelCanvas.getContext('2d'); const spinBtn = document.getElementById('spinBtn'); const centerSpinBtn = document.getElementById('centerSpinBtn'); // Modal Elements const questionModal = document.getElementById('questionModal'); const modalPlayerAvatar = document.getElementById('modalPlayerAvatar'); const modalPlayerName = document.getElementById('modalPlayerName'); const modalRewardText = document.getElementById('modalRewardText'); const questionIllustration = document.getElementById('questionIllustration'); const questionText = document.getElementById('questionText'); const optionsContainer = document.getElementById('optionsContainer'); const modalFeedback = document.getElementById('modalFeedback'); // Victory Modal const victoryModal = document.getElementById('victoryModal'); const winnerName = document.getElementById('winnerName'); const winnerScore = document.getElem
26
HARDIYANTI, S.Pd.SDSD NEGERI 2 BULUSULUR198307272014062007Buka LinkBuka Link
27
Dhiyana Hulyati,S.Pd.ISD Negeri 2 Pokoh Kidul198410042019022001Buka LinkBuka Link
28
Fransiska Yuli Winarsih,S.PdSDN 1 Giriwono198207102022212029Buka LinkBuka Link
29
Siti Mulyani, S. PD. SDSD Negeri 2 Pokoh Kidul198612142020122004Buka LinkBuka Link
30
Elviko Ary Wibowo, S.Pd.SD Negeri 3 Wonokerto199312062020121005Buka LinkBuka Link
31
Umi Azizah Fauzana, S.Pd.SD Negeri 7 Wonogiri199005272015032002Buka LinkBuka Link
32
Fitria Purnamasari, M.Pd.SD Negeri 3 Wonokerto198905212019022003Buka LinkBuka Link
33
Margiyanti, S.Pd.AUDSD Negeri 1 Purworejo196610182008012003Buka LinkBuka Link
34
Zahro Sri Tanjung, S.Pd.SD Negeri 2 Bulusulur199006242022212009Buka LinkBuka Link
35
Eko Budi Aryastuti, S.Pd.AUDSD Negeri Selopukang197201282008012003Buka LinkBuka Link
36
Nurul Faridawati, S.Pd.SDSD Negeri Kedungringin197704042022212009Buka LinkBuka Link
37
Hety Wulandari, S. Pd.SD IT Al Huda Wonogiri-Buka LinkBuka Link
38
Sonya Eiffel, S.Pd.SD Negeri 7 Wonogiri199405312023212015Buka LinkBuka Link
39
Dian Fitri Astuti, S.PdSD Negeri Selopukang198905092022212016Buka LinkBuka Link
40
Dwi Sriyatni, S. Pd. SDSDN 1 Wonokarto197506161999032009Buka LinkBuka Link
41
Agung Irwan Saputro,S.Pd.SD Negeri Selopukang197705202022211005Buka LinkBuka Link
42
Novie Asih Anggreini, S. Pd.SDN 1 Giripurwo198711232022212009Buka LinkBuka Link
43
SRI PAMUNGKAS ARIANI S.Pd.SDSD N 1 Wonogiri197805042014062007Buka LinkBuka Link
44
YENIE FITRIANA DEWI, S.Pd.SDSD Negeri 2 Pokoh Kidul197808172022212005Buka LinkBuka Link
45
Amalia Putri Suciantika, S. PdSD Negeri 1 Giripurwo199101232022212007Buka LinkBuka Link
46
LINA PUSPITA NINGRUM, S.Pd.SD Negeri Selopukang198605192022212012Buka LinkBuka Link
47
MARSELIA DEWI LOVELY, S.PdSD Negeri 3 Wonoboyo199604092022212006Buka LinkBuka Link
48
Indra Litasari, S.PdSD Negeri 1 Sonoharjo198905132020122004Buka LinkBuka Link
49
Umi Azizah Fauzani, S.Pd.SDN 8 WONOGIRI199005272022212007Buka LinkBuka Link
50
Bivin, S.PdSDN 1 Wonogiri198806252020122004Buka LinkBuka Link
51
Andi Purwono,S.PdSD Negeri 3 Sendang198908132023211018Buka LinkBuka Link
52
Suharyati, S.PdSD NEGERI KETIMANG196712042022212002Buka LinkBuka Link
53
SAFINA ANDRIANA ALFALATI, S.PdSD NEGERI 1 GIRITIRTO198411152022212011Buka LinkBuka Link
54
Risti Meingga Wijayanti, S.PdSD Negeri 3 Wonokerto198805072022212002Buka LinkBuka Link
55
Sri Adhi Endaryati, M.Pd.SD Negeri 3 Giriwono198508012009032007Buka LinkBuka Link
56
Maulana Agung Prabowo,S.PdSD NEGERI 1 WONOKARTO199312112020121005Buka LinkBuka Link
57
RATNA SULISTIYANI, S.Pd.SD N 1 Wonogiri198211072008012006Buka LinkBuka Link
58
Suharmanto, S. PdSD NEGERI 2 GIRIPURWO199206282019021001Buka LinkBuka Link
59
ENDANG SAYUTINIGSIH, S. Pd. SDSD NEGERI KALORAN197803272022212009Buka LinkBuka Link
60
Ibnu Sri Nawanto,S.Pd.SDSD Negeri 3 Wuryorejo198409032022211008Buka LinkBuka Link
61
SHIMA INDAH ROSITA, S.Pd.SD NEGERI 2 BULUSULUR199310102022212003Buka LinkBuka Link
62
Herry Setyawan, S.Pd.SD., M.PdSD NEGERI 8 WONOGIRI1986017 200903 1 001Buka LinkBuka Link
63
Risna Ekawati, S.Pd.SDN 2 Giritirto199007112023212015Buka LinkBuka Link
64
Umi Rokhana, S.Pd., Gr.SD NEGERI 1 WONOGIRI199009072017082001Buka LinkBuka Link
65
Sri Budi Lestari S.Pd.SDSD NEGERI 3 WURYOREJO196807312022212001Buka LinkBuka Link
66
SHANTI PERTIWI, S.Pd.SD NEGERI KEDUNGRINGIN198712212022212004Buka LinkBuka Link
67
Wargiyanti,S.Pd.SDSD negeri 2 Purworejo196701191992112001Buka LinkBuka Link
68
Satya Wijayanto, S.Pd.SD Negeri 1 Manjung199209012020121005Buka LinkBuka Link
69
Wida Febriati Ningrum, S.PdSD Negeri 1 Giripurwo198902262022212005Buka LinkBuka Link
70
WIDIYANTI, S.Pd.SDSD Negeri 2 Wuryorejo197906022022212007Buka Link
file:///C:/Users/USER/Downloads/game_evaluasi_bahasa_indonesia_kelas_2_mengenal_perasaan.html
71
Sri Wiyati, S. Pd. AUDSDN 1 Giritirto196702061986032002Buka LinkBuka Link
72
SRI RAHAYU,S.Pd.AUDSD Negeri 2 Wonoharjo196807132008012009Buka LinkBuka Link
73
Dian Eko Santoso, S.Pd.SD.SDN 2 GIRITIRTO198802242020121001Buka LinkBuka Link
74
Ernilia Kurniawati, S. Pd., GrSDIT AL HUDA WonogiriBuka LinkBuka Link
75
KRISTIN AYU DAMAIYANTI, S. Pd.SD N 1 WONOKARTO199312212022212006Buka Link
file:///C:/Users/HP/Downloads/game_luas_bangun_ai.html
76
Rini Hernawati, S.Pd.SD Negeri Wonomulyo198201212022212010Buka LinkBuka Link
77
Dian Kusumawardani, S. Pd.SDN Kedungringin199309252023212027Buka LinkBuka Link
78
Tri Wijayanti,S.Pd.SDSD Negeri Ketimang19731017202321001Buka LinkBuka Link
79
APRILIYA FITRI UTOMO, S.Pd.SD NEGERI KALORAN199104232022212019Buka Link
<!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>SD Negeri Kaloran - Petualangan Lompat Bintang Islam</title> <!-- Tailwind CSS CDN --> <script src="https://cdn.tailwindcss.com"></script> <!-- Font Awesome untuk Icon --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <!-- Google Fonts --> <link href="https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600;700&family=Nunito:wght@400;700;800&display=swap" rel="stylesheet"> <style> * { font-family: 'Nunito', sans-serif; user-select: none; -webkit-user-select: none; } h1, h2, h3, .font-heading { font-family: 'Fredoka', cursive; } .bg-pattern { background-color: #0f172a; background-image: radial-gradient(#1e293b 2px, transparent 2px); background-size: 24px 24px; } .glass-panel { background: rgba(15, 23, 42, 0.85); backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.15); } .btn-bounce { transition: transform 0.1s ease, box-shadow 0.1s ease; } .btn-bounce:active { transform: scale(0.95); } /* Custom scrollbar */ ::-webkit-scrollbar { width: 8px; } ::-webkit-scrollbar-track { background: #0f172a; } ::-webkit-scrollbar-thumb { background: #334155; border-radius: 4px; } </style> </head> <body class="bg-pattern min-h-screen text-slate-100 flex flex-col justify-between overflow-x-hidden"> <!-- TOP HEADER BAR --> <header class="w-full bg-slate-900/90 border-b border-slate-700/60 p-3 px-4 sm:px-8 flex justify-between items-center z-30 sticky top-0 backdrop-blur-md"> <div class="flex items-center gap-3"> <!-- LOGO SD NEGERI KALORAN --> <div class="relative w-12 h-12 rounded-xl bg-slate-800 border-2 border-amber-400/60 p-0.5 overflow-hidden shadow-lg shadow-amber-500/10 flex items-center justify-center shrink-0"> <img id="headerLogo" src="WhatsApp Image 2026-08-01 at 11.22.56.jpeg" alt="SD Negeri Kaloran" class="w-full h-full object-contain" onerror="this.onerror=null; this.parentElement.innerHTML='<i class=\'fa-solid fa-school text-amber-400 text-xl\'></i>';"> </div> <div> <div class="flex items-center gap-2"> <span class="text-[10px] font-extrabold uppercase px-2 py-0.5 bg-amber-500/20 text-amber-300 border border-amber-500/40 rounded-full tracking-wider">SD Negeri Kaloran</span> </div> <h1 class="text-base sm:text-lg font-bold bg-gradient-to-r from-amber-300 via-emerald-300 to-teal-200 bg-clip-text text-transparent"> Lompat Bintang Islam </h1> </div> </div> <!-- Audio Settings Controls --> <div class="flex items-center gap-2"> <button id="bgmToggleBtn" onclick="toggleBGM()" class="p-2.5 px-3 bg-slate-800 hover:bg-slate-700 border border-slate-600/50 rounded-xl text-amber-400 transition flex items-center gap-2 text-sm"> <i id="bgmIcon" class="fa-solid fa-music"></i> <span class="hidden md:inline text-xs font-semibold">Musik</span> </button> <button id="sfxToggleBtn" onclick="toggleSFX()" class="p-2.5 px-3 bg-slate-800 hover:bg-slate-700 border border-slate-600/50 rounded-xl text-emerald-400 transition flex items-center gap-2 text-sm"> <i id="sfxIcon" class="fa-solid fa-volume-high"></i> <span class="hidden md:inline text-xs font-semibold">Efek</span> </button> </div> </header> <main class="w-full max-w-5xl mx-auto p-3 sm:p-6 flex-1 flex flex-col justify-center items-center"> <!-- SCREEN 1: LOBBY & SETUP PLAYER --> <div id="setupScreen" class="w-full max-w-xl glass-panel p-6 sm:p-8 rounded-3xl shadow-2xl border border-emerald-500/20 text-center animate-fade-in"> <!-- School Emblem Banner --> <div class="flex flex-col items-center justify-center mb-6"> <div class="w-24 h-24 sm:w-28 sm:h-28 rounded-2xl bg-slate-900/90 border-2 border-amber-400/80 p-2 shadow-2xl shadow-amber-500/20 mb-3 flex items-center justify-center"> <img src="WhatsApp Image 2026-08-01 at 11.22.56.jpeg" alt="Logo SD Negeri Kaloran" class="w-full h-full object-contain" onerror="this.onerror=null; this.parentElement.innerHTML='<i class=\'fa-solid fa-school text-amber-400 text-4xl\'></i>';"> </div> <h2 class="text-2xl sm:text-3xl font-black text-amber-300 tracking-wide uppercase">SD NEGERI KALORAN</h2> <span class="text-xs font-bold text-emerald-400 tracking-widest uppercase mt-1 px-3 py-1 bg-emerald-950/60 border border-emerald-500/40 rounded-full"> BERILMU &bull; BERKARAKTER &bull; BERPRESTASI </span> </div> <div class="mb-6 border-t border-slate-700/60 pt-4"> <span class="inline-block px-3 py-1 bg-emerald-500/10 text-emerald-400 border border-emerald-500/30 rounded-full text-xs font-bold uppercase tracking-wider mb-2"> Multiplayer 1 - 4 Pemain &bull; Powered by Gemini AI </span> <h3 class="text-xl font-extrabold text-white">Petualangan Lompat Bintang Islam</h3> <p class="text-xs sm:text-sm text-slate-300 mt-1">Jawab kuis agama Islam dan kumpulkan poin Pahala setinggi-tingginya!</p> </div> <!-- Quiz Mode Selection: Standard vs Gemini AI --> <div class="mb-6 bg-slate-900/60 p-3 rounded-2xl border border-slate-700/80 text-left"> <label class="block text-xs font-bold text-amber-400 uppercase tracking-wider mb-2 flex items-center gap-1.5"> <i class="fa-solid fa-wand-magic-sparkles"></i> Pilih Sumber Soal Kuis </label> <div class="grid grid-cols-2 gap-2 mb-3"> <button id="modeStandardBtn" onclick="selectQuizMode('standard')" class="p-2.5 rounded-xl bg-emerald-600 text-white font-bold text-xs border-2 border-emerald-400 transition flex items-center justify-center gap-2"> <i class="fa-solid fa-book"></i> Bank Soal Standar </button> <button id="modeAIBtn" onclick="selectQuizMode('ai')" class="p-2.5 rounded-xl bg-slate-800 text-slate-300 font-bold text-xs border border-slate-700 hover:bg-slate-700 transition flex items-center justify-center gap-2"> <i class="fa-solid fa-robot"></i> Generasi Kuis AI </button> </div> <!-- AI Topic & Difficulty Options (Hidden by default) --> <div id="aiQuizConfig" class="hidden space-y-3 pt-2 border-t border-slate-700/60"> <div> <label class="block text-[11px] font-bold text-slate-400 mb-1">Topik Kuis Agama Islam</label> <select id="aiTopicSelect" class="w-full bg-slate-800 border border-slate-600 text-slate-200 text-xs rounded-xl p-2.5 focus:outline-none focus:border-amber-400"> <option value="Kisah Para Nabi & Rasul">Kisah 25 Nabi & Rasul</option> <option value="Rukun Islam & Tata Cara Shalat">Rukun Islam, Wudhu & Shalat</option> <option value="Akhlak Terpuji & Adab Islam">Akhlak Terpuji & Adab Harian</option> <option value="Sejarah Peradaban Islam">Sejarah Peradaban Islam & Sahabat</option> <option value="Hafalan Surat Pendek & Tajwid">Surat Pendek & Tajwid Ringkas</option> </select> </div> <div> <label class="block text-[11px] font-bold text-slate-400 mb-1">Tingkat Kesulitan</label> <select id="aiDifficultySelect" class="w-full bg-slate-800 border border-slate-600 text-slate-200 text-xs rounded-xl p-2.5 focus:outline-none focus:border-amber-400"> <option value="Mudah (Anak SD Kelas 1-3)">Mudah (Anak SD Kelas 1-3)</option> <option value="Sedang (Anak SD Kelas 4-6)" selected>Sedang (Anak SD Kelas 4-6)</option> <option value="Tantangan (SMP / Umum)">Tantangan (SMP / Umum)</option> </select> </div> </div> </div> <!-- Player Count Selection --> <div class="mb-6"> <label class="block text-xs font-bold text-slate-400 uppercase tracking-wider mb-3">Pilih Jumlah Pemain</label> <div class="grid grid-cols-4 gap-2 sm:gap-3"> <button onclick="setPlayerCount(1)" id="pCountBtn1" class="player-count-btn p-3 rounded-2xl bg-emerald-600 text-white font-bold border-2 border-emerald-400 transition shadow-lg">1</button> <button onclick="setPlayerCount(2)" id="pCountBtn2" class="player-count-btn p-3 rounded-2xl bg-slate-800 text-slate-300 font-bold border border-slate-700 hover:bg-slate-700 transition">2</button> <button onclick="setPlayerCount(3)" id="pCountBtn3" class="player-count-btn p-3 rounded-2xl bg-slate-800 text-slate-300 font-bold border border-slate-700 hover:bg-slate-700 transition">3</button> <button onclick="setPlayerCount(4)" id="pCountBtn4" class="player-count-btn p-3 rounded-2xl bg-slate-800 text-slate-300 font-bold border border-slate-700 hover:bg-slate-700 transition">4</button> </div> </div> <!-- Player Names Input List --> <div id="playerInputsContainer" class="space-y-3 mb-8 text-left"> <!-- Dynamic Player Inputs Inserted Here --> </div> <button onclick="startGame()" class="w-full py-4 bg-gradient-to-r from-emerald-500 via-teal-500 to-amber-500 hover:from-emerald-400 hover:to-amber-400 text-slate-950 font-black text-lg rounded-2xl shadow-xl shadow-emerald-500/25 btn-bounce flex items-center justify-center gap-2"> <i class="fa-solid fa-play"></i> MULAI PETUALANGAN </button> </div> <!-- SCREEN 2: GAMEPLAY CONTAINER (QUIZ + LOMPAT CANVAS) --> <div id="gameplayScreen" class="w-full hidden flex-col items-center"> <!-- Top Turn Status Header --> <div class="w-full max-w-4xl glass-panel p-4 rounded-2xl mb-4 flex flex-wrap justify-between items-center gap-3 border-b-2 border-amber-500/40"> <div class="flex items-center gap-3"> <div id="activePlayerAvatar" class="w-12 h-12 rounded-xl flex items-center justify-center text-2xl border-2 shadow-md"> <!-- SVG / Icon Avatar --> </div> <div> <span class="text-xs text-slate-400 font-bold uppercase tracking-wider block">Giliran Pemain</span> <h3 id="activePlayerName" class="text-lg font-extrabold text-amber-300">Pemain 1</h3> </div> </div> <div class="flex items-center gap-6"> <div class="text-right"> <span class="text-xs text-slate-400 font-bold block">Soal Ke</span> <span id="questionNumBadge" class="text-base font-extrabold text-emerald-400">1 / 10</span> </div> <div class="text-right border-l border-slate-700 pl-6"> <span class="text-xs text-slate-400 font-bold block">Pahala (Skor)</span> <span id="activePlayerScore" class="text-xl font-black text-amber-400">0</span> </div> </div> </div> <!-- Grid Content: Canvas Jump Engine Left/Top, Quiz Form Right/Bottom --> <div class="w-full max-w-4xl grid grid-cols-1 md:grid-cols-12 gap-4 items-start"> <!-- CANVAS LOMPAT CHAR (8 Cols Desktop) --> <div class="md:col-span-7 w-full flex flex-col items-center"> <div class="relative w-full aspect-[4/5] sm:aspect-[4/4] bg-slate-950 rounded-3xl overflow-hidden border-2 border-slate-700 shadow-2xl"> <!-- HUD Canvas Overlay --> <div class="absolute top-3 left-3 right-3 flex justify-between items-center z-10 pointer-events-none"> <span id="canvasPhaseBadge" class="px-3 py-1 bg-slate-900/80 backdrop-blur border border-amber-500/30 text-amber-300 rounded-full text-xs font-bold"> Phase: Menjawab Kuis </span> <span id="heightMeter" class="px-3 py-1 bg-slate-900/80 backdrop-blur border border-emerald-500/30 text-emerald-400 rounded-full text-xs font-bold"> Tinggi: 0 m </span> </div> <canvas id="gameCanvas" class="w-full h-full block cursor-pointer"></canvas> <!-- Mobile Touch Jump Controls Overlay --> <div id="touchControls" class="absolute bottom-3 left-3 right-3 flex justify-between gap-3 pointer-events-auto opacity-80 md:hidden"> <button id="btnLeft" class="flex-1 py-3 bg-slate-800/80 border border-slate-600 rounded-2xl text-2xl text-white active:bg-amber-500 active:text-slate-950"> <i class="fa-solid fa-arrow-left"></i> </button> <button id="btnRight" class="flex-1 py-3 bg-slate-800/80 border border-slate-600 rounded-2xl text-2xl text-white active:bg-amber-500 active:text-slate-950"> <i class="fa-solid fa-arrow-right"></i> </button> </div> </div> <p class="text-xs text-slate-400 mt-2 text-center hidden md:block"> <i class="fa-solid fa-keyboard mr-1"></i> Gunakan Tombol Panah <span class="text-amber-400 font-bold">&larr; / &rarr;</span> atau tombol <span class="text-amber-400 font-bold">A / D</span> untuk bergerak saat melompat. </p> </div> <!-- QUIZ QUESTION PANEL (5 Cols Desktop) --> <div class="md:col-span-5 w-full glass-panel p-5 rounded-3xl border border-slate-700/80 flex flex-col justify-between h-full min-h-[380px]"> <div id="quizContainer"> <div class="flex justify-between items-center mb-3"> <span id="categoryBadge" class="text-xs font-bold text-teal-400 uppercase tracking-wide bg-teal-950/60 border border-teal-800/50 px-2.5 py-1 rounded-lg"> Materi Agama Islam </span> <!-- Timer Countdown --> <div id="quizTimer" class="flex items-center gap-1.5 text-amber-400 font-bold text-sm"> <i class="fa-solid fa-stopwatch"></i> <span id="timerVal">15</span>s </div> </div> <!-- Question Text --> <h4 id="questionText" class="text-base sm:text-lg font-extrabold text-white mb-3 leading-snug"> Memuat pertanyaan... </h4> <!-- AI Hint Button --> <button id="aiHintBtn" onclick="fetchAIHint()" class="mb-3 w-full py-1.5 px-3 bg-amber-500/10 hover:bg-amber-500/20 border border-amber-500/30 text-amber-300 hover:text-amber-200 rounded-xl text-xs font-bold transition flex items-center justify-center gap-1.5"> <i class="fa-solid fa-lightbulb text-amber-400"></i> Minta Petunjuk Ustaz AI </button> <!-- Answer Options --> <div id="optionsContainer" class="space-y-2.5"> <!-- Dynamic Options Button List --> </div> </div> <!-- Feedback / Jump Action Overlay Panel --> <div id="jumpActionPanel" class="hidden flex-col items-center justify-center text-center p-4 bg-slate-900/90 rounded-2xl border border-amber-500/30"> <div id="feedbackIcon" class="text-4xl mb-2"></div> <h4 id="feedbackTitle" class="text-lg font-bold text-white mb-1"> Jawaban Benar!</h4> <p id="feedbackDesc" class="text-xs text-slate-300 mb-3">Lompatan Super terbuka! Bersiaplah melompat setinggi mungkin!</p> <button onclick="fetchAIExplanation()" class="w-full mb-2.5 py-2 px-3 bg-teal-500/10 hover:bg-teal-500/20 border border-teal-500/30 text-teal-300 rounded-xl text-xs font-bold transition flex items-center justify-center gap-2"> <i class="fa-solid fa-graduation-cap"></i> Penjelasan Hikmah Ustaz AI </button> <button id="startJumpBtn" onclick="triggerJumpPhase()" class="w-full py-3 bg-amber-500 hover:bg-amber-400 text-slate-950 font-black rounded-xl shadow-lg shadow-amber-500/20 btn-bounce flex items-center justify-center gap-2"> <i class="fa-solid fa-person-running"></i> MULAI MELOMPAT! </button> </div> </div> </div> </div> <!-- SCREEN 3: GAME OVER / LEADERBOARD --> <div id="resultScreen" class="w-full max-w-xl glass-panel p-6 sm:p-8 rounded-3xl shadow-2xl border border-amber-500/30 text-center hidden animate-fade-in"> <div class="w-20 h-20 bg-slate-900 border-2 border-amber-400 text-amber-400 rounded-2xl flex items-center justify-center p-2 mx-auto mb-3 shadow-xl shadow-amber-500/20"> <img src="WhatsApp Image 2026-08-01 at 11.22.56.jpeg" alt="SD Negeri Kaloran" class="w-full h-full object-contain" onerror="this.onerror=null; this.parentElement.innerHTML='<i class=\'fa-solid fa-trophy text-4xl text-amber-400\'></i>';"> </div> <span class="text-xs font-bold text-emerald-400 tracking-wider uppercase block mb-1">SD NEGERI KALORAN</span> <h2 class="text-3xl font-black text-white mb-1">Hasil Pertandingan!</h2> <p class="text-xs text-slate-400 mb-6">Selamat! Kalian telah menyelesaikan Soal Kuis Agama Islam.</p> <!-- Leaderboard List --> <div id="leaderboardList" class="space-y-3 mb-8"> <!-- Dynamic Ranks Inserted Here --> </div> <button onclick="resetToLobby()" class="w-full py-4 bg-gradient-to-r from-emerald-500 to-teal-500 text-slate-950 font-black text-lg rounded-2xl shadow-xl btn-bounce"> <i class="fa-solid fa-rotate-right mr-2"></i> MAIN LAGI </button> </div> </main> <!-- GEMINI AI DIALOG MODAL --> <div id="aiModal" class="fixed inset-0 bg-slate-950/80 backdrop-blur-md z-50 flex items-center justify-center p-4 hidden animate-fade-in"> <div class="glass-panel max-w-md w-full p-6 rounded-3xl border border-amber-500/40 shadow-2xl relative text-left"> <button onclick="closeAIModal()" class="absolute top-4 right-4 w-8 h-8 rounded-full bg-slate-800 text-slate-400 hover:text-white flex items-center justify-center transition"> <i class="fa-solid fa-xmark"></i> </button> <div class="flex items-center gap-3 mb-4"> <div class="w-10 h-10 rounded-2xl bg-amber-500/20 border border-amber-500/40 text-amber-400 flex items-center justify-center text-xl shadow-lg"> <i class="fa-solid fa-robot"></i> </div> <div> <h3 id="aiModalTitle" class="text-base font-extrabold text-white">Ustaz AI Bintang</h3> <p class="text-xs text-amber-400 font-medium">Bimbingan Belajar Agama Islam</p> </div> </div> <!-- Modal Dynamic Content / Spinner --> <div id="aiModalContent" class="text-xs sm:text-sm text-slate-200 leading-relaxed min-h-[90px] flex items-center justify-center"> <!-- Dynamic text or loading state inserted here --> </div> <div class="mt-5 text-right"> <button onclick="closeAIModal()" class="py-2.5 px-5 bg-amber-500 hover:bg-amber-400 text-slate-950 font-bold rounded-xl text-xs transition shadow-lg"> Mengerti <i class="fa-solid fa-check ml-1"></i> </button> </div> </div> </div> <!-- FOOTER --> <footer class="w-full text-center py-3 text-xs text-slate-500 border-t border-slate-800/80"> &copy; 2026 SD Negeri Kaloran &bull; Game Edukasi Lompat Bintang Islam </footer> <script> /* =================================================================== * AUDIO ENGINE (Web Audio API - Synthesizer BGM & SFX tanpa link external) * =================================================================== */ let audioCtx = null; let bgmInterval = null; let bgmEnabled = true; let sfxEnabled = true; function initAudio() { if (!audioCtx) { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } if (audioCtx.state === 'suspended') { audioCtx.resume(); } } // SFX Generator function playSound(type) { if (!sfxEnabled) return; initAudio(); const now = audioCtx.currentTime; const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.connect(gain); gain.connect(audioCtx.destination); if (type === 'jump') { osc.type = 'sine'; osc.frequency.setValueAtTime(180, now); osc.frequency.exponentialRampToValueAtTime(450, now + 0.15); gain.gain.setValueAtTime(0.3, now); gain.gain.linearRampToValueAtTime(0.01, now + 0.15); osc.start(now); osc.stop(now + 0.15); } else if (type === 'correct') { osc.type = 'triangle'; osc.frequency.setValueAtTime(523.25, now); // C5 osc.frequency.setValueAtTime(659.25, now + 0.1); // E5 osc.frequency.setValueAtTime(783.99, now + 0.2); // G5 gain.gain.setValueAtTime(0.25, now); gain.gain.linearRampToValueAtTime(0.01, now + 0.35); osc.start(now); osc.stop(now + 0.35); } else if (type === 'wrong') { osc.type = 'sawtooth'; osc.frequency.setValueAtTime(220, now); osc.frequency.setValueAtTime(180, now + 0.12); gain.gain.setValueAtTime(0.3, now); gain.gain.linearRampToValueAtTime(0.01, now + 0.3); osc.start(now); osc.stop(now + 0.3); } else if (type === 'coin') { osc.type = 'sine'; osc.frequency.setValueAtTime(987.77, now); osc.frequency.setValueAtTime(1318.51, now + 0.08); gain.gain.setValueAtTime(0.2, now); gain.gain.linearRampToValueAtTime(0.01, now + 0.2); osc.start(now); osc.stop(now + 0.2); } } // Procedural Ambient Music Generator (Pentatonic Islamic Feel) function startBGM() { if (bgmInterval || !bgmEnabled) return; initAudio(); const notes = [261.63, 293.66, 329.63, 392.00, 440.00, 523.25]; // Pentatonic notes let idx = 0; bgmInterval = setInterval(() => { if (!bgmEnabled || !audioCtx) return; const now = audioCtx.currentTime; const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.type = 'sine'; const freq = notes[Math.floor(Math.random() * notes.length)]; osc.frequency.setValueAtTime(freq, now); gain.gain.setValueAtTime(0.03, now); gain.gain.exponentialRampToValueAtTime(0.001, now + 0.8); osc.connect(gain); gain.connect(audioCtx.destination); osc.start(now); osc.stop(now + 0.8); }, 600); } function stopBGM() { if (bgmInterval) { clearInterval(bgmInterval); bgmInterval = null; } } function toggleBGM() { bgmEnabled = !bgmEnabled; const icon = document.getElementById('bgmIcon'); if (bgmEnabled) { icon.className = "fa-solid fa-music"; startBGM(); } else { icon.className = "fa-solid fa-volume-xmark"; stopBGM(); } } function toggleSFX() { sfxEnabled = !sfxEnabled; const icon = document.getElementById('sfxIcon'); icon.className = sfxEnabled ? "fa-solid fa-volume-high" : "fa-solid fa-volume-xmark"; } /* =================================================================== * ISLAMIC QUIZ BANK (10 Core Agama Islam Questions) * =================================================================== */ const QUESTION_BANK = [ { q: "Rukun Islam yang ke-3 adalah...", options: ["Membayar Zakat", "Menjalankan Puasa Ramadan", "Mengucapkan Syahadat", "Mengerjakan Shalat"], answer: 1, explanation: "Rukun Islam ke-3 adalah menunaikan Puasa pada bulan Ramadan." }, { q: "Kitab suci yang diturunkan kepada Nabi Muhammad SAW adalah...", options: ["Taurat", "Zabur", "Injil", "Al-Qur'an"], answer: 3, explanation: "Al-Qur'an adalah mukjizat terbesar dan kitab suci terakhir yang diwahyukan kepada Nabi Muhammad SAW." }, { q: "Siapakah Nabi pertama yang diciptakan oleh Allah SWT?", options: ["Nabi Adam a.s.", "Nabi Ibrahim a.s.", "Nabi Nuh a.s.", "Nabi Musa a.s."], answer: 0, explanation: "Nabi Adam a.s. adalah manusia pertama sekaligus nabi pertama di bumi." }, { q: "Shalat fardhu yang berjumlah 3 rakaat dalam sehari semalam adalah shalat...", options: ["Subuh", "Dzuhur", "Maghrib", "Isya"], answer: 2, explanation: "Shalat Maghrib dikerjakan sebanyak 3 rakaat." }, { q: "Malaikat yang bertugas menyampaikan wahyu dari Allah SWT adalah...", options: ["Malaikat Mikail", "Malaikat Jibril", "Malaikat Israfil", "Malaikat Izrail"], answer: 1, explanation: "Malaikat Jibril bertugas menyampaikan wahyu kepada para nabi dan rasul." }, { q: "Kota suci umat Islam tempat berdirinya Ka'bah adalah...", options: ["Madinah", "Yerusalem", "Makkah", "Kairo"], answer: 2, explanation: "Ka'bah terletak di Masjidil Haram, Makkah Al-Mukarramah." }, { q: "Peristiwa Isra' Mi'raj memperingati perintah wajib shalat sebanyak...", options: ["3 Waktu", "5 Waktu", "7 Waktu", "10 Waktu"], answer: 1, explanation: "Melalui peristiwa Isra' Mi'raj, Nabi Muhammad SAW menerima perintah shalat 5 waktu." }, { q: "Surah pertama yang diwahyukan kepada Nabi Muhammad SAW di Gua Hira adalah...", options: ["Surah Al-Fatihah", "Surah Al-Ikhlas", "Surah Al-'Alaq", "Surah Al-Baqarah"], answer: 2, explanation: "Ayat 1-5 Surah Al-'Alaq ('Iqra') adalah wahyu pertama yang turun." }, { q: "Sifat wajib bagi Rasul 'Siddiq' artinya adalah...", options: ["Dapat dipercaya", "Cerdas", "Jujur / Benar", "Menyampaikan"], answer: 2, explanation: "Siddiq artinya selalu berkata benar / jujur." }, { q: "Hari Raya umat Islam yang dirayakan setelah menunaikan puasa Ramadan adalah...", options: ["Idul Adha", "Idul Fitri", "Tahun Baru Hijriah", "Maulid Nabi"], answer: 1, explanation: "Idul Fitri dirayakan pada tanggal 1 Syawal setelah sebulan berpuasa." } ]; // Player Avatars List const AVATARS = [ { name: "Ahmad", color: "#10b981", bgClass: "bg-emerald-500/20 text-emerald-400 border-emerald-500", icon: "fa-user-ninja" }, { name: "Aisyah", color: "#f59e0b", bgClass: "bg-amber-500/20 text-amber-400 border-amber-500", icon: "fa-graduation-cap" }, { name: "Bilal", color: "#06b6d4", bgClass: "bg-cyan-500/20 text-cyan-400 border-cyan-500", icon: "fa-star" }, { name: "Fatimah", color: "#ec4899", bgClass: "bg-pink-500/20 text-pink-400 border-pink-500", icon: "fa-heart" } ]; /* =================================================================== * GAME STATE VARIABLES * =================================================================== */ let playerCount = 1; let players = []; let currentQuestionIdx = 0; let currentPlayerTurnIdx = 0; let timerInterval = null; let timeLeft = 15; let jumpBoostPower = 1; let quizMode = 'standard'; // 'standard' or 'ai' let activeQuestionBank = [...QUESTION_BANK]; const GEMINI_MODEL = "gemini-3-flash-preview"; const API_KEY = ""; // Injected by Canvas runtime environment const API_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${API_KEY}`; // Helper function for Gemini API call with Exponential Backoff async function fetchGemini(payload, retries = 3, delay = 1000) { for (let i = 0; i < retries; i++) { try { const response = await fetch(API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (err) { if (i === retries - 1) throw err; await new Promise(r => setTimeout(r, delay * Math.pow(2, i))); } } } function selectQuizMode(mode) { quizMode = mode; const btnStd = document.getElementById('modeStandardBtn'); const btnAI = document.getElementById('modeAIBtn'); const configBox = document.getElementById('aiQuizConfig'); if (mode === 'ai') { btnAI.className = "p-2.5 rounded-xl bg-amber-600 text-white font-bold text-xs border-2 border-amber-400 transition flex items-center justify-center gap-2 shadow-lg shadow-amber-500/20"; btnStd.className = "p-2.5 rounded-xl bg-slate-800 text-slate-300 font-bold text-xs border border-slate-700 hover:bg-slate-700 transition flex items-center justify
80
Linggar Dyah Kusuma Wati,S.Pd.SD Negeri 2 Mento199206022022212021Buka LinkBuka Link
81
Tini Rahayu, S. PdSD Negeri 2 Mento197009251996032003Buka LinkBuka Link
82
TRI CAHYO SARJANA PUTRA., S.PdSD NEGERI KALORAN-Buka LinkBuka Link
83
ALIP PRAPTIWI,S.PdSD Negeri 2 Wonoharjo198512292022212028Buka LinkBuka Link
84
SUHARYANTI,S.Pd.SD.SD Negeri 3 Wonoboyo197807182022212003Buka LinkBuka Link
85
YUSELG PUTRIKAM IKHTIARI, S.Pd.SD NEGERI KALORAN199407262022212006Buka LinkBuka Link
86
Mulatsih Ari Widya Pangestika, S.Pd.SD Negeri 2 Wonoharjo199201152022212015Buka LinkBuka Link
87
NIKEN NOVITASARI, S. PdSD Negeri 2 Giripurwo198711252009032001Buka LinkBuka Link
88
Anik Nia Kusmayanti, S.Pd.SD Negeri 1 Manjung198001132021212007Buka LinkBuka Link
89
Agina Fitri Pratiwi,S.Pd.SDSD Negeri Ketimang198705152009032005Buka LinkBuka Link
90
DWI RETNO WIJAYANTI , S.PdSD NEGERI KALORAN196812211993012001Buka Link
<!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Lompat Bintang Islami - Game Edukasi Agama Islam AI</title> <!-- Tailwind CSS for styling --> <script src="https://cdn.tailwindcss.com"></script> <!-- Tone.js for web audio music and sound effects --> <script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script> <!-- Font Inter & Lexend for modern typography --> <link href="https://fonts.googleapis.com/css2?family=Fredoka+One&family=Lexend:wght@400;600;700;800&display=swap" rel="stylesheet"> <style> body { font-family: 'Lexend', sans-serif; user-select: none; -webkit-user-select: none; } .font-game { font-family: 'Fredoka One', cursive; } /* Custom scrollbars */ ::-webkit-scrollbar { width: 8px; } ::-webkit-scrollbar-track { background: rgba(15, 23, 42, 0.6); } ::-webkit-scrollbar-thumb { background: #3b82f6; border-radius: 4px; } /* Sparkle pulse animation */ @keyframes pulseGlow { 0%, 100% { opacity: 0.6; transform: scale(1); } 50% { opacity: 1; transform: scale(1.15); } } .animate-glow { animation: pulseGlow 2s infinite ease-in-out; } /* Bounce jump keyframe */ @keyframes characterJump { 0% { transform: translateY(0) scale(1, 1); } 30% { transform: translateY(-80px) scale(0.9, 1.1); } 70% { transform: translateY(-110px) scale(1.05, 0.95); } 100% { transform: translateY(-140px) scale(1, 1); } } .animate-jump { animation: characterJump 0.8s ease-out forwards; } /* Loading pulse shine */ @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } .animate-shimmer { background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0) 100%); background-size: 200% 100%; animation: shimmer 1.5s infinite; } </style> </head> <body class="bg-slate-900 text-white min-h-screen flex flex-col justify-between overflow-x-hidden relative selection:bg-amber-400 selection:text-slate-900"> <!-- Background Gradient & Decorative Stars --> <div class="fixed inset-0 bg-gradient-to-b from-indigo-950 via-slate-900 to-emerald-950 -z-20 pointer-events-none"></div> <div id="stars-container" class="fixed inset-0 pointer-events-none -z-10 opacity-70"></div> <!-- Header Navigation Bar --> <header class="w-full max-w-5xl mx-auto px-4 py-3 flex items-center justify-between z-30"> <div class="flex items-center space-x-3"> <div class="w-10 h-10 bg-amber-400 rounded-2xl flex items-center justify-center shadow-lg shadow-amber-500/30 text-slate-900 font-bold text-xl"> ☪ </div> <div> <div class="flex items-center gap-2"> <h1 class="font-game text-xl md:text-2xl text-amber-300 tracking-wide">Lompat Bintang Islami</h1> <span class="px-2 py-0.5 bg-gradient-to-r from-purple-600 to-indigo-600 text-[10px] font-bold rounded-full border border-purple-400/40 text-purple-200">AI Powered</span> </div> <p class="text-xs text-slate-300">Petualangan Edukasi Islam 1 - 4 Pemain</p> </div> </div> <!-- Sound Controls --> <div class="flex items-center space-x-2"> <button id="btn-sound" onclick="toggleAudio()" class="px-4 py-2 bg-slate-800/80 hover:bg-slate-700 text-amber-300 rounded-xl text-sm font-semibold border border-amber-400/30 flex items-center gap-2 transition active:scale-95 shadow-md"> <span id="sound-icon">🔊</span> <span id="sound-text">Musik: ON</span> </button> </div> </header> <!-- MAIN CONTAINER --> <main class="flex-1 w-full max-w-5xl mx-auto p-4 flex flex-col items-center justify-center relative z-20"> <!-- SCREEN 1: PLAYER SETUP & GAME MODE MENU --> <div id="screen-setup" class="w-full max-w-2xl bg-slate-800/90 backdrop-blur-md rounded-3xl p-6 md:p-8 border border-amber-400/20 shadow-2xl flex flex-col items-center text-center"> <div class="w-20 h-20 bg-gradient-to-tr from-amber-400 to-yellow-200 rounded-full flex items-center justify-center shadow-xl shadow-amber-400/20 mb-3 animate-glow"> <svg class="w-12 h-12 text-slate-900" fill="currentColor" viewBox="0 0 24 24"> <path d="M12 2L14.5 8.5L21.5 9L16 14L17.8 21L12 17.2L6.2 21L8 14L2.5 9L9.5 8.5L12 2Z"/> </svg> </div> <h2 class="font-game text-3xl md:text-4xl text-amber-300 mb-1">Selamat Datang, Bintang Kecil!</h2> <p class="text-slate-300 text-sm md:text-base max-w-md mb-6"> Jawab pertanyaan agama Islam dengan tepat untuk melompat menembus awan dan meraih puncak **Jannah Sky**! </p> <!-- Mode Selector Tabs --> <div class="w-full bg-slate-900/80 p-1.5 rounded-2xl border border-slate-700/80 flex gap-2 mb-6"> <button id="mode-btn-standard" onclick="setQuizMode('standard')" class="flex-1 py-2.5 rounded-xl font-bold text-xs md:text-sm transition-all bg-amber-400 text-slate-950 shadow"> 📚 Soal Standar (10 Soal) </button> <button id="mode-btn-ai" onclick="setQuizMode('ai')" class="flex-1 py-2.5 rounded-xl font-bold text-xs md:text-sm transition-all text-slate-400 hover:text-white flex items-center justify-center gap-1.5"> ✨ Mode AI Custom </button> </div> <!-- AI Quiz Customizer Panel (Hidden by default) --> <div id="ai-customizer-panel" class="w-full bg-slate-900/60 border border-purple-500/30 p-4 rounded-2xl mb-6 text-left hidden"> <div class="flex items-center gap-2 mb-3"> <span class="text-purple-300 text-lg">🤖</span> <h3 class="font-bold text-sm text-purple-200">Pengaturan Kuis AI Gemini</h3> </div> <div class="grid grid-cols-1 sm:grid-cols-2 gap-3 mb-3"> <div> <label class="block text-xs font-semibold text-slate-300 mb-1">Topik Pembelajaran Agama:</label> <select id="ai-topic" class="w-full bg-slate-800 border border-slate-700 rounded-xl px-3 py-2 text-xs font-semibold text-amber-300 focus:outline-none focus:border-amber-400"> <option value="Kisah Para Nabi dan Rasul">Kisah Para Nabi & Rasul</option> <option value="Fiqih Sholat dan Thaharah">Fiqih Sholat & Thaharah</option> <option value="Akhlak Terpuji dan Adab Anak Muslim">Akhlak & Adab Muslim</option> <option value="Al-Qur'an dan Hafalan Surah Pendek">Al-Qur'an & Surah Pendek</option> <option value="Sejarah Kebudayaan Islam (SKI)">Sejarah Kebudayaan Islam</option> <option value="Rukun Iman dan Asmaul Husna">Rukun Iman & Asmaul Husna</option> </select> </div> <div> <label class="block text-xs font-semibold text-slate-300 mb-1">Tingkat Kesulitan Keseluruhan:</label> <select id="ai-difficulty" class="w-full bg-slate-800 border border-slate-700 rounded-xl px-3 py-2 text-xs font-semibold text-amber-300 focus:outline-none focus:border-amber-400"> <option value="Mudah untuk Anak SD Cilik">Mudah (SD Cilik / Pemula)</option> <option value="Sedang untuk Santri Utama">Sedang (Santri / SMP)</option> <option value="Tantangan Tinggi">Tantangan Cendekia</option> </select> </div> </div> <p class="text-[11px] text-purple-300/80 italic">Gemini API akan meracik 10 pertanyaan khusus secara interaktif sesuai topik pilihanmu!</p> </div> <!-- Number of Players Selector --> <div class="w-full mb-6"> <label class="block text-slate-300 text-xs font-bold mb-2 uppercase tracking-wider">Pilih Jumlah Pemain (1-4 Orang)</label> <div class="grid grid-cols-4 gap-3 max-w-xs mx-auto"> <button onclick="selectPlayerCount(1)" id="pcount-1" class="btn-pcount py-3 rounded-2xl bg-amber-400 text-slate-950 font-bold text-lg border-2 border-amber-300 shadow-lg hover:scale-105 transition">1</button> <button onclick="selectPlayerCount(2)" id="pcount-2" class="btn-pcount py-3 rounded-2xl bg-slate-700 text-slate-200 font-bold text-lg border-2 border-slate-600 shadow hover:scale-105 transition">2</button> <button onclick="selectPlayerCount(3)" id="pcount-3" class="btn-pcount py-3 rounded-2xl bg-slate-700 text-slate-200 font-bold text-lg border-2 border-slate-600 shadow hover:scale-105 transition">3</button> <button onclick="selectPlayerCount(4)" id="pcount-4" class="btn-pcount py-3 rounded-2xl bg-slate-700 text-slate-200 font-bold text-lg border-2 border-slate-600 shadow hover:scale-105 transition">4</button> </div> </div> <!-- Player Avatars Preview Grid --> <div id="player-names-container" class="w-full grid grid-cols-1 sm:grid-cols-2 gap-3 mb-8"> <!-- Dynamic Player Avatars Cards inserted by JS --> </div> <button id="btn-start-game" onclick="startGame()" class="w-full max-w-md py-4 bg-gradient-to-r from-amber-400 via-amber-500 to-yellow-500 hover:from-amber-300 hover:to-yellow-400 text-slate-950 font-bold font-game text-xl rounded-2xl shadow-xl shadow-amber-500/30 transform hover:-translate-y-1 transition active:translate-y-0 flex items-center justify-center gap-2"> <span>🚀 MULAI PETUALANGAN</span> </button> </div> <!-- SCREEN 2: GAMEPLAY & JUMP PLATFORM --> <div id="screen-game" class="w-full flex flex-col md:flex-row gap-6 hidden"> <!-- Left Side: Interactive Jump Canvas / Stage Visualizer --> <div class="w-full md:w-1/2 bg-slate-800/80 backdrop-blur-md rounded-3xl border border-amber-400/20 p-4 flex flex-col items-center justify-between min-h-[480px] relative overflow-hidden shadow-2xl"> <!-- Stage Sky Header --> <div class="w-full flex items-center justify-between z-10 bg-slate-900/60 p-3 rounded-2xl border border-slate-700/50"> <div class="flex items-center gap-2"> <span id="turn-badge" class="px-3 py-1 bg-amber-400 text-slate-950 rounded-full font-bold text-xs">Giliran: Pemain 1</span> </div> <div class="text-xs text-amber-300 font-semibold" id="question-tracker"> Pertanyaan: 1 / 10 </div> </div> <!-- Vertical Jump Tower Visual --> <div id="tower-container" class="w-full flex-1 relative flex flex-col justify-end items-center my-4 overflow-hidden min-h-[320px]"> <!-- Clouds & Sky Platforms --> <div class="absolute inset-0 flex flex-col justify-between items-center py-4 opacity-30 pointer-events-none"> <div class="text-xs text-amber-200 bg-amber-400/20 px-3 py-1 rounded-full">☁️ Level 10: Jannah Sky</div> <div class="text-xs text-emerald-200 bg-emerald-400/20 px-3 py-1 rounded-full">☁️ Level 7: Awan Ihsan</div> <div class="text-xs text-blue-200 bg-blue-400/20 px-3 py-1 rounded-full">☁️ Level 4: Awan Puasa</div> <div class="text-xs text-indigo-200 bg-indigo-400/20 px-3 py-1 rounded-full">☁️ Level 1: Bumi Kebaikan</div> </div> <!-- Visual Tower Platforms (Clouds/Stars) --> <div id="platform-stack" class="w-full h-full flex flex-col-reverse justify-start items-center gap-3 py-2 relative z-10"> <!-- Platforms generated dynamically --> </div> </div> <!-- Player Score Summary Row --> <div id="players-score-bar" class="w-full grid grid-cols-2 sm:grid-cols-4 gap-2 z-10"> <!-- Dynamic score badges for each player --> </div> </div> <!-- Right Side: Quiz & Question Panel with AI Assist --> <div class="w-full md:w-1/2 bg-slate-800/90 backdrop-blur-md rounded-3xl border border-amber-400/20 p-6 flex flex-col justify-between shadow-2xl relative"> <div> <!-- Active Player Header Card --> <div id="active-player-header" class="flex items-center justify-between p-3 bg-slate-900/80 rounded-2xl border border-amber-400/30 mb-4"> <div class="flex items-center gap-3"> <div id="active-player-avatar" class="w-12 h-12 rounded-xl bg-amber-400/20 p-1 flex items-center justify-center"> <!-- Active Avatar SVG --> </div> <div> <h3 id="active-player-name" class="font-game text-amber-300 text-lg">Ahmad</h3> <p class="text-xs text-slate-300">Siap melompat ke platform berikutnya!</p> </div> </div> <!-- AI Hint Button --> <button id="btn-ai-hint" onclick="getAIHint()" class="px-3 py-2 bg-purple-900/60 hover:bg-purple-800 text-purple-200 rounded-xl border border-purple-400/40 text-xs font-bold flex items-center gap-1.5 transition active:scale-95 shadow"> <span>💡 Hint AI</span> </button> </div> <!-- AI Hint Display Banner --> <div id="ai-hint-box" class="hidden p-3 bg-purple-950/80 rounded-2xl border border-purple-400/40 mb-4 text-xs text-purple-200 flex items-start gap-2"> <span class="text-base">🧙‍♂️</span> <div class="flex-1"> <div class="font-bold text-purple-300 mb-0.5">Petunjuk Ustadz AI:</div> <div id="ai-hint-text" class="leading-relaxed">Sedang memikirkan petunjuk...</div> </div> </div> <!-- Question Text Card --> <div class="bg-slate-900/60 p-5 rounded-2xl border border-slate-700/60 mb-4 min-h-[110px] flex items-center relative"> <p id="question-text" class="text-base md:text-lg font-semibold text-slate-100 leading-relaxed"> Loading pertanyaan... </p> </div> <!-- Answer Options Grid --> <div id="options-grid" class="grid grid-cols-1 gap-3 mb-4"> <!-- Options buttons populated dynamically --> </div> </div> <!-- Explanation / Feedback Banner --> <div id="feedback-banner" class="hidden p-4 rounded-2xl text-sm font-semibold border transition-all duration-300 mb-3"> <div class="flex justify-between items-start mb-1"> <div id="feedback-title" class="font-bold text-base"></div> <button id="btn-ai-expand" onclick="expandExplanationAI()" class="hidden px-2.5 py-1 bg-amber-400/20 hover:bg-amber-400/30 text-amber-300 border border-amber-400/40 rounded-lg text-[11px] font-bold flex items-center gap-1"> 📖 Hikmah AI Lebih Dalam </button> </div> <div id="feedback-text" class="text-xs opacity-90 leading-relaxed"></div> <!-- Extra AI Deep Explanation Box --> <div id="ai-deep-explanation" class="hidden mt-3 pt-2 border-t border-white/20 text-xs font-normal leading-relaxed text-amber-200"> </div> </div> <!-- Next Question Button --> <button id="btn-next" onclick="nextQuestion()" class="hidden w-full py-3.5 bg-amber-400 hover:bg-amber-300 text-slate-950 font-bold font-game rounded-xl shadow-lg shadow-amber-400/20 transition active:scale-95"> LANJUTKAN LOMPATAN ➡️ </button> </div> </div> <!-- SCREEN 3: GAME OVER & PODIUM --> <div id="screen-gameover" class="w-full max-w-2xl bg-slate-800/90 backdrop-blur-md rounded-3xl p-6 md:p-8 border border-amber-400/20 shadow-2xl flex flex-col items-center text-center hidden"> <div class="w-20 h-20 bg-gradient-to-tr from-amber-400 to-yellow-300 rounded-full flex items-center justify-center shadow-xl shadow-amber-400/30 mb-3 animate-bounce"> 🏆 </div> <h2 class="font-game text-3xl md:text-4xl text-amber-300 mb-1">Petualangan Selesai!</h2> <p class="text-slate-300 text-sm mb-6">Selamat kepada seluruh santri cilik atas ilmu dan keberhasilannya!</p> <!-- Leaderboard List --> <div id="leaderboard-container" class="w-full space-y-3 mb-6"> <!-- Dynamic Leaderboard Items --> </div> <!-- AI Prayer & Encouragement Box --> <div id="ai-doa-card" class="w-full bg-slate-900/80 border border-amber-400/40 p-4 rounded-2xl mb-6 text-left"> <div class="flex items-center gap-2 mb-2 text-amber-300 font-bold text-sm"> <span>✨</span> Doa & Nasihat Kelulusan dari Ustadz AI Gemini: </div> <div id="ai-doa-text" class="text-xs text-slate-200 italic leading-relaxed"> Sedang meracik doa dan ucapan selamat khusus dari AI... </div> </div> <!-- Action Buttons --> <div class="flex flex-col sm:flex-row gap-3 w-full max-w-md"> <button onclick="resetGame()" class="flex-1 py-3.5 bg-amber-400 hover:bg-amber-300 text-slate-950 font-bold font-game rounded-2xl shadow-lg transition"> 🔄 MAIN LAGI </button> </div> </div> </main> <!-- Footer --> <footer class="w-full text-center py-4 text-xs text-slate-500 z-10"> Game Edukasi Agama Islam &bull; Lompat Bintang Ceria AI &copy; 2026 </footer> <script> // Gemini API Config const apiKey = ""; const geminiApiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent?key=${apiKey}`; // Standard 10 Islamic Questions const standardIslamicQuestions = [ { q: "Rukun Islam yang pertama dan utama sebagai syarat menjadi muslim adalah...", options: ["Mendirikan Sholat", "Mengucapkan Dua Kalimat Syahadat", "Membayar Zakat", "Menjalankan Ibadah Haji"], correct: 1, exp: "Dua kalimat syahadat adalah persaksian bahwa tiada Tuhan selain Allah dan Nabi Muhammad SAW adalah utusan Allah." }, { q: "Kitab suci yang diturunkan oleh Allah SWT kepada Nabi Muhammad SAW adalah...", options: ["Taurat", "Zabur", "Injil", "Al-Qur'an"], correct: 3, exp: "Al-Qur'an adalah petunjuk hidup utama bagi umat Islam yang diturunkan secara bertahap kepada Nabi Muhammad SAW." }, { q: "Ibadah sholat fardhu yang berjumlah 4 rakaat dan dilaksanakan pada malam hari adalah...", options: ["Sholat Subuh", "Sholat Dzuhur", "Sholat Maghrib", "Sholat Isya"], correct: 3, exp: "Sholat Isya dilaksanakan pada waktu malam hari dengan jumlah 4 rakaat." }, { q: "Nabi yang dianugerahi mukjizat dapat membelah Laut Merah dengan tongkat atas izin Allah adalah...", options: ["Nabi Ibrahim A.S.", "Nabi Musa A.S.", "Nabi Isa A.S.", "Nabi Yunus A.S."], correct: 1, exp: "Nabi Musa A.S. membelah Laut Merah saat menyelamatkan kaumnya dari kejaran Raja Fir'aun." }, { q: "Menjalankan ibadah puasa di bulan Ramadhan bagi umat Islam yang berakal dan baligh hukumnya adalah...", options: ["Wajib", "Sunnah", "Makruh", "Mubah"], correct: 0, exp: "Puasa Ramadhan merupakan salah satu Rukun Islam yang hukumnya wajib dilaksanakan setiap tahun." }, { q: "Malaikat yang bertugas dari Allah SWT untuk menyampaikan wahyu kepada para Nabi dan Rasul adalah...", options: ["Malaikat Mikail", "Malaikat Israfil", "Malaikat Jibril", "Malaikat Izrail"], correct: 2, exp: "Malaikat Jibril adalah pemimpin para malaikat yang bertugas membawa wahyu Allah." }, { q: "Malaikat yang mencatat segala perbuatan dan amal BAIK manusia selama di dunia adalah...", options: ["Malaikat Raqib", "Malaikat 'Atid", "Malaikat Munkar", "Malaikat Nakir"], correct: 0, exp: "Malaikat Raqib bertugas mencatat amal kebaikan, sedangkan Malaikat 'Atid mencatat perbuatan buruk." }, { q: "Peristiwa luar biasa perjalanan malam Nabi Muhammad SAW dari Masjidil Haram ke Masjidil Aqsa lalu naik ke Sidratul Muntaha disebut...", options: ["Nuzulul Qur'an", "Isra Mi'raj", "Hijrah", "Maulid Nabi"], correct: 1, exp: "Isra Mi'raj adalah peristiwa agung di mana Nabi Muhammad SAW menerima perintah ibadah sholat 5 waktu." }, { q: "Tempat suci yang dipergunakan oleh umat Islam untuk beribadah secara berjamaah disebut...", options: ["Gereja", "Pura", "Vihara", "Masjid"], correct: 3, exp: "Masjid adalah rumah Allah yang suci bagi umat Islam untuk melaksanakan sholat dan kegiatan keagamaan." }, { q: "Rukun Iman yang ke-3 dalam ajaran agama Islam adalah beriman kepada...", options: ["Malaikat-Malaikat Allah", "Kitab-Kitab Allah", "Rasul-Rasul Allah", "Hari Kiamat"], correct: 1, exp: "Urutan Rukun Iman: 1. Allah, 2. Malaikat, 3. Kitab-kitab Allah, 4. Rasul, 5. Hari Kiamat, 6. Qada & Qadar." } ]; let activeQuestions = [...standardIslamicQuestions]; let quizMode = 'standard'; // 'standard' or 'ai' // Avatar SVG Definitions const AVATARS = [ { id: 'ahmad', name: 'Ahmad', color: 'bg-emerald-500', borderColor: 'border-emerald-400', svg: `<svg viewBox="0 0 100 100" class="w-full h-full"> <circle cx="50" cy="55" r="30" fill="#fcd34d"/> <path d="M 22 45 Q 50 20 78 45 Z" fill="#059669"/> <rect x="22" y="42" width="56" height="8" rx="2" fill="#047857"/> <circle cx="40" cy="55" r="4" fill="#0f172a"/> <circle cx="60" cy="55" r="4" fill="#0f172a"/> <path d="M 42 66 Q 50 74 58 66" fill="none" stroke="#0f172a" stroke-width="3" stroke-linecap="round"/> <circle cx="34" cy="62" r="3" fill="#f87171" opacity="0.6"/> <circle cx="66" cy="62" r="3" fill="#f87171" opacity="0.6"/> </svg>` }, { id: 'fatimah', name: 'Fatimah', color: 'bg-pink-500', borderColor: 'border-pink-400', svg: `<svg viewBox="0 0 100 100" class="w-full h-full"> <path d="M 20 50 Q 50 10 80 50 Q 85 85 50 90 Q 15 85 20 50 Z" fill="#ec4899"/> <circle cx="50" cy="52" r="22" fill="#fcd34d"/> <path d="M 28 50 Q 50 30 72 50 Q 72 70 50 74 Q 28 70 28 50 Z" fill="none" stroke="#db2777" stroke-width="4"/> <circle cx="42" cy="52" r="3.5" fill="#0f172a"/> <circle cx="58" cy="52" r="3.5" fill="#0f172a"/> <path d="M 44 62 Q 50 67 56 62" fill="none" stroke="#0f172a" stroke-width="2.5" stroke-linecap="round"/> <circle cx="36" cy="58" r="3" fill="#f43f5e" opacity="0.5"/> <circle cx="64" cy="58" r="3" fill="#f43f5e" opacity="0.5"/> </svg>` }, { id: 'ali', name: 'Ali', color: 'bg-blue-500', borderColor: 'border-blue-400', svg: `<svg viewBox="0 0 100 100" class="w-full h-full"> <circle cx="50" cy="55" r="30" fill="#fcd34d"/> <path d="M 22 45 Q 50 20 78 45 Z" fill="#2563eb"/> <rect x="22" y="42" width="56" height="8" rx="2" fill="#1d4ed8"/> <path d="M 22 45 Q 50 38 78 45" fill="none" stroke="#f59e0b" stroke-width="4"/> <circle cx="40" cy="55" r="4" fill="#0f172a"/> <circle cx="60" cy="55" r="4" fill="#0f172a"/> <path d="M 42 66 Q 50 74 58 66" fill="none" stroke="#0f172a" stroke-width="3" stroke-linecap="round"/> </svg>` }, { id: 'aisyah', name: 'Aisyah', color: 'bg-amber-500', borderColor: 'border-amber-400', svg: `<svg viewBox="0 0 100 100" class="w-full h-full"> <path d="M 20 50 Q 50 10 80 50 Q 85 85 50 90 Q 15 85 20 50 Z" fill="#f59e0b"/> <circle cx="50" cy="52" r="22" fill="#fcd34d"/> <circle cx="42" cy="52" r="3.5" fill="#0f172a"/> <circle cx="58" cy="52" r="3.5" fill="#0f172a"/> <path d="M 44 62 Q 50 67 56 62" fill="none" stroke="#0f172a" stroke-width="2.5" stroke-linecap="round"/> <circle cx="70" cy="35" r="6" fill="#ef4444"/> </svg>` } ]; let playerCount = 1; let players = []; let currentQuestionIndex = 0; let currentPlayerTurn = 0; let soundEnabled = true; // Tone.js Sound Synthesizers let polySynth, sfxSynth, musicLoop; function initAudio() { if (polySynth) return; try { polySynth = new Tone.PolySynth(Tone.Synth, { oscillator: { type: "sine" }, envelope: { attack: 0.1, decay: 0.2, sustain: 0.3, release: 0.8 } }).toDestination(); polySynth.volume.value = -16; sfxSynth = new Tone.Synth({ oscillator: { type: "triangle" }, envelope: { attack: 0.01, decay: 0.15, sustain: 0.1, release: 0.2 } }).toDestination(); sfxSynth.volume.value = -6; const notes = ["C4", "E4", "G4", "A4", "C5", "G4", "E4", "D4"]; let step = 0; musicLoop = new Tone.Loop(time => { if (soundEnabled) { polySynth.triggerAttackRelease(notes[step % notes.length], "8n", time); step++; } }, "4n"); Tone.Transport.bpm.value = 95; Tone.Transport.start(); musicLoop.start(0); } catch (e) { console.log("Audio initialized on interaction"); } } function toggleAudio() { soundEnabled = !soundEnabled; const icon = document.getElementById("sound-icon"); const text = document.getElementById("sound-text"); if (soundEnabled) { icon.textContent = "🔊"; text.textContent = "Musik: ON"; Tone.start(); if (Tone.Transport.state !== "started") Tone.Transport.start(); } else { icon.textContent = "🔇"; text.textContent = "Musik: OFF"; } } function playJumpSFX() { if (!soundEnabled || !sfxSynth) return; sfxSynth.triggerAttackRelease("C5", "8n"); setTimeout(() => sfxSynth.triggerAttackRelease("G5", "8n"), 80); } function playCorrectSFX() { if (!soundEnabled || !polySynth) return; polySynth.triggerAttackRelease(["C4", "E4", "G4", "C5"], "4n"); } function playWrongSFX() { if (!soundEnabled || !sfxSynth) return; sfxSynth.triggerAttackRelease("F3", "4n"); } // Render Background Stars const starsContainer = document.getElementById("stars-container"); for (let i = 0; i < 40; i++) { const star = document.createElement("div"); star.className = "absolute rounded-full bg-amber-200 animate-pulse"; star.style.width = `${Math.random() * 3 + 1}px`; star.style.height = star.style.width; star.style.top = `${Math.random() * 100}%`; star.style.left = `${Math.random() * 100}%`; star.style.animationDuration = `${Math.random() * 3 + 2}s`; starsContainer.appendChild(star); } function setQuizMode(mode) { quizMode = mode; const btnStandard = document.getElementById("mode-btn-standard"); const btnAi = document.getElementById("mode-btn-ai"); const aiPanel = document.getElementById("ai-customizer-panel"); if (mode === 'standard') { btnStandard.className = "flex-1 py-2.5 rounded-xl font-bold text-xs md:text-sm transition-all bg-amber-400 text-slate-950 shadow"; btnAi.className = "flex-1 py-2.5 rounded-xl font-bold text-xs md:text-sm transition-all text-slate-400 hover:text-white flex items-center justify-center gap-1.5"; aiPanel.classList.add("hidden"); } else { btnAi.className = "flex-1 py-2.5 rounded-xl font-bold text-xs md:text-sm transition-all bg-gradient-to-r from-purple-500 to-indigo-500 text-white shadow"; btnStandard.className = "flex-1 py-2.5 rounded-xl font-bold text-xs md:text-sm transition-all text-slate-400 hover:text-white flex items-center justify-center gap-1.5"; aiPanel.classList.remove("hidden"); } } function selectPlayerCount(count) { playerCount = count; document.querySelectorAll(".btn-pcount").forEach((btn, idx) => { if (idx + 1 === count) { btn.className = "btn-pcount py-3 rounded-2xl bg-amber-400 text-slate-950 font-bold text-lg border-2 border-amber-300 shadow-lg hover:scale-105 transition"; } else { btn.className = "btn-pcount py-3 rounded-2xl bg-slate-700 text-slate-200 font-bold text-lg border-2 border-slate-600 shadow hover:scale-105 transition"; } }); renderPlayerSetupCards(); } function renderPlayerSetupCards() { const container = document.getElementById("player-names-container"); container.innerHTML = ""; for (let i = 0; i < playerCount; i++) { const avatar = AVATARS[i]; const card = document.createElement("div"); card.className = "bg-slate-90
91
Haryanti, S.Pd., Gr.SD IT Al Huda WonogiriBuka LinkBuka Link
92
ANIS AYU AGUSTIN, S.Pd., M.Pd.SD N 1 Wonogiri199108222019022002Buka LinkBuka Link
93
Dina Sukawati, S.Pd.SD Kanisius Wonogiri-Buka LinkBuka Link
94
ANGGUN TRISNAWATI DEWI, S.PdSD MUHAMMADIYAHBuka LinkBuka Link
95
Nunik Indra Meylani, S.Pd.SD Negeri 2 Purworejo198905292023212027Buka LinkBuka Link
96
MURNI, S.Pd.SD NEGERI 2 GIRIPURWO198610132022212011Buka LinkBuka Link
97
Djarjanto, S.Pd.SDN 2 Giritirto196804032007011025Buka LinkBuka Link
98
Linda Anggita, S.Pd.SD Negeri 3 Wonoboyo-Buka LinkBuka Link
99
Ilham Fitri Astuti, S.PdSDN 2 MENTOBuka LinkBuka Link
100
FETY YULIANI, S.PdSD Negeri 2 Mento196807301997032004Buka LinkBuka Link