This repository has been archived on 2025-05-02. You can view files and clone it, but cannot push or open issues or pull requests.
Webtris/js/webtris.js
2019-10-24 16:54:59 +02:00

181 lines
4.7 KiB
JavaScript

const MINO_SIZE = 20
const LINES = 20
const COLLUMNS = 10
const INIT_POSITION = [4, -1]
const ACTION_KEY = {
MOVE_LEFT: "ArrowLeft",
MOVE_RIGHT: "ArrowRight",
SOFT_DROP: "ArrowDown",
ROTATE_CW: "ArrowUp",
ROTATE_CCW: "z"
}
const MOVEMENT = {
LEFT: [-1, 0],
RIGHT: [1, 0],
DOWN: [0, 1]
}
const SPIN = {
CW: -1,
CCW: 1
}
class Tetromino {
constructor() {
this.pos = INIT_POSITION
this.orientation = 0
this.rotated_last = false
this.rotation_point_5_used = false
this.hold_enabled = true
this.SRS = new Map([
[
SPIN.CW,
[
[[0, 0], [-1, 0], [-1, -1], [0, 2], [-1, 2]],
[[0, 0], [1, 0], [1, 1], [0, -2], [1, -2]],
[[0, 0], [1, 0], [1, -1], [0, 2], [1, 2]],
[[0, 0], [-1, 0], [-1, 1], [0, 2], [-1, -2]],
]
],
[
SPIN.CCW,
[
[[0, 0], [1, 0], [1, -1], [0, 2], [1, 2]],
[[0, 0], [1, 0], [1, 1], [0, -2], [1, -2]],
[[0, 0], [-1, 0], [-1, -1], [0, 2], [-1, 2]],
[[0, 0], [-1, 0], [-1, 1], [0, -2], [-1, -2]],
]
],
])
}
draw(context) {
for(const pos of this.minoes_pos) {
draw_mino(context, this.pos[0]+pos[0], this.pos[1]+pos[1], this.color)
}
}
}
class T_Tetrimino extends Tetromino {
constructor() {
super()
this.color = "magenta"
this.minoes_pos = [[-1, 0], [0, 0], [1, 0], [0, 1]]
}
}
function draw_mino(context, x, y, color) {
context.fillStyle = color
context.fillRect(x*MINO_SIZE, y*MINO_SIZE, MINO_SIZE, MINO_SIZE);
context.strokeStyle = "rgba(255, 255, 255, 128)";
context.strokeRect(x*MINO_SIZE, y*MINO_SIZE, MINO_SIZE, MINO_SIZE);
}
class Matrix {
constructor() {
this.cells = Array.from(Array(COLLUMNS), y => Array(LINES))
}
occupied_cell(x, y) {
if (0 <= x && x < COLLUMNS && y < LINES)
return this.cells[x][y]
else
return true
}
space_to_move(piece_pos, minoes_pos) {
for (const mino_pos of minoes_pos) {
if (this.occupied_cell(piece_pos[0]+mino_pos[0], piece_pos[1]+mino_pos[1]))
return false
}
return true
}
draw(context) {
// grid
context.strokeStyle = "rgba(128, 128, 128, 128)";
context.beginPath();
for (var x = 0; x <= COLLUMNS*MINO_SIZE; x += MINO_SIZE) {
context.moveTo(x, 0);
context.lineTo(x, matrixCanvas.height);
}
for (var y = 0; y <= LINES*MINO_SIZE; y += MINO_SIZE) {
context.moveTo(0, y);
context.lineTo(matrixCanvas.width, y);
}
context.stroke();
}
}
function move(movement) {
const test_pos = [tetro.pos[0]+movement[0], tetro.pos[1]+movement[1]]
if (matrix.space_to_move(test_pos, tetro.minoes_pos)) {
tetro.pos = test_pos
draw()
}
}
function rotate(spin) {
const text_minoes_pos = tetro.minoes_pos.map(pos => [spin*pos[1], pos[0]])
rotation_point = 0
for (const movement of tetro.SRS.get(spin)[tetro.orientation]) {
const test_pos = [tetro.pos[0]+movement[0], tetro.pos[1]+movement[1]]
if (matrix.space_to_move(test_pos, text_minoes_pos)) {
tetro.pos = test_pos
tetro.minoes_pos = text_minoes_pos
tetro.orientation = (tetro.orientation + spin + 4) % 4
draw()
break;
}
rotation_point++
}
}
function fall() {
move(MOVEMENT.DOWN);
}
function keyDownHandler(e) {
switch(e.key){
case ACTION_KEY.MOVE_LEFT:
move(MOVEMENT.LEFT);
break
case ACTION_KEY.MOVE_RIGHT:
move(MOVEMENT.RIGHT);
break
case ACTION_KEY.SOFT_DROP:
move(MOVEMENT.DOWN);
break
case ACTION_KEY.ROTATE_CW:
rotate(SPIN.CW);
break
case ACTION_KEY.ROTATE_CCW:
rotate(SPIN.CCW);
break
}
}
function keyUpHandler(e) {
}
function draw() {
matrixContext.clearRect(0, 0, COLLUMNS*MINO_SIZE, LINES*MINO_SIZE);
matrix.draw(matrixContext)
tetro.draw(matrixContext)
}
window.onload = function() {
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
setInterval(fall, 1000);
matrixCanvas = document.getElementById("matrix");
matrixContext = matrixCanvas.getContext("2d");
tetro = new T_Tetrimino()
matrix = new Matrix()
}