Algebra Adventure: Candy Kingdom Rescue
by AtomicBolt10377 lines13.4 KB
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Algebra Adventure: Candy Kingdom Rescue</title>
<style>
/* === COLOR PALETTE & FONTS === */
@import url('https://fonts.googleapis.com/css2?family=Fredoka+One&family=Nunito:wght@400;700&display=swap');
:root {
--bg-candy: linear-gradient(135deg, #FFB7B2 0%, #E2F0CB 100%);
--glass-bg: rgba(255, 255, 255, 0.4);
--glass-border: rgba(255, 255, 255, 0.6);
--btn-glow: 0 0 15px rgba(255, 154, 162, 0.8);
--text-dark: #6B5B95;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--bg-candy);
font-family: 'Nunito', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
overflow: hidden;
}
/* === GAME CONTAINER (16:9) === */
#game-container {
width: 100%;
max-width: 900px;
aspect-ratio: 16/9;
background: url('https://www.transparenttextures.com/patterns/stardust.png'), radial-gradient(circle, #FFDAC1 0%, #FFB7B2 100%);
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.2);
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
}
.screen {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: opacity 0.5s ease;
padding: 20px;
text-align: center;
}
.hidden { opacity: 0; pointer-events: none; z-index: -1; }
.active { opacity: 1; z-index: 10; }
/* === UI ELEMENTS === */
h1, h2 { font-family: 'Fredoka One', cursive; color: #FF9AA2; text-shadow: 2px 2px 0px #fff; letter-spacing: 2px; }
.glass-panel {
background: var(--glass-bg);
backdrop-filter: blur(10px);
border: 2px solid var(--glass-border);
border-radius: 20px;
padding: 20px;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
}
.btn {
background: linear-gradient(45deg, #FF9AA2, #FFDAC1);
border: none;
border-radius: 30px;
padding: 12px 25px;
font-size: 1.2rem;
font-family: 'Fredoka One', cursive;
color: white;
cursor: pointer;
margin: 10px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
text-shadow: 1px 1px 0px rgba(0,0,0,0.2);
box-shadow: 0 4px 10px rgba(255, 154, 162, 0.5);
}
.btn:hover {
transform: translateY(-5px) scale(1.05);
box-shadow: var(--btn-glow);
}
/* === HUD (Heads Up Display) === */
#hud {
position: absolute;
top: 15px; left: 15px; right: 15px;
display: flex;
justify-content: space-between;
font-family: 'Fredoka One', cursive;
color: var(--text-dark);
z-index: 20;
}
.hud-box {
background: rgba(255,255,255,0.7);
padding: 5px 15px;
border-radius: 20px;
display: flex;
align-items: center;
gap: 10px;
}
/* === CHARACTER & ANIMATIONS === */
.character {
font-size: 80px;
animation: float 3s ease-in-out infinite;
filter: drop-shadow(0 10px 10px rgba(0,0,0,0.2));
margin-bottom: 10px;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-15px); }
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-10px); }
40%, 80% { transform: translateX(10px); }
}
.shake { animation: shake 0.5s; }
/* === QUIZ LAYOUT === */
#options { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; width: 100%; max-width: 600px; margin-top: 20px;}
.dialog-box { font-size: 1.2rem; color: var(--text-dark); margin-bottom: 20px; font-weight: bold; }
/* Particle / Confetti Layer */
#particles { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 100;}
</style>
</head>
<body>
<div id="game-container">
<!-- HUD Layer -->
<div id="hud" class="hidden">
<div class="hud-box" id="health-bar">❤️❤️❤️</div>
<div class="hud-box">⏳ <span id="timer">30</span>s</div>
<div class="hud-box">💎 <span id="score">0</span></div>
</div>
<!-- Intro Screen -->
<div id="intro-screen" class="screen active">
<div class="character">🧙♂️🧸</div>
<h1>Algebra Adventure</h1>
<div class="glass-panel" style="margin: 20px 0;">
<p style="color: var(--text-dark); font-weight: bold;">Candy Kingdom Diserang Monster Aljabar!</p>
<p style="color: var(--text-dark);">Bantu Milo si petualang kecil menyelesaikan misi matematika untuk mendapatkan Crystal Power!</p>
</div>
<button class="btn" onclick="startGame()">▶ Start Game</button>
</div>
<!-- Quiz Screen -->
<div id="quiz-screen" class="screen hidden">
<div class="character" id="milo-sprite">🧙♂️🧸</div>
<div class="glass-panel dialog-box" id="question-text">Loading question...</div>
<div id="options">
<!-- Buttons generated via JS -->
</div>
</div>
<!-- Game Over Screen -->
<div id="game-over-screen" class="screen hidden">
<div class="character">😿</div>
<h1 style="color: #FF6B6B;">Game Over!</h1>
<p class="dialog-box">Candy Kingdom masih dalam bahaya. Ayo coba lagi, Milo!</p>
<button class="btn" onclick="location.reload()">🔄 Restart</button>
</div>
<!-- Victory Screen -->
<div id="victory-screen" class="screen hidden">
<div class="character">🎉🧙♂️✨</div>
<h1 style="color: #A8E6CF;">Victory!</h1>
<p class="dialog-box">Kamu berhasil menyelamatkan Candy Kingdom!</p>
<div class="glass-panel" style="margin-bottom: 20px;">
<p>Total Crystal: 💎 <span id="final-score">0</span></p>
<p>Sisa Nyawa: <span id="final-health"></span></p>
</div>
<button class="btn" onclick="location.reload()">🔄 Main Lagi</button>
</div>
<div id="particles"></div>
</div>
<script>
// --- DATA SOAL MATEMATIKA (Kontekstual SMP) ---
const questions = [
{
q: "Milo ingin membeli 3 Ramuan Permen (x). Koin Milo awalnya 50, dan kini sisa 20. Persamaan aljabar yang tepat adalah?",
opts: ["50 - 3x = 20", "50 + 3x = 20", "3x - 50 = 20", "20 - 3x = 50"],
ans: 0
},
{
q: "Di hutan, Milo menemukan suku sejenis! Bentuk paling sederhana dari 4a + 3b - 2a + b adalah?",
opts: ["2a + 2b", "6a + 4b", "2a + 4b", "4a - 2b"],
ans: 2
},
{
q: "Tongkat crystal Milo memiliki kekuatan sihir 5y - 7. Jika energi batu crystal (y) bernilai 4, berapa total kekuatan Milo?",
opts: ["12", "13", "14", "15"],
ans: 1
},
{
q: "Boss Monster Aljabar memiliki HP = 100. Milo menyerang dengan pedang '2p + 10'. Jika p = 20, berapa sisa HP monster?",
opts: ["0", "40", "50", "60"],
ans: 2
}
];
// --- GAME STATE ---
let currentLevel = 0;
let score = 0;
let health = 3;
let timerInterval;
let timeLeft = 30;
// --- DOM ELEMENTS ---
const screens = {
intro: document.getElementById('intro-screen'),
quiz: document.getElementById('quiz-screen'),
gameOver: document.getElementById('game-over-screen'),
victory: document.getElementById('victory-screen')
};
const hud = document.getElementById('hud');
const healthBar = document.getElementById('health-bar');
const timerDisplay = document.getElementById('timer');
const scoreDisplay = document.getElementById('score');
const questionText = document.getElementById('question-text');
const optionsContainer = document.getElementById('options');
const miloSprite = document.getElementById('milo-sprite');
// --- FUNCTIONS ---
function switchScreen(screenKey) {
Object.values(screens).forEach(s => s.classList.remove('active'));
Object.values(screens).forEach(s => s.classList.add('hidden'));
screens[screenKey].classList.remove('hidden');
screens[screenKey].classList.add('active');
}
function startGame() {
switchScreen('quiz');
hud.classList.remove('hidden');
loadQuestion();
}
function loadQuestion() {
if (currentLevel >= questions.length) {
winGame();
return;
}
miloSprite.textContent = "🧙♂️🧸"; // Reset animasi idle
timeLeft = 30; // Reset Timer per soal
timerDisplay.textContent = timeLeft;
clearInterval(timerInterval);
timerInterval = setInterval(() => {
timeLeft--;
timerDisplay.textContent = timeLeft;
if (timeLeft <= 0) {
clearInterval(timerInterval);
takeDamage();
}
}, 1000);
const currentQ = questions[currentLevel];
questionText.textContent = `Level ${currentLevel + 1}: ${currentQ.q}`;
optionsContainer.innerHTML = '';
currentQ.opts.forEach((opt, index) => {
const btn = document.createElement('button');
btn.className = 'btn glass-panel';
btn.style.color = 'var(--text-dark)';
btn.textContent = opt;
btn.onclick = () => checkAnswer(index);
optionsContainer.appendChild(btn);
});
}
function checkAnswer(selectedIndex) {
clearInterval(timerInterval);
const correctIndex = questions[currentLevel].ans;
if (selectedIndex === correctIndex) {
// BENAR
miloSprite.textContent = "✨🤩✨";
score += 100 + (timeLeft * 2); // Bonus waktu
scoreDisplay.textContent = score;
createConfetti();
setTimeout(() => {
currentLevel++;
loadQuestion();
}, 1500);
} else {
// SALAH
takeDamage();
}
}
function takeDamage() {
miloSprite.textContent = "🤕😿";
screens.quiz.classList.add('shake');
setTimeout(() => screens.quiz.classList.remove('shake'), 500);
health--;
updateHealthBar();
if (health <= 0) {
setTimeout(loseGame, 1000);
} else {
setTimeout(loadQuestion, 1500); // Reload current question
}
}
function updateHealthBar() {
healthBar.textContent = '❤️'.repeat(health) + '🖤'.repeat(3 - health);
}
function winGame() {
hud.classList.add('hidden');
switchScreen('victory');
document.getElementById('final-score').textContent = score;
document.getElementById('final-health').textContent = '❤️'.repeat(health);
createConfetti();
createConfetti(); // Double confetti for win!
}
function loseGame() {
hud.classList.add('hidden');
switchScreen('gameOver');
}
// --- VISUAL EFFECTS ---
function createConfetti() {
const colors = ['#FF9AA2', '#FFB7B2', '#FFDAC1', '#E2F0CB', '#B5EAD7', '#C7CEEA'];
const particlesContainer = document.getElementById('particles');
for(let i=0; i<30; i++) {
const particle = document.createElement('div');
particle.style.position = 'absolute';
particle.style.width = '10px';
particle.style.height = '10px';
particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
particle.style.borderRadius = '50%';
// Random start position near character
particle.style.left = '50%';
particle.style.top = '30%';
const destX = (Math.random() - 0.5) * 300;
const destY = (Math.random() - 0.5) * 300;
particle.animate([
{ transform: 'translate(0, 0) scale(1)', opacity: 1 },
{ transform: `translate(${destX}px, ${destY}px) scale(0)`, opacity: 0 }
], {
duration: 1000 + Math.random() * 500,
easing: 'cubic-bezier(0, .9, .57, 1)'
});
particlesContainer.appendChild(particle);
setTimeout(() => particle.remove(), 1500);
}
}
</script>
</body>
</html>Game Source: Algebra Adventure: Candy Kingdom Rescue
Creator: AtomicBolt10
Libraries: none
Complexity: complex (377 lines, 13.4 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: algebra-adventure-candy-kingdom-rescue-atomicbolt10" to link back to the original. Then publish at arcadelab.ai/publish.