anycoder-bbf4ad2e / index.html
pedromsfaria's picture
Upload folder using huggingface_hub
d9ec52c verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jogo de Plinko</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
color: white;
}
.header {
text-align: center;
margin-bottom: 20px;
width: 100%;
}
.header h1 {
font-size: 2.5rem;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.built-with {
margin-top: 10px;
font-size: 0.9rem;
opacity: 0.8;
}
.built-with a {
color: #ffeb3b;
text-decoration: none;
transition: color 0.3s;
}
.built-with a:hover {
color: #fff;
text-decoration: underline;
}
.game-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
max-width: 800px;
width: 100%;
}
.stats-panel {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
padding: 15px 25px;
border-radius: 15px;
display: flex;
justify-content: space-between;
width: 100%;
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
}
.stat {
text-align: center;
}
.stat-value {
font-size: 1.8rem;
font-weight: bold;
color: #ffeb3b;
}
.stat-label {
font-size: 0.9rem;
opacity: 0.8;
}
.game-board {
position: relative;
width: 100%;
height: 500px;
background: rgba(255, 255, 255, 0.05);
border-radius: 15px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
.peg-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.peg {
position: absolute;
width: 12px;
height: 12px;
background: #ffeb3b;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 10px rgba(255, 235, 59, 0.5);
}
.ball {
position: absolute;
width: 20px;
height: 20px;
background: #ff4081;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 15px rgba(255, 64, 129, 0.7);
z-index: 10;
transition: transform 0.1s;
}
.slot-container {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 60px;
display: flex;
justify-content: space-around;
padding: 0 10px;
}
.slot {
flex: 1;
height: 100%;
margin: 0 5px;
background: rgba(255, 255, 255, 0.1);
border-radius: 10px 10px 0 0;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 1.2rem;
color: #ffeb3b;
transition: all 0.3s;
}
.slot.active {
background: rgba(255, 235, 59, 0.3);
transform: scale(1.05);
}
.controls {
display: flex;
gap: 15px;
flex-wrap: wrap;
justify-content: center;
}
.btn {
padding: 12px 25px;
background: rgba(255, 255, 255, 0.2);
border: none;
border-radius: 25px;
color: white;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
backdrop-filter: blur(10px);
}
.btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
}
.btn:active {
transform: translateY(0);
}
.btn-primary {
background: linear-gradient(45deg, #ff4081, #ff9800);
}
.btn-primary:hover {
background: linear-gradient(45deg, #f50057, #ff5722);
}
.message {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.8);
padding: 30px 50px;
border-radius: 15px;
text-align: center;
z-index: 100;
backdrop-filter: blur(10px);
display: none;
}
.message h2 {
margin-bottom: 15px;
color: #ffeb3b;
}
@media (max-width: 768px) {
.game-board {
height: 400px;
}
.header h1 {
font-size: 2rem;
}
.stat-value {
font-size: 1.5rem;
}
.btn {
padding: 10px 20px;
font-size: 0.9rem;
}
}
@media (max-width: 480px) {
.game-board {
height: 350px;
}
.stats-panel {
flex-direction: column;
gap: 10px;
}
.controls {
flex-direction: column;
width: 100%;
}
.btn {
width: 100%;
}
}
</style>
</head>
<body>
<div class="header">
<h1>🎯 Jogo de Plinko</h1>
<p>Solte a bola e veja onde ela vai cair!</p>
<div class="built-with">
Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
</div>
</div>
<div class="game-container">
<div class="stats-panel">
<div class="stat">
<div class="stat-value" id="score">0</div>
<div class="stat-label">Pontuação</div>
</div>
<div class="stat">
<div class="stat-value" id="balls-left">10</div>
<div class="stat-label">Bolas Restantes</div>
</div>
<div class="stat">
<div class="stat-value" id="multiplier">1x</div>
<div class="stat-label">Multiplicador</div>
</div>
</div>
<div class="game-board" id="gameBoard">
<div class="peg-container" id="pegContainer"></div>
<div class="slot-container" id="slotContainer"></div>
</div>
<div class="controls">
<button class="btn btn-primary" id="dropBall">Soltar Bola</button>
<button class="btn" id="resetGame">Reiniciar Jogo</button>
</div>
</div>
<div class="message" id="gameOverMessage">
<h2>Fim de Jogo!</h2>
<p>Sua pontuação final: <span id="finalScore">0</span></p>
<button class="btn btn-primary" id="playAgain">Jogar Novamente</button>
</div>
<script>
class PlinkoGame {
constructor() {
this.gameBoard = document.getElementById('gameBoard');
this.pegContainer = document.getElementById('pegContainer');
this.slotContainer = document.getElementById('slotContainer');
this.scoreElement = document.getElementById('score');
this.ballsLeftElement = document.getElementById('balls-left');
this.multiplierElement = document.getElementById('multiplier');
this.dropBallBtn = document.getElementById('dropBall');
this.resetGameBtn = document.getElementById('resetGame');
this.gameOverMessage = document.getElementById('gameOverMessage');
this.finalScoreElement = document.getElementById('finalScore');
this.playAgainBtn = document.getElementById('playAgain');
this.score = 0;
this.ballsLeft = 10;
this.multiplier = 1;
this.isDropping = false;
this.balls = [];
this.pegs = [];
this.slots = [];
this.init();
this.setupEventListeners();
}
init() {
this.createPegs();
this.createSlots();
this.updateUI();
}
createPegs() {
const rows = 10;
const boardWidth = this.gameBoard.clientWidth;
const boardHeight = this.gameBoard.clientHeight - 60; // Subtract slot height
for (let row = 1; row <= rows; row++) {
const pegsInRow = row + 5;
const y = (row / (rows + 1)) * boardHeight + 50;
for (let col = 0; col < pegsInRow; col++) {
const x = (col + 0.5) / pegsInRow * boardWidth;
const peg = document.createElement('div');
peg.className = 'peg';
peg.style.left = `${x}px`;
peg.style.top = `${y}px`;
this.pegContainer.appendChild(peg);
this.pegs.push({
element: peg,
x: x,
y: y,
radius: 6
});
}
}
}
createSlots() {
const slotCount = 7;
const slotValues = [1, 2, 5, 10, 5, 2, 1];
for (let i = 0; i < slotCount; i++) {
const slot = document.createElement('div');
slot.className = 'slot';
slot.textContent = slotValues[i];
slot.dataset.value = slotValues[i];
this.slotContainer.appendChild(slot);
this.slots.push({
element: slot,
value: slotValues[i],
x: (i + 0.5) * (this.gameBoard.clientWidth / slotCount),
width: this.gameBoard.clientWidth / slotCount
});
}
}
dropBall() {
if (this.isDropping || this.ballsLeft <= 0) return;
this.isDropping = true;
this.ballsLeft--;
const startX = this.gameBoard.clientWidth / 2;
const ball = document.createElement('div');
ball.className = 'ball';
ball.style.left = `${startX}px`;
ball.style.top = '30px';
this.gameBoard.appendChild(ball);
const ballObj = {
element: ball,
x: startX,
y: 30,
vx: (Math.random() - 0.5) * 2,
vy: 0,
radius: 10,
active: true
};
this.balls.push(ballObj);
this.animateBall(ballObj);
this.updateUI();
}
animateBall(ball) {
const gravity = 0.2;
const friction = 0.99;
const bounce = 0.7;
const animate = () => {
if (!ball.active) return;
// Apply gravity
ball.vy += gravity;
// Update position
ball.x += ball.vx;
ball.y += ball.vy;
// Check collisions with pegs
this.checkPegCollisions(ball);
// Check wall collisions
if (ball.x <= ball.radius || ball.x >= this.gameBoard.clientWidth - ball.radius) {
ball.vx *= -bounce;
ball.x = Math.max(ball.radius, Math.min(this.gameBoard.clientWidth - ball.radius, ball.x));
}
// Check if ball reached bottom
if (ball.y >= this.gameBoard.clientHeight - 60 - ball.radius) {
this.handleBallLanded(ball);
return;
}
// Apply friction
ball.vx *= friction;
ball.vy *= friction;
// Update ball position
ball.element.style.left = `${ball.x}px`;
ball.element.style.top = `${ball.y}px`;
requestAnimationFrame(animate);
};
animate();
}
checkPegCollisions(ball) {
for (const peg of this.pegs) {
const dx = ball.x - peg.x;
const dy = ball.y - peg.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < ball.radius + peg.radius) {
// Collision detected
const angle = Math.atan2(dy, dx);
const targetX = peg.x + Math.cos(angle) * (ball.radius + peg.radius);
const targetY = peg.y + Math.sin(angle) * (ball.radius + peg.radius);
const ax = (targetX - ball.x) * 0.1;
const ay = (targetY - ball.y) * 0.1;
ball.vx -= ax;
ball.vy -= ay;
// Add some random variation
ball.vx += (Math.random() - 0.5) * 0.5;
// Move ball outside peg
ball.x = targetX;
ball.y = targetY;
}
}
}
handleBallLanded(ball) {
ball.active = false;
this.isDropping = false;
// Find which slot the ball landed in
const slotIndex = this.findSlotForBall(ball.x);
if (slotIndex !== -1) {
const slotValue = this.slots[slotIndex].value;
const points = slotValue * this.multiplier;
this.score += points;
this.multiplier = Math.min(this.multiplier + 0.2, 5);
// Highlight the slot
this.slots[slotIndex].element.classList.add('active');
setTimeout(() => {
this.slots[slotIndex].element.classList.remove('active');
}, 1000);
// Remove ball after a delay
setTimeout(() => {
ball.element.remove();
this.balls = this.balls.filter(b => b !== ball);
}, 500);
}
this.updateUI();
// Check game over
if (this.ballsLeft === 0 && this.balls.length === 0) {
setTimeout(() => this.showGameOver(), 1000);
}
}
findSlotForBall(x) {
for (let i = 0; i < this.slots.length; i++) {
const slot = this.slots[i];
const slotLeft = slot.x - slot.width / 2;
const slotRight = slot.x + slot.width / 2;
if (x >= slotLeft && x <= slotRight) {
return i;
}
}
return -1;
}
updateUI() {
this.scoreElement.textContent = this.score;
this.ballsLeftElement.textContent = this.ballsLeft;
this.multiplierElement.textContent = `${this.multiplier.toFixed(1)}x`;
// Update button state
this.dropBallBtn.disabled = this.isDropping || this.ballsLeft <= 0;
}
showGameOver() {
this.finalScoreElement.textContent = this.score;
this.gameOverMessage.style.display = 'block';
}
resetGame() {
// Remove all balls
this.balls.forEach(ball => {
ball.element.remove();
});
this.balls = [];
this.score = 0;
this.ballsLeft = 10;
this.multiplier = 1;
this.isDropping = false;
this.gameOverMessage.style.display = 'none';
this.updateUI();
}
setupEventListeners() {
this.dropBallBtn.addEventListener('click', () => this.dropBall());
this.resetGameBtn.addEventListener('click', () => this.resetGame());
this.playAgainBtn.addEventListener('click', () => this.resetGame());
// Allow dropping ball by pressing spacebar
document.addEventListener('keydown', (e) => {
if (e.code === 'Space' && !this.isDropping && this.ballsLeft > 0) {
e.preventDefault();
this.dropBall();
}
});
}
}
// Initialize the game when the page loads
document.addEventListener('DOMContentLoaded', () => {
new PlinkoGame();
});
</script>
</body>
</html>