forca-m-gica / index.html
rocch's picture
Redesign my website
19cccc1 verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Forca Mágica</title>
<link rel="icon" type="image/x-icon" href="http://static.photos/gaming/64x64/42">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/animejs/lib/anime.iife.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Fredoka:wght@400;600;700&display=swap');
body { font-family: 'Fredoka', sans-serif; }
.glow { box-shadow: 0 0 20px rgba(255,255,255,.35); }
.btn-key { transition: transform .15s ease, background .2s ease; }
.btn-key:hover { transform: translateY(-3px); }
.btn-key:active { transform: translateY(0); }
.shake { animation: shake .4s ease; }
@keyframes shake { 0%,100%{transform:translateX(0)} 25%{transform:translateX(-6px)} 75%{transform:translateX(6px)} }
.fade-in { animation: fadeIn .6s ease forwards; }
@keyframes fadeIn { from{opacity:0;transform:translateY(20px)} to{opacity:1;transform:translateY(0)} }
</style>
</head>
<body class="bg-gradient-to-br from-purple-900 via-indigo-900 to-black min-h-screen text-white flex items-center justify-center p-4">
<!-- Background Vanta Globe -->
<div id="vanta" class="absolute inset-0 z-0"></div>
<!-- Main Card -->
<main class="relative z-10 w-full max-w-3xl bg-white/10 backdrop-blur-xl rounded-3xl shadow-2xl glow p-6 md:p-10 fade-in">
<!-- Header -->
<header class="flex items-center justify-between mb-6">
<h1 class="text-2xl md:text-4xl font-bold tracking-wide flex items-center gap-3">
<i data-feather="zap" class="text-yellow-300"></i>
Forca Mágica
</h1>
<button id="infoBtn" class="btn-icon text-indigo-200 hover:text-white transition">
<i data-feather="info"></i>
</button>
</header>
<!-- Game Board -->
<section class="grid md:grid-cols-2 gap-6">
<!-- Left: Gallows & Word -->
<div class="flex flex-col items-center justify-center">
<canvas id="gallows" width="220" height="220" class="mb-4"></canvas>
<div id="wordDisplay" class="text-3xl md:text-4xl font-bold tracking-widest select-none"></div>
<p id="errors" class="mt-3 text-sm text-indigo-200">Erros: <span id="errCount">0</span> / 6</p>
</div>
<!-- Right: Keyboard & Actions -->
<div class="flex flex-col gap-4">
<div id="keyboard" class="grid grid-cols-9 gap-2"></div>
<div class="flex gap-3 mt-2">
<button id="newGame" class="flex-1 bg-gradient-to-r from-green-400 to-teal-400 text-black font-semibold py-3 rounded-xl shadow hover:shadow-lg transition transform hover:-translate-y-1">
🎮 Nova Partida
</button>
<button id="hintBtn" class="bg-yellow-400 text-black font-semibold px-4 py-3 rounded-xl shadow hover:shadow-lg transition transform hover:-translate-y-1">
<i data-feather="lightbulb"></i>
</button>
</div>
<p id="message" class="text-center text-sm text-indigo-200">Novo jogo iniciado! Tente adivinhar a palavra.</p>
</div>
</section>
</main>
<!-- Modal Info -->
<div id="infoModal" class="fixed inset-0 bg-black/60 backdrop-blur-sm hidden items-center justify-center z-20">
<div class="bg-white/10 backdrop-blur-xl rounded-2xl p-6 max-w-md mx-4 text-center glow">
<h2 class="text-xl font-bold mb-2">Como jogar</h2>
<p class="text-sm text-indigo-200 mb-4">Clique nas letras para adivinhar a palavra antes de completar a forca. Use a lâmpada para dicas!</p>
<button id="closeModal" class="bg-indigo-500 hover:bg-indigo-600 px-4 py-2 rounded-lg transition">Entendi</button>
</div>
</div>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script>
<script>
VANTA.GLOBE({ el: "#vanta", mouseControls: true, touchControls: true, gyroControls: false, minHeight: 200.00, minWidth: 200.00, scale: 1.00, scaleMobile: 1.00, color: 0x3b82f6, backgroundColor: 0x111827 })
</script>
<script>
feather.replace();
const words = [
{ w: "JAVASCRIPT", h: "Linguagem da web" },
{ w: "TAILWIND", h: "Framework CSS utilitário" },
{ w: "REACT", h: "Biblioteca para interfaces" },
{ w: "DESIGN", h: "Arte de criar experiências" },
{ w: "RESPONSIVE", h: "Adapta-se a qualquer tela" },
{ w: "ANIMATION", h: "Dá vida à interface" },
{ w: "GITHUB", h: "Rede de repositórios" },
{ w: "CODING", h: "Escrever programas" }
];
let secret, display, errors, guessed, hint, canvas, ctx;
function init() {
canvas = document.getElementById("gallows");
ctx = canvas.getContext("2d");
ctx.strokeStyle = "#fff";
ctx.lineWidth = 3;
newGame();
buildKeyboard();
}
function newGame() {
const pick = words[Math.floor(Math.random() * words.length)];
secret = pick.w;
hint = pick.h;
display = Array(secret.length).fill("_");
errors = 0;
guessed = new Set();
updateWord();
drawGallows();
document.getElementById("errCount").textContent = errors;
document.getElementById("message").textContent = "Novo jogo iniciado! Tente adivinhar a palavra.";
document.querySelectorAll(".btn-key").forEach(b => b.disabled = false);
}
function buildKeyboard() {
const kb = document.getElementById("keyboard");
kb.innerHTML = "";
"QWERTYUIOPASDFGHJKLZXCVBNM".split("").forEach(l => {
const btn = document.createElement("button");
btn.className = "btn-key bg-indigo-500 hover:bg-indigo-600 text-white font-semibold rounded-lg h-10";
btn.textContent = l;
btn.onclick = () => guess(l, btn);
kb.appendChild(btn);
});
}
function guess(letter, btn) {
if (guessed.has(letter) || errors >= 6 || !display.includes("_")) return;
guessed.add(letter);
btn.disabled = true;
btn.classList.remove("bg-indigo-500", "hover:bg-indigo-600");
if (secret.includes(letter)) {
btn.classList.add("bg-green-500");
for (let i = 0; i < secret.length; i++) if (secret[i] === letter) display[i] = letter;
updateWord();
if (!display.includes("_")) endGame(true);
} else {
btn.classList.add("bg-red-500");
errors++;
document.getElementById("errCount").textContent = errors;
drawMan();
if (errors === 6) endGame(false);
}
}
function updateWord() {
document.getElementById("wordDisplay").textContent = display.join(" ");
}
function drawGallows() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(20, 200);
ctx.lineTo(120, 200);
ctx.moveTo(70, 200);
ctx.lineTo(70, 20);
ctx.lineTo(150, 20);
ctx.lineTo(150, 40);
ctx.stroke();
}
function drawMan() {
ctx.beginPath();
if (errors === 1) { ctx.arc(150, 50, 10, 0, Math.PI * 2); ctx.stroke(); } // head
if (errors === 2) { ctx.moveTo(150, 60); ctx.lineTo(150, 120); ctx.stroke(); } // body
if (errors === 3) { ctx.moveTo(150, 80); ctx.lineTo(120, 100); ctx.stroke(); } // left arm
if (errors === 4) { ctx.moveTo(150, 80); ctx.lineTo(180, 100); ctx.stroke(); } // right arm
if (errors === 5) { ctx.moveTo(150, 120); ctx.lineTo(120, 160); ctx.stroke(); } // left leg
if (errors === 6) { ctx.moveTo(150, 120); ctx.lineTo(180, 160); ctx.stroke(); } // right leg
}
function endGame(won) {
const msg = won ? "🎉 Parabéns, você venceu!" : `😢 Game Over! A palavra era ${secret}`;
document.getElementById("message").textContent = msg;
document.querySelector("main").classList.add("shake");
setTimeout(() => document.querySelector("main").classList.remove("shake"), 400);
}
document.getElementById("newGame").onclick = newGame;
document.getElementById("hintBtn").onclick = () => {
if (hint) {
document.getElementById("message").textContent = `💡 Dica: ${hint}`;
anime({ targets: "#message", scale: [1, 1.05, 1], duration: 300 });
}
};
document.getElementById("infoBtn").onclick = () => document.getElementById("infoModal").classList.remove("hidden");
document.getElementById("closeModal").onclick = () => document.getElementById("infoModal").classList.add("hidden");
init();
</script>
</body>
</html>