Как установить изображение для каждого прямоугольника шаблона по отдельности в Тетрисе

#javascript #canvas #html5-canvas

#javascript #холст #html5-холст

Вопрос:

Я играл здесь с игрой в тетрис. Я хотел добавить изображение в каждое отдельное поле в падающем шаблоне.

Я немного изменил render.js файл для предварительной загрузки изображения и добавления его, если это оранжевое изображение, поэтому вместо оранжевых цветных прямоугольников я мог видеть, что каждый rect в шаблоне содержит изображение.

Но каким-то образом изображение отображается в полном шаблоне, когда я устанавливаю createpattern as repeat , и оно не отображается, если я устанавливаю createpattern as no-repeat .

Может ли кто-нибудь помочь мне здесь, пожалуйста?

Вот render.js после настройки:

 var canvas = document.getElementsByTagName( 'canvas' )[ 0 ];
var ctx = canvas.getContext( '2d' );
var W = 300, H = 600;
var BLOCK_W = W / COLS, BLOCK_H = H / ROWS;


var img,ptrn;
function setColors(){
    img = new Image();
    img.src = 'img/wood.png';
    img.onload = function(){
      console.log('Inside orangeload');
      // create pattern
      ptrn = ctx.createPattern(orangeImg, 'repeat'); // Create a pattern with this image, and set it to "repeat".

  }
}

setColors();

// draw a single square at (x, y)
function drawBlock( x, y ) {
    ctx.fillRect( BLOCK_W * x, BLOCK_H * y, BLOCK_W - 1 , BLOCK_H - 1 );
    ctx.strokeRect( BLOCK_W * x, BLOCK_H * y, BLOCK_W - 1 , BLOCK_H - 1 );
}

// draws the board and the moving shape
function render() {
    ctx.clearRect( 0, 0, W, H );

    ctx.strokeStyle = 'black';
    for ( var x = 0; x < COLS;   x ) {
        for ( var y = 0; y < ROWS;   y ) {
            if ( board[ y ][ x ] ) {
                ctx.fillStyle = colors[ board[ y ][ x ] - 1 ];
                drawBlock( x, y );
            }
        }
    }

    ctx.fillStyle = 'red';
    ctx.strokeStyle = 'black';
    for ( var y = 0; y < 4;   y ) {
        for ( var x = 0; x < 4;   x ) {
            if ( current[ y ][ x ] ) {
              if((colors[board[ y ][ x ]-1]) == 'orange'){
                ctx.fillStyle = ptrn;
              }else{
                ctx.fillStyle = colors[ board[ y ][ x ] - 1 ];
              }
                drawBlock( currentX   x, currentY   y );
            }
        }
    }
}
  

Ответ №1:

Если я правильно понимаю, вам нужна другая текстура для предоставленного тетриса, для достижения этой цели вы можете использовать функцию canvas drawImage

 var COLS = 10, ROWS = 20;
var board = [];
var lose;
var interval;
var current; // current moving shape
var currentX, currentY; // position of current shape
var shapes = [
    [ 1, 1, 1, 1 ],
    [ 1, 1, 1, 0,
      1 ],
    [ 1, 1, 1, 0,
      0, 0, 1 ],
    [ 1, 1, 0, 0,
      1, 1 ],
    [ 1, 1, 0, 0,
      0, 1, 1 ],
    [ 0, 1, 1, 0,
      1, 1 ],
    [ 0, 1, 0, 0,
      1, 1, 1 ]
];
let images = [];
let imagePaths = ["https://opengameart.org/sites/default/files/forum-attachments/grass20.png","https://www.hioutlet.com/sm/product/24540/Saddle-swash.jpg"];

let chosenPic = 0;

var colors = [
    'cyan', 'orange', 'blue', 'yellow', 'red', 'green', 'purple'
];

// creates a new 4x4 shape in global variable 'current'
// 4x4 so as to cover the size when the shape is rotated
function newShape() {
    var id = Math.floor( Math.random() * shapes.length );
    var shape = shapes[ id ]; // maintain id for color filling

    current = [];
    for ( var y = 0; y < 4;   y ) {
        current[ y ] = [];
        for ( var x = 0; x < 4;   x ) {
            var i = 4 * y   x;
            if ( typeof shape[ i ] != 'undefined' amp;amp; shape[ i ] ) {
                current[ y ][ x ] = id   1;
            }
            else {
                current[ y ][ x ] = 0;
            }
        }
    }
    // position where the shape will evolve
    currentX = 5;
    currentY = 0;
}

// clears the board
function init() {
    for ( var y = 0; y < ROWS;   y ) {
        board[ y ] = [];
        for ( var x = 0; x < COLS;   x ) {
            board[ y ][ x ] = 0;
        }
    }
}

// keep the element moving down, creating new shapes and clearing lines
function tick() {
    if ( valid( 0, 1 ) ) {
          currentY;
    }
    // if the element settled
    else {
        freeze();
        clearLines();
        if (lose) {
            newGame();
            return false;
        }
        newShape();
    }
}

// stop shape at its position and fix it to board
function freeze() {
    for ( var y = 0; y < 4;   y ) {
        for ( var x = 0; x < 4;   x ) {
            if ( current[ y ][ x ] ) {
                board[ y   currentY ][ x   currentX ] = current[ y ][ x ];
            }
        }
    }
}

// returns rotates the rotated shape 'current' perpendicularly anticlockwise
function rotate( current ) {
    var newCurrent = [];
    for ( var y = 0; y < 4;   y ) {
        newCurrent[ y ] = [];
        for ( var x = 0; x < 4;   x ) {
            newCurrent[ y ][ x ] = current[ 3 - x ][ y ];
        }
    }

    return newCurrent;
}

// check if any lines are filled and clear them
function clearLines() {
    for ( var y = ROWS - 1; y >= 0; --y ) {
        var rowFilled = true;
        for ( var x = 0; x < COLS;   x ) {
            if ( board[ y ][ x ] == 0 ) {
                rowFilled = false;
                break;
            }
        }
        if ( rowFilled ) {
            document.getElementById( 'clearsound' ).play();
            for ( var yy = y; yy > 0; --yy ) {
                for ( var x = 0; x < COLS;   x ) {
                    board[ yy ][ x ] = board[ yy - 1 ][ x ];
                }
            }
              y;
        }
    }
}

function keyPress( key ) {
    switch ( key ) {
        case 'left':
            if ( valid( -1 ) ) {
                --currentX;
            }
            break;
        case 'right':
            if ( valid( 1 ) ) {
                  currentX;
            }
            break;
        case 'down':
            if ( valid( 0, 1 ) ) {
                  currentY;
            }
            break;
        case 'rotate':
            var rotated = rotate( current );
            if ( valid( 0, 0, rotated ) ) {
                current = rotated;
            }
            break;
    }
}

// checks if the resulting position of current shape will be feasible
function valid( offsetX, offsetY, newCurrent ) {
    offsetX = offsetX || 0;
    offsetY = offsetY || 0;
    offsetX = currentX   offsetX;
    offsetY = currentY   offsetY;
    newCurrent = newCurrent || current;



    for ( var y = 0; y < 4;   y ) {
        for ( var x = 0; x < 4;   x ) {
            if ( newCurrent[ y ][ x ] ) {
                if ( typeof board[ y   offsetY ] == 'undefined'
                  || typeof board[ y   offsetY ][ x   offsetX ] == 'undefined'
                  || board[ y   offsetY ][ x   offsetX ]
                  || x   offsetX < 0
                  || y   offsetY >= ROWS
                  || x   offsetX >= COLS ) {
                    if (offsetY == 1) lose = true; // lose if the current shape at the top row when checked
                    return false;
                }
            }
        }
    }
    return true;
}

function newGame() {
    clearInterval(interval);
    init();
    newShape();
    lose = false;
    interval = setInterval( tick, 250 );
}

var ctx = mycan.getContext( '2d' );
var W = 300, H = 600;
mycan.width = W;
mycan.height= H;
var BLOCK_W = W / COLS, BLOCK_H = H / ROWS;

// draw a single square at (x, y)
function drawBlock( x, y ) {
ctx.drawImage(images[chosenPic],BLOCK_W * x, BLOCK_H * y, BLOCK_W - 1 , BLOCK_H - 1);
    //ctx.fillRect( BLOCK_W * x, BLOCK_H * y, BLOCK_W - 1 , BLOCK_H - 1 );
    ctx.strokeRect( BLOCK_W * x, BLOCK_H * y, BLOCK_W - 1 , BLOCK_H - 1 );
}

// draws the board and the moving shape
function render() {
    ctx.clearRect( 0, 0, W, H );

    ctx.strokeStyle = 'black';
    for ( var x = 0; x < COLS;   x ) {
        for ( var y = 0; y < ROWS;   y ) {
            if ( board[ y ][ x ] ) {
                ctx.fillStyle = colors[ board[ y ][ x ] - 1 ];         
                chosenPic = Object.keys(colors)[board[ y ][ x ] - 1] %2;
                drawBlock( x, y );
            }
        }
    }

    ctx.fillStyle = 'red';
    ctx.strokeStyle = 'black';
    for ( var y = 0; y < 4;   y ) {
        for ( var x = 0; x < 4;   x ) {
            if ( current[ y ][ x ] ) {
                ctx.fillStyle = colors[ current[ y ][ x ] - 1 ];
                chosenPic = Object.keys(colors)[current[ y ][ x ] - 1] %2;
                
                drawBlock( currentX   x, currentY   y );
            }
        }
    }
}

for(let cur of shapes)
{
  images.push(new Image());
  images[images.length-1].src = imagePaths[Math.floor(Math.random()*imagePaths.length)];
  let imagePromise = new Promise((resolve, reject) => {
  images[images.length-1].onload = () => {resolve(true)};
  });
  imagePromise.then(()=>{
    newGame();
    setInterval( render, 30 );
  });
  
}  
 <canvas id=mycan ></canvas>  

в этом примере я использую обещание дождаться загрузки всех изображений, см.: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise