이번 시리즈에서는 보드와 현재 화면에 내려가고 있는 작품을 어떻게 표시하는지 살펴보겠습니다. 이렇게 하려면 브라우저에서 그려야 하며, 그렇게 해야 하는 옵션은 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... }
이 캔버스 클래스는 생성자에서 매개변수로 전달되는 동일한 이름의 HTML 요소를 나타냅니다. 보드를 그릴 예정이므로 그릴 포인트에 접근하기 위해 매개변수로도 전달됩니다.
가장 먼저 하는 일은 보드 자체가 열 및 행을 통해 보고하는 크기에 따라 보드를 수용할 수 있도록 캔버스 요소의 크기를 조정하는 것입니다. . 보드는 또한 PIXEL_SIZE를 통해 보드의 각 조각 또는 각 셀이 몇 개의 픽셀을 점으로 구성하는지 알려줍니다.
게임을 다시 그리다
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 ); } }먼저 캔버스에 그림을 그릴 수 있는 2D의 맥락을 살펴보겠습니다. 호기심에 WebGL을 기반으로 하는 3D에 대한 맥락도 있습니다.
여러 스레드가 동시에(다른 지점에서) 특정 시간에 메서드를 실행하는 것을 방지하는 가드(
_painting)가 있습니다. 다시 그리기 사이의 시간보다 오랫동안 메서드가 실행된 경우 이런 일이 발생할 수 있습니다. 뭐, 그렇게 되면 다른 문제도 많이 생기겠지만...
다음 단계는 이전 다시 그리기에서 화면에 있던 내용(프레임)을 삭제하는 것입니다. clearRect()를 사용하여 캔버스의 이미지를 삭제하는 clear() 메서드를 사용하여 이 작업을 수행합니다.
그런 다음 보드를 칠한 다음 그 순간에 내려오는 조각을 칠합니다. 글쎄, 그게 다야. 에일 배송완료.안돼. 보드와 조각이 어떻게 칠해지는지 봅시다. 가장 먼저 할 일은 보드를 그리는 것입니다. SEP는 조각과 보드 사각형 사이에 남겨두는 분리입니다. 이 상자는
Draw Frame이라는 코드 단락에서 가장 먼저 그리는 것입니다. 스트로크Rect()를 사용하여 그릴 수 있는 간단한 직사각형입니다. 이 직사각형은 왼쪽 상단 꼭지점의 위치와 너비, 높이를 포함하는 4개의 매개변수를 받습니다.
보드 페인팅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; numRow < this.board.rows; ++numRow) { const row = this.board.getRow( numRow ); for(let numCol = 0; numCol < row.length; ++numCol) { if ( Boolean( row[ numCol ] ) ) { ctx.strokeWidth = 1; ctx.strokeStyle = this.board.color; ctx.fillStyle = this.board.color; ctx.fillRect( SEP + ( Board.PIXEL_SIZE * numCol ), SEP + ( Board.PIXEL_SIZE * numRow ), Board.PIXEL_SIZE, Board.PIXEL_SIZE ); } } } return; } }다음에는 중첩 루프(행과 열)가 나오므로 보드의 어느 셀에 내용(정수 1과 정수 0)이 있는지 확인한 다음 변이 PIXEL_SIZE인 작은 정사각형을 그립니다.
그래서 첫 번째 루프는
Board.행까지 행을 통과합니다. 그런 다음 Board.cols.까지 내부 루프를 통해 순회하기 위해 getRow() 메서드를 사용하여 전체 행을 얻습니다.
행/열의 셀f/c, Board.getCell(f, c) 및 JavaScript에는 0을 제외한 모든 값이 true를 의미하는 정수를 허용하는 Boolean에 대한 생성자가 있다는 점을 고려하여 변이 PIXEL_SIZE인 정사각형을 그립니다. 따라서 f 행을 어디에 칠해야 할지 알려면 PIXEL_SIZE를 곱하고 보드 상자와 첫 번째 셀 사이에 간격을 추가해야 합니다. 정사각형이므로 SEP + (c * PIXEL_SIZE)와 같은 방식으로 c 열을 찾습니다.
작품을 그림shape)을 가짐으로써 우리는 다시 두 개의 루프, 즉 행을 위한 외부 루프와 열을 위한 내부 루프를 갖게 됩니다.
class Canvas { // más cosas... paintPiece(ctx, SEP) { const SHAPE = this.piece.shape; for(let numRow = 0; numRow < SHAPE.length; ++numRow) { const ROW = SHAPE[ numRow ]; for(let numCol = 0; numCol < ROW.length; ++numCol) { if ( Boolean( ROW[ numCol ] ) ) { ctx.strokeWidth = 1; ctx.strokeStyle = this.piece.color; ctx.fillStyle = this.piece.color; ctx.fillRect( SEP + ( this.piece.col * Board.PIXEL_SIZE ) + ( numCol * Board.PIXEL_SIZE ), SEP + + ( this.piece.row * Board.PIXEL_SIZE ) + ( numRow * Board.PIXEL_SIZE ), Board.PIXEL_SIZE, Board.PIXEL_SIZE ); } } } return; } }다시 1을 찾으면 변이 PIXEL_SIZE인 정사각형을 칠합니다. 조각을 구성하는 각 사각형을 칠하는 위치는 행/열 조각 자체의 위치(
Piece.row/Piece. 열 ). 여기에 PIXEL_SIZE를 곱하고 상자로 구분을 추가해야 합니다.
현재 우리가 볼 수 있는 것은 꽤... 평범합니다. 보드는 비어 있고 게임 루프도 없으므로 조각이 내려가지도 않습니다. 위의 이미지와 유사한 내용을 볼 수 있도록 다음 회에서 해당 주제에 대해 논의하겠습니다.
위 내용은 JavaScript IV로 테트리스 만들기: 캔버스의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!