Initial Commit
This commit is contained in:
commit
6d9e0b3ef4
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/.etc
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 UwU
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
304
public/assets/css/theme-haxxor.css
Normal file
304
public/assets/css/theme-haxxor.css
Normal file
@ -0,0 +1,304 @@
|
||||
:root {
|
||||
--is-haxxorman: true;
|
||||
--is-dark-theme: true;
|
||||
--color-primary: #54a13c;
|
||||
--color-primary-contrast: rgb(115, 222, 82);
|
||||
--color-primary-dark-1: #82ad74;
|
||||
--color-primary-dark-2: #679cd0;
|
||||
--color-primary-dark-3: #7aa8d6;
|
||||
--color-primary-dark-4: #8db5dc;
|
||||
--color-primary-dark-5: #b3cde7;
|
||||
--color-primary-dark-6: #d9e6f3;
|
||||
--color-primary-dark-7: #f4f8fb;
|
||||
--color-primary-light-1: #3876b3;
|
||||
--color-primary-light-2: #31699f;
|
||||
--color-primary-light-3: #2b5c8b;
|
||||
--color-primary-light-4: #254f77;
|
||||
--color-primary-light-5: #193450;
|
||||
--color-primary-light-6: #0c1a28;
|
||||
--color-primary-light-7: #04080c;
|
||||
--color-primary-alpha-10: #4183c419;
|
||||
--color-primary-alpha-20: #4183c433;
|
||||
--color-primary-alpha-30: #4183c44b;
|
||||
--color-primary-alpha-40: #4183c466;
|
||||
--color-primary-alpha-50: #4183c480;
|
||||
--color-primary-alpha-60: #4183c499;
|
||||
--color-primary-alpha-70: #4183c4b3;
|
||||
--color-primary-alpha-80: #4183c4cc;
|
||||
--color-primary-alpha-90: #4183c4e1;
|
||||
--color-primary-hover: #172d11;
|
||||
--color-primary-active: #172d11;
|
||||
--color-secondary: #224019;
|
||||
--color-secondary-dark-1: #294c1e;
|
||||
--color-secondary-dark-2: #284a1d;
|
||||
--color-secondary-dark-3: #2b5120;
|
||||
--color-secondary-dark-4: #2d5521;
|
||||
--color-secondary-dark-5: #305923;
|
||||
--color-secondary-dark-6: #335e26;
|
||||
--color-secondary-dark-7: #356428;
|
||||
--color-secondary-dark-8: #3e762f;
|
||||
--color-secondary-dark-9: #3c712d;
|
||||
--color-secondary-dark-10: #b7bfc7;
|
||||
--color-secondary-dark-11: #c5cbd2;
|
||||
--color-secondary-dark-12: #cfd4da;
|
||||
--color-secondary-dark-13: #d2d7dc;
|
||||
--color-secondary-light-1: #313940;
|
||||
--color-secondary-light-2: #292f35;
|
||||
--color-secondary-light-3: #1d2226;
|
||||
--color-secondary-light-4: #171b1e;
|
||||
--color-secondary-alpha-10: #3b444c19;
|
||||
--color-secondary-alpha-20: #3b444c33;
|
||||
--color-secondary-alpha-30: #3b444c4b;
|
||||
--color-secondary-alpha-40: #3b444c66;
|
||||
--color-secondary-alpha-50: #3b444c80;
|
||||
--color-secondary-alpha-60: #3b444c99;
|
||||
--color-secondary-alpha-70: #3b444cb3;
|
||||
--color-secondary-alpha-80: #3b444ccc;
|
||||
--color-secondary-alpha-90: #3b444ce1;
|
||||
--color-secondary-button: var(--color-secondary-dark-4);
|
||||
--color-secondary-hover: var(--color-secondary-dark-3);
|
||||
--color-secondary-active: var(--color-secondary-dark-2);
|
||||
/* console colors - used for actions console and console files */
|
||||
--color-console-fg: #f7f8f9;
|
||||
--color-console-fg-subtle: #bdc4cc;
|
||||
--color-console-bg: #171b1e;
|
||||
--color-console-border: #2e353b;
|
||||
--color-console-hover-bg: #272d33;
|
||||
--color-console-active-bg: #2e353b;
|
||||
--color-console-menu-bg: #262b31;
|
||||
--color-console-menu-border: #414b55;
|
||||
/* named colors */
|
||||
--color-red: #cc4848;
|
||||
--color-orange: #cc580c;
|
||||
--color-yellow: #cc9903;
|
||||
--color-olive: #91a313;
|
||||
--color-green: #87ab63;
|
||||
--color-teal: #00918a;
|
||||
--color-blue: #3a8ac6;
|
||||
--color-violet: #906ae1;
|
||||
--color-purple: #b259d0;
|
||||
--color-pink: #d22e8b;
|
||||
--color-brown: #a47252;
|
||||
--color-black: #1d2328;
|
||||
/* light variants - produced via Sass scale-color(color, $lightness: +10%) */
|
||||
--color-red-light: #d15a5a;
|
||||
--color-orange-light: #f6a066;
|
||||
--color-yellow-light: #eaaf03;
|
||||
--color-olive-light: #abc016;
|
||||
--color-green-light: #93b373;
|
||||
--color-teal-light: #00b6ad;
|
||||
--color-blue-light: #4e96cc;
|
||||
--color-violet-light: #9b79e4;
|
||||
--color-purple-light: #ba6ad5;
|
||||
--color-pink-light: #d74397;
|
||||
--color-brown-light: #b08061;
|
||||
--color-black-light: #424851;
|
||||
/* dark 1 variants - produced via Sass scale-color(color, $lightness: -10%) */
|
||||
--color-red-dark-1: #c23636;
|
||||
--color-orange-dark-1: #f38236;
|
||||
--color-yellow-dark-1: #b88a03;
|
||||
--color-olive-dark-1: #839311;
|
||||
--color-green-dark-1: #7a9e55;
|
||||
--color-teal-dark-1: #00837c;
|
||||
--color-blue-dark-1: #347cb3;
|
||||
--color-violet-dark-1: #7b4edb;
|
||||
--color-purple-dark-1: #a742c9;
|
||||
--color-pink-dark-1: #be297d;
|
||||
--color-brown-dark-1: #94674a;
|
||||
--color-black-dark-1: #292e38;
|
||||
/* dark 2 variants - produced via Sass scale-color(color, $lightness: -20%) */
|
||||
--color-red-dark-2: #ad3030;
|
||||
--color-orange-dark-2: #f16e17;
|
||||
--color-yellow-dark-2: #a37a02;
|
||||
--color-olive-dark-2: #74820f;
|
||||
--color-green-dark-2: #6c8c4c;
|
||||
--color-teal-dark-2: #00746e;
|
||||
--color-blue-dark-2: #2e6e9f;
|
||||
--color-violet-dark-2: #6733d6;
|
||||
--color-purple-dark-2: #9834b9;
|
||||
--color-pink-dark-2: #a9246f;
|
||||
--color-brown-dark-2: #835b42;
|
||||
--color-black-dark-2: #272930;
|
||||
/* ansi colors used for actions console and console files */
|
||||
--color-ansi-black: #1e2327;
|
||||
--color-ansi-red: #cc4848;
|
||||
--color-ansi-green: #87ab63;
|
||||
--color-ansi-yellow: #cc9903;
|
||||
--color-ansi-blue: #3a8ac6;
|
||||
--color-ansi-magenta: #d22e8b;
|
||||
--color-ansi-cyan: #00918a;
|
||||
--color-ansi-white: var(--color-console-fg-subtle);
|
||||
--color-ansi-bright-black: #424851;
|
||||
--color-ansi-bright-red: #d15a5a;
|
||||
--color-ansi-bright-green: #93b373;
|
||||
--color-ansi-bright-yellow: #eaaf03;
|
||||
--color-ansi-bright-blue: #4e96cc;
|
||||
--color-ansi-bright-magenta: #d74397;
|
||||
--color-ansi-bright-cyan: #00b6ad;
|
||||
--color-ansi-bright-white: var(--color-console-fg);
|
||||
/* other colors */
|
||||
--color-grey: #384149;
|
||||
--color-grey-light: #818f9e;
|
||||
--color-gold: #b1983b;
|
||||
--color-white: #ffffff;
|
||||
--color-diff-added-linenum-bg: #274227;
|
||||
--color-diff-added-row-bg: #203224;
|
||||
--color-diff-added-row-border: #314a37;
|
||||
--color-diff-added-word-bg: #3c653c;
|
||||
--color-diff-moved-row-bg: #818044;
|
||||
--color-diff-moved-row-border: #bcca6f;
|
||||
--color-diff-removed-linenum-bg: #482121;
|
||||
--color-diff-removed-row-bg: #301e1e;
|
||||
--color-diff-removed-row-border: #634343;
|
||||
--color-diff-removed-word-bg: #6f3333;
|
||||
--color-diff-inactive: #22282d;
|
||||
--color-error-border: #a04141;
|
||||
--color-error-bg: #522;
|
||||
--color-error-bg-active: #744;
|
||||
--color-error-bg-hover: #633;
|
||||
--color-error-text: #f9cbcb;
|
||||
--color-success-border: #458a57;
|
||||
--color-success-bg: #284034;
|
||||
--color-success-text: #6cc664;
|
||||
--color-warning-border: #bb9d00;
|
||||
--color-warning-bg: #3a3a30;
|
||||
--color-warning-text: #fbbd08;
|
||||
--color-info-border: #306090;
|
||||
--color-info-bg: #26354c;
|
||||
--color-info-text: #38a8e8;
|
||||
--color-red-badge: #db2828;
|
||||
--color-red-badge-bg: #db28281a;
|
||||
--color-red-badge-hover-bg: #db28284d;
|
||||
--color-green-badge: #21ba45;
|
||||
--color-green-badge-bg: #21ba451a;
|
||||
--color-green-badge-hover-bg: #21ba454d;
|
||||
--color-yellow-badge: #fbbd08;
|
||||
--color-yellow-badge-bg: #fbbd081a;
|
||||
--color-yellow-badge-hover-bg: #fbbd084d;
|
||||
--color-orange-badge: #f2711c;
|
||||
--color-orange-badge-bg: #f2711c1a;
|
||||
--color-orange-badge-hover-bg: #f2711c4d;
|
||||
--color-git: #f05133;
|
||||
/* target-based colors */
|
||||
--color-body: #000000;
|
||||
--color-box-header: #000000;
|
||||
--color-box-body: #000000;
|
||||
--color-box-body-highlight: #1b1f1a;
|
||||
--color-text-dark: #54a13c;
|
||||
--color-text: #54a13c;
|
||||
--color-text-light: #54a13c;
|
||||
--color-text-light-1: #417d2f;
|
||||
--color-text-light-2: #457636;
|
||||
--color-text-light-3: #234519;
|
||||
--color-footer: #000000;
|
||||
--color-timeline: #343c44;
|
||||
--color-input-text: var(--color-text-dark);
|
||||
--color-input-background: #000000;
|
||||
--color-input-toggle-background: #11210c;
|
||||
--color-input-border: var(--color-secondary);
|
||||
--color-input-border-hover: var(--color-secondary-dark-1);
|
||||
--color-light: #00001728;
|
||||
--color-light-mimic-enabled: rgba(0, 0, 0, calc(40 / 255 * 222 / 255 / var(--opacity-disabled)));
|
||||
--color-light-border: #e8f3ff28;
|
||||
--color-hover: #13240e;
|
||||
--color-active: #101f0c;
|
||||
--color-menu: #000000;
|
||||
--color-card: #000000;
|
||||
--color-markup-table-row: #e8f3ff0f;
|
||||
--color-markup-code-block: #e8f3ff12;
|
||||
--color-markup-code-inline: #e8f3ff28;
|
||||
--color-button: #171a1e;
|
||||
--color-code-bg: #14171a;
|
||||
--color-shadow: #00001758;
|
||||
--color-secondary-bg: #000;
|
||||
--color-expand-button: #2f363d;
|
||||
--color-placeholder-text: var(--color-text-light-3);
|
||||
--color-editor-line-highlight: var(--color-primary-light-5);
|
||||
--color-project-board-bg: var(--color-secondary-light-2);
|
||||
--color-caret: var(--color-text); /* should ideally be --color-text-dark, see #15651 */
|
||||
--color-reaction-bg: #e8f3ff12;
|
||||
--color-reaction-hover-bg: var(--color-primary-light-4);
|
||||
--color-reaction-active-bg: var(--color-primary-light-5);
|
||||
--color-tooltip-text: #f9fafb;
|
||||
--color-tooltip-bg: #000b17f0;
|
||||
--color-nav-bg: #000000;
|
||||
--color-nav-hover-bg: #0d160a;
|
||||
--color-nav-text: #54a13c;
|
||||
--color-secondary-nav-bg: #000000;
|
||||
--color-label-text: var(--color-text);
|
||||
--color-label-bg: #7282924b;
|
||||
--color-label-hover-bg: #728292a0;
|
||||
--color-label-active-bg: #728292ff;
|
||||
--color-accent: var(--color-primary-light-1);
|
||||
--color-small-accent: var(--color-primary-light-5);
|
||||
--color-highlight-fg: #87651e;
|
||||
--color-highlight-bg: #352c1c;
|
||||
--color-overlay-backdrop: #080808c0;
|
||||
accent-color: #54a13c;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
|
||||
.ui.input {
|
||||
animation: glow 800ms ease-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes glow {
|
||||
0% {
|
||||
border-color: #393;
|
||||
box-shadow: 0 0 5px rgba(0,255,0,.2), inset 0 0 5px rgba(0,255,0,.1), 0 2px 0 #000;
|
||||
}
|
||||
100% {
|
||||
border-color: #6f6;
|
||||
box-shadow: 0 0 20px rgba(0,255,0,.6), inset 0 0 10px rgba(0,255,0,.4), 0 2px 0 #000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ui.primary.button {
|
||||
background: #000000
|
||||
}
|
||||
|
||||
.ui.ui.ui.ui.small.button {
|
||||
background: #000000
|
||||
}
|
||||
|
||||
|
||||
@keyframes bg-animation {
|
||||
0% { transform: translate(0,0) }
|
||||
10% { transform: translate(-5%,-5%) }
|
||||
20% { transform: translate(-10%,5%) }
|
||||
30% { transform: translate(5%,-10%) }
|
||||
40% { transform: translate(-5%,15%) }
|
||||
50% { transform: translate(-10%,5%) }
|
||||
60% { transform: translate(15%,0) }
|
||||
70% { transform: translate(0,10%) }
|
||||
80% { transform: translate(-15%,0) }
|
||||
90% { transform: translate(10%,5%) }
|
||||
100% { transform: translate(5%,0) }
|
||||
}
|
||||
|
||||
/* invert emojis that are hard to read otherwise */
|
||||
.emoji[aria-label="check mark"],
|
||||
.emoji[aria-label="currency exchange"],
|
||||
.emoji[aria-label="TOP arrow"],
|
||||
.emoji[aria-label="END arrow"],
|
||||
.emoji[aria-label="ON! arrow"],
|
||||
.emoji[aria-label="SOON arrow"],
|
||||
.emoji[aria-label="heavy dollar sign"],
|
||||
.emoji[aria-label="copyright"],
|
||||
.emoji[aria-label="registered"],
|
||||
.emoji[aria-label="trade mark"],
|
||||
.emoji[aria-label="multiply"],
|
||||
.emoji[aria-label="plus"],
|
||||
.emoji[aria-label="minus"],
|
||||
.emoji[aria-label="divide"],
|
||||
.emoji[aria-label="curly loop"],
|
||||
.emoji[aria-label="double curly loop"],
|
||||
.emoji[aria-label="wavy dash"],
|
||||
.emoji[aria-label="paw prints"],
|
||||
.emoji[aria-label="musical note"],
|
||||
.emoji[aria-label="musical notes"] {
|
||||
color: #54a13c;
|
||||
/*filter: invert(100%) hue-rotate(180deg);*/
|
||||
}
|
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);
|
1
public/assets/templates/custom/header.tmpl
Normal file
1
public/assets/templates/custom/header.tmpl
Normal file
@ -0,0 +1 @@
|
||||
<script src="{{AppSubUrl}}/assets/scripts/haxxor.js"></script>
|
Loading…
x
Reference in New Issue
Block a user