tetris-js/tetris.js
2021-10-19 22:22:50 +02:00

219 lines
6.0 KiB
JavaScript

"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<grid_x );
board = Array.from(Array(grid_y - newBoard.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 );