"use strict"; let tetris = function () { const grid_x = 10; const grid_y = 20; const tetrimonios = [ /*'I'*/{ mR:2, r:[ [ [0,0],[0,1],[0,2],[0,3] ], [ [0,0],[1,0],[2,0],[3,0] ] ] }, /*'O':*/{ mR:1, r:[ [ [0,0],[0,1],[1,0],[1,1] ] ] }, /*'L':*/{ mR:4, r:[ [ [0,0],[0,1],[0,2],[1,2] ], [ [0,0],[1,0],[2,0],[0,1] ], [ [0,0],[1,0],[1,1],[1,2] ], [ [2,0],[2,1],[1,1],[0,1] ] ] }, /*'L2':*/{ mR:4, r:[ [ [1,0],[1,1],[1,2],[0,2] ], [ [0,0],[0,1],[1,1],[2,1] ], [ [1,0],[0,0],[0,1],[0,2] ], [ [0,0],[1,0],[2,0],[2,1] ] ] }, /*'Z':*/{ mR:2, r:[ [ [0,0],[1,0],[1,1],[2,1] ], [ [1,0],[1,1],[0,1],[0,2] ] ] }, /*'Z2':*/{ mR:2, r:[ [ [0,1],[1,1],[1,0],[2,0] ], [ [0,0],[0,1],[1,1],[1,2] ] ] }, /*'T':*/{ mR:4, r:[ [ [1,0],[0,1],[1,1],[2,1] ], [ [0,0],[0,1],[0,2],[1,1] ], [ [0,0],[1,0],[2,0],[1,1] ], [ [1,0],[1,1],[1,2],[0,1] ] ] } ]; let timer, canvas, ctx, blockSize; let next_t; let board, board_x, board_y; let t = {t:null,x:0,y:0,r:0}; function control(e) { switch(e.key) { case 'r': clean(t); newGame(); break; case 'a': clean(t); nextT(); break; case 'ArrowUp': moveUp(t); break; case 'ArrowDown': moveDown(t); break; case 'ArrowLeft': moveLeft(t); break; case 'ArrowRight': moveRight(t);break; } } function clean(p) { ctx.fillStyle = "#FFFFFF";drawBlocks(p,drawBlock_clean); } function draw(p) { ctx.fillStyle = "#F66666";drawBlocks(p,drawBlock_filled); } function drawBlocks(p, drawBlock) { p.t.r[p.r].forEach(b => drawBlock(p.x + b[0], p.y + b[1])); } function drawBlock_clean(x,y) { ctx.fillRect(board_x + blockSize*x, board_y + blockSize*y, blockSize, blockSize); } function drawBlock_filled(x,y) { ctx.fillRect(board_x + blockSize*x, board_y + blockSize*y, blockSize, blockSize); } function drawBlock_glue(x,y) { ctx.fillStyle = "#666666"; ctx.fillRect(board_x + blockSize*x, board_y + blockSize*y, blockSize, blockSize); } function moveUp(p) { clean(t); let r = p.r; p.r = (++p.r)% p.t.mR; if ( collision(p) ) p.r = r; draw(t); } function moveDown(p) { clean(t); p.y++; if ( collision(p) ) { p.y--; glue(p); return; } draw(t); } function moveLeft(p) { clean(t); p.x--; if ( collision(p) ) p.x++; draw(t); } function moveRight(p) { clean(t); p.x++; if ( collision(p) ) p.x--; draw(t); } function glue(p) { p.t.r[p.r].forEach(b => { board[p.y+b[1]][p.x+b[0]]=1; } ); drawBlocks(p,drawBlock_glue); deleteRows( board.filter( r=>r.filter(c=>c==1).length==grid_x ) ); dropShape(t); } function collision(p) { if ( p.x<0 || p.x>=grid_x || p.y<0 || p.y>=grid_y ) return true; if ( p.t.r[p.r].filter(b => ( p.x+b[0]>=grid_x || p.y+b[1]>=grid_y || board[p.y+b[1]][p.x+b[0]]==1 ) ).length>0 ) return true; return false } function deleteRows(r) { if (r.length>0) { // ToDo: Stop timer // ToDo: blinking let newBoard = board.filter( r=>r.filter(c=>c==1).length new Array(grid_x)); board = board.concat(newBoard); cleanBoard(); ctx.fillStyle = "#666666"; board.forEach((r,y)=>r.forEach((c,x)=>{if(c==1)drawBlock_filled(x,y);})) } } function getNextT() { let tNum = Math.floor(Math.random() * tetrimonios.length); return tetrimonios[ tNum ]; } function dropShape(p) { p.t = next_t; p.x = grid_x/2 - 1; p.y = 0; p.r = 0; next_t = getNextT(); } function cleanBoard() { ctx.fillStyle = "#FFFFFF"; ctx.fillRect(board_x, board_y, blockSize*grid_x, blockSize*grid_y); } function newGame() { drawBackground(); cleanBoard(); board = Array.from(Array(grid_y), () => new Array(grid_x)); // Board[Y][X] next_t = getNextT(); dropShape( t ); if (!timer) timer = setInterval(()=>moveDown(t), 1000); } function getBlockSize() { const space_top = 5; const space_right = 10; const { width, height } = canvas.getBoundingClientRect(); return Math.floor( Math.min( height / (space_top + grid_y), width / (space_right + grid_x) ) ); } function drawBackground() { ctx.fillStyle = "#FFFFFF"; ctx.fillRect(0,0,canvas.getBoundingClientRect().width,canvas.getBoundingClientRect().height); ctx.strokeStyle = "#0074cc"; ctx.strokeRect(board_x -1, board_y - 1, blockSize*grid_x +2, blockSize*grid_y +2); } function init() { canvas = document.getElementById("app"); canvas.width = window.innerWidth canvas.height = window.innerHeight ctx = canvas.getContext("2d"); blockSize = getBlockSize(); board_x = blockSize*1; board_y = canvas.height - blockSize*grid_y - blockSize*1; document.addEventListener('keydown', control); newGame(); } init(); } document.addEventListener('DOMContentLoaded', tetris );