anycoder-0cdde324 / index.html
ApprikatAI's picture
Upload folder using huggingface_hub
4372718 verified
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tetris - Juego Completo</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary-color: #1a1a2e;
--secondary-color: #16213e;
--accent-color: #0f3460;
--tetris-blue: #00d9ff;
--tetris-purple: #e94560;
--tetris-yellow: #ffbe0b;
--tetris-green: #8ac926;
--tetris-red: #ff595e;
--tetris-orange: #ff9f1c;
--tetris-pink: #ff006e;
--tetris-cyan: #00f5ff;
--text-color: #ffffff;
--grid-size: 30px;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: var(--text-color);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
overflow-x: hidden;
}
header {
width: 100%;
text-align: center;
margin-bottom: 20px;
}
h1 {
font-size: 3rem;
margin-bottom: 10px;
background: linear-gradient(90deg, var(--tetris-blue), var(--tetris-purple));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 30px rgba(0, 217, 255, 0.5);
}
.built-with {
font-size: 0.9rem;
opacity: 0.8;
margin-top: 5px;
}
.built-with a {
color: var(--tetris-blue);
text-decoration: none;
transition: all 0.3s ease;
}
.built-with a:hover {
text-decoration: underline;
transform: scale(1.05);
}
.game-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 30px;
max-width: 1200px;
width: 100%;
}
.game-board {
background: rgba(0, 0, 0, 0.3);
border-radius: 10px;
padding: 10px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
border: 2px solid rgba(255, 255, 255, 0.1);
}
.grid {
display: grid;
grid-template-columns: repeat(10, var(--grid-size));
grid-template-rows: repeat(20, var(--grid-size));
gap: 1px;
background: rgba(0, 0, 0, 0.5);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.cell {
width: var(--grid-size);
height: var(--grid-size);
background: rgba(0, 0, 0, 0.8);
border-radius: 2px;
transition: all 0.1s ease;
}
.cell.filled {
border: 1px solid rgba(255, 255, 255, 0.3);
}
.cell.I { background-color: var(--tetris-cyan); }
.cell.O { background-color: var(--tetris-yellow); }
.cell.T { background-color: var(--tetris-purple); }
.cell.S { background-color: var(--tetris-green); }
.cell.Z { background-color: var(--tetris-red); }
.cell.J { background-color: var(--tetris-blue); }
.cell.L { background-color: var(--tetris-orange); }
.sidebar {
display: flex;
flex-direction: column;
gap: 20px;
min-width: 250px;
}
.info-panel {
background: rgba(0, 0, 0, 0.3);
border-radius: 10px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
border: 2px solid rgba(255, 255, 255, 0.1);
}
.info-panel h2 {
font-size: 1.5rem;
margin-bottom: 15px;
color: var(--tetris-blue);
}
.score-display, .level-display, .lines-display {
font-size: 1.2rem;
margin: 10px 0;
display: flex;
justify-content: space-between;
}
.score-value, .level-value, .lines-value {
font-weight: bold;
color: var(--tetris-yellow);
}
.next-piece-container {
margin-top: 20px;
}
.next-piece-grid {
display: grid;
grid-template-columns: repeat(4, 20px);
grid-template-rows: repeat(4, 20px);
gap: 1px;
background: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
margin: 10px auto;
width: fit-content;
}
.next-cell {
width: 20px;
height: 20px;
background: rgba(0, 0, 0, 0.8);
border-radius: 2px;
}
.next-cell.filled {
border: 1px solid rgba(255, 255, 255, 0.3);
}
.controls {
margin-top: 20px;
}
.control-button {
background: linear-gradient(135deg, var(--accent-color), var(--secondary-color));
color: var(--text-color);
border: none;
padding: 12px 24px;
border-radius: 5px;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s ease;
margin: 5px;
width: 100%;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
.control-button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
.control-button:active {
transform: translateY(0);
}
.control-button.play {
background: linear-gradient(135deg, var(--tetris-green), var(--tetris-blue));
}
.control-button.pause {
background: linear-gradient(135deg, var(--tetris-purple), var(--tetris-pink));
}
.instructions {
margin-top: 20px;
font-size: 0.9rem;
opacity: 0.8;
line-height: 1.5;
}
.game-over {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.9);
padding: 30px;
border-radius: 10px;
text-align: center;
display: none;
z-index: 100;
box-shadow: 0 0 50px rgba(0, 0, 0, 0.8);
}
.game-over h2 {
color: var(--tetris-red);
margin-bottom: 20px;
font-size: 2rem;
}
.game-over p {
margin-bottom: 20px;
font-size: 1.2rem;
}
.mobile-controls {
display: none;
flex-direction: column;
gap: 10px;
margin-top: 20px;
}
.control-row {
display: flex;
justify-content: center;
gap: 10px;
}
.mobile-button {
width: 60px;
height: 60px;
background: rgba(255, 255, 255, 0.1);
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
cursor: pointer;
transition: all 0.2s ease;
}
.mobile-button:active {
background: rgba(255, 255, 255, 0.2);
transform: scale(0.95);
}
@media (max-width: 768px) {
:root {
--grid-size: 20px;
}
h1 {
font-size: 2rem;
}
.sidebar {
min-width: 200px;
}
.next-piece-grid {
grid-template-columns: repeat(4, 15px);
grid-template-rows: repeat(4, 15px);
}
.next-cell {
width: 15px;
height: 15px;
}
.mobile-controls {
display: flex;
}
.control-button {
padding: 10px 20px;
font-size: 0.9rem;
}
}
@media (max-width: 480px) {
:root {
--grid-size: 15px;
}
h1 {
font-size: 1.5rem;
}
.game-container {
gap: 15px;
}
.sidebar {
min-width: 150px;
}
}
.particle {
position: absolute;
pointer-events: none;
opacity: 0;
animation: particle-float 1s ease-out forwards;
}
@keyframes particle-float {
0% {
opacity: 1;
transform: translateY(0) scale(1);
}
100% {
opacity: 0;
transform: translateY(-50px) scale(0.5);
}
}
</style>
</head>
<body>
<header>
<h1>Tetris</h1>
<div class="built-with">
Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
</div>
</header>
<main class="game-container">
<div class="game-board">
<div class="grid" id="gameGrid"></div>
</div>
<aside class="sidebar">
<div class="info-panel">
<h2>Puntuación</h2>
<div class="score-display">
<span>Puntos:</span>
<span class="score-value" id="score">0</span>
</div>
<div class="level-display">
<span>Nivel:</span>
<span class="level-value" id="level">1</span>
</div>
<div class="lines-display">
<span>Líneas:</span>
<span class="lines-value" id="lines">0</span>
</div>
</div>
<div class="info-panel next-piece-container">
<h2>Siguiente Pieza</h2>
<div class="next-piece-grid" id="nextPieceGrid"></div>
</div>
<div class="info-panel controls">
<button class="control-button play" id="startBtn">Iniciar Juego</button>
<button class="control-button pause" id="pauseBtn">Pausar</button>
<div class="instructions">
<p><strong>Controles:</strong></p>
<p>← → Mover</p>
<p>↑ Rotar</p>
<p>↓ Bajar rápido</p>
<p>Espacio: Dropear</p>
</div>
</div>
<div class="mobile-controls">
<div class="control-row">
<div class="mobile-button" id="rotateBtn"></div>
</div>
<div class="control-row">
<div class="mobile-button" id="leftBtn"></div>
<div class="mobile-button" id="downBtn"></div>
<div class="mobile-button" id="rightBtn"></div>
</div>
<div class="control-row">
<div class="mobile-button" id="dropBtn"></div>
</div>
</div>
</aside>
</main>
<div class="game-over" id="gameOver">
<h2>¡Juego Terminado!</h2>
<p>Puntuación final: <span id="finalScore">0</span></p>
<button class="control-button play" id="restartBtn">Reiniciar</button>
</div>
<script>
class Tetris {
constructor() {
this.grid = document.getElementById('gameGrid');
this.nextPieceGrid = document.getElementById('nextPieceGrid');
this.scoreElement = document.getElementById('score');
this.levelElement = document.getElementById('level');
this.linesElement = document.getElementById('lines');
this.gameOverElement = document.getElementById('gameOver');
this.finalScoreElement = document.getElementById('finalScore');
this.board = [];
this.currentPiece = null;
this.nextPiece = null;
this.score = 0;
this.level = 1;
this.lines = 0;
this.gameRunning = false;
this.gamePaused = false;
this.dropInterval = null;
this.dropSpeed = 1000;
this.boardWidth = 10;
this.boardHeight = 20;
this.pieces = [
{ name: 'I', shape: [[1,1,1,1]], color: 'I' },
{ name: 'O', shape: [[1,1],[1,1]], color: 'O' },
{ name: 'T', shape: [[0,1,0],[1,1,1]], color: 'T' },
{ name: 'S', shape: [[0,1,1],[1,1,0]], color: 'S' },
{ name: 'Z', shape: [[1,1,0],[0,1,1]], color: 'Z' },
{ name: 'J', shape: [[1,0,0],[1,1,1]], color: 'J' },
{ name: 'L', shape: [[0,0,1],[1,1,1]], color: 'L' }
];
this.init();
}
init() {
this.createBoard();
this.setupEventListeners();
this.renderNextPiece();
}
createBoard() {
this.board = Array(this.boardHeight).fill().map(() => Array(this.boardWidth).fill(0));
this.grid.innerHTML = '';
for (let y = 0; y < this.boardHeight; y++) {
for (let x = 0; x < this.boardWidth; x++) {
const cell = document.createElement('div');
cell.className = 'cell';
cell.dataset.x = x;
cell.dataset.y = y;
this.grid.appendChild(cell);
}
}
}
setupEventListeners() {
document.getElementById('startBtn').addEventListener('click', () => this.startGame());
document.getElementById('pauseBtn').addEventListener('click', () => this.togglePause());
document.getElementById('restartBtn').addEventListener('click', () => this.restartGame());
// Mobile controls
document.getElementById('rotateBtn').addEventListener('click', () => this.rotatePiece());
document.getElementById('leftBtn').addEventListener('click', () => this.movePiece(-1, 0));
document.getElementById('rightBtn').addEventListener('click', () => this.movePiece(1, 0));
document.getElementById('downBtn').addEventListener('click', () => this.movePiece(0, 1));
document.getElementById('dropBtn').addEventListener('click', () => this.dropPiece());
document.addEventListener('keydown', (e) => {
if (!this.gameRunning || this.gamePaused) return;
switch(e.key) {
case 'ArrowLeft':
e.preventDefault();
this.movePiece(-1, 0);
break;
case 'ArrowRight':
e.preventDefault();
this.movePiece(1, 0);
break;
case 'ArrowDown':
e.preventDefault();
this.movePiece(0, 1);
break;
case 'ArrowUp':
e.preventDefault();
this.rotatePiece();
break;
case ' ':
e.preventDefault();
this.dropPiece();
break;
}
});
}
startGame() {
if (this.gameRunning) return;
this.gameRunning = true;
this.gamePaused = false;
this.score = 0;
this.level = 1;
this.lines = 0;
this.dropSpeed = 1000;
this.updateScore();
this.createBoard();
this.spawnPiece();
this.startDrop();
}
togglePause() {
if (!this.gameRunning) return;
this.gamePaused = !this.gamePaused;
if (this.gamePaused) {
clearInterval(this.dropInterval);
} else {
this.startDrop();
}
}
restartGame() {
this.gameOverElement.style.display = 'none';
this.startGame();
}
spawnPiece() {
if (!this.nextPiece) {
this.nextPiece = this.getRandomPiece();
}
this.currentPiece = {
...this.nextPiece,
x: Math.floor(this.boardWidth / 2) - Math.floor(this.nextPiece.shape[0].length / 2),
y: 0
};
this.nextPiece = this.getRandomPiece();
this.renderNextPiece();
if (this.collision()) {
this.endGame();
}
}
getRandomPiece() {
const piece = this.pieces[Math.floor(Math.random() * this.pieces.length)];
return {
shape: piece.shape,
color: piece.color,
name: piece.name
};
}
renderNextPiece() {
this.nextPieceGrid.innerHTML = '';
for (let y = 0; y < 4; y++) {
for (let x = 0; x < 4; x++) {
const cell = document.createElement('div');
cell.className = 'next-cell';
if (this.nextPiece &&
y < this.nextPiece.shape.length &&
x < this.nextPiece.shape[0].length &&
this.nextPiece.shape[y][x]) {
cell.classList.add('filled', `cell.${this.nextPiece.color}`);
}
this.nextPieceGrid.appendChild(cell);
}
}
}
startDrop() {
clearInterval(this.dropInterval);
this.dropInterval = setInterval(() => {
this.movePiece(0, 1);
}, this.dropSpeed);
}
movePiece(dx, dy) {
if (!this.currentPiece || this.gamePaused) return;
this.currentPiece.x += dx;
this.currentPiece.y += dy;
if (this.collision()) {
this.currentPiece.x -= dx;
this.currentPiece.y -= dy;
if (dy > 0) {
this.lockPiece();
}
}
this.render();
}
rotatePiece() {
if (!this.currentPiece || this.gamePaused) return;
const rotated = this.rotateMatrix(this.currentPiece.shape);
const previousShape = this.currentPiece.shape;
this.currentPiece.shape = rotated;
if (this.collision()) {
this.currentPiece.shape = previousShape;
} else {
this.render();
}
}
rotateMatrix(matrix) {
const rows = matrix.length;
const cols = matrix[0].length;
const rotated = Array(cols).fill().map(() => Array(rows).fill(0));
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
rotated[j][rows - 1 - i] = matrix[i][j];
}
}
return rotated;
}
dropPiece() {
if (!this.currentPiece || this.gamePaused) return;
while (!this.collision()) {
this.currentPiece.y++;
}
this.currentPiece.y--;
this.lockPiece();
}
collision() {
for (let y = 0; y < this.currentPiece.shape.length; y++) {
for (let x = 0; x < this.currentPiece.shape[y].length; x++) {
if (this.currentPiece.shape[y][x]) {
const boardX = this.currentPiece.x + x;
const boardY = this.currentPiece.y + y;
if (boardX < 0 || boardX >= this.boardWidth ||
boardY >= this.boardHeight ||
(boardY >= 0 && this.board[boardY][boardX])) {
return true;
}
}
}
}
return false;
}
lockPiece() {
for (let y = 0; y < this.currentPiece.shape.length; y++) {
for (let x = 0; x < this.currentPiece.shape[y].length; x++) {
if (this.currentPiece.shape[y][x]) {
const boardY = this.currentPiece.y + y;
const boardX = this.currentPiece.x + x;
if (boardY >= 0) {
this.board[boardY][boardX] = this.currentPiece.color;
}
}
}
}
this.clearLines();
this.spawnPiece();
}
clearLines() {
let linesCleared = 0;
for (let y = this.boardHeight - 1; y >= 0; y--) {
if (this.board[y].every(cell => cell !== 0)) {
this.board.splice(y, 1);
this.board.unshift(Array(this.boardWidth).fill(0));
linesCleared++;
y++;
}
}
if (linesCleared > 0) {
this.lines += linesCleared;
this.score += linesCleared * 100 * this.level;
if (this.lines >= this.level * 10) {
this.level++;
this.dropSpeed = Math.max(100, this.dropSpeed - 100);
if (this.gameRunning && !this.gamePaused) {
this.startDrop();
}
}
this.updateScore();
this.createParticles();
}
}
createParticles() {
const colors = ['var(--tetris-blue)', 'var(--tetris-purple)', 'var(--tetris-yellow)',
'var(--tetris-green)', 'var(--tetris-red)', 'var(--tetris-orange)'];
for (let i = 0; i < 10; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
particle.style.left = Math.random() * window.innerWidth + 'px';
particle.style.top = window.innerHeight / 2 + 'px';
particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
particle.style.width = Math.random() * 10 + 5 + 'px';
particle.style.height = particle.style.width;
document.body.appendChild(particle);
setTimeout(() => particle.remove(), 1000);
}
}
updateScore() {
this.scoreElement.textContent = this.score;
this.levelElement.textContent = this.level;
this.linesElement.textContent = this.lines;
}
render() {
const cells = this.grid.querySelectorAll('.cell');
cells.forEach(cell => {
cell.className = 'cell';
});
// Render locked pieces
for (let y = 0; y < this.boardHeight; y++) {
for (let x = 0; x < this.boardWidth; x++) {
if (this.board[y][x]) {
const index = y * this.boardWidth + x;
cells[index].classList.add('filled', `cell.${this.board[y][x]}`);
}
}
}
// Render current piece
if (this.currentPiece) {
for (let y = 0; y < this.currentPiece.shape.length; y++) {
for (let x = 0; x < this.currentPiece.shape[y].length; x++) {
if (this.currentPiece.shape[y][x]) {
const boardX = this.currentPiece.x + x;
const boardY = this.currentPiece.y + y;
if (boardY >= 0 && boardY < this.boardHeight &&
boardX >= 0 && boardX < this.boardWidth) {
const index = boardY * this.boardWidth + boardX;
cells[index].classList.add('filled', `cell.${this.currentPiece.color}`);
}
}
}
}
}
}
endGame() {
this.gameRunning = false;
clearInterval(this.dropInterval);
this.finalScoreElement.textContent = this.score;
this.gameOverElement.style.display = 'block';
}
}
// Initialize the game when the page loads
document.addEventListener('DOMContentLoaded', () => {
new Tetris();
});
</script>
</body>
</html>