| D | G | H | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | nama_lengkap | asal_school | nip | M2 Link | M3 Link | ||||||||||||||
2 | Musalim Djaka Sasmita, S.Pd. | SD N 6 WONOGIRI | 199001312022211004 | Buka Link | Buka Link | ||||||||||||||
3 | Rekyan Pandhiga Dewi, S.Pd. | SDN 7 Wonogiri | 199505212019022002 | Buka Link | Buka Link | ||||||||||||||
4 | Dwi Purnama Utami, S.Pd.SD | SD N 1 Giritirto | 197307262022212008 | Buka Link | Buka Link | ||||||||||||||
5 | Catur Rahmadani, S.Pd.SD | SD Negeri 1 Wonogiri | 198206272022212021 | Buka Link | Buka Link | ||||||||||||||
6 | RATRI CAHYANINGRUM, S.Pd | SD Negeri 1 Giripurwo | 198901162022212004 | Buka Link | Buka Link | ||||||||||||||
7 | MEILANI ANDITA IFANI, S.Pd. | SD NEGERI 3 POKOH KIDUL | 199705202023212019 | Buka Link | Buka Link | ||||||||||||||
8 | Riyanto, S.Pd.SD | SD Negeri 7 Wonogiri | 198406222022211004 | Buka Link | Buka Link | ||||||||||||||
9 | Nunung Nurhiqmah, S.Psi., M.Pd. | SD Negeri 1 Wonogiri | 198211202008012008 | Buka Link | Buka Link | ||||||||||||||
10 | Sekti Sumarni,S Pd | SD N 2 Pokoh Kidul | 197010011997032007 | Buka Link | Buka Link | ||||||||||||||
11 | Sri Wahyuni,S.Pd.AUD | SD N 4 Wonoboyo | 196806162008012014 | Buka Link | Buka Link | ||||||||||||||
12 | ANGGIT HASTUTI, S. Pd. SD | SDN 6 WONOGIRI | 198411172022212020 | Buka Link | Buka Link | ||||||||||||||
13 | ENDANG DWI ANJARI, S.Pd AUD | SD NEGERI 3 WONOKERTO | 19750422 200801 2007 | Buka Link | Buka Link | ||||||||||||||
14 | Sri Harumi, S. E. | SD Negeri 2 Wonoboyo | 197702092022212007 | Buka Link | Buka Link | ||||||||||||||
15 | Noniek Dian Pratiwi,S.Pd | SD Negeri 2 Wonoboyo | 198305832022212016 | Buka Link | Buka Link | ||||||||||||||
16 | HERIKA YUTI KURNIA, S.Pd.SD | SD Negeri 6 Wonogiri | 19850405 201001 2 024 | Buka Link | Buka Link | ||||||||||||||
17 | INTAN LISTIA PUTRI PRIYADI,S.Pd | SD NEGERI 1 PELEM | 199505082023212024 | Buka Link | Buka Link | ||||||||||||||
18 | Tulus Wijayanti S.Pd | SD NEGERI 2 BULUSULUR | 199510032025212106 | Buka Link | Buka Link | ||||||||||||||
19 | Indah Rahmawati | SD Negeri Selopukang | Buka Link | Buka Link | |||||||||||||||
20 | Yenni Roosita, S.Pd | SD Negeri 1 Wonogiri | 197912312014062012 | Buka 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.Pd | SD Negeri 2 Wonoharjo | - | Buka Link | Buka Link | ||||||||||||||
22 | PARAMITA AYU HAPSARI, S.Pd.SD | SD Negeri 2 Wonoboyo | 198609252022212004 | Buka Link | Buka Link | ||||||||||||||
23 | Wahyu Agus Riyanto, S. Pd. | SD Negeri Selopukang | 198008142022211002 | Buka Link | Buka Link | ||||||||||||||
24 | DJUMADI. S. Pd | SD Negeri Selopukang | 196808072008011012 | Buka 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.Pd | SD Negeri 1 Wonogiri | 198106222021212004 | Buka 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.SD | SD NEGERI 2 BULUSULUR | 198307272014062007 | Buka Link | Buka Link | ||||||||||||||
27 | Dhiyana Hulyati,S.Pd.I | SD Negeri 2 Pokoh Kidul | 198410042019022001 | Buka Link | Buka Link | ||||||||||||||
28 | Fransiska Yuli Winarsih,S.Pd | SDN 1 Giriwono | 198207102022212029 | Buka Link | Buka Link | ||||||||||||||
29 | Siti Mulyani, S. PD. SD | SD Negeri 2 Pokoh Kidul | 198612142020122004 | Buka Link | Buka Link | ||||||||||||||
30 | Elviko Ary Wibowo, S.Pd. | SD Negeri 3 Wonokerto | 199312062020121005 | Buka Link | Buka Link | ||||||||||||||
31 | Umi Azizah Fauzana, S.Pd. | SD Negeri 7 Wonogiri | 199005272015032002 | Buka Link | Buka Link | ||||||||||||||
32 | Fitria Purnamasari, M.Pd. | SD Negeri 3 Wonokerto | 198905212019022003 | Buka Link | Buka Link | ||||||||||||||
33 | Margiyanti, S.Pd.AUD | SD Negeri 1 Purworejo | 196610182008012003 | Buka Link | Buka Link | ||||||||||||||
34 | Zahro Sri Tanjung, S.Pd. | SD Negeri 2 Bulusulur | 199006242022212009 | Buka Link | Buka Link | ||||||||||||||
35 | Eko Budi Aryastuti, S.Pd.AUD | SD Negeri Selopukang | 197201282008012003 | Buka Link | Buka Link | ||||||||||||||
36 | Nurul Faridawati, S.Pd.SD | SD Negeri Kedungringin | 197704042022212009 | Buka Link | Buka Link | ||||||||||||||
37 | Hety Wulandari, S. Pd. | SD IT Al Huda Wonogiri | - | Buka Link | Buka Link | ||||||||||||||
38 | Sonya Eiffel, S.Pd. | SD Negeri 7 Wonogiri | 199405312023212015 | Buka Link | Buka Link | ||||||||||||||
39 | Dian Fitri Astuti, S.Pd | SD Negeri Selopukang | 198905092022212016 | Buka Link | Buka Link | ||||||||||||||
40 | Dwi Sriyatni, S. Pd. SD | SDN 1 Wonokarto | 197506161999032009 | Buka Link | Buka Link | ||||||||||||||
41 | Agung Irwan Saputro,S.Pd. | SD Negeri Selopukang | 197705202022211005 | Buka Link | Buka Link | ||||||||||||||
42 | Novie Asih Anggreini, S. Pd. | SDN 1 Giripurwo | 198711232022212009 | Buka Link | Buka Link | ||||||||||||||
43 | SRI PAMUNGKAS ARIANI S.Pd.SD | SD N 1 Wonogiri | 197805042014062007 | Buka Link | Buka Link | ||||||||||||||
44 | YENIE FITRIANA DEWI, S.Pd.SD | SD Negeri 2 Pokoh Kidul | 197808172022212005 | Buka Link | Buka Link | ||||||||||||||
45 | Amalia Putri Suciantika, S. Pd | SD Negeri 1 Giripurwo | 199101232022212007 | Buka Link | Buka Link | ||||||||||||||
46 | LINA PUSPITA NINGRUM, S.Pd. | SD Negeri Selopukang | 198605192022212012 | Buka Link | Buka Link | ||||||||||||||
47 | MARSELIA DEWI LOVELY, S.Pd | SD Negeri 3 Wonoboyo | 199604092022212006 | Buka Link | Buka Link | ||||||||||||||
48 | Indra Litasari, S.Pd | SD Negeri 1 Sonoharjo | 198905132020122004 | Buka Link | Buka Link | ||||||||||||||
49 | Umi Azizah Fauzani, S.Pd. | SDN 8 WONOGIRI | 199005272022212007 | Buka Link | Buka Link | ||||||||||||||
50 | Bivin, S.Pd | SDN 1 Wonogiri | 198806252020122004 | Buka Link | Buka Link | ||||||||||||||
51 | Andi Purwono,S.Pd | SD Negeri 3 Sendang | 198908132023211018 | Buka Link | Buka Link | ||||||||||||||
52 | Suharyati, S.Pd | SD NEGERI KETIMANG | 196712042022212002 | Buka Link | Buka Link | ||||||||||||||
53 | SAFINA ANDRIANA ALFALATI, S.Pd | SD NEGERI 1 GIRITIRTO | 198411152022212011 | Buka Link | Buka Link | ||||||||||||||
54 | Risti Meingga Wijayanti, S.Pd | SD Negeri 3 Wonokerto | 198805072022212002 | Buka Link | Buka Link | ||||||||||||||
55 | Sri Adhi Endaryati, M.Pd. | SD Negeri 3 Giriwono | 198508012009032007 | Buka Link | Buka Link | ||||||||||||||
56 | Maulana Agung Prabowo,S.Pd | SD NEGERI 1 WONOKARTO | 199312112020121005 | Buka Link | Buka Link | ||||||||||||||
57 | RATNA SULISTIYANI, S.Pd. | SD N 1 Wonogiri | 198211072008012006 | Buka Link | Buka Link | ||||||||||||||
58 | Suharmanto, S. Pd | SD NEGERI 2 GIRIPURWO | 199206282019021001 | Buka Link | Buka Link | ||||||||||||||
59 | ENDANG SAYUTINIGSIH, S. Pd. SD | SD NEGERI KALORAN | 197803272022212009 | Buka Link | Buka Link | ||||||||||||||
60 | Ibnu Sri Nawanto,S.Pd.SD | SD Negeri 3 Wuryorejo | 198409032022211008 | Buka Link | Buka Link | ||||||||||||||
61 | SHIMA INDAH ROSITA, S.Pd. | SD NEGERI 2 BULUSULUR | 199310102022212003 | Buka Link | Buka Link | ||||||||||||||
62 | Herry Setyawan, S.Pd.SD., M.Pd | SD NEGERI 8 WONOGIRI | 1986017 200903 1 001 | Buka Link | Buka Link | ||||||||||||||
63 | Risna Ekawati, S.Pd. | SDN 2 Giritirto | 199007112023212015 | Buka Link | Buka Link | ||||||||||||||
64 | Umi Rokhana, S.Pd., Gr. | SD NEGERI 1 WONOGIRI | 199009072017082001 | Buka Link | Buka Link | ||||||||||||||
65 | Sri Budi Lestari S.Pd.SD | SD NEGERI 3 WURYOREJO | 196807312022212001 | Buka Link | Buka Link | ||||||||||||||
66 | SHANTI PERTIWI, S.Pd. | SD NEGERI KEDUNGRINGIN | 198712212022212004 | Buka Link | Buka Link | ||||||||||||||
67 | Wargiyanti,S.Pd.SD | SD negeri 2 Purworejo | 196701191992112001 | Buka Link | Buka Link | ||||||||||||||
68 | Satya Wijayanto, S.Pd. | SD Negeri 1 Manjung | 199209012020121005 | Buka Link | Buka Link | ||||||||||||||
69 | Wida Febriati Ningrum, S.Pd | SD Negeri 1 Giripurwo | 198902262022212005 | Buka Link | Buka Link | ||||||||||||||
70 | WIDIYANTI, S.Pd.SD | SD Negeri 2 Wuryorejo | 197906022022212007 | Buka Link | file:///C:/Users/USER/Downloads/game_evaluasi_bahasa_indonesia_kelas_2_mengenal_perasaan.html | ||||||||||||||
71 | Sri Wiyati, S. Pd. AUD | SDN 1 Giritirto | 196702061986032002 | Buka Link | Buka Link | ||||||||||||||
72 | SRI RAHAYU,S.Pd.AUD | SD Negeri 2 Wonoharjo | 196807132008012009 | Buka Link | Buka Link | ||||||||||||||
73 | Dian Eko Santoso, S.Pd.SD. | SDN 2 GIRITIRTO | 198802242020121001 | Buka Link | Buka Link | ||||||||||||||
74 | Ernilia Kurniawati, S. Pd., Gr | SDIT AL HUDA Wonogiri | Buka Link | Buka Link | |||||||||||||||
75 | KRISTIN AYU DAMAIYANTI, S. Pd. | SD N 1 WONOKARTO | 199312212022212006 | Buka Link | file:///C:/Users/HP/Downloads/game_luas_bangun_ai.html | ||||||||||||||
76 | Rini Hernawati, S.Pd. | SD Negeri Wonomulyo | 198201212022212010 | Buka Link | Buka Link | ||||||||||||||
77 | Dian Kusumawardani, S. Pd. | SDN Kedungringin | 199309252023212027 | Buka Link | Buka Link | ||||||||||||||
78 | Tri Wijayanti,S.Pd.SD | SD Negeri Ketimang | 19731017202321001 | Buka Link | Buka Link | ||||||||||||||
79 | APRILIYA FITRI UTOMO, S.Pd. | SD NEGERI KALORAN | 199104232022212019 | Buka 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 • BERKARAKTER • 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 • 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">← / →</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"> © 2026 SD Negeri Kaloran • 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 Mento | 199206022022212021 | Buka Link | Buka Link | ||||||||||||||
81 | Tini Rahayu, S. Pd | SD Negeri 2 Mento | 197009251996032003 | Buka Link | Buka Link | ||||||||||||||
82 | TRI CAHYO SARJANA PUTRA., S.Pd | SD NEGERI KALORAN | - | Buka Link | Buka Link | ||||||||||||||
83 | ALIP PRAPTIWI,S.Pd | SD Negeri 2 Wonoharjo | 198512292022212028 | Buka Link | Buka Link | ||||||||||||||
84 | SUHARYANTI,S.Pd.SD. | SD Negeri 3 Wonoboyo | 197807182022212003 | Buka Link | Buka Link | ||||||||||||||
85 | YUSELG PUTRIKAM IKHTIARI, S.Pd. | SD NEGERI KALORAN | 199407262022212006 | Buka Link | Buka Link | ||||||||||||||
86 | Mulatsih Ari Widya Pangestika, S.Pd. | SD Negeri 2 Wonoharjo | 199201152022212015 | Buka Link | Buka Link | ||||||||||||||
87 | NIKEN NOVITASARI, S. Pd | SD Negeri 2 Giripurwo | 198711252009032001 | Buka Link | Buka Link | ||||||||||||||
88 | Anik Nia Kusmayanti, S.Pd. | SD Negeri 1 Manjung | 198001132021212007 | Buka Link | Buka Link | ||||||||||||||
89 | Agina Fitri Pratiwi,S.Pd.SD | SD Negeri Ketimang | 198705152009032005 | Buka Link | Buka Link | ||||||||||||||
90 | DWI RETNO WIJAYANTI , S.Pd | SD NEGERI KALORAN | 196812211993012001 | Buka 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 • Lompat Bintang Ceria AI © 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 Wonogiri | Buka Link | Buka Link | |||||||||||||||
92 | ANIS AYU AGUSTIN, S.Pd., M.Pd. | SD N 1 Wonogiri | 199108222019022002 | Buka Link | Buka Link | ||||||||||||||
93 | Dina Sukawati, S.Pd. | SD Kanisius Wonogiri | - | Buka Link | Buka Link | ||||||||||||||
94 | ANGGUN TRISNAWATI DEWI, S.Pd | SD MUHAMMADIYAH | Buka Link | Buka Link | |||||||||||||||
95 | Nunik Indra Meylani, S.Pd. | SD Negeri 2 Purworejo | 198905292023212027 | Buka Link | Buka Link | ||||||||||||||
96 | MURNI, S.Pd. | SD NEGERI 2 GIRIPURWO | 198610132022212011 | Buka Link | Buka Link | ||||||||||||||
97 | Djarjanto, S.Pd. | SDN 2 Giritirto | 196804032007011025 | Buka Link | Buka Link | ||||||||||||||
98 | Linda Anggita, S.Pd. | SD Negeri 3 Wonoboyo | - | Buka Link | Buka Link | ||||||||||||||
99 | Ilham Fitri Astuti, S.Pd | SDN 2 MENTO | Buka Link | Buka Link | |||||||||||||||
100 | FETY YULIANI, S.Pd | SD Negeri 2 Mento | 196807301997032004 | Buka Link | Buka Link |