
Definindo o Ano Atual como Valor Padrão em Migrations do Laravel
Ao trabalhar com migrations no Laravel, uma tarefa comum é definir valores padrão para colunas em tabelas de banco de... Leia mais
Desenvolvedor de Software
E vamos a mais um tutorial de outro joguinho clássico só que dessa vez vamos recriar o Tetris.
Link do repositório: https://github.com/paulodm145/tetris
/projeto-tetris
│
├── index.html
├── styles.css
└── script.js
Este arquivo contém a estrutura básica da página do jogo.
<!DOCTYPE html>
<html lang="pt">
<head>
<meta charset="UTF-8">
<title>Tetris</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="tetris-container">
<div id="score">Pontuação: <span>0</span></div>
<div id="tetris"></div>
<div class="buttons">
<button id="restart">Reiniciar</button>
<button id="pause">Pausar</button>
<button id="reset-score">Zerar Pontuação</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
#tetris
), a exibição da pontuação e os botões de controle.Este arquivo contém os estilos do jogo.
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #e0e0e0;
font-family: Arial, sans-serif;
margin: 0;
}
#tetris-container {
display: flex;
flex-direction: column;
align-items: center;
}
#tetris {
width: 300px;
height: 600px;
border: 2px solid #333;
background-color: #fff;
display: grid;
grid-template-columns: repeat(10, 1fr);
grid-template-rows: repeat(20, 1fr);
gap: 1px;
margin-bottom: 20px;
}
#tetris div {
background-color: #f0f0f0;
box-sizing: border-box;
}
#score {
font-size: 1.5em;
color: #333;
margin-bottom: 10px;
}
#score span {
font-weight: bold;
}
.buttons {
display: flex;
gap: 10px;
}
button {
padding: 10px 20px;
font-size: 1em;
color: #fff;
background-color: #007bff;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
Este arquivo contém a lógica do jogo de Tetris.
document.addEventListener('DOMContentLoaded', () => {
const grid = document.querySelector('#tetris');
const width = 10;
let timerId;
let score = 0;
const colors = ['orange', 'red', 'purple', 'green', 'blue'];
// Criar a grade e preencher com divs
function createBoard() {
for (let i = 0; i < 200; i++) { // 200 divs para o tabuleiro
let square = document.createElement('div');
grid.appendChild(square);
}
for (let i = 0; i < 10; i++) { // 10 divs para a linha de base
let square = document.createElement('div');
square.classList.add('taken');
grid.appendChild(square);
}
}
createBoard();
let squares = Array.from(grid.querySelectorAll('div'));
const scoreDisplay = document.querySelector('#score span');
let nextRandom = 0; // inicialização correta de nextRandom
// Os Tetrominos e suas rotações
const lTetromino = [
[1, width+1, width*2+1, 2],
[width, width+1, width+2, width*2+2],
[1, width+1, width*2+1, width*2],
[width, width*2, width*2+1, width*2+2]
];
const zTetromino = [
[0, width, width+1, width*2+1],
[width+1, width+2, width*2, width*2+1],
[0, width, width+1, width*2+1],
[width+1, width+2, width*2, width*2+1]
];
const tTetromino = [
[1, width, width+1, width+2],
[1, width+1, width+2, width*2+1],
[width, width+1, width+2, width*2+1],
[1, width, width+1, width*2+1]
];
const oTetromino = [
[0, 1, width, width+1],
[0, 1, width, width+1],
[0, 1, width, width+1],
[0, 1, width, width+1]
];
const iTetromino = [
[1, width+1, width*2+1, width*3+1],
[width, width+1, width+2, width+3],
[1, width+1, width*2+1, width*3+1],
[width, width+1, width+2, width+3]
];
const theTetrominos = [lTetromino, zTetromino, tTetromino, oTetromino, iTetromino];
let currentPosition = 4;
let currentRotation = 0;
let random = Math.floor(Math.random() * theTetrominos.length);
let current = theTetrominos[random][currentRotation];
// Desenhar o Tetromino
function draw() {
current.forEach(index => {
squares[currentPosition + index].style.backgroundColor = colors[random];
});
}
// Desfazer o desenho do Tetromino
function undraw() {
current.forEach(index => {
squares[currentPosition + index].style.backgroundColor = '';
});
}
// Fazer o Tetromino cair a cada segundo
timerId = setInterval(moveDown, 1000);
// Mover Tetromino para baixo
function moveDown() {
undraw();
currentPosition += width;
draw();
freeze();
}
// Congelar quando o Tetromino atinge o fundo da grade
function freeze() {
if (current.some(index => squares[currentPosition + index + width].classList.contains('taken'))) {
current.forEach(index => squares[currentPosition + index].classList.add('taken'));
random = nextRandom;
nextRandom = Math.floor(Math.random() * theTetrominos.length);
current = theTetrominos[random][currentRotation];
currentPosition = 4;
draw();
addScore();
gameOver();
}
}
// Adicionar pontuação
function addScore() {
for (let i = 0; i < 199; i += width) {
const row = [i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9];
if (row.every(index => squares[index].classList.contains('taken'))) {
score += 10;
scoreDisplay.innerText = score;
row.forEach(index => {
squares[index].classList.remove('taken');
squares[index].style.backgroundColor = '';
});
const squaresRemoved = squares.splice(i, width);
squares = squaresRemoved.concat(squares);
squares.forEach(cell => grid.appendChild(cell));
}
}
}
// Verificar o fim do jogo
function gameOver() {
if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
scoreDisplay.innerText = 'Fim de jogo';
clearInterval(timerId);
}
}
document.addEventListener('keyup', control);
function control(e) {
if (e.keyCode === 37) {
moveLeft();
} else if (e.keyCode === 38) {
rotate();
} else if (e.keyCode === 39) {
moveRight();
} else if (e.keyCode === 40) {
moveDown();
}
}
function moveLeft() {
undraw();
const isAtLeftEdge = current.some(index => (currentPosition + index) % width === 0);
if (!isAtLeftEdge) currentPosition -= 1;
if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
currentPosition += 1;
}
draw();
}
function moveRight() {
undraw();
const isAtRightEdge = current.some(index => (currentPosition + index) % width === width - 1);
if (!isAtRightEdge) currentPosition += 1;
if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
currentPosition -= 1;
}
draw();
}
function rotate() {
undraw();
currentRotation++;
if (currentRotation === current.length) {
currentRotation = 0;
}
current = theTetrominos[random][currentRotation];
draw();
}
document.querySelector('#restart').addEventListener('click', () => {
clearInterval(timerId);
score = 0;
scoreDisplay.innerText = score;
nextRandom = 0;
createBoard();
random = Math.floor(Math.random() * theTetrominos.length);
current = theTetrominos[random][currentRotation];
currentPosition = 4;
draw();
timerId = setInterval(moveDown, 1000);
});
document.querySelector('#pause').addEventListener('click', () => {
if (timerId) {
clearInterval(timerId);
timerId = null;
document.querySelector('#pause').innerText = 'Retomar';
} else {
timerId = setInterval(moveDown, 1000);
document.querySelector('#pause').innerText = 'Pausar';
}
});
document.querySelector('#reset-score').addEventListener('click', () => {
score = 0;
scoreDisplay.innerText = score;
});
});
index.html
em um navegador web.Ao trabalhar com migrations no Laravel, uma tarefa comum é definir valores padrão para colunas em tabelas de banco de... Leia mais
Neste tutorial, vamos aprender como exportar uma lista de cadastros de clientes para uma planilha Excel, incluindo as fotos dos... Leia mais
O método PDO::pgsqlCopyFromArray permite copiar dados de um array diretamente para uma tabela no PostgreSQL. Este tutorial mostra como usar... Leia mais
Este tutorial rápido e objetivo vai te mostrar como instalar e configurar o OpenSSH no Ubuntu, além de incluir algumas... Leia mais