Initial Commit
This commit is contained in:
507
public/assets/scripts/haxxor.js
Normal file
507
public/assets/scripts/haxxor.js
Normal file
@@ -0,0 +1,507 @@
|
||||
// Stolen from https://codepen.io/loktar00/pen/BaGqXY
|
||||
// However has modifications to work good as a theme
|
||||
|
||||
"use strict";
|
||||
function createTetris() {
|
||||
var tetrominos = [
|
||||
{
|
||||
// box
|
||||
colors: ["rgb(00, 00, 00)", "#47ba23", "rgb(00, 00, 00)"],
|
||||
data: [
|
||||
[0, 0, 0, 0],
|
||||
[0, 1, 1, 0],
|
||||
[0, 1, 1, 0],
|
||||
[0, 0, 0, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
// stick
|
||||
colors: ["rgb(00, 00, 00)", "#47ba23", "rgb(00, 00, 00)"],
|
||||
data: [
|
||||
[0, 0, 0, 0],
|
||||
[0, 0, 0, 0],
|
||||
[1, 1, 1, 1],
|
||||
[0, 0, 0, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
// z
|
||||
colors: ["rgb(00, 00, 00)", "#47ba23", "rgb(00, 00, 00)"],
|
||||
data: [
|
||||
[0, 0, 0, 0],
|
||||
[0, 1, 1, 0],
|
||||
[0, 0, 1, 1],
|
||||
[0, 0, 0, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
// T
|
||||
colors: ["rgb(00, 00, 00)", "#47ba23", "rgb(00, 00, 00)"],
|
||||
data: [
|
||||
[0, 0, 0, 0],
|
||||
[0, 1, 1, 1],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
// s
|
||||
colors: ["rgb(00, 00, 00)", "#47ba23", "rgb(00, 00, 00)"],
|
||||
data: [
|
||||
[0, 0, 0, 0],
|
||||
[0, 1, 1, 0],
|
||||
[1, 1, 0, 0],
|
||||
[0, 0, 0, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
// backwards L
|
||||
colors: ["rgb(00, 00, 00)", "#47ba23", "rgb(00, 00, 00)"],
|
||||
data: [
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 1, 1, 0],
|
||||
[0, 0, 0, 0],
|
||||
],
|
||||
},
|
||||
{
|
||||
// L
|
||||
colors: ["rgb(00, 00, 00)", "#47ba23", "rgb(00, 00, 00)"],
|
||||
data: [
|
||||
[0, 1, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 1, 1, 0],
|
||||
[0, 0, 0, 0],
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
var Tetris = function (x, y, width, height) {
|
||||
this.posX = x || 0;
|
||||
this.posY = y || 0;
|
||||
|
||||
this.width = width || window.innerWidth;
|
||||
this.height = height || window.innerHeight;
|
||||
|
||||
this.bgCanvas = document.createElement("canvas");
|
||||
this.fgCanvas = document.createElement("canvas");
|
||||
|
||||
this.bgCanvas.width = this.fgCanvas.width = this.width;
|
||||
this.bgCanvas.height = this.fgCanvas.height = this.height;
|
||||
|
||||
this.bgCtx = this.bgCanvas.getContext("2d");
|
||||
this.fgCtx = this.fgCanvas.getContext("2d");
|
||||
|
||||
this.bgCanvas.style.left = this.posX + "px";
|
||||
this.bgCanvas.style.top = this.posY + "px";
|
||||
|
||||
// Stay in background
|
||||
this.bgCanvas.style.position = "absolute";
|
||||
this.fgCanvas.style.position = "absolute";
|
||||
|
||||
this.fgCanvas.style.left = this.posX + "px";
|
||||
this.fgCanvas.style.top = this.posY + "px";
|
||||
|
||||
document.body.insertBefore(this.fgCanvas, document.body.firstChild);
|
||||
document.body.insertBefore(this.bgCanvas, document.body.firstChild);
|
||||
this.init();
|
||||
};
|
||||
|
||||
Tetris.prototype.init = function () {
|
||||
this.curPiece = {
|
||||
data: null,
|
||||
colors: [0, 0, 0],
|
||||
x: 0,
|
||||
y: 0,
|
||||
};
|
||||
|
||||
this.lastMove = Date.now();
|
||||
this.curSpeed = 50 + Math.random() * 50;
|
||||
this.unitSize = 20;
|
||||
this.linesCleared = 0;
|
||||
this.level = 0;
|
||||
this.loseBlock = 0;
|
||||
|
||||
// init the board
|
||||
this.board = [];
|
||||
this.boardWidth = Math.floor(this.width / this.unitSize);
|
||||
this.boardHeight = Math.floor(this.height / this.unitSize);
|
||||
|
||||
var board = this.board,
|
||||
boardWidth = this.boardWidth,
|
||||
boardHeight = this.boardHeight,
|
||||
halfHeight = boardHeight / 2,
|
||||
curPiece = this.curPiece,
|
||||
x = 0,
|
||||
y = 0;
|
||||
|
||||
// init board
|
||||
for (x = 0; x <= boardWidth; x++) {
|
||||
board[x] = [];
|
||||
for (y = 0; y <= boardHeight; y++) {
|
||||
board[x][y] = {
|
||||
data: 0,
|
||||
colors: ["rgb(0,0,0)", "rgb(0,0,0)", "rgb(0,0,0)"],
|
||||
};
|
||||
|
||||
if (Math.random() > 0.15 && y > halfHeight) {
|
||||
board[x][y] = {
|
||||
data: 1,
|
||||
colors:
|
||||
tetrominos[Math.floor(Math.random() * tetrominos.length)].colors,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collapse the board a bit
|
||||
for (x = 0; x <= boardWidth; x++) {
|
||||
for (y = boardHeight - 1; y > -1; y--) {
|
||||
if (board[x][y].data === 0 && y > 0) {
|
||||
for (var yy = y; yy > 0; yy--) {
|
||||
if (board[x][yy - 1].data) {
|
||||
board[x][yy].data = 1;
|
||||
board[x][yy].colors = board[x][yy - 1].colors;
|
||||
|
||||
board[x][yy - 1].data = 0;
|
||||
board[x][yy - 1].colors = [
|
||||
"rgb(0,0,0)",
|
||||
"rgb(0,0,0)",
|
||||
"rgb(0,0,0)",
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
window.addEventListener("keydown", function (e) {
|
||||
switch (e.keyCode) {
|
||||
case 37:
|
||||
if (self.checkMovement(curPiece, -1, 0)) {
|
||||
curPiece.x--;
|
||||
}
|
||||
break;
|
||||
case 39:
|
||||
if (self.checkMovement(curPiece, 1, 0)) {
|
||||
curPiece.x++;
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
if (self.checkMovement(curPiece, 0, 1)) {
|
||||
curPiece.y++;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
case 38:
|
||||
curPiece.data = self.rotateTetrimono(curPiece);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// render the board
|
||||
this.checkLines();
|
||||
this.renderBoard();
|
||||
|
||||
// assign the first tetri
|
||||
this.newTetromino();
|
||||
this.update();
|
||||
};
|
||||
|
||||
Tetris.prototype.update = function () {
|
||||
var curPiece = this.curPiece;
|
||||
|
||||
if (!this.checkMovement(curPiece, 0, 1)) {
|
||||
if (curPiece.y < -1) {
|
||||
// you lose
|
||||
this.loseScreen();
|
||||
return true;
|
||||
} else {
|
||||
this.fillBoard(curPiece);
|
||||
this.newTetromino();
|
||||
}
|
||||
} else {
|
||||
if (Date.now() > this.lastMove) {
|
||||
this.lastMove = Date.now() + this.curSpeed;
|
||||
if (this.checkMovement(curPiece, 0, 1)) {
|
||||
curPiece.y++;
|
||||
} else {
|
||||
this.fillBoard(curPiece);
|
||||
this.newTetromino();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.render();
|
||||
|
||||
var self = this;
|
||||
requestAnimationFrame(function () {
|
||||
self.update();
|
||||
});
|
||||
};
|
||||
|
||||
// render only the board.
|
||||
Tetris.prototype.renderBoard = function () {
|
||||
var canvas = this.bgCanvas,
|
||||
ctx = this.bgCtx,
|
||||
unitSize = this.unitSize,
|
||||
board = this.board,
|
||||
boardWidth = this.boardWidth,
|
||||
boardHeight = this.boardHeight;
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
for (var x = 0; x <= boardWidth; x++) {
|
||||
for (var y = 0; y <= boardHeight; y++) {
|
||||
if (board[x][y].data !== 0) {
|
||||
var bX = x * unitSize,
|
||||
bY = y * unitSize;
|
||||
//ctx.shadowBlur = 5;
|
||||
//ctx.shadowColor = "rgba(0,255,0,.6)";
|
||||
ctx.fillStyle = board[x][y].colors[0];
|
||||
ctx.fillRect(bX, bY, unitSize, unitSize);
|
||||
|
||||
ctx.fillStyle = board[x][y].colors[1];
|
||||
ctx.fillRect(bX + 2, bY + 2, unitSize - 4, unitSize - 4);
|
||||
|
||||
ctx.fillStyle = board[x][y].colors[2];
|
||||
ctx.fillRect(bX + 4, bY + 4, unitSize - 8, unitSize - 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Render the current active piece
|
||||
Tetris.prototype.render = function () {
|
||||
var canvas = this.fgCanvas,
|
||||
ctx = this.fgCtx,
|
||||
unitSize = this.unitSize,
|
||||
curPiece = this.curPiece;
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
for (var x = 0; x < 4; x++) {
|
||||
for (var y = 0; y < 4; y++) {
|
||||
if (curPiece.data[x][y] === 1) {
|
||||
var xPos = (curPiece.x + x) * unitSize,
|
||||
yPos = (curPiece.y + y) * unitSize;
|
||||
|
||||
if (yPos > -1) {
|
||||
ctx.shadowBlur = 10;
|
||||
ctx.shadowColor = "rgba(0,255,0,.6)";
|
||||
ctx.fillStyle = curPiece.colors[0];
|
||||
ctx.fillRect(xPos, yPos, unitSize, unitSize);
|
||||
|
||||
ctx.fillStyle = curPiece.colors[1];
|
||||
ctx.fillRect(xPos + 2, yPos + 2, unitSize - 4, unitSize - 4);
|
||||
|
||||
ctx.fillStyle = curPiece.colors[2];
|
||||
ctx.fillRect(xPos + 4, yPos + 4, unitSize - 8, unitSize - 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure we can mov where we want.
|
||||
Tetris.prototype.checkMovement = function (curPiece, newX, newY) {
|
||||
var piece = curPiece.data,
|
||||
posX = curPiece.x,
|
||||
posY = curPiece.y,
|
||||
board = this.board,
|
||||
boardWidth = this.boardWidth,
|
||||
boardHeight = this.boardHeight;
|
||||
|
||||
for (var x = 0; x < 4; x++) {
|
||||
for (var y = 0; y < 4; y++) {
|
||||
if (piece[x][y] === 1) {
|
||||
if (!board[posX + x + newX]) {
|
||||
board[posX + x + newX] = [];
|
||||
}
|
||||
|
||||
if (!board[posX + x + newX][y + posY + newY]) {
|
||||
board[posX + x + newX][y + posY + newY] = {
|
||||
data: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
posX + x + newX >= boardWidth ||
|
||||
posX + x + newX < 0 ||
|
||||
board[posX + x + newX][y + posY + newY].data == 1
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (posY + y + newY > boardHeight) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// checks for completed lines and clears them
|
||||
Tetris.prototype.checkLines = function () {
|
||||
var board = this.board,
|
||||
boardWidth = this.boardWidth,
|
||||
boardHeight = this.boardHeight,
|
||||
linesCleared = this.linesCleared,
|
||||
level = this.level,
|
||||
y = boardHeight + 1;
|
||||
|
||||
while (y--) {
|
||||
var x = boardWidth,
|
||||
lines = 0;
|
||||
|
||||
while (x--) {
|
||||
if (board[x][y].data === 1) {
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
|
||||
if (lines === boardWidth) {
|
||||
linesCleared++;
|
||||
level = Math.round(linesCleared / 20) * 20;
|
||||
|
||||
var lineY = y;
|
||||
while (lineY) {
|
||||
for (x = 0; x <= boardWidth; x++) {
|
||||
if (lineY - 1 > 0) {
|
||||
board[x][lineY].data = board[x][lineY - 1].data;
|
||||
board[x][lineY].colors = board[x][lineY - 1].colors;
|
||||
}
|
||||
}
|
||||
lineY--;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Lose animation
|
||||
Tetris.prototype.loseScreen = function () {
|
||||
var ctx = this.bgCtx,
|
||||
unitSize = this.unitSize,
|
||||
boardWidth = this.boardWidth,
|
||||
boardHeight = this.boardHeight,
|
||||
y = boardHeight - this.loseBlock;
|
||||
|
||||
for (var x = 0; x < boardWidth; x++) {
|
||||
var bX = x * unitSize,
|
||||
bY = y * unitSize;
|
||||
|
||||
ctx.fillStyle = "rgb(0,0,0)";
|
||||
ctx.fillRect(bX, bY, unitSize, unitSize);
|
||||
|
||||
ctx.fillStyle = "#54a13c";
|
||||
ctx.fillRect(bX + 2, bY + 2, unitSize - 4, unitSize - 4);
|
||||
|
||||
ctx.fillStyle = "rgb(0,0,0)";
|
||||
ctx.fillRect(bX + 4, bY + 4, unitSize - 8, unitSize - 8);
|
||||
}
|
||||
|
||||
if (this.loseBlock <= boardHeight + 1) {
|
||||
this.loseBlock++;
|
||||
|
||||
var self = this;
|
||||
requestAnimationFrame(function () {
|
||||
self.loseScreen();
|
||||
});
|
||||
} else {
|
||||
this.init();
|
||||
}
|
||||
};
|
||||
|
||||
// adds the piece as part of the board
|
||||
Tetris.prototype.fillBoard = function (curPiece) {
|
||||
var piece = curPiece.data,
|
||||
posX = curPiece.x,
|
||||
posY = curPiece.y,
|
||||
board = this.board;
|
||||
|
||||
for (var x = 0; x < 4; x++) {
|
||||
for (var y = 0; y < 4; y++) {
|
||||
if (piece[x][y] === 1) {
|
||||
board[x + posX][y + posY].data = 1;
|
||||
board[x + posX][y + posY].colors = curPiece.colors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.checkLines();
|
||||
this.renderBoard();
|
||||
};
|
||||
|
||||
// rotate a piece
|
||||
Tetris.prototype.rotateTetrimono = function (curPiece) {
|
||||
var rotated = [];
|
||||
|
||||
for (var x = 0; x < 4; x++) {
|
||||
rotated[x] = [];
|
||||
for (var y = 0; y < 4; y++) {
|
||||
rotated[x][y] = curPiece.data[3 - y][x];
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!this.checkMovement(
|
||||
{
|
||||
data: rotated,
|
||||
x: curPiece.x,
|
||||
y: curPiece.y,
|
||||
},
|
||||
0,
|
||||
0
|
||||
)
|
||||
) {
|
||||
rotated = curPiece.data;
|
||||
}
|
||||
|
||||
return rotated;
|
||||
};
|
||||
|
||||
// assign the player a new peice
|
||||
Tetris.prototype.newTetromino = function () {
|
||||
var pieceNum = Math.floor(Math.random() * tetrominos.length),
|
||||
curPiece = this.curPiece;
|
||||
|
||||
curPiece.data = tetrominos[pieceNum].data;
|
||||
curPiece.colors = tetrominos[pieceNum].colors;
|
||||
curPiece.x = Math.floor(
|
||||
Math.random() * (this.boardWidth - curPiece.data.length + 1)
|
||||
);
|
||||
curPiece.y = -4;
|
||||
};
|
||||
|
||||
var width = window.innerWidth,
|
||||
boardDiv = 20 * Math.round(window.innerWidth / 20),
|
||||
boards = 8,
|
||||
bWidth = boardDiv / boards,
|
||||
tetrisInstances = [];
|
||||
|
||||
for (var w = 0; w < boards; w++) {
|
||||
tetrisInstances.push(
|
||||
new Tetris(20 * Math.round((w * bWidth) / 20), 0, bWidth)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function main() {
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
createTetris();
|
||||
}
|
||||
|
||||
function isActive() {
|
||||
let style = getComputedStyle(document.body);
|
||||
return style.getPropertyValue("--is-haxxorman") == "true"
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", main);
|
Reference in New Issue
Block a user