Nesta nova edição da série, veremos como exibir o tabuleiro e a peça que está caindo na tela. Para isso teremos que desenhá-lo no navegador, e a opção que temos para fazer isso é o elemento HTML Canvas.
class Canvas { static SEPARATION = 2; #_painting = false; #_element = null; #_board = null; #_piece = null; constructor(element, board) { element.width = 5 ( board.cols * Board.PIXEL_SIZE ); element.height = 5 ( board.rows * Board.PIXEL_SIZE ); this._board = board; this._element = element; } // más cosas... }
Esta classe Canvas representa o elemento HTML de mesmo nome, que é passado como parâmetro no construtor. Como você vai desenhar o tabuleiro, ele também é passado como parâmetro, para acessar os pontos a serem desenhados.
A primeira coisa que ele faz é dimensionar o elemento Canvas para acomodar o quadro, de acordo com as dimensões que o próprio quadro informa através de suas propriedades cols e rows. O tabuleiro também nos informa quantos pixels compõem um ponto de cada peça ou de cada célula do tabuleiro, através de PIXEL_SIZE.
Vamos parar com os desvios. Temos que pintar o tabuleiro e a peça que está descendo naquele momento, certo? Bem, vamos lá.
class Canvas { // más cosas... paint() { if ( this._painting ) { return; } const ctx = this.element.getContext( "2d" ); const SEP = Canvas.SEPARATION; this._painting = true; this.clear(); this.paintBoard( ctx, SEP ); this.paintPiece( ctx, SEP ); this._painting = false; } clear() { const ctx = this.element.getContext( "2d" ); ctx.clearRect( 0, 0, this.element.width, this.element.height ); } }
Primeiro pegamos o contexto para 2D, o que nos permitirá desenhar na tela. A título de curiosidade, existe também um contexto para 3D, que é baseado em WebGL.
Temos algumas proteções (_painting), que impedem que diversas threads executem o método ao mesmo tempo (em pontos diferentes), em um determinado momento. Isso poderia acontecer se o método fosse executado por mais tempo do que o tempo entre os redesenhos. Embora bem, nesse caso teríamos muitos outros problemas...
O próximo passo é deletar o que estava na tela no redesenho anterior (quadro). Fazemos isso com o método clear(), que usa clearRect() para excluir a imagem na tela.
E aí a gente pinta o quadro, e depois a peça que desce naquele momento. Bem, seria isso. Ale, entrega concluída.
Eu disse não. Vamos ver como o tabuleiro e a peça são pintados. A primeira coisa é pintar o quadro. SEP é a separação que deixaremos entre as peças e o quadrado do tabuleiro. Esta caixa é a primeira coisa que desenhamos no parágrafo de código intitulado Draw frame. É um retângulo simples que pode ser desenhado com strokeRect(), que aceita quatro parâmetros com a posição do vértice superior esquerdo, e depois sua largura e altura.
class Canvas { // más cosas... paintBoard(ctx, SEP) { // Draw frame ctx.strokeWidth = 1; ctx.strokeStyle = this.board.color; ctx.strokeRect( 1, 1, this.element.width - 1, this.element.height -1 ); // Draw board for(let numRow = 0; numRowEm seguida vem um loop aninhado (linhas e colunas), então veremos quais das células do quadro têm conteúdo (um número inteiro 1, versus um número inteiro 0) e, em seguida, desenharemos um pequeno quadrado com lado PIXEL_SIZE.
Assim, o primeiro loop percorre as linhas até Board.rows. Obtemos então a linha completa com o método getRow(), para percorrê-la com o loop interno, até Board.cols.
Então, dada uma célula na linha/coluna f/c, Board.getCell(f, c), e levando em consideração que JavaScript possui um construtor para Boolean que aceita um inteiro que com qualquer valor exceto 0, significa true, pintamos um quadrado com lado PIXEL_SIZE. Então, para saber onde pintar a linha f, temos que multiplicar por PIXEL_SIZE e somar a separação entre a caixa do tabuleiro e a primeira célula. Como são quadradas, encontraremos a coluna c da mesma forma: SEP (c * PIXEL_SIZE).
Pintando a peça
Fazemos algo parecido com as peças. Por termos uma forma (shape), que nada mais é do que uma matriz, teremos novamente dois loops, o externo para linhas e o interno para colunas.
class Canvas { // más cosas... paintPiece(ctx, SEP) { const SHAPE = this.piece.shape; for(let numRow = 0; numRowNovamente, se encontrarmos 1, pintaremos um quadrado com lado PIXEL_SIZE. A posição para pintar cada quadrado que compõe a peça é dada pela posição da linha/coluna da própria peça (Peça.linha/Peça. repolho). Você tem que multiplicar isso por PIXEL_SIZE e adicionar a separação com a caixa.
No momento, o que poderemos ver é bastante... insípido. O tabuleiro está vazio e não temos loop de jogo, então as peças nem caem. Discutiremos esse assunto na próxima edição, para que possamos começar a ver algo semelhante à imagem acima.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3