Math Match 1.0 - VideojuCan
by CosmicCobra59473 lines16.6 KB
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Math Match 1.0 - VideojuCan</title>
<style>
:root {
--bg: #1a1a2e;
--card: #16213e;
--primary: #e94560;
--secondary: #0f3460;
--text: #eee;
--muted: #aaa;
--border: #2a2a4a;
--success: #2ecc71;
--gold: #f1c40f;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg);
color: var(--text);
font-family: 'Segoe UI', 'Courier New', monospace;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
touch-action: manipulation;
user-select: none;
-webkit-user-select: none;
}
#gameContainer {
width: 100%;
max-width: 500px;
background: var(--card);
border-radius: 20px;
padding: 1.5rem;
border: 2px solid var(--primary);
box-shadow: 0 0 30px rgba(233,68,96,0.3);
text-align: center;
}
h1 {
font-size: 2rem;
color: var(--gold);
margin-bottom: 0.5rem;
}
.battle-area {
display: flex;
justify-content: space-around;
align-items: center;
margin: 1rem 0;
}
.player-box {
text-align: center;
padding: 1rem;
border-radius: 12px;
border: 2px solid var(--border);
min-width: 120px;
transition: all 0.3s;
}
.player-box.active {
border-color: var(--gold);
box-shadow: 0 0 15px rgba(241,196,15,0.4);
}
.player-name {
font-weight: bold;
font-size: 1.1rem;
}
.player-hp {
font-size: 2rem;
color: var(--success);
margin: 0.3rem 0;
}
.player-hp.danger { color: #e74c3c; }
.vs-text {
font-size: 1.5rem;
font-weight: bold;
color: var(--gold);
}
.phase-info {
color: var(--muted);
font-size: 0.9rem;
margin: 0.5rem 0;
}
.number-pad {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
justify-content: center;
margin: 1rem 0;
}
.num-btn {
width: 55px;
height: 55px;
border-radius: 12px;
border: 2px solid var(--border);
background: var(--secondary);
color: var(--text);
font-size: 1.4rem;
font-weight: bold;
cursor: pointer;
transition: all 0.2s;
}
.num-btn:hover:not(:disabled) {
border-color: var(--primary);
background: var(--primary);
color: #fff;
transform: scale(1.05);
}
.num-btn:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.num-uses {
font-size: 0.7rem;
color: var(--muted);
margin-top: -0.3rem;
}
.uses-bar {
width: 40px;
height: 4px;
background: #333;
border-radius: 2px;
margin: 2px auto;
overflow: hidden;
}
.uses-fill {
height: 100%;
border-radius: 2px;
transition: width 0.3s;
}
.sword-btn {
font-family: inherit;
padding: 0.6rem 1.5rem;
border-radius: 10px;
border: 2px solid var(--gold);
background: #8b4513;
color: var(--gold);
font-size: 1rem;
font-weight: bold;
cursor: pointer;
margin: 0.5rem;
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0%, 100% { box-shadow: 0 0 10px rgba(241,196,15,0.4); }
50% { box-shadow: 0 0 20px rgba(241,196,15,0.8); }
}
.sword-btn:disabled {
opacity: 0.4;
animation: none;
cursor: not-allowed;
}
.btn {
font-family: inherit;
padding: 0.6rem 1.5rem;
border-radius: 10px;
border: none;
font-size: 1rem;
font-weight: bold;
cursor: pointer;
margin: 0.3rem;
transition: all 0.2s;
}
.btn-primary { background: var(--primary); color: #fff; }
.btn-outline { background: transparent; border: 2px solid var(--primary); color: var(--primary); }
.victory-text {
font-size: 1.5rem;
color: var(--gold);
font-weight: bold;
margin: 1rem 0;
}
.stats-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
margin: 1rem 0;
font-size: 0.85rem;
color: var(--muted);
}
.hidden { display: none !important; }
@media (max-width: 400px) {
.num-btn { width: 42px; height: 42px; font-size: 1.1rem; }
}
</style>
</head>
<body>
<div id="gameContainer">
<h1>⚔️ MATH MATCH</h1>
<!-- MENÚ -->
<div id="menuScreen">
<p style="color:var(--muted);">Elige modo de juego</p>
<button class="btn btn-primary" onclick="startGame('pvp')">👥 1 vs 1 Local</button>
<br>
<button class="btn btn-outline" onclick="startGame('bot')">🤖 vs Bot</button>
</div>
<!-- BATALLA -->
<div id="battleScreen" class="hidden">
<div class="battle-area">
<div class="player-box" id="player1Box">
<div class="player-name" id="p1Name">Orco 1</div>
<div class="player-hp" id="p1Hp">1</div>
</div>
<div class="vs-text">VS</div>
<div class="player-box" id="player2Box">
<div class="player-name" id="p2Name">Orco 2</div>
<div class="player-hp" id="p2Hp">1</div>
</div>
</div>
<div class="phase-info" id="phaseInfo"></div>
<div id="turnInfo" style="color:var(--gold); font-weight:bold; margin:0.5rem;"></div>
<div class="number-pad" id="numberPad"></div>
<button class="sword-btn hidden" id="swordBtn" onclick="useSword()">🗡️ Espada de Suma (5)</button>
<button class="btn btn-outline" onclick="backToMenu()" style="margin-top:1rem;">⬅️ Menú</button>
</div>
<!-- VICTORIA -->
<div id="victoryScreen" class="hidden">
<div class="victory-text" id="victoryText"></div>
<div class="stats-grid" id="statsGrid"></div>
<button class="btn btn-primary" onclick="restartGame()">🔄 Revancha</button>
<button class="btn btn-outline" onclick="backToMenu()">⬅️ Menú</button>
</div>
</div>
<script>
// ========== ESTADO DEL JUEGO ==========
const MAX_USES = { 1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10, 7: 10, 8: 5, 9: 5 };
let players = {};
let game = {
mode: 'pvp',
turn: 1,
phase: 'attack', // 'attack' | 'defend'
currentAttacker: 1,
currentDefender: 2,
attackValue: 0,
swordBonus: 0,
gameOver: false,
stats: { turns: 0, swordUses: 0, biggestHit: 0, numbersUsed: [] }
};
function initPlayers() {
players = {
1: { name: 'Orco 1', hp: 1, numbers: { ...MAX_USES }, swordUses: 5 },
2: { name: 'Orco 2', hp: 1, numbers: { ...MAX_USES }, swordUses: 5 }
};
game.turn = 1;
game.phase = 'attack';
game.currentAttacker = 1;
game.currentDefender = 2;
game.attackValue = 0;
game.swordBonus = 0;
game.gameOver = false;
game.stats = { turns: 0, swordUses: 0, biggestHit: 0, numbersUsed: [] };
}
// ========== UI ==========
function showScreen(id) {
document.getElementById('menuScreen').classList.add('hidden');
document.getElementById('battleScreen').classList.add('hidden');
document.getElementById('victoryScreen').classList.add('hidden');
document.getElementById(id).classList.remove('hidden');
}
function startGame(mode) {
game.mode = mode;
initPlayers();
showScreen('battleScreen');
renderBattle();
}
function backToMenu() {
showScreen('menuScreen');
}
function restartGame() {
startGame(game.mode);
}
// ========== RENDERIZADO ==========
function renderBattle() {
if (game.gameOver) return;
const atk = players[game.currentAttacker];
const def = players[game.currentDefender];
// Nombres
document.getElementById('p1Name').textContent = players[1].name;
document.getElementById('p2Name').textContent = players[2].name;
// HP
const hp1 = document.getElementById('p1Hp');
const hp2 = document.getElementById('p2Hp');
hp1.textContent = players[1].hp;
hp2.textContent = players[2].hp;
hp1.className = 'player-hp' + (players[1].hp < 5 ? ' danger' : '');
hp2.className = 'player-hp' + (players[2].hp < 5 ? ' danger' : '');
// Activo
document.getElementById('player1Box').classList.toggle('active', game.currentAttacker === 1 || game
.currentDefender === 1);
document.getElementById('player2Box').classList.toggle('active', game.currentAttacker === 2 || game
.currentDefender === 2);
// Fase
const defHp = def.hp;
const phaseLabel = defHp < 10 ?
'Fase 1: Ataque (Resta) / Defensa (Suma)' :
'Fase 2: Ataque (División) / Defensa (Multiplicación)';
document.getElementById('phaseInfo').textContent = phaseLabel;
// Turno
const action = game.phase === 'attack' ? 'ATACA' : 'DEFIENDE';
document.getElementById('turnInfo').textContent =
`TURNO ${game.turn} — ${atk.name} ${action}`;
// Números
renderNumberPad(atk.numbers);
// Espada
const swordBtn = document.getElementById('swordBtn');
if (atk.hp >= 100 && atk.swordUses > 0 && game.phase === 'attack') {
swordBtn.classList.remove('hidden');
swordBtn.textContent = `🗡️ Espada de Suma (${atk.swordUses})`;
} else {
swordBtn.classList.add('hidden');
}
// Bot IA
if (game.mode === 'bot' && game.currentAttacker === 2 && game.phase === 'attack') {
setTimeout(botAttack, 600);
}
if (game.mode === 'bot' && game.currentDefender === 2 && game.phase === 'defend') {
setTimeout(botDefend, 600);
}
}
function renderNumberPad(pool) {
const pad = document.getElementById('numberPad');
pad.innerHTML = '';
for (let i = 1; i <= 9; i++) {
const uses = pool[i] || 0;
const max = MAX_USES[i];
const pct = (uses / max) * 100;
const barColor = uses <= 2 ? '#e74c3c' : uses <= 5 ? '#f39c12' : '#2ecc71';
const wrapper = document.createElement('div');
wrapper.style.textAlign = 'center';
const btn = document.createElement('button');
btn.className = 'num-btn';
btn.textContent = i;
btn.disabled = uses <= 0 || game.gameOver;
btn.onclick = () => pickNumber(i);
wrapper.appendChild(btn);
const bar = document.createElement('div');
bar.className = 'uses-bar';
const fill = document.createElement('div');
fill.className = 'uses-fill';
fill.style.width = pct + '%';
fill.style.background = barColor;
bar.appendChild(fill);
wrapper.appendChild(bar);
const label = document.createElement('div');
label.className = 'num-uses';
label.textContent = uses;
wrapper.appendChild(label);
pad.appendChild(wrapper);
}
}
// ========== LÓGICA DE JUEGO ==========
function pickNumber(num) {
if (game.gameOver) return;
const player = game.phase === 'attack' ? players[game.currentAttacker] : players[game.currentDefender];
if (player.numbers[num] <= 0) return;
player.numbers[num]--;
game.stats.numbersUsed.push(num);
if (game.phase === 'attack') {
game.attackValue = num + game.swordBonus;
if (game.swordBonus > 0) game.stats.swordUses++;
if (game.attackValue > game.stats.biggestHit) game.stats.biggestHit = game.attackValue;
game.swordBonus = 0;
game.phase = 'defend';
renderBattle();
} else {
resolveTurn(num);
}
}
function useSword() {
const atk = players[game.currentAttacker];
if (atk.hp < 100 || atk.swordUses <= 0 || game.phase !== 'attack') return;
game.swordBonus = Math.random() < 0.5 ? 1 : 2;
atk.swordUses--;
document.getElementById('swordBtn').textContent =
`🗡️ Espada (+${game.swordBonus})`;
}
function resolveTurn(defNum) {
const atk = players[game.currentAttacker];
const def = players[game.currentDefender];
let newHp;
if (def.hp < 10) {
// Fase 1: suma y resta
newHp = def.hp + defNum - game.attackValue;
} else {
// Fase 2: multiplicación y división
const divisor = game.attackValue === 0 ? 1 : game.attackValue;
newHp = Math.max(1, Math.floor(def.hp * defNum / divisor));
}
def.hp = Math.max(0, newHp);
game.attackValue = 0;
game.stats.turns++;
// ¿Victoria?
if (def.hp <= 0) {
game.gameOver = true;
const winner = players[game.currentAttacker];
document.getElementById('victoryText').textContent =
`🏆 ¡${winner.name} GANA! 🏆`;
document.getElementById('statsGrid').innerHTML = `
<div>🔄 Turnos: ${game.stats.turns}</div>
<div>💥 Mayor golpe: ${game.stats.biggestHit}</div>
<div>🗡️ Espadas: ${game.stats.swordUses}</div>
<div>🔢 Números usados: ${game.stats.numbersUsed.length}</div>
`;
showScreen('victoryScreen');
return;
}
// Cambiar turno
game.turn++;
game.currentAttacker = game.currentAttacker === 1 ? 2 : 1;
game.currentDefender = game.currentAttacker === 1 ? 2 : 1;
game.phase = 'attack';
renderBattle();
}
function botAttack() {
if (game.gameOver || game.currentAttacker !== 2 || game.phase !== 'attack') return;
const pool = players[2].numbers;
const available = Object.entries(pool).filter(([, c]) => c > 0).map(([n]) => Number(n));
if (available.length === 0) return;
const pick = available[Math.floor(Math.random() * available.length)];
pickNumber(pick);
}
function botDefend() {
if (game.gameOver || game.currentDefender !== 2 || game.phase !== 'defend') return;
const pool = players[2].numbers;
const available = Object.entries(pool).filter(([, c]) => c > 0).map(([n]) => Number(n));
if (available.length === 0) return;
const pick = available[Math.floor(Math.random() * available.length)];
pickNumber(pick);
}
// ========== INICIALIZAR ==========
initPlayers();
showScreen('menuScreen');
</script>
</body>
</html>Game Source: Math Match 1.0 - VideojuCan
Creator: CosmicCobra59
Libraries: none
Complexity: complex (473 lines, 16.6 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: math-match-1-0-videojucan-cosmiccobra59" to link back to the original. Then publish at arcadelab.ai/publish.