<!DOCTYPE html>
<html>
<head>
    <title>Tetris</title>
    <style>
        body {
            background-color: #000000;
        }
<pre><code>    #canvas {
        background-color: #FFFFFF;
        border: 5px solid #000000;
        margin-left: auto;
        margin-right: auto;
        display: block;
    }
&lt;/style&gt;
</code></pre>
</head>
<body>
    <h1 style="text-align: center; color: #FFFFFF;">Tetris</h1>
    <div style="text-align: center;">
        <canvas id="canvas" width="400" height="600"></canvas>
    </div>
    <script>
        const canvas = document.getElementById("canvas");
        const ctx = canvas.getContext("2d");
<pre><code>    // constants
    const ROW = 20;
    const COL = COLUMN = 10;
    const SQ = squareSize = 20;
    const VACANT = 'WHITE'; // color of an empty square

    // draw a square
    function drawSquare(x,y,color){
        ctx.fillStyle = color;
        ctx.fillRect(x*SQ,y*SQ,SQ,SQ);

        ctx.strokeStyle = 'BLACK';
        ctx.strokeRect(x*SQ,y*SQ,SQ,SQ);
    }

    // create the board
    let board = [];
    for( r = 0; r &lt;ROW; r++){
        board[r] = [];
        for(c = 0; c &lt; COL; c++){
            board[r][c] = VACANT;
        }
    }

    // draw the board
    function drawBoard(){
        for( r = 0; r &lt;ROW; r++){
            for(c = 0; c &lt; COL; c++){
                drawSquare(c,r,board[r][c]);
            }
        }
    }

    drawBoard();

    // the pieces and their colors
    const PIECES = [
        [Z,'red'],
        [S,'green'],
        [T,'yellow'],
        [O,'blue'],
        [L,'purple'],
        [I,'cyan'],
        [J,'orange']
    ];

    // generate random pieces
    function randomPiece(){
        let r = randomN = Math.floor(Math.random() * PIECES.length) // 0 -&gt; 6
        return new Piece( PIECES[r][0],PIECES[r][1]);
    }

    let p = randomPiece();

    // The Object Piece
    function Piece(tetromino,color){
        this.tetromino = tetromino;
        this.color = color;
        
        this.tetrominoN = 0; // we start from the first pattern
        this.activeTetromino = this.tetromino[this.tetrominoN];
        
        // we need to control the pieces
        this.x = 3;
        this.y = -2;
    }

    // fill function
    Piece.prototype.fill = function(color){
        for( r = 0; r &lt; this.activeTetromino.length; r++){
            for(c = 0; c &lt; this.activeTetromino.length; c++){
                // we draw only occupied squares
                if( this.activeTetromino[r][c]){
                    drawSquare(this.x + c,this.y + r, color);
                }
            }
        }
    }

    // draw a piece to the board
    Piece.prototype.draw = function(){
        this.fill(this.color);
    }

    // undraw a piece
    Piece.prototype.unDraw = function(){
        this.fill(VACANT);
    }

    // move Down the piece
    Piece.prototype.moveDown = function(){
        if(!this.collision(0,1,this.activeTetromino)){
            this.unDraw();
            this.y++;
            this.draw();
        }else{
            // we lock the piece and generate a new one
            this.lock();
            p = randomPiece();
        }
        
    }

    // move Right the piece
    Piece.prototype.moveRight = function(){
        if(!this.collision(1,0,this.activeTetromino)){
            this.unDraw();
            this.x++;
            this.draw();
        }
    }

    // move Left the piece
    Piece.prototype.moveLeft = function(){
        if(!this.collision(-1,0,this.activeTetromino)){
            this.unDraw();
            this.x--;
            this.draw();
        }
    }

    // rotate the piece
    Piece.prototype.rotate = function(){
        let nextPattern = this.tetromino[(this.tetrominoN + 1)%this.tetromino.length];
        let kick = 0;
        
        if(this.collision(0,0,nextPattern)){
            if(this.x &gt; COL/2){
                // it's the right wall
                kick = -1; // we need to move the piece to the left
            }else{
                // it's the left wall
                kick = 1; // we need to move the piece to the right
            }
        }
        
        if(!this.collision(kick,0,nextPattern)){
            this.unDraw();
            this.x += kick;
            this.tetrominoN = (this.tetrominoN + 1)%this.tetromino.length; // (0+1)%4 =&gt; 1
            this.activeTetromino = this.tetromino[this.tetrominoN];
            this.draw();
        }
    }

    let score = 0;
    // lock the piece
    Piece.prototype.lock = function(){
        for( r = 0; r &lt; this.activeTetromino.length; r++){
            for(c = 0; c &lt; this.activeTetromino.length; c++){
                // we skip the vacant squares
                if( !this.activeTetromino[r][c]){
                    continue;
                }
                // pieces to lock on top = game over
                if(this.y + r &lt; 0){
                    alert('Game Over');
                    // stop request animation frame
                    gameOver = true;
                    break;
                }
                // we lock the piece
                board[this.y+r][this.x+c] = this.color;
            }
        }
        // remove full rows
        for(r = 0; r &lt; ROW; r++){
            let isRowFull = true;
            for( c = 0; c &lt; COL; c++){
                isRowFull = isRowFull &amp;&amp; (board[r][c] != VACANT);
            }
            if(isRowFull){
                // if the row is full
                // we move down all the rows above it
                for( y = r; y &gt; 1; y--){
                    for( c = 0; c &lt; COL; c++){
                        board[y][c] = board[y-1][c];
                    }
                }
                // the top row board[0][..] has no row above it
                for( c = 0; c &lt; COL; c++){
                    board[0][c] = VACANT;
                }
                // increment the score
                score += 10;
            }
        }
        // update the board
        drawBoard();
        
        // update the score
        scoreElement.innerHTML = score;
    }

    // collision fucntion
    Piece.prototype.collision = function(x,y,piece){
        for( r = 0; r &lt; piece.length; r++){
            for(c = 0; c &lt; piece.length; c++){
                // if the square is empty, we skip it
                if(!piece[r][c]){
                    continue;
                }
                // coordinates of the piece after movement
                let newX = this.x + c + x;
                let newY = this.y + r + y;
                
                // conditions
                if(newX &lt; 0 || newX &gt;= COL || newY &gt;= ROW){
                    return true;
                }
                // skip newY &lt; 0
                if(newY &lt; 0){
                    continue;
                }
                // check if the piece collides with the board
                if(board[newY][newX] != VACANT){
                    return true;
                }
            }
        }
        return false;
    }

    // control the piece
    document.addEventListener('keydown', (event) =&gt; {
        if(event.keyCode === 37){ // left arrow
            p.moveLeft();
        }else if(event.keyCode === 38){ // up arrow
            p.rotate();
        }else if(event.keyCode === 39){ // right arrow
            p.moveRight();
        }else if(event.keyCode === 40){ // down arrow
            p.moveDown();
        }
    });

    // setInterval to move the piece down every 1 second
    setInterval(function(){
        p.moveDown();
    },1000);

&lt;/script&gt;
</code></pre>
</body>
</htm

原文地址: https://www.cveoy.top/t/topic/lmug 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录