2 Commits

Author SHA1 Message Date
36112f1ec8 less drop-shadows 2026-03-04 00:30:50 +01:00
b28b44507b white border 2026-03-03 14:52:31 +01:00
123 changed files with 950 additions and 15708 deletions

View File

@@ -1,204 +0,0 @@
body .select2-container--bootstrap-5 .select2-selection {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border: var(--bs-border-width) solid var(--bs-border-color);
}
body
.select2-container--bootstrap-5.select2-container--focus
.select2-selection,
body
.select2-container--bootstrap-5.select2-container--open
.select2-selection {
border-color: var(--bs-link-hover-color);
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
}
body
.select2-container--bootstrap-5
.select2-selection--multiple
.select2-selection__clear,
body
.select2-container--bootstrap-5
.select2-selection--single
.select2-selection__clear {
background: transparent
url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23676a6d'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e")
50%/0.75rem auto no-repeat;
}
body
.select2-container--bootstrap-5
.select2-selection--multiple
.select2-selection__clear:hover,
body
.select2-container--bootstrap-5
.select2-selection--single
.select2-selection__clear:hover {
background: transparent
url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e")
50%/0.75rem auto no-repeat;
}
body .select2-container--bootstrap-5 .select2-dropdown {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
border-color: var(--bs-link-hover-color);
}
body
.select2-container--bootstrap-5
.select2-dropdown
.select2-search
.select2-search__field {
color: var(--bs-body-color);
background-color: var(--bs-body-bg);
background-clip: padding-box;
border: var(--bs-border-width) solid var(--bs-border-color);
}
body
.select2-container--bootstrap-5
.select2-dropdown
.select2-search
.select2-search__field:focus {
border-color: var(--bs-link-hover-color);
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
}
body
.select2-container--bootstrap-5
.select2-dropdown
.select2-results__options
.select2-results__option.select2-results__message {
color: #6c757d;
}
body
.select2-container--bootstrap-5
.select2-dropdown
.select2-results__options
.select2-results__option.select2-results__option--highlighted {
color: var(--bs-body-color);
background-color: var(--bs-light-bg-subtle) !important;
}
body
.select2-container--bootstrap-5
.select2-dropdown
.select2-results__options
.select2-results__option.select2-results__option--selected,
body
.select2-container--bootstrap-5
.select2-dropdown
.select2-results__options
.select2-results__option[aria-selected="true"]:not(
.select2-results__option--highlighted
) {
color: var(--bs-body-color);
background-color: var(--bs-dark-bg-subtle);
}
body
.select2-container--bootstrap-5
.select2-dropdown
.select2-results__options
.select2-results__option.select2-results__option--disabled,
body
.select2-container--bootstrap-5
.select2-dropdown
.select2-results__options
.select2-results__option[aria-disabled="true"] {
color: #6c757d;
}
body
.select2-container--bootstrap-5
.select2-dropdown
.select2-results__options
.select2-results__option[role="group"]
.select2-results__group {
color: #6c757d;
}
body
.select2-container--bootstrap-5
.select2-selection--single
.select2-selection__rendered {
color: var(--bs-body-color);
}
body
.select2-container--bootstrap-5
.select2-selection--single
.select2-selection__rendered
.select2-selection__placeholder {
color: #6c757d;
}
body
.select2-container--bootstrap-5
.select2-selection--multiple
.select2-selection__rendered
.select2-selection__choice {
color: var(--bs-body-color);
border: var(--bs-border-width) solid var(--bs-border-color);
}
body
.select2-container--bootstrap-5.select2-container--disabled
.select2-selection,
body
.select2-container--bootstrap-5.select2-container--disabled.select2-container--focus
.select2-selection {
color: #6c757d;
background-color: var(--bs-light-bg-subtle);
border-color: var(--bs-dark-bg-subtle);
}
.is-valid + body .select2-container--bootstrap-5 .select2-selection,
.was-validated
select:valid
+ body
.select2-container--bootstrap-5
.select2-selection {
border-color: #198754;
}
.is-valid
+ body
.select2-container--bootstrap-5.select2-container--focus
.select2-selection,
.is-valid
+ body
.select2-container--bootstrap-5.select2-container--open
.select2-selection,
.was-validated
select:valid
+ body
.select2-container--bootstrap-5.select2-container--focus
.select2-selection,
.was-validated
select:valid
+ body
.select2-container--bootstrap-5.select2-container--open
.select2-selection {
border-color: #198754;
box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25);
}
.is-invalid + body .select2-container--bootstrap-5 .select2-selection,
.was-validated
select:invalid
+ body
.select2-container--bootstrap-5
.select2-selection {
border-color: #dc3545;
}
.is-invalid
+ body
.select2-container--bootstrap-5.select2-container--focus
.select2-selection,
.is-invalid
+ body
.select2-container--bootstrap-5.select2-container--open
.select2-selection,
.was-validated
select:invalid
+ body
.select2-container--bootstrap-5.select2-container--focus
.select2-selection,
.was-validated
select:invalid
+ body
.select2-container--bootstrap-5.select2-container--open
.select2-selection {
border-color: #dc3545;
box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25);
}

View File

@@ -1,3 +1,9 @@
.minoes-table {
filter:
drop-shadow(-1px -1px 0 white)
drop-shadow( 1px 1px 0 white);
}
.minoes-table tr {
z-index: calc(100 - var(--row));
position: sticky;
@@ -6,6 +12,8 @@
tr.matrix td:not(.mino) {
border-left: none;
border-bottom: none;
border-right: 1px solid #30303003;
border-top: 1px solid #30303003;
}
.mino {
@@ -38,8 +46,7 @@ tr.matrix td:not(.mino) {
box-shadow:
inset 2px 0 4px rgba(0,0,0,.06),
inset -2px 0 4px rgba(0,0,0,.12),
0 -4px 0 var(--top),
0 2px 4px #0008;
0 -4px 0 var(--top);
filter: saturate(1.1) contrast(1.05);
}
@@ -79,10 +86,34 @@ tr.matrix td:not(.mino) {
}
.ghost {
border: 3px solid #fff2;
padding: 3px;
background-color: #fff2;
border: 3px solid #fff1;
padding: 2px;
background-color: #fff1;
background-clip: content-box;
background-image: none;
box-shadow: none;
}
@keyframes trail-animation {
from {
background-color: #ceffff10;
}
to {
background-color: transparent;
}
}
@keyframes cleared-line-animation {
from {
background-color: #fff6;
filter: saturate(50%) brightness(300%);
box-shadow: 0 0 0 #adb5bd66, 0 0 0 #adb5bd66;
}
60% {
box-shadow: -60px 0 2px #adb5bd33, 60px 0 2px #adb5bd33;
}
to {
background-color: transparent;
box-shadow: -100px 0 5px transparent, 100px 0 5px transparent;
}
}

View File

@@ -1,5 +1,5 @@
:root {
--cell-size: 25px;
--cell-side: 25px;
--rX: -15;
--rY: 0;
--tZ: 25px;
@@ -11,7 +11,7 @@ body {
@supports (backdrop-filter: blur()) {
.modal::before {
content: '';
content: "";
position: absolute;
top: 0;
bottom: 0;
@@ -31,7 +31,7 @@ body {
}
#matrixCard {
background-image: radial-gradient(#222, #25292d);
background-image: radial-gradient(#222, #25292d)
}
.card-header {
@@ -62,16 +62,16 @@ td#timeCell {
}
#matrixTable {
margin-top: calc(-1 * var(--buffer-zone-rows) * var(--cell-size));
margin-top: calc(-1 * var(--buffer-zone-rows) * var(--cell-side));
}
@keyframes hard-dropped-table-animation {
50% {
transform: translate(0, 5px);
25% {
transform: translateY(3px);
}
}
.hard-dropped-table-animation {
animation: hard-dropped-table-animation ease-in-out 0.2s;
animation: hard-dropped-table-animation .2s;
}
tr.buffer-zone td:not(.mino) {
@@ -87,8 +87,8 @@ tr.matrix td:not(.mino) {
td {
overflow: hidden;
width: var(--cell-size);
height: var(--cell-size);
width: var(--cell-side);
height: var(--cell-side);
box-sizing: border-box;
}
@@ -113,32 +113,26 @@ td {
}
td.trail-animation {
animation: trail-animation ease-out 0.3s;
animation: trail-animation ease-out .3s;
}
@keyframes cleared-line-animation {
from {
background-color: white;
filter: saturate(50%) brightness(300%);
box-shadow:
0 0 0 #adb5bd,
0 0 0 #adb5bd;
box-shadow: 0 0 0 #adb5bd, 0 0 0 #adb5bd;
}
60% {
box-shadow:
-60px 0 2px #adb5bd66,
60px 0 2px #adb5bd66;
box-shadow: -60px 0 2px #adb5bd66, 60px 0 2px #adb5bd66;
}
to {
background-color: transparent;
box-shadow:
-100px 0 5px transparent,
100px 0 5px transparent;
box-shadow: -100px 0 5px transparent, 100px 0 5px transparent;
}
}
tr.cleared-line-animation {
animation: cleared-line-animation ease-out 0.3s;
animation: cleared-line-animation ease-out .3s;
}
#holdTable .J,
@@ -163,7 +157,6 @@ tr.cleared-line-animation {
text-shadow: 1px 1px #000c;
font-size: 3vmin;
text-align: center;
z-index: 200;
}
#messagesSpan div {
@@ -199,6 +192,7 @@ tr.cleared-line-animation {
opacity: 0;
transform: scale3d(0.3, 0.3, 0.3);
line-height: var(--bs-body-line-height);
}
30% {
opacity: 1;
@@ -241,13 +235,13 @@ tr.cleared-line-animation {
#messagesSpan div.rotate-in-animation {
animation-name: rotate-in-animation;
animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
animation-timing-function: cubic-bezier(.25,.46,.45,.94);
animation-duration: 1s;
}
#messagesSpan div.zoom-in-animation {
animation-name: zoom-in-animation;
animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
animation-timing-function: cubic-bezier(.25,.46,.45,.94);
transform-origin:center;
animation-duration: 1s;
}
@@ -294,11 +288,3 @@ tr.cleared-line-animation {
#statsModal tr:last-child td {
border-bottom: none;
}
.select2-dropdown {
width: min-content !important;
}
.select2-results__group {
display: inline-block;
}

View File

@@ -1,9 +1,9 @@
body {
background-image: url('electro/bg.jpg');
background-image: url("electro/bg.jpg");
background-size: cover;
}
body[data-bs-theme='dark'] {
body[data-bs-theme="dark"] {
--bs-body-bg: #2125296b;
}
@@ -30,7 +30,7 @@ tr.matrix td:not(.mino) {
}
.mino:not(.ghost):not(.locking):before {
content: '';
content: "";
position: absolute;
z-index: -1;
inset: 0;
@@ -42,8 +42,7 @@ tr.matrix td:not(.mino) {
background: radial-gradient(
at var(--glint-x) var(--glint-y),
rgba(204, 238, 247, 0.9) 0%,
rgba(10, 159, 218, 0.9) 150%
);
rgba(10, 159, 218, 0.9) 150%);
mask:
linear-gradient(#666 0 0) content-box,
linear-gradient(#fff 0 0);

View File

@@ -1,61 +0,0 @@
#sceneDiv {
perspective: 500px;
}
#screenRow {
transform: rotateX(15deg);
}
#screenRow .card {
box-shadow:
0 10px 3px #25292d,
0 15px 0 var(--bs-card-border-color) !important;;
}
tr.matrix td:not(.mino) {
border-left: none;
border-bottom: none;
}
.mino {
background-color: hsl(var(--hue), 55%, 55%);
background-image: linear-gradient(30deg, #fff4, transparent);
border: 1px outset hsl(var(--hue), 55%, 45%);
border-radius: 2px;
box-shadow:
0 10px 3px hsl(var(--hue), 70%, 10%),
0 15px 0 hsla(var(--hue), 90%, 40%, 70%);
opacity: 80%;
backdrop-filter: blur(6px);
}
.I {
--hue: 197;
}
.J {
--hue: 217;
}
.L {
--hue: 36;
}
.O {
--hue: 60;
}
.S {
--hue: 113;
}
.T {
--hue: 268;
}
.Z {
--hue: 0;
}
.ghost {
opacity: 30%;
}

View File

@@ -1,217 +0,0 @@
body {
--bs-gutter-x: 0;
background: black !important;
}
#screenRow {
gap: 0 !important;
margin: 0;
text-transform: uppercase;
letter-spacing: 0.1em;
}
#screenRow {
--bs-gutter-x: 0;
}
.card {
background: black;
border: none;
border-radius: 0;
margin-bottom: 0.5em !important;
}
.card:first-of-type {
border-bottom: 3px solid white;
}
.card-header,
.card-header th {
background: transparent;
font-weight: 400 !important;
font-size: 1.3em;
border: none;
}
#screenRow .table {
--bs-border-width: 0;
}
.minoes-table {
display: flex;
flex-direction: column;
filter: drop-shadow(-2px 0 0 white) drop-shadow(2px 0 0 white) drop-shadow(0 -2px 0 white)
drop-shadow(0 2px 0 white) drop-shadow(5px 8px 0 rgba(9, 9, 9, 22%));
}
.minoes-table tr {
display: flex;
position: relative;
flex-direction: row;
z-index: calc(100 - var(--row));
}
#holdTable {
margin: 0 !important;
}
#statsTable {
width: 10rem;
}
#statsTable tr {
display: flex;
flex-flow: column;
align-items: center;
}
#statsTable td,
#statsTable th {
margin: 0;
padding: 0 !important;
width: auto;
height: auto;
text-transform: uppercase;
}
#statsTable th {
display: inline;
flex-flow: row;
font-size: 0.8em;
text-align: center;
width: 200%;
}
#statsTable td {
font-size: 1.3em;
font-weight: 600;
color: white;
}
td#timeCell {
text-align: center;
}
#matrixCard {
background: transparent;
border-top: none;
border-left: 3px solid white;
border-right: 3px solid white;
border-bottom: 3px solid white;
}
tr.matrix td:not(.mino) {
border: 0;
}
.minoes-table td {
display: inline-block;
width: var(--cell-size);
height: var(--cell-size);
padding: 0 !important;
z-index: calc(200 - var(--row));
}
.mino {
width: inherit;
height: inherit;
display: block;
padding: 0;
opacity: 100%;
border-width: 1px;
border-style: solid;
box-shadow: 0 -6px 0 var(--box-shadow-color);
}
.I.mino {
background-color: #42afe1;
border-color: #6ceaff;
--box-shadow-color: #6ceaff;
}
.J.mino {
background-color: #1165b5;
border-color: #339bff;
--box-shadow-color: #339bff;
}
.L.mino {
background-color: #f38927;
border-color: #ffba59;
--box-shadow-color: #ffba59;
}
.O.mino {
background-color: #f6d03c;
border-color: #ffff7f;
--box-shadow-color: #ffff7f;
}
.S.mino {
background-color: #32ee3e;
border-color: #84f880;
--box-shadow-color: #84f880;
}
.T.mino {
background-color: #9739a2;
border-color: #d958e9;
--box-shadow-color: #d958e9;
}
.Z.mino {
background-color: #eb4f65;
border-color: #ff7f79;
--box-shadow-color: #ff7f79;
}
.ghost.mino {
background-color: #fff4;
border: none;
opacity: 5%;
box-shadow: none;
transform: translateY(-3px);
}
.moving.mino {
filter: saturate(80%) brightness(130%);
}
.locking.mino {
filter: saturate(20%) brightness(300%);
}
.locked.mino {
animation: locked-animation;
animation-duration: 0.2s;
}
.disabled.mino {
filter: brightness(50%) contrast(65%);
opacity: 70%;
}
@keyframes locked-animation {
from {
filter: saturate(50%) brightness(300%);
}
}
@keyframes cleared-line-animation {
from {
background-color: #eeeeee;
}
to {
background-color: transparent;
}
}
@keyframes trail-animation {
from {
background-color: #ceffff05;
filter: saturate(50%) brightness(110%);
}
to {
background-color: transparent;
}
}

View File

@@ -1,118 +0,0 @@
.minoes-table {
display: flex;
flex-direction: column;
filter: drop-shadow(0 8px 1px #0008);
}
.minoes-table tr {
display: flex;
position: relative;
flex-direction: row;
z-index: calc(100 - var(--row));
}
tr.matrix td:not(.mino) {
border: none;
border-right: 1px solid #8884;
}
.minoes-table td {
display: inline-block;
width: var(--cell-size);
height: var(--cell-size);
padding: 0 !important;
z-index: calc(200 - var(--row));
}
.mino {
width: inherit;
height: inherit;
display: block;
padding: 0;
opacity: 100%;
border: none;
box-shadow: 0 -6px 0 var(--box-shadow-color);
}
.I.mino {
background-color: #0293b0;
--box-shadow-color: #05d2f2;
}
.J.mino {
background-color: #2c69c2;
--box-shadow-color: #7bb7f6;
}
.L.mino {
background-color: #fa9b23;
--box-shadow-color: #ffba59;
}
.O.mino {
background-color: #f9d92c;
--box-shadow-color: #fff194;
}
.S.mino {
background-color: #01a493;
--box-shadow-color: #03e7d3;
}
.T.mino {
background-color: #6830d1;
--box-shadow-color: #bb88fc;
}
.Z.mino {
background-color: #ee2b58;
--box-shadow-color: #fd4487;
}
.ghost.mino {
background-color: #fff8;
box-shadow: none;
transform: blue(4px);
}
.moving.mino {
filter: saturate(80%) brightness(130%);
}
.locking.mino {
filter: saturate(20%) brightness(300%);
}
.locked.mino {
animation: locked-animation;
animation-duration: 0.2s;
}
.disabled.mino {
filter: brightness(50%) contrast(65%);
}
@keyframes locked-animation {
from {
filter: saturate(50%) brightness(300%);
}
}
@keyframes cleared-line-animation {
from {
background-color: #eeeeee;
}
to {
background-color: transparent;
}
}
@keyframes trail-animation {
from {
background-color: #ceffff05;
filter: saturate(50%) brightness(110%);
}
to {
background-color: transparent;
}
}

View File

@@ -1,81 +0,0 @@
:root {
--cell-size: 24px;
--sprite-size: round(100% / 8, 1px);
--skin-url: url(https://i.imgur.com/HqGYC5G.png);
}
.card {
background-color: #1c1c1c;
}
.card-body {
background-color: black;
}
#matrixCard {
background-image: url(jstris-skin/jstris-grid.png);
background-position: bottom;
background-repeat: no-repeat;
}
tr.matrix td:not(.mino) {
border: none;
}
.mino {
background-image: var(--skin-url);
background-size: cover;
background-repeat: no-repeat;
background-position-x: calc(var(--sprite-pos) * var(--sprite-size));
}
.I {
--sprite-pos: 6;
}
.J {
--sprite-pos: 7;
}
.L {
--sprite-pos: 3;
}
.O {
--sprite-pos: 4;
}
.S {
--sprite-pos: 5;
}
.T {
--sprite-pos: 8;
}
.Z {
--sprite-pos: 2;
}
.ghost {
--sprite-pos: 1;
opacity: 50%;
}
.disabled {
--sprite-pos: 0;
}
.locking.mino {
filter: saturate(60%) brightness(180%);
}
#holdTable .mino,
#nextTable .mino {
box-shadow: 4px 4px 10px #0002;
}
.preview {
--cell-size: 24px;
height: var(--cell-size);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -5,8 +5,12 @@
.minoes-table {
display: flex;
flex-direction: column;
filter: drop-shadow(-2px 0 0 white) drop-shadow(2px 0 0 white) drop-shadow(0 -2px 0 white)
drop-shadow(0 2px 0 white) drop-shadow(5px 8px 0 rgba(9, 9, 9, 22%));
filter:
drop-shadow(-2px 0 0 white)
drop-shadow(2px 0 0 white)
drop-shadow(0 -2px 0 white)
drop-shadow(0 2px 0 white)
drop-shadow(5px 8px 0 rgba(9, 9, 9, 22%));
}
.minoes-table tr {
@@ -22,8 +26,8 @@ tr.matrix td:not(.mino) {
.minoes-table td {
display: inline-block;
width: var(--cell-size);
height: var(--cell-size);
width: var(--cell-side);
height: var(--cell-side);
padding: 0 !important;
z-index: calc(200 - var(--row));
}
@@ -37,38 +41,38 @@ tr.matrix td:not(.mino) {
}
.I.mino {
--background-color: #42afe1;
--box-shadow-color: #6ceaff;
--background-color: #42AFE1;
--box-shadow-color: #6CEAFF;
}
.J.mino {
--background-color: #1165b5;
--box-shadow-color: #339bff;
--background-color: #1165B5;
--box-shadow-color: #339BFF;
}
.L.mino {
--background-color: #f38927;
--box-shadow-color: #ffba59;
--background-color: #F38927;
--box-shadow-color: #FFBA59;
}
.O.mino {
--background-color: #f6d03c;
--box-shadow-color: #ffff7f;
--background-color: #F6D03C;
--box-shadow-color: #FFFF7F;
}
.S.mino {
--background-color: #51b84d;
--box-shadow-color: #84f880;
--background-color: #51B84D;
--box-shadow-color: #84F880;
}
.T.mino {
--background-color: #9739a2;
--box-shadow-color: #d958e9;
--background-color: #9739A2;
--box-shadow-color: #D958E9;
}
.Z.mino {
--background-color: #eb4f65;
--box-shadow-color: #ff7f79;
--background-color: #EB4F65;
--box-shadow-color: #FF7F79;
}
.ghost.mino {
@@ -83,7 +87,7 @@ tr.matrix td:not(.mino) {
.locking.mino {
--background-color: white;
--box-shadow-color: #ddd;
--box-shadow-color: #DDD;
}
.locked.mino {

View File

@@ -1,89 +0,0 @@
.minoes-table tr {
z-index: calc(100 - var(--row));
position: sticky;
}
tr.matrix td:not(.mino) {
border-left: none;
border-bottom: none;
}
.mino {
--color: hsl(var(--hue), var(--saturation), 60%);
--dark: hsl(var(--hue), var(--saturation), 28%);
--light: hsl(var(--hue), calc(0.66 * var(--saturation)), 90%);
--border: hsl(var(--hue), var(--saturation), 40%);
--top: hsl(var(--hue), calc(0.6 * var(--saturation)), 75%);
position: relative;
background-color: var(--dark);
background-image: radial-gradient(
ellipse 200% 120% at 50% 75%,
#fff8 10%,
var(--dark) 28%,
#fff8 38%,
var(--dark) 48%
);
border: 1px outset var(--border);
border-radius: 3px;
box-shadow:
inset 3px 0 4px rgba(0,0,0,.06),
inset -3px 0 4px rgba(0,0,0,.12),
0 -3px 0 var(--top),
0 2px 2px #0004;
}
.mino:after {
--size: calc(var(--cell-size) - 12px);
position: absolute;
content: "";
box-sizing: content-box;
width: var(--size);
height: var(--size);
opacity: 40%;
background: var(--color);
left: 3px;
top: 3px;
border: 2px solid var(--border);
border-top-color: white;
}
.I {
--hue: 193;
--saturation: 100%;
}
.J {
--hue: 215;
--saturation: 100%;
}
.L {
--hue: 25;
--saturation: 100%;
}
.O {
--hue: 42;
--saturation: 100%;
}
.S {
--hue: 95;
--saturation: 100%;
}
.T {
--hue: 300;
--saturation: 56%;
}
.Z {
--hue: 357;
--saturation: 84%;
}
.ghost {
--hue: 0;
--saturation: 0%;
opacity: 30%;
}

View File

@@ -1,171 +0,0 @@
:root {
--cell-size: 20px;
--sprite-size: 40px;
}
@font-face {
font-family: 'Early GameBoy';
src: url('old-school/Early GameBoy.ttf');
}
#screenRow {
background-image: url('old-school/bg.png');
background-size: 10px;
padding: 40px 20px;
border: 3px inset black;
border-radius: 10px;
}
.col {
gap: 8px;
}
.card {
background: #8d8e04;
border-radius: 0;
border-image-source: url('old-school/border-sm.png');
border-image-slice: 25;
border-image-width: 13px;
border-image-repeat: repeat;
border-image-outset: 12px;
box-shadow: unset;
width: 100%;
}
.card-header {
background: #8d8e04;
}
#matrixCard {
background: #808302;
border-image-source: url('old-school/border-lg.png');
border-image-slice: 30;
border-image-width: 15px;
border-image-outset: 15px;
}
#statsTable,
.card,
.card-header,
#messagesSpan div {
font-family: 'Early GameBoy', monospace;
font-smooth: never;
-webkit-font-smoothing: none;
color: #254806;
text-shadow:
-1px -1px 3px rgba(0, 0, 0, 40%),
1px 1px 1px rgba(0, 0, 0, 40%);
}
#statsTable {
font-size: 0.7em;
letter-spacing: -0.1em;
}
#statsTable tr {
display: flex;
flex-flow: column;
}
#statsTable th,
#statsTable td {
border: 0;
padding: 0 0.2rem;
}
#statsTable td {
width: auto;
text-align: end;
}
#messagesSpan {
text-shadow:
-2px -2px #808302,
-2px 2px #808302,
2px -2px #808302,
2px 2px #808302;
}
.minoes-table td {
border: 0 !important;
}
.mino {
box-shadow:
-2px -2px 5px rgba(0, 0, 0, 40%),
1px 1px 2px rgba(0, 0, 0, 40%);
background-size: cover;
background-image: url('old-school/sprites.png');
background-position: calc(var(--sprite-pos) * var(--sprite-size)) 0px;
}
.I.mino {
--sprite-pos: 0;
}
.J.mino {
--sprite-pos: 1;
}
.L.mino {
--sprite-pos: 2;
}
.O.mino {
--sprite-pos: 3;
}
.S.mino {
--sprite-pos: 4;
}
.T.mino {
--sprite-pos: 5;
}
.Z.mino {
--sprite-pos: 6;
}
@keyframes blinker {
35% {
opacity: 50%;
}
}
.locking.mino {
filter: brightness(135%) contrast(70%);
}
.ghost.mino,
.disabled.mino {
opacity: 50%;
}
.locked.mino {
animation: none;
}
.hard-dropped-table-animation {
animation: hard-dropped-table-animation steps(1) 0.2s;
}
@keyframes cleared-line-animation {
10%,
30%,
50%,
70%,
90% {
opacity: 0;
}
20%,
40%,
60%,
80% {
opacity: 100%;
}
}
tr.cleared-line-animation {
animation: cleared-line-animation ease-out 0.4s;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -7,7 +7,7 @@ body {
gap: 0 !important;
margin: 0;
text-transform: uppercase;
letter-spacing: 0.1em;
letter-spacing: .1em;
}
#screenRow {
@@ -95,38 +95,38 @@ td#timeCell {
}
.I.mino {
background-color: #42afe1;
border-color: #6ceaff;
background-color: #42AFE1;
border-color: #6CEAFF;
}
.J.mino {
background-color: #1165b5;
border-color: #339bff;
background-color: #1165B5;
border-color: #339BFF;
}
.L.mino {
background-color: #f38927;
border-color: #ffba59;
background-color: #F38927;
border-color: #FFBA59;
}
.O.mino {
background-color: #f6d03c;
border-color: #ffff7f;
background-color: #F6D03C;
border-color: #FFFF7F;
}
.S.mino {
background-color: #32ee3e;
border-color: #84f880;
border-color: #84F880;
}
.T.mino {
background-color: #9739a2;
border-color: #d958e9;
background-color: #9739A2;
border-color: #D958E9;
}
.Z.mino {
background-color: #eb4f65;
border-color: #ff7f79;
background-color: #EB4F65;
border-color: #FF7F79;
}
.ghost.mino {

153
css/retro.css Normal file
View File

@@ -0,0 +1,153 @@
:root {
--cell-side: 20px;
}
@font-face {
font-family: "Early GameBoy";
src: url("retro/Early GameBoy.ttf");
}
#screenRow {
background-image: url("retro/bg.png");
background-size: 10px;
padding: 40px 20px;
border: 3px inset black;
border-radius: 10px;
}
.col {
gap: 8px;
}
.card {
background: #8D8E04;
border-radius: 0;
border-image-source: url("retro/border-sm.png");
border-image-slice: 25;
border-image-width: 13px;
border-image-repeat: repeat;
border-image-outset: 12px;
box-shadow: unset;
width: 100%;
}
.card-header {
background: #8D8E04;
}
#matrixCard {
background: #808302;
border-image-source: url("retro/border-lg.png");
border-image-slice: 30;
border-image-width: 15px;
border-image-outset: 15px;
}
#statsTable,
.card,
.card-header,
#messagesSpan {
font-family: "Early GameBoy", monospace;
font-smooth: never;
-webkit-font-smoothing: none;
color: #254806;
text-shadow: -1px -1px 3px rgba(0, 0, 0, 40%), 1px 1px 1px rgba(0, 0, 0, 40%);
}
#statsTable {
font-size: .7em;
letter-spacing: -.1em;
}
#statsTable tr {
display: flex;
flex-flow: column;
}
#statsTable th,
#statsTable td {
border: 0;
padding: 0 .2rem;
}
#statsTable td {
width: auto;
text-align: end;
}
#messagesSpan {
text-shadow: -2px -2px #808302, -2px 2px #808302, 2px -2px #808302, 2px 2px #808302;
}
.minoes-table td {
border: 0 !important;
}
.mino {
box-shadow: -2px -2px 5px rgba(0, 0, 0, 40%), 1px 1px 2px rgba(0, 0, 0, 40%);
background-size: 100%;
}
.I.mino {
background-image: url("retro/I-mino.png")
}
.J.mino {
background-image: url("retro/J-mino.png")
}
.L.mino {
background-image: url("retro/L-mino.png")
}
.O.mino {
background-image: url("retro/O-mino.png")
}
.S.mino {
background-image: url("retro/S-mino.png")
}
.T.mino {
background-image: url("retro/T-mino.png")
}
.Z.mino {
background-image: url("retro/Z-mino.png")
}
@keyframes blinker {
35% {
opacity: 50%;
}
}
.locking.mino {
animation: blinker 0.08s step-start infinite;
}
.ghost.mino,
.disabled.mino {
opacity: 50%;
}
.locked.mino {
animation: none;
}
.hard-dropped-table-animation {
animation: hard-dropped-table-animation steps(1) .2s;
}
@keyframes cleared-line-animation {
10%, 30%, 50%, 70%, 90% {
opacity: 0;
}
20%, 40%, 60%, 80% {
opacity: 100%;
}
}
tr.cleared-line-animation {
animation: cleared-line-animation ease-out .4s;
}

BIN
css/retro/I-mino.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
css/retro/J-mino.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
css/retro/L-mino.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
css/retro/O-mino.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
css/retro/S-mino.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
css/retro/T-mino.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
css/retro/Z-mino.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 870 B

After

Width:  |  Height:  |  Size: 870 B

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 298 KiB

View File

@@ -1,15 +1,6 @@
:root {
--rbw: 4px;
--tl: calc(-1 * var(--rbw));
--cell-size-opposite: calc(-1 * var(--cell-size));
--t3d: translate3d(var(--tl), var(--tl), var(--cell-size-opposite));
}
body {
background-image:
url(stereo/bg.jpg),
radial-gradient(
circle at center,
background-image: url(stereo/bg.jpg),
radial-gradient(circle at center,
#39444f 0%,
#2c323b 25%,
#293036 28%,
@@ -20,8 +11,7 @@ body {
#151519 63%,
#141418 65%,
#0f0f12 74%,
#0a0c0d 100%
);
#0a0c0d 100%);
background-repeat: space;
background-position: center;
background-size: cover;
@@ -36,25 +26,17 @@ body {
cursor: grabbing;
}
#screenRow {
--light-rX: calc(-1 * var(--rY) / 30);
--light-rY: calc(var(--rX) / 20);
display: block;
transform: translateZ(var(--tZ)) rotateX(calc((var(--rX)) * 1deg))
rotateY(calc((var(--rY)) * 1deg));
#sceneDiv * {
transform-style: preserve-3d;
}
#sceneDiv,
#screenRow,
#screenRow .col,
#screenRow .card,
#screenRow .card-body,
.minoes-table,
.minoes-table tbody,
.minoes-table tr,
.minoes-table td {
#screenRow {
display: block;
transform: translateZ(var(--tZ)) rotateX(calc((var(--rX)) * 1deg)) rotateY(calc((var(--rY)) * 1deg));
}
#screenRow * {
display: block;
transform-style: preserve-3d;
}
#screenRow .col {
@@ -70,11 +52,10 @@ body {
#matrixCard {
background-image: none;
transform-origin: bottom;
}
#screenRow .card>* {
transform: translateZ(var(--cell-size));
transform: translateZ(var(--cell-side));
}
#screenRow .card-header {
@@ -84,7 +65,8 @@ body {
.card,
.card-header {
text-shadow: calc(-0.3px * var(--rY)) calc(0.4px * var(--rX)) 5px #0008;
text-shadow:
calc(-0.3px * var(--rY)) calc(0.4px * var(--rX)) 5px #0008;
}
#holdTable .mino {
@@ -105,7 +87,7 @@ body {
.minoes-table tr {
width: max-content;
height: var(--cell-size);
height: var(--cell-side);
}
#statsTable tr {
@@ -124,30 +106,27 @@ tr.matrix td:not(.mino) {
}
.minoes-table td {
width: var(--cell-size);
height: var(--cell-size);
width: var(--cell-side) !important;
height: var(--cell-side) !important;
overflow: visible;
position: relative;
}
.mino,
.mino::before,
.mino + :not(.mino)::before,
.mino::after {
--light-pX: calc(0.5 - var(--column) / 10);
--light-pY: calc(3.5 - var(--row) / 6);
--light-x: calc(var(--light-rX) + var(--light-pX));
--light-y: calc(var(--light-rY) + var(--light-pY));
.minoes-table .mino,
.minoes-table .mino::before,
.minoes-table .mino + :not(.mino)::before,
.minoes-table .mino::after {
--light-x: calc(-0.5 - var(--rY) / 30 - var(--column) / 10 + 1);
--light-y: calc(-0.5 + var(--rX) / 20 - var(--row) / 6 + 4);
--center-color: hsla(var(--h), var(--s), calc(var(--l) * var(--light) * 1.1), var(--a));
--edge-color: hsla(var(--h), var(--s), calc(var(--l) * (var(--light) * 0.9)), var(--a));
background: var(--center-color);
border-radius: 4px;
border-radius: 2px;
border: 2px outset var(--center-color);
}
.mino::before,
.mino + :not(.mino)::before,
.mino::after,
.minoes-table .mino::before,
.minoes-table .mino + :not(.mino)::before,
.minoes-table .mino::after,
td.trail-animation::before,
td.trail-animation::after,
tr.cleared-line-animation td::before,
@@ -157,14 +136,18 @@ tr.cleared-line-animation td::after {
top: 0;
left: 0;
display: block;
width: var(--cell-size);
height: var(--cell-size);
width: var(--cell-side);
height: var(--cell-side);
}
/* Front face */
.mino,
.minoes-table .mino,
td.trail-animation {
--light: calc(1 + (var(--light-y) * 0.3) + (var(--light-x) * 0.2));
--light: calc(
1
+ (var(--light-y) * 0.3)
+ (var(--light-x) * 0.2)
);
--center-x: calc(35% + var(--light-x) * 10%);
--center-y: calc(35% + var(--light-y) * 10%);
background: radial-gradient(
@@ -172,131 +155,83 @@ td.trail-animation {
var(--center-color) 15%,
var(--edge-color) 100%
);
box-shadow: 0 0 6px hsla(var(--h), var(--s), calc(var(--l) * var(--light) * 1.3), 40%);
border-style: ridge;
border-width: var(--rbw);
box-shadow: 0 0 7px hsla(var(--h), var(--s), calc(var(--l) * var(--light) * 1.3), 20%);
}
/* Left face */
.mino::before,
.minoes-table .mino::before,
td.trail-animation::before,
tr.cleared-line-animation td::before,
.mino + .mino::before {
--light: calc(1.1 + (var(--light-x) * -0.2) + (var(--light-y) * 0.15));
transform: var(--t3d) rotateY(-90deg);
.left .minoes-table .mino + .mino::before {
--light: calc(
1.1
+ (var(--light-x) * -0.2)
+ (var(--light-y) * 0.15)
);
transform: translate3d(-1.5px, -1.5px, calc(-1 * var(--cell-side))) rotateY(-90deg);
transform-origin: left;
}
/* Right face */
.mino + :not(.mino)::before,
.right .mino + .mino::before,
.right .minoes-table .mino + .mino::before,
.minoes-table .mino + :not(.mino)::before,
.right td.trail-animation::before,
.right tr.cleared-line-animation td::before {
--light: calc(0.85 + (var(--light-x) * -0.2) + (var(--light-y) * -0.15));
--light: calc(
0.85
+ (var(--light-x) * -0.2)
+ (var(--light-y) * -0.15)
);
--center-x: calc(65% + var(--light-x) * 10%);
--center-y: calc(35% + var(--light-y) * 10%);
filter: saturate(0.95);
transform: translate3d(0, 0, var(--cell-size-opposite)) rotateY(-90deg);
transform: translate3d(0, 0, calc(-1 * var(--cell-side))) rotateY(-90deg);
transform-origin: left;
}
.right .mino:last-child::before {
transform: var(--t3d) rotateY(90deg) !important;
.right .minoes-table .mino:last-child::before {
transform: translate3d(-1.5px, -1.5px, calc(-1 * var(--cell-side))) rotateY(90deg) !important;
transform-origin: right !important;
}
/* Top face */
.mino::after,
.minoes-table .mino::after,
td.trail-animation::after,
tr.cleared-line-animation td::after {
--light: calc(1.5 + (var(--light-y) * 0.2));
transform: var(--t3d) rotateX(90deg);
--light: calc(
1.5
+ (var(--light-y) * 0.2)
);
transform: translate3d(-1.5px, -1.5px, calc(-1 * var(--cell-side))) rotateX(90deg);
transform-origin: top;
}
/* Bottom face */
.bottom .mino::after,
.bottom .minoes-table .mino::after,
.bottom td.trail-animation::after,
.bottom tr.cleared-line-animation td::after {
--light: calc(1.1 + (var(--light-y) * -0.3));
--light: calc(
1.1
+ (var(--light-y) * -0.3)
);
--center-x: calc(65% + var(--light-x) * 10%);
--center-y: calc(65% + var(--light-y) * 10%);
filter: saturate(0.95);
transform: var(--t3d) rotateX(-90deg);
transform: translate3d(-1.5px, -1.5px, calc(-1 * var(--cell-side))) rotateX(-90deg);
transform-origin: bottom;
}
.J,
.J + :not(.mino) {
--h: 210deg;
--s: 78%;
--l: 52%;
--a: 0.75;
}
.L,
.L + :not(.mino) {
--h: 28deg;
--s: 85%;
--l: 52%;
--a: 0.75;
}
.O,
.O + :not(.mino) {
--h: 48deg;
--s: 88%;
--l: 52%;
--a: 0.75;
}
.I,
.I + :not(.mino) {
--h: 200deg;
--s: 70%;
--l: 52%;
--a: 0.75;
}
.S,
.S + :not(.mino) {
--h: 118deg;
--s: 45%;
--l: 52%;
--a: 0.75;
}
.T,
.T + :not(.mino) {
--h: 293deg;
--s: 48%;
--l: 52%;
--a: 0.75;
}
.Z,
.Z + :not(.mino) {
--h: 352deg;
--s: 75%;
--l: 52%;
--a: 0.75;
}
.J.mino, .J.mino + :not(.mino) { --h: 210deg; --s: 78%; --l: 52%; --a: 0.75; }
.L.mino, .L.mino + :not(.mino) { --h: 28deg; --s: 85%; --l: 52%; --a: 0.75; }
.O.mino, .O.mino + :not(.mino) { --h: 48deg; --s: 88%; --l: 52%; --a: 0.75; }
.I.mino, .I.mino + :not(.mino) { --h: 200deg; --s: 70%; --l: 52%; --a: 0.75; }
.S.mino, .S.mino + :not(.mino) { --h: 118deg; --s: 45%; --l: 52%; --a: 0.75; }
.T.mino, .T.mino + :not(.mino) { --h: 293deg; --s: 48%; --l: 52%; --a: 0.75; }
.Z.mino, .Z.mino + :not(.mino) { --h: 352deg; --s: 75%; --l: 52%; --a: 0.75; }
.ghost.mino,
.ghost.mino + :not(.mino) {
--h: 0deg;
--s: 0%;
--l: 55%;
--a: 0.4;
}
.locking.mino,
.locking.mino + :not(.mino) {
--h: 0deg;
--s: 0%;
--l: 92%;
--a: 0.72;
}
.disabled.mino,
.disabled.mino + :not(.mino) {
--h: 0deg;
--s: 0%;
--l: 45%;
--a: 0.72;
}
.ghost.mino, .ghost.mino + :not(.mino) { --h: 0deg; --s: 0%; --l: 55%; --a: 0.40; }
.locking.mino, .locking.mino + :not(.mino) { --h: 0deg; --s: 0%; --l: 92%; --a: 0.72; }
.disabled.mino, .disabled.mino + :not(.mino) { --h: 0deg; --s: 0%; --l: 45%; --a: 0.72; }
#holdTable .J + :not(.mino),
#holdTable .L + :not(.mino),
@@ -324,21 +259,12 @@ tr.cleared-line-animation td::after {
td.trail-animation::before,
td.trail-animation::after {
animation: trail-animation ease-out 0.3s;
}
@keyframes hard-dropped-table-animation {
50% {
transform: translateY(10px) rotateX(-3deg);
}
animation: trail-animation ease-out .3s;
}
@keyframes locked-animation {
from {
--h: 0deg;
--s: 0%;
--l: 100%;
--a: 1;
--h: 0deg; --s: 0%; --l: 100%; --a: 1;
box-shadow: 0 0 10px hsla(180, 100%, 100%, 0.2);
}
}
@@ -346,7 +272,7 @@ td.trail-animation::after {
.locked.mino::before,
.locked.mino::after {
animation: locked-animation;
animation-duration: 0.2s;
animation-duration: .2s;
}
@keyframes cleared-line-animation {
@@ -362,7 +288,7 @@ td.trail-animation::after {
tr.cleared-line-animation td::before,
tr.cleared-line-animation td::after {
animation: cleared-line-animation ease-out 0.3s;
animation: cleared-line-animation ease-out .3s;
}
@keyframes show-level-animation {
@@ -414,7 +340,8 @@ tr.cleared-line-animation td::after {
}
30% {
transform: translateZ(0) scale3d(1, 1, 1);
transform: translateZ(0);
transform: scale3d(1, 1, 1);
}
80% {

View File

@@ -1,43 +0,0 @@
tr.matrix td:not(.mino),
tr.matrix td.mino {
border-left: none;
border-right: 1px solid #333;
border-top: 1px solid #333;
border-bottom: none;
}
.mino {
background-size: cover
}
.I {
background-image: url(https://www.svgrepo.com/show/395902/blue-square.svg)
}
.J {
background-image: url(https://www.svgrepo.com/show/395944/brown-square.svg);
}
.L {
background-image: url(https://www.svgrepo.com/show/397681/orange-square.svg);
}
.O {
background-image: url(https://www.svgrepo.com/show/398716/yellow-square.svg);
}
.S {
background-image: url(https://www.svgrepo.com/show/396582/green-square.svg);
}
.T {
background-image: url(https://www.svgrepo.com/show/398143/purple-square.svg);
}
.Z {
background-image: url(https://www.svgrepo.com/show/397699/red-square.svg);
}
.ghost {
background-image: url(https://www.svgrepo.com/show/398610/white-large-square.svg);
}

View File

@@ -1,9 +1,9 @@
body {
background-image: url(synthwave/wtCSusF.jpeg);
background-image: url(synthwave/bg.png);
background-size: cover;
}
body[data-bs-theme='dark'] {
body[data-bs-theme="dark"] {
--bs-body-bg: #2125296b;
}
@@ -21,31 +21,18 @@ body[data-bs-theme='dark'] {
.card,
#matrixCard {
background: repeating-linear-gradient(transparent, transparent 2px, #1114 2px, #1114 5px);
background: repeating-linear-gradient(transparent, #111 1px);
backdrop-filter: blur(3px);
}
.minoes-table {
background: transparent;
border-spacing: 2px;
}
#matrixTable {
margin-top: calc(-1 * var(--buffer-zone-rows) * var(--cell-size) - 8px);
}
#matrixTable td:not(.mino) {
border-color: #8881;
border-top: none;
border-bottom: none;
}
.mino {
background: var(--color);
border: 3px solid var(--border);
border-radius: 6px;
box-shadow: 0 0 8px var(--border);
filter: blur(0.5px);
}
.I {
@@ -79,8 +66,8 @@ body[data-bs-theme='dark'] {
}
.Z {
--color: #e67d8666;
--border: #e67d86;
--color: #E67D8666;
--border: #E67D86;
}
.ghost {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 972 KiB

View File

@@ -1,68 +0,0 @@
:root {
--cell-size: 30px;
--sprite-size: round(100% / 11, 1px);
--skin-url: url(tetrio-skin/a_forest.png);
}
tr.matrix td:not(.mino) {
border-left: none;
border-bottom: none;
}
.mino {
background-image: var(--skin-url);
background-size: cover;
background-repeat: no-repeat;
background-position-x: calc(var(--sprite-pos) * var(--sprite-size));
}
.I {
--sprite-pos: 4;
}
.J {
--sprite-pos: 5;
}
.L {
--sprite-pos: 1;
}
.O {
--sprite-pos: 2;
}
.S {
--sprite-pos: 3;
}
.T {
--sprite-pos: 6;
}
.Z {
--sprite-pos: 0;
}
.ghost {
--sprite-pos: 7;
opacity: 40%;
}
.disabled {
--sprite-pos: 8;
}
.locking.mino {
filter: saturate(60%) brightness(180%);
}
#holdTable .mino,
#nextTable .mino {
box-shadow: 4px 4px 10px #0002;
}
.preview {
--cell-size: 24px;
height: var(--cell-size);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html lang="fr" data-bs-theme="dark">
<html lang="fr">
<head>
<meta charset="utf-8" />
@@ -8,24 +8,15 @@
<meta name="color-scheme" content="dark">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.4/font/bootstrap-icons.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" />
<link rel="stylesheet" href="css/_select2-dark.css">
<link rel="stylesheet" href="css/_common.css">
<link rel="stylesheet" href="css/tetrio-skin.css" title="Thème sélectionné" id="selectedStyleSheet">
<link rel="alternate stylesheet" href="css/tetrio-skin.css" title="Sample Tetr.io...">
<link rel="alternate stylesheet" href="css/jstris-skin.css" title="Sample JStris...">
<link rel="stylesheet" href="css/common.css">
<link rel="stylesheet" href="css/classic.css" title="Thème sélectionné" id="selectedStyleSheet">
<link rel="alternate stylesheet" href="css/classic.css" title="Classique">
<link rel="alternate stylesheet" href="css/neo-classic.css" title="Néo-classique">
<link rel="alternate stylesheet" href="css/minimal.css" title="Minimal">
<link rel="alternate stylesheet" href="css/electro.css" title="Électro">
<link rel="alternate stylesheet" href="css/synthwave.css" title="Synthwave">
<link rel="alternate stylesheet" href="css/heavy-metal.css" title="Heavy metal">
<link rel="alternate stylesheet" href="css/jazz.css" title="Jazz">
<link rel="alternate stylesheet" href="css/old-school.css" title="Old School">
<link rel="alternate stylesheet" href="css/stereo.css" title="3D">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.1.0-rc.0/js/select2.min.js"></script>
<link rel="alternate stylesheet" href="css/retro.css" title="Rétro">
<link rel="alternate stylesheet" href="css/opera.css" title="Opéra">
<link rel="alternate stylesheet" href="css/stereo.css" title="Stéréo">
<link rel="apple-touch-icon" sizes="180x180" href="favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="favicons/T-2.png">
<link rel="icon" type="image/png" sizes="16x16" href="favicons/favicon-16x16.png">
@@ -36,12 +27,12 @@
<meta property="og:image" content="https://adrien.malingrey.fr/jeux/quatuor/thumbnail.png"/>
<meta property="og:image:width" content="288"/>
<meta property="og:image:height" content="288"/>
<meta property="og:description" content="Un jeu de quatuors de blocs qui tombent."/>
<meta property="og:description" content="Un jeu avec un quatuor de blocs qui tombent."/>
<meta property="og:locale" content="fr_FR"/>
<meta property="og:site_name" content="adrien.malingrey.fr"/>
</head>
<body>
<body data-bs-theme="dark">
<div class="modal fade" id="settingsModal" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered">
@@ -69,8 +60,7 @@
<div class="col-4"><input name="pause" id="pauseInput" type="text" class="form-control text-center" value="Échap." onfocus="changeKey(this)" placeholder="Touche ?" title="Modifier la touche" required></div>
<label for="pauseInput" title="Pause" class="col-2 col-form-label d-flex align-items-center justify-content-center"><i class="bi bi-pause"></i></label>
</fieldset>
<fieldset id="autorepeatFieldset" class="row g-2 mb-3 align-items-center text-center">
<!--<legend class="text-start">Répétition automatique</legend>-->
<fieldset id="autorepeatFieldset" class="row g-2 mb-3 align-items-center text-center"><!--<legend class="text-start">Répétition automatique</legend>-->
<label for="arrInput" class="col-2 col-form-label"><abbr title="Automatic Repeat Rate : période de répétition de l'action">ARR</abbr></label>
<div class="col-4"><div class="input-group"><input name="arr" id="arrInput" type="number" class="form-control text-center" value="50" min="2" max="200" step="1"><div class="input-group-text">ms</div></div></div>
<div class="col-4"><div class="input-group"><input name="das" id="dasInput" type="number" class="form-control text-center" value="300" min="100" max="500" step="5"><div class="input-group-text">ms</div></div></div>
@@ -78,30 +68,15 @@
</fieldset>
<fieldset class="row g-2 mb-3 align-items-center text-center"><legend class="text-start">Interface</legend>
<label for="stylesheetSelect" class="col-2 col-form-label">Thème</label>
<div class="col-4">
<select name="stylesheet" id="stylesheetSelect" class="form-select">
<option value="css/tetrio-skin.css" selected>Sample Tetr.io...</option>
<option value="css/jstris-skin.css">Sample JStris...</option>
<option value="css/classic.css">Classique</option>
<option value="css/neo-classic.css">Néo-classique</option>
<div class="col-4"><select name="stylesheet" id="stylesheetSelect" class="form-select" oninput="selectedStyleSheet.href = this.value">
<option value="css/classic.css" selected>Classique</option>
<option value="css/minimal.css">Minimal</option>
<option value="css/synthwave.css">Synthwave</option>
<option value="css/electro.css">Électro</option>
<option value="css/heavy-metal.css">Heavy metal</option>
<option value="css/jazz.css">Jazz</option>
<option value="css/old-school.css">Old School</option>
<option value="css/stereo.css">3D</option>
</select>
</div>
<div class="col-4">
<select name="skinURL" id="skinURLSelect" class="form-select"
oninput="document.documentElement.style.setProperty('--skin-url', `url(${this.value})`)">
</select>
</div>
<label for="skinURLSelect" class="col-2 col-form-label">Sample</label>
<label for="sfxVolumeRange" class="col-2 col-form-label"><abbr title="Auteur des effets sonores : 25Pi25">Volume</abbr></label>
<div class="col-4 d-flex align-items-baseline">
<input name="sfxVolumeRange" id="sfxVolumeRange" class="form-range" type="range" min="0" max="1" step="any" value="0.7">
</div>
<option value="css/retro.css">Rétro</option>
<option value="css/opera.css">Opéra</option>
<option value="css/stereo.css">Stéréo</option>
</select></div>
<div class="col-4">
<div class="form-check form-switch text-start">
<input id="fullscreenCheckbox" type="checkbox" role="switch" class="form-check-input" tabindex="0">
@@ -109,6 +84,8 @@
</div>
</div>
<div class="col-2"></div>
<label for="sfxVolumeRange" class="col-2 col-form-label">Volume</label>
<div class="col-4 d-flex align-items-baseline"><input name="sfxVolumeRange" id="sfxVolumeRange" class="form-range" type="range" min="0" max="1" step="any" value="0.7"></div>
</fieldset>
<fieldset class="row g-2 mb-3 align-items-center text-center"><legend class="text-start">Partie</legend>
<label for="levelInput" class="col-2 col-form-label text-center">Niveau</label>
@@ -216,7 +193,7 @@
</div>
<div class="modal fade" id="statsModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
<div class="modal fade" id="statsModal" data-bs-backdrop="static" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-dialog">
<div class="modal-content">
@@ -227,7 +204,7 @@
<div class="modal-body p-0">
<table class="table mb-0">
<tr><th>Score</th> <td id="statsModalScoreCell"></td> <th>Quatuors</th> <td id="statsModalNbQuatuors"></td> </tr>
<tr><th>Meilleur score</th><td id="statsModalHighScoreCell"></td> <th>Pirouettes</th> <td id="statsModalNbTSpin"></td> </tr>
<tr><th>Meilleur score</th><td id="statsModalHighScoreCell"></td> <th>Pirouettes</th> <td id="statsModalNbTSpin"></td></td> </tr>
<tr><th>Temps</th> <td id="statsModalTimeCell"></td> <th>Plus long combo</th> <td id="statsModalMaxCombo"></td> </tr>
<tr><th>Niveau</th> <td id="statsModalLevelCell"></td> <th>Plus long bout à bout</th><td id="statsModalMaxB2B"></td> </tr>
<tr><th>Lignes</th> <td id="statsModaltotalClearedLines"></td><th>Lignes par minute</th> <td id="statsModaltotalClearedLinesPM"></td></tr>
@@ -250,59 +227,14 @@
<img src="favicons/T-0.png"/><img src="favicons/T-1.png"/><img src="favicons/T-2.png"/><img src="favicons/T-3.png"/>
<img src="favicons/Z-0.png"/><img src="favicons/Z-1.png"/><img src="favicons/Z-2.png"/><img src="favicons/Z-3.png"/>
<audio id="btb_1" src="snd/btb_1.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="btb_2" src="snd/btb_2.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="btb_3" src="snd/btb_3.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="btb_break" src="snd/btb_break.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="clearbtb" src="snd/clearbtb.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="clearline" src="snd/clearline.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="clearquad" src="snd/clearquad.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="clearspin" src="snd/clearspin.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="combo_1_power" src="snd/combo_1_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_1" src="snd/combo_1.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_10_power" src="snd/combo_10_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_10" src="snd/combo_10.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_11_power" src="snd/combo_11_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_11" src="snd/combo_11.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_12_power" src="snd/combo_12_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_12" src="snd/combo_12.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_13_power" src="snd/combo_13_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_13" src="snd/combo_13.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_14_power" src="snd/combo_14_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_14" src="snd/combo_14.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_15_power" src="snd/combo_15_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_15" src="snd/combo_15.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_16_power" src="snd/combo_16_power.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="combo_16" src="snd/combo_16.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="combo_2_power" src="snd/combo_2_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_2" src="snd/combo_2.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_3_power" src="snd/combo_3_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_3" src="snd/combo_3.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_4_power" src="snd/combo_4_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_4" src="snd/combo_4.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_5_power" src="snd/combo_5_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_5" src="snd/combo_5.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_6_power" src="snd/combo_6_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_6" src="snd/combo_6.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_7_power" src="snd/combo_7_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_7" src="snd/combo_7.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_8_power" src="snd/combo_8_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_8" src="snd/combo_8.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_9_power" src="snd/combo_9_power.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combo_9" src="snd/combo_9.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="combobreak" src="snd/combobreak.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="floor" src="snd/floor.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="gameover" src="snd/topout.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="harddrop" src="snd/harddrop.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="hit" src="snd/hit.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="hold" src="snd/hold.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="menuconfirm" src="snd/menuconfirm.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="menuhover" src="snd/menuhover.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="move" src="snd/move.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="rotate" src="snd/rotate.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="spin" src="snd/spin.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="wallSound" src="sounds/808K_A.wav" preload="auto" type="audio/wav"></audio>
<audio id="hardDropSound" src="sounds/909S.wav" preload="auto" type="audio/wav"></audio>
<audio id="lineClearSound" src="sounds/808COW.wav" preload="auto" type="audio/wav"></audio>
<audio id="tSpinSound" src="sounds/78GUIR.wav" preload="auto" type="audio/wav"></audio>
<audio id="quatuorSound" src="sounds/BRRDC1.wav" preload="auto" type="audio/wav"></audio>
</span>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<script src="js/game_logic.js" language="Javascript" type="text/javascript"></script>
<script src="js/interface.js" language="Javascript" type="text/javascript"></script>
<script src="js/app.js" language="Javascript" type="text/javascript"></script>

473
js/app.js
View File

@@ -1,189 +1,210 @@
let scheduler = new Scheduler()
let settings = new Settings()
let stats = new Stats()
let holdQueue = new HoldQueue()
let matrix = new Matrix()
let nextQueue = new NextQueue()
let playing = false
//let lastActionSucceded = true
let favicon
window.onload = function(event) {
document.selectedStyleSheetSet = selectedStyleSheet.title
selectedStyleSheet.href = stylesheetSelect.value
favicon = document.querySelector("link[rel~='icon']")
fullscreenCheckbox.onchange = function() {
if (this.checked) {
document.documentElement.requestFullscreen()
} else {
document.exitFullscreen()
}
}
restart()
}
document.onfullscreenchange = function() {
if (document.fullscreenElement) {
fullscreenCheckbox.checked = true;
fullscreenCheckbox.checked = true
} else {
fullscreenCheckbox.checked = false;
if (playing) pauseSettings();
fullscreenCheckbox.checked = false
if (playing) pauseSettings()
}
}
};
document.onfullscreenerror = function() {
fullscreenCheckbox.checked = false;
};
fullscreenCheckbox.checked = false
}
function restart() {
stats.modal.hide();
holdQueue.init();
holdQueue.redraw();
stats.init();
matrix.init();
nextQueue.init();
settings.init();
pauseSettings();
stats.modal.hide()
holdQueue.init()
holdQueue.redraw()
stats.init()
matrix.init()
nextQueue.init()
settings.init()
pauseSettings()
}
function pauseSettings() {
scheduler.clearInterval(fall);
scheduler.clearTimeout(lockDown);
scheduler.clearTimeout(repeat);
scheduler.clearInterval(autorepeat);
scheduler.clearInterval(ticktack);
stats.pauseTime = stats.time;
scheduler.clearInterval(fall)
scheduler.clearTimeout(lockDown)
scheduler.clearTimeout(repeat)
scheduler.clearInterval(autorepeat)
scheduler.clearInterval(ticktack)
stats.pauseTime = stats.time
document.onkeydown = null;
document.onkeydown = null
settings.show();
playSound(menuhover)
settings.show()
}
function newGame(event) {
if (!settings.form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
settings.form.reportValidity();
settings.form.classList.add('was-validated');
event.preventDefault()
event.stopPropagation()
settings.form.reportValidity()
settings.form.classList.add('was-validated')
} else {
const audioContext = new AudioContext();
for (const sound of document.getElementsByTagName('audio')) {
sound.preservesPitch = false;
audioContext.createMediaElementSource(sound).connect(audioContext.destination);
const audioContext = new AudioContext()
for(const sound of document.getElementsByTagName("audio")) {
sound.preservesPitch = false
audioContext.createMediaElementSource(sound).connect(audioContext.destination)
}
levelInput.name = 'level';
levelInput.disabled = true;
titleHeader.innerHTML = 'PAUSE';
resumeButton.innerHTML = 'Reprendre';
event.target.onsubmit = resume;
stats.level = levelInput.valueAsNumber;
localStorage['startLevel'] = levelInput.value;
playing = true;
onblur = pauseSettings;
resume(event);
levelInput.name = "level"
levelInput.disabled = true
titleHeader.innerHTML = "PAUSE"
resumeButton.innerHTML = "Reprendre"
event.target.onsubmit = resume
stats.level = levelInput.valueAsNumber
localStorage["startLevel"] = levelInput.value
playing = true
onblur = pauseSettings
resume(event)
}
}
function resume(event) {
event.preventDefault();
event.stopPropagation();
event.preventDefault()
event.stopPropagation()
settings.form.reportValidity();
settings.form.classList.add('was-validated');
settings.form.reportValidity()
settings.form.classList.add('was-validated')
if (settings.form.checkValidity()) {
for (const sound of document.getElementsByTagName('audio'))
sound.volume = sfxVolumeRange.value;
for(const sound of document.getElementsByTagName("audio"))
sound.volume = sfxVolumeRange.value
settings.modal.hide();
settings.getInputs();
settings.modal.hide()
settings.getInputs()
document.onkeydown = onkeydown;
document.onkeyup = onkeyup;
document.onkeydown = onkeydown
document.onkeyup = onkeyup
stats.time = stats.pauseTime;
scheduler.setInterval(ticktack, 1000);
stats.time = stats.pauseTime
scheduler.setInterval(ticktack, 1000)
if (matrix.piece) scheduler.setInterval(fall, stats.fallPeriod);
else generate();
playSound(menuconfirm)
if (matrix.piece) scheduler.setInterval(fall, stats.fallPeriod)
else generate()
}
}
function ticktack() {
timeCell.innerText = stats.timeFormat.format(stats.time);
timeCell.innerText = stats.timeFormat.format(stats.time)
}
function generate(piece) {
matrix.piece = piece || nextQueue.shift();
if (!piece && holdQueue.piece) holdQueue.drawPiece();
matrix.piece = piece || nextQueue.shift()
if (!piece && holdQueue.piece) holdQueue.drawPiece()
//lastActionSucceded = true
favicon.href = matrix.piece.favicon_href;
favicon.href = matrix.piece.favicon_href
if (matrix.piece.canMove(TRANSLATION.NONE)) {
scheduler.setInterval(fall, stats.fallPeriod);
scheduler.setInterval(fall, stats.fallPeriod)
} else {
gameOver(); // block out
gameOver() // block out
}
}
let playerActions = {
moveLeft: () => matrix.piece.move(TRANSLATION.LEFT)? playSound(move) : playSound(hit),
moveLeft: () => matrix.piece.move(TRANSLATION.LEFT),
moveRight: () => matrix.piece.move(TRANSLATION.RIGHT)? playSound(move) : playSound(hit),
moveRight: () => matrix.piece.move(TRANSLATION.RIGHT),
rotateClockwise: () => matrix.piece.rotate(ROTATION.CW)? playSound(rotate) : playSound(hit),
rotateClockwise: () => matrix.piece.rotate(ROTATION.CW),
rotateCounterclockwise: () => matrix.piece.rotate(ROTATION.CCW)? playSound(rotate) : playSound(hit),
rotateCounterclockwise: () => matrix.piece.rotate(ROTATION.CCW),
softDrop: () => (matrix.piece.move(TRANSLATION.DOWN) && ++stats.score)? playSound(move) : playSound(floor),
softDrop: () => matrix.piece.move(TRANSLATION.DOWN) && ++stats.score,
hardDrop: function() {
scheduler.clearTimeout(lockDown);
playSound(harddrop);
while (matrix.piece.move(TRANSLATION.DOWN, ROTATION.NONE, true)) stats.score += 2;
matrixCard.classList.remove('hard-dropped-table-animation');
scheduler.clearTimeout(lockDown)
playSound(hardDropSound)
while (matrix.piece.move(TRANSLATION.DOWN, ROTATION.NONE, true)) stats.score += 2
matrixCard.classList.remove("hard-dropped-table-animation")
matrixCard.offsetHeight;
matrixCard.classList.add('hard-dropped-table-animation'); // restart animation
lockDown();
return true;
matrixCard.classList.add("hard-dropped-table-animation") // restart animation
lockDown()
return true
},
hold: function() {
if (matrix.piece.holdEnabled) {
scheduler.clearInterval(fall);
scheduler.clearTimeout(lockDown);
playSound(hold)
scheduler.clearInterval(fall)
scheduler.clearTimeout(lockDown)
let piece = matrix.piece;
piece.facing = FACING.NORTH;
piece.locked = false;
generate(holdQueue.piece);
matrix.piece.holdEnabled = false;
holdQueue.piece = piece;
let piece = matrix.piece
piece.facing = FACING.NORTH
piece.locked = false
generate(holdQueue.piece)
matrix.piece.holdEnabled = false
holdQueue.piece = piece
}
},
pause: pauseSettings,
};
}
// Handle player inputs
const REPEATABLE_ACTIONS = [
playerActions.moveLeft,
playerActions.moveRight,
playerActions.softDrop,
];
pressedKeys = new Set();
actionsQueue = [];
playerActions.softDrop
]
pressedKeys = new Set()
actionsQueue = []
function onkeydown(event) {
if (event.key in settings.keyBind) {
event.preventDefault();
event.preventDefault()
if (!pressedKeys.has(event.key)) {
pressedKeys.add(event.key);
action = settings.keyBind[event.key];
pressedKeys.add(event.key)
action = settings.keyBind[event.key]
/*if (action()) {
lastActionSucceded = true
} else if (lastActionSucceded || !(action in REPEATABLE_ACTIONS)) {
playSound(wallSound)
lastActionSucceded = false
}*/
action();
action()
if (REPEATABLE_ACTIONS.includes(action)) {
actionsQueue.unshift(action);
scheduler.clearTimeout(repeat);
scheduler.clearInterval(autorepeat);
if (action == playerActions.softDrop)
scheduler.setInterval(autorepeat, settings.fallPeriod / 20);
else scheduler.setTimeout(repeat, settings.das);
actionsQueue.unshift(action)
scheduler.clearTimeout(repeat)
scheduler.clearInterval(autorepeat)
if (action == playerActions.softDrop) scheduler.setInterval(autorepeat, settings.fallPeriod/20)
else scheduler.setTimeout(repeat, settings.das)
}
matrix.drawPiece();
matrix.drawPiece()
}
}
}
function repeat() {
if (actionsQueue.length) {
actionsQueue[0]();
scheduler.setInterval(autorepeat, settings.arr);
actionsQueue[0]()
scheduler.setInterval(autorepeat, settings.arr)
}
}
@@ -195,241 +216,121 @@ function autorepeat() {
wallSound.play()
lastActionSucceded = false
}*/
actionsQueue[0]();
} else scheduler.clearInterval(autorepeat);
actionsQueue[0]()
}
else scheduler.clearInterval(autorepeat)
}
function onkeyup(event) {
if (event.key in settings.keyBind) {
event.preventDefault();
pressedKeys.delete(event.key);
action = settings.keyBind[event.key];
event.preventDefault()
pressedKeys.delete(event.key)
action = settings.keyBind[event.key]
if (actionsQueue.includes(action)) {
actionsQueue.splice(actionsQueue.indexOf(action), 1);
scheduler.clearTimeout(repeat);
scheduler.clearInterval(autorepeat);
actionsQueue.splice(actionsQueue.indexOf(action), 1)
scheduler.clearTimeout(repeat)
scheduler.clearInterval(autorepeat)
if (actionsQueue.length) {
if (actionsQueue[0] == playerActions.softDrop)
scheduler.setInterval(autorepeat, settings.fallPeriod / 20);
else scheduler.setTimeout(repeat, settings.das);
if (actionsQueue[0] == playerActions.softDrop) scheduler.setInterval(autorepeat, settings.fallPeriod/20)
else scheduler.setTimeout(repeat, settings.das)
} else {
matrix.drawPiece();
matrix.drawPiece()
}
}
}
}
function fall() {
matrix.piece.move(TRANSLATION.DOWN);
matrix.piece.move(TRANSLATION.DOWN)
}
function lockDown() {
scheduler.clearTimeout(lockDown);
scheduler.clearInterval(fall);
scheduler.clearTimeout(lockDown)
scheduler.clearInterval(fall)
if (matrix.lock()) {
stats.lockDown(matrix.piece.tSpin, matrix.clearLines());
stats.lockDown(matrix.piece.tSpin, matrix.clearLines())
generate();
generate()
} else {
gameOver(); // lock out
gameOver() // lock out
}
}
onanimationend = function (event) {
event.target.classList.remove(event.animationName);
};
event.target.classList.remove(event.animationName)
}
messagesSpan.onanimationend = function(event) {
event.target.remove();
};
event.target.remove()
}
function gameOver() {
matrix.piece.locked = true;
matrix.drawPiece();
matrix.piece.locked = true
matrix.drawPiece()
document.onkeydown = null;
onblur = null;
scheduler.clearInterval(ticktack);
playing = false;
document.onkeydown = null
onblur = null
scheduler.clearInterval(ticktack)
playing = false
stats.show();
playSound(gameover)
stats.show()
}
window.onbeforeunload = function(event) {
stats.save();
settings.save();
stats.save()
settings.save()
if (playing) return false;
};
}
// Play with 3D
let mousedown = false;
let rX0 = -15;
let rY0 = 0;
let clientX0 = 0;
let clientY0 = 0;
let mousedown = false
let rX0 = -15
let rY0 = 0
let clientX0 = 0
let clientY0 = 0
sceneDiv.onmousedown = function(event) {
mousedown = true;
rX0 = parseInt(getComputedStyle(screenRow).getPropertyValue('--rX'));
dy0 = parseInt(getComputedStyle(screenRow).getPropertyValue('--rY'));
clientX0 = event.clientX;
clientY0 = event.clientY;
};
mousedown = true
rX0 = parseInt(getComputedStyle(screenRow).getPropertyValue("--rX"))
dy0 = parseInt(getComputedStyle(screenRow).getPropertyValue("--rY"))
clientX0 = event.clientX
clientY0 = event.clientY
}
sceneDiv.onmousemove = function(event) {
if (mousedown) {
event.preventDefault();
event.stopPropagation();
rX = (rX0 - 0.5 * (event.clientY - clientY0)) % 360;
screenRow.style.setProperty('--rX', rX);
event.preventDefault()
event.stopPropagation()
rX = (rX0 - 0.5 * (event.clientY - clientY0)) % 360
screenRow.style.setProperty("--rX", rX)
if (rX >= 0) {
screenRow.classList.remove('top');
screenRow.classList.add('bottom');
screenRow.classList.remove("top")
screenRow.classList.add("bottom")
} else {
screenRow.classList.add('top');
screenRow.classList.remove('bottom');
screenRow.classList.add("top")
screenRow.classList.remove("bottom")
}
rY = (rY0 + 0.5 * (event.clientX - clientX0)) % 360;
screenRow.style.setProperty('--rY', rY);
rY = (rY0 + 0.5 * (event.clientX - clientX0)) % 360
screenRow.style.setProperty("--rY", rY)
if (rY <= 0) {
screenRow.classList.remove('left');
screenRow.classList.add('right');
screenRow.classList.remove("left")
screenRow.classList.add("right")
} else {
screenRow.classList.add('left');
screenRow.classList.remove('right');
screenRow.classList.add("left")
screenRow.classList.remove("right")
}
}
}
};
sceneDiv.onmouseup = document.onmouseleave = function(event) {
mousedown = false;
};
fullscreenCheckbox.onchange = function () {
if (this.checked) {
document.documentElement.requestFullscreen();
} else {
document.exitFullscreen();
mousedown = false
}
};
sceneDiv.onwheel = function(event) {
event.preventDefault();
event.stopPropagation();
let tZ = parseInt(getComputedStyle(screenRow).getPropertyValue('--tZ'));
tZ -= event.deltaY;
screenRow.style.setProperty('--tZ', tZ + 'px');
};
const ImageURLPattern = /^(https?:\/\/.*\.(?:png|jpg|jpeg|gif|bmp|webp|svg))$/i
$.fn.select2.defaults.set("templateResult", (state) =>
state.id
? $(`<img class="preview" src="${state.id}" title="${state.text}" loading="lazy"/>`)
: state.text
)
$.fn.select2.defaults.set("templateSelection", (state) =>
state.id
? $(`
<table class="minoes-table preview" style="--skin-url: url(${state.id});">
<tr><td class="Z mino"></td><td class="O mino"></td><td class="T mino"></td><td class="I mino"></td></tr>
</table>
`)
: state.text
)
$.fn.select2.defaults.set("theme", "bootstrap-5")
$.fn.select2.defaults.set("selectionCssClass", 'form-select')
$.fn.select2.defaults.set("dropdownParent", $('#settingsModal'))
$.fn.select2.defaults.set("dropdownAutoWidth", true)
$.fn.select2.defaults.set("placeholder", "URL de l'image")
$.fn.select2.defaults.set("tags", true)
$.fn.select2.defaults.set("createTag", function (params) {
const url = encodeURI(params.term);
if (ImageURLPattern.test(url)) {
return {
id: url,
text: 'Source externe',
newTag: true,
};
event.preventDefault()
event.stopPropagation()
let tZ = parseInt(getComputedStyle(screenRow).getPropertyValue("--tZ"))
tZ -= event.deltaY
screenRow.style.setProperty("--tZ", tZ + "px")
}
});
stylesheetSelect.oninput = function (event) {
selectedStyleSheet.href = this.value;
$("#skinURLSelect").empty();
switch (this.value) {
case 'css/tetrio-skin.css':
skinURLSelect.disabled = false;
const baseURL = "https://you.have.fail/tetrioplus/data"
fetch(`${baseURL}/data.json`)
.then((resp) => resp.json())
.then((json) => {
json = json.filter((item) => (item.type == "skin" && item.format == "tetrioraster" && /\.(?:png|jpg|jpeg|gif|bmp|webp|svg)$/i.test(item.path)))
const groups = Map.groupBy(json, (skin) => skin.author)
var data = groups.entries().map(([author, skins]) => {
return {
text: author,
children: skins.map((skin) => {
return {
id: `${baseURL}/${encodeURI(skin.path)}`,
text:`${skin.name}\n${skin.description}`
}
})
}
}).toArray()
data.push({
text: "AdrienMalin",
children: [{
id: `${document.location.href}/css/tetrio-skin/a_forest.png`,
text: "A forest"
}]
})
data.sort((group1, group2) => group1.text > group2.text)
$('#skinURLSelect').select2({data: data});
})
break;
case 'css/jstris-skin.css':
skinURLSelect.disabled = false;
fetch('https://konsola5.github.io/jstris-customization-database/jstrisCustomizationDatabase.json')
.then(response => response.json())
.then(json => {
const data = [];
for (const group in json) {
const groupData = {
text: group,
children: json[group].map(skin => ({
id: skin.link,
text: `${skin.name} by ${skin.author}`,
})),
};
data.push(groupData);
}
$('#skinURLSelect').select2({data: data});
});
break;
default:
skinURLSelect.disabled = true;
break;
}
}
let scheduler = new Scheduler();
let settings = new Settings();
let stats = new Stats();
let holdQueue = new HoldQueue();
let matrix = new Matrix();
let nextQueue = new NextQueue();
let playing = false;
//let lastActionSucceded = true
let favicon = document.querySelector("link[rel~='icon']");
window.onload = function (event) {
restart();
};

View File

@@ -17,7 +17,7 @@ const T_SPIN = {
T_SPIN: "PIROUETTE"
}
// score = AWARDED_LINE_CLEARS[tSpin][clearedLines]
// score = AWARDED_LINE_CLEARS[tSpin][nbClearedLines]
const AWARDED_LINE_CLEARS = {
[T_SPIN.NONE]: [0, 1, 3, 5, 8],
[T_SPIN.MINI]: [1, 2],
@@ -282,18 +282,18 @@ class Matrix extends MinoesTable {
}
clearLines() {
let clearedLines = 0
let nbClearedLines = 0
for (let y=0; y<this.rows; y++) {
let row = this.blocks[y]
if (row.filter(lockedMino => lockedMino).length == this.columns) {
clearedLines++
nbClearedLines++
this.blocks.splice(y, 1)
this.blocks.unshift(Array(matrix.columns))
this.table.rows[y].classList.add("cleared-line-animation")
}
}
this.redraw()
return clearedLines
return nbClearedLines
}
}
Matrix.prototype.init_center = [4, 4]

View File

@@ -1,399 +1,335 @@
const KEY_NAMES = new Proxy(
{
['ArrowLeft']: '←',
['←']: 'ArrowLeft',
['ArrowRight']: '→',
['→']: 'ArrowRight',
['ArrowUp']: '↑',
['↑']: 'ArrowUp',
['ArrowDown']: '↓',
['↓']: 'ArrowDown',
[' ']: 'Espace',
['Espace']: ' ',
['Escape']: 'Échap.',
['Échap.']: 'Escape',
['Backspace']: 'Ret. arrière',
['Ret. arrière']: 'Backspace',
['Enter']: 'Entrée',
['Entrée']: 'Enter',
},
{
const KEY_NAMES = new Proxy({
["ArrowLeft"] : "←",
["←"] : "ArrowLeft",
["ArrowRight"] : "→",
["→"] : "ArrowRight",
["ArrowUp"] : "↑",
["↑"] : "ArrowUp",
["ArrowDown"] : "↓",
["↓"] : "ArrowDown",
[" "] : "Espace",
["Espace"] : " ",
["Escape"] : "Échap.",
["Échap."] : "Escape",
["Backspace"] : "Ret. arrière",
["Ret. arrière"]: "Backspace",
["Enter"] : "Entrée",
["Entrée"] : "Enter",
}, {
get(target, key) {
return key in target ? target[key] : key;
},
},
);
return key in target? target[key] : key
}
})
class Settings {
constructor() {
this.form = settingsForm;
this.load();
this.modal = new bootstrap.Modal('#settingsModal');
settingsModal.addEventListener('shown.bs.modal', () => resumeButton.focus());
this.form = settingsForm
this.load()
this.modal = new bootstrap.Modal('#settingsModal')
settingsModal.addEventListener('shown.bs.modal', () => resumeButton.focus())
}
load() {
this.form.querySelectorAll('[name]').forEach(element => {
if (element.name in localStorage) element.value = localStorage[element.name];
});
stylesheetSelect.oninput();
if (localStorage['skinURL']) {
if ($('#skinURLSelect').find("option[value='" + localStorage['skinURL'] + "']").length) {
$('#skinURLSelect').val(localStorage['skinURL']).trigger('change');
} else {
var option = new Option('Sample sauvegardé', localStorage['skinURL']);
$('#skinURLSelect').append(option).trigger('change');
}
skinURLSelect.oninput();
}
this.form.querySelectorAll("[name]").forEach(element => {
if (element.name in localStorage)
element.value = localStorage[element.name]
})
window.document.selectedStyleSheetSet = stylesheetSelect.value
}
save() {
this.form
.querySelectorAll('[name]')
.forEach(element => (localStorage[element.name] = element.value));
this.form.querySelectorAll("[name]").forEach(element => localStorage[element.name] = element.value)
}
init() {
this.form.onsubmit = newGame;
levelInput.name = 'startLevel';
levelInput.disabled = false;
titleHeader.innerHTML = 'QUATUOR';
resumeButton.innerHTML = 'Jouer';
this.form.onsubmit = newGame
levelInput.name = "startLevel"
levelInput.disabled = false
titleHeader.innerHTML = "QUATUOR"
resumeButton.innerHTML = "Jouer"
}
show() {
resumeButton.disabled = false;
settings.form.classList.remove('was-validated');
settings.modal.show();
settings.form.reportValidity();
resumeButton.disabled = false
settings.form.classList.remove('was-validated')
settings.modal.show()
settings.form.reportValidity()
}
getInputs() {
for (let input of this.form.querySelectorAll("input[type='text']")) {
this[input.name] = KEY_NAMES[input.value];
this[input.name] = KEY_NAMES[input.value]
}
for (let input of this.form.querySelectorAll("input[type='number'], input[type='range']")) {
this[input.name] = input.valueAsNumber;
this[input.name] = input.valueAsNumber
}
for (let input of this.form.querySelectorAll("input[type='checkbox']")) {
this[input.name] = input.checked == true;
this[input.name] = input.checked == true
}
this.keyBind = new Proxy(
{},
{
this.keyBind = new Proxy({}, {
get: (target, key) => target[key.toLowerCase()],
set: (target, key, value) => (target[key.toLowerCase()] = value),
has: (target, key) => key.toLowerCase() in target,
},
);
set: (target, key, value) => target[key.toLowerCase()] = value,
has: (target, key) => key.toLowerCase() in target
})
for (let actionName in playerActions) {
this.keyBind[settings[actionName]] = playerActions[actionName];
this.keyBind[settings[actionName]] = playerActions[actionName]
}
}
}
function changeKey(input) {
prevValue = input.value;
input.value = '';
keyInputs = Array.from(input.form.querySelectorAll("input[type='text']"));
prevValue = input.value
input.value = ""
keyInputs = Array.from(input.form.querySelectorAll("input[type='text']"))
input.onkeydown = function (event) {
event.preventDefault();
input.value = KEY_NAMES[event.key];
event.preventDefault()
input.value = KEY_NAMES[event.key]
keyInputs.forEach(input => {
input.setCustomValidity('');
input.classList.remove('is-invalid');
});
input.setCustomValidity("")
input.classList.remove("is-invalid")
})
keyInputs.sort((input1, input2) => {
if(input1.value == input2.value) {
input1.setCustomValidity('Touche déjà utilisée');
input1.classList.add('is-invalid');
input2.setCustomValidity('Touche déjà utilisée');
input2.classList.add('is-invalid');
input1.setCustomValidity("Touche déjà utilisée")
input1.classList.add("is-invalid")
input2.setCustomValidity("Touche déjà utilisée")
input2.classList.add("is-invalid")
}
return input1.value > input2.value;
});
return input1.value > input2.value
})
if (input.checkValidity()) {
input.blur();
input.blur()
}
}
};
input.onblur = function (event) {
if (!input.value) input.value = prevValue;
input.onkeydown = null;
input.onblur = null;
};
if (!input.value) input.value = prevValue
input.onkeydown = null
input.onblur = null
}
}
class Stats {
constructor() {
this.modal = new bootstrap.Modal('#statsModal');
this.load();
this.modal = new bootstrap.Modal('#statsModal')
this.load()
}
load() {
this.highScore = Number(localStorage['highScore']) || 0;
this.highScore = Number(localStorage["highScore"]) || 0
}
init() {
levelInput.value = localStorage['startLevel'] || 1;
this.score = 0;
this.goal = 0;
this.combo = -1;
this.b2b = -1;
this.startTime = new Date();
this.lockDelay = DELAY.LOCK;
this.totalClearedLines = 0;
this.nbQuatuors = 0;
this.nbTSpin = 0;
this.maxCombo = 0;
this.maxB2B = 0;
levelInput.value = localStorage["startLevel"] || 1
this.score = 0
this.goal = 0
this.combo = 0
this.b2b = 0
this.startTime = new Date()
this.lockDelay = DELAY.LOCK
this.totalClearedLines = 0
this.nbQuatuors = 0
this.nbTSpin = 0
this.maxCombo = 0
this.maxB2B = 0
}
set score(score) {
this._score = score;
scoreCell.innerText = score.toLocaleString();
this._score = score
scoreCell.innerText = score.toLocaleString()
if (score > this.highScore) {
this.highScore = score;
this.highScore = score
}
}
get score() {
return this._score;
return this._score
}
set highScore(highScore) {
this._highScore = highScore;
highScoreCell.innerText = highScore.toLocaleString();
this._highScore = highScore
highScoreCell.innerText = highScore.toLocaleString()
}
get highScore() {
return this._highScore;
return this._highScore
}
set level(level) {
this._level = level;
this.goal += level * 5;
this._level = level
this.goal += level * 5
if (level <= 20){
this.fallPeriod = 1000 * Math.pow(0.8 - (level - 1) * 0.007, level - 1);
this.fallPeriod = 1000 * Math.pow(0.8 - ((level - 1) * 0.007), level - 1)
}
if (level > 15) this.lockDelay = 500 * Math.pow(0.9, level - 15);
levelInput.value = level;
levelCell.innerText = level;
messagesSpan.addNewChild('div', {
className: 'show-level-animation',
innerHTML: `<h1>NIVEAU<br/>${this.level}</h1>`,
});
if (level > 15)
this.lockDelay = 500 * Math.pow(0.9, level - 15)
levelInput.value = level
levelCell.innerText = level
messagesSpan.addNewChild("div", { className: "show-level-animation", innerHTML: `<h1>NIVEAU<br/>${this.level}</h1>` })
}
get level() {
return this._level;
return this._level
}
set goal(goal) {
this._goal = goal;
goalCell.innerText = goal;
this._goal = goal
goalCell.innerText = goal
}
get goal() {
return this._goal;
return this._goal
}
set combo(combo) {
this._combo = combo;
if (combo > this.maxCombo) this.maxCombo = combo;
this._combo = combo
if (combo > this.maxCombo) this.maxCombo = combo
}
get combo() {
return this._combo;
return this._combo
}
set b2b(b2b) {
this._b2b = b2b;
if (b2b > this.maxB2B) this.maxB2B = b2b;
this._b2b = b2b
if (b2b > this.maxB2B) this.maxB2B = b2b
}
get b2b() {
return this._b2b;
return this._b2b
}
set time(time) {
this.startTime = new Date() - time;
ticktack();
this.startTime = new Date() - time
ticktack()
}
get time() {
return new Date() - this.startTime;
return new Date() - this.startTime
}
lockDown(tSpin, clearedLines) {
this.totalClearedLines += clearedLines;
if (clearedLines == 4) this.nbQuatuors++;
if (tSpin == T_SPIN.T_SPIN) this.nbTSpin++;
lockDown(tSpin, nbClearedLines) {
this.totalClearedLines += nbClearedLines
if (nbClearedLines == 4) this.nbQuatuors++
if (tSpin == T_SPIN.T_SPIN) this.nbTSpin++
// Cleared lines & T-Spin
let awardedLineClears = AWARDED_LINE_CLEARS[tSpin][clearedLines];
let patternScore = 100 * this.level * awardedLineClears;
if (tSpin)
messagesSpan.addNewChild('div', {
className: 'rotate-in-animation',
innerHTML: tSpin,
});
if (clearedLines)
messagesSpan.addNewChild('div', {
className: 'zoom-in-animation',
innerHTML: CLEARED_LINES_NAMES[clearedLines],
});
let awardedLineClears = AWARDED_LINE_CLEARS[tSpin][nbClearedLines]
let patternScore = 100 * this.level * awardedLineClears
if (tSpin) messagesSpan.addNewChild("div", {
className: "rotate-in-animation",
innerHTML: tSpin
})
if (nbClearedLines) messagesSpan.addNewChild("div", {
className: "zoom-in-animation",
innerHTML: CLEARED_LINES_NAMES[nbClearedLines]
})
if (patternScore) {
messagesSpan.addNewChild('div', {
className: 'zoom-in-animation',
style: 'animation-delay: .2s',
innerHTML: patternScore,
});
this.score += patternScore;
messagesSpan.addNewChild("div", {
className: "zoom-in-animation",
style: "animation-delay: .2s",
innerHTML: patternScore
})
this.score += patternScore
}
// Combo
if (clearedLines) {
this.combo++;
if (nbClearedLines) {
this.combo++
if (this.combo >= 1) {
let comboScore = (clearedLines == 1 ? 20 : 50) * this.combo * this.level;
let comboScore = (nbClearedLines == 1 ? 20 : 50) * this.combo * this.level
if (this.combo == 1) {
messagesSpan.addNewChild('div', {
className: 'zoom-in-animation',
style: 'animation-delay: .4s',
innerHTML: `COMBO<br/>${comboScore}`,
});
messagesSpan.addNewChild("div", {
className: "zoom-in-animation",
style: "animation-delay: .4s",
innerHTML: `COMBO<br/>${comboScore}`
})
} else {
messagesSpan.addNewChild('div', {
className: 'zoom-in-animation',
style: 'animation-delay: .4s',
innerHTML: `COMBO x${this.combo}<br/>${comboScore}`,
});
messagesSpan.addNewChild("div", {
className: "zoom-in-animation",
style: "animation-delay: .4s",
innerHTML: `COMBO x${this.combo}<br/>${comboScore}`
})
}
this.score += comboScore;
this.score += comboScore
}
} else {
if (this.combo >= 1) playSound(combobreak)
this.combo = -1;
this.combo = -1
}
// Back to back sequence
if (clearedLines == 4 || (tSpin && clearedLines)) {
this.b2b++;
if ((nbClearedLines == 4) || (tSpin && nbClearedLines)) {
this.b2b++
if (this.b2b >= 1) {
let b2bScore = patternScore / 2;
let b2bScore = patternScore / 2
if (this.b2b == 1) {
messagesSpan.addNewChild('div', {
className: 'zoom-in-animation',
style: 'animation-delay: .4s',
innerHTML: `BOUT À BOUT<br/>${b2bScore}`,
});
messagesSpan.addNewChild("div", {
className: "zoom-in-animation",
style: "animation-delay: .4s",
innerHTML: `BOUT À BOUT<br/>${b2bScore}`
})
} else {
messagesSpan.addNewChild('div', {
className: 'zoom-in-animation',
style: 'animation-delay: .4s',
innerHTML: `BOUT À BOUT x${this.b2b}<br/>${b2bScore}`,
});
messagesSpan.addNewChild("div", {
className: "zoom-in-animation",
style: "animation-delay: .4s",
innerHTML: `BOUT À BOUT x${this.b2b}<br/>${b2bScore}`
})
}
this.score += b2bScore;
this.score += b2bScore
}
} else if (clearedLines && !tSpin) {
} else if (nbClearedLines && !tSpin ) {
if (this.b2b >= 1) {
messagesSpan.addNewChild('div', {
className: 'zoom-in-animation',
style: 'animation-delay: .4s',
innerHTML: `FIN DU BOUT À BOUT`,
});
playSound(btb_break)
messagesSpan.addNewChild("div", {
className: "zoom-in-animation",
style: "animation-delay: .4s",
innerHTML: `FIN DU BOUT À BOUT`
})
}
this.b2b = -1;
this.b2b = -1
}
// Sounds
// Sound
if (sfxVolumeRange.value) {
if (clearedLines == 4 || (tSpin && clearedLines)) switch(this.b2b) {
case -1:
case 0: playSound(clearbtb); break
case 1: playSound(btb_1); break
case 2: playSound(btb_2); break
default: playSound(btb_3)
} else if (tSpin) switch(this.combo) {
case -1: playSound(spin); break
case 0: playSound(clearspin); break
case 1: playSound(combo_1_power); break
case 2: playSound(combo_2_power); break
case 3: playSound(combo_3_power); break
case 4: playSound(combo_4_power); break
case 5: playSound(combo_5_power); break
case 6: playSound(combo_6_power); break
case 7: playSound(combo_7_power); break
case 8: playSound(combo_8_power); break
case 9: playSound(combo_9_power); break
case 10: playSound(combo_10_power); break
case 11: playSound(combo_11_power); break
case 12: playSound(combo_12_power); break
case 13: playSound(combo_13_power); break
case 14: playSound(combo_14_power); break
case 15: playSound(combo_15_power); break
default: playSound(combo_16_power)
} else switch(this.combo) {
case -1: break;
case 0: playSound(clearline); break
case 1: playSound(combo_1); break
case 2: playSound(combo_2); break
case 3: playSound(combo_3); break
case 4: playSound(combo_4); break
case 5: playSound(combo_5); break
case 6: playSound(combo_6); break
case 7: playSound(combo_7); break
case 8: playSound(combo_8); break
case 9: playSound(combo_9); break
case 10: playSound(combo_10); break
case 11: playSound(combo_11); break
case 12: playSound(combo_12); break
case 13: playSound(combo_13); break
case 14: playSound(combo_14); break
case 15: playSound(combo_15); break
default: playSound(combo_16)
}
if (nbClearedLines == 4) playSound(quatuorSound, this.combo)
else if (nbClearedLines) playSound(lineClearSound, this.combo)
if (tSpin) playSound(tSpinSound, this.combo)
}
this.goal -= awardedLineClears;
if (this.goal <= 0) this.level++;
this.goal -= awardedLineClears
if (this.goal <= 0) this.level++
}
show() {
let time = stats.time;
statsModalScoreCell.innerText = this.score.toLocaleString();
statsModalHighScoreCell.innerText = this.highScore.toLocaleString();
statsModalLevelCell.innerText = this.level;
statsModalTimeCell.innerText = this.timeFormat.format(time);
statsModaltotalClearedLines.innerText = this.totalClearedLines;
statsModaltotalClearedLinesPM.innerText = (
(stats.totalClearedLines * 60000) /
time
).toFixed(2);
statsModalNbQuatuors.innerText = this.nbQuatuors;
statsModalNbTSpin.innerText = this.nbTSpin;
statsModalMaxCombo.innerText = this.maxCombo;
statsModalMaxB2B.innerText = this.maxB2B;
this.modal.show();
let time = stats.time
statsModalScoreCell.innerText = this.score.toLocaleString()
statsModalHighScoreCell.innerText = this.highScore.toLocaleString()
statsModalLevelCell.innerText = this.level
statsModalTimeCell.innerText = this.timeFormat.format(time)
statsModaltotalClearedLines.innerText = this.totalClearedLines
statsModaltotalClearedLinesPM.innerText = (stats.totalClearedLines * 60000 / time).toFixed(2)
statsModalNbQuatuors.innerText = this.nbQuatuors
statsModalNbTSpin.innerText = this.nbTSpin
statsModalMaxCombo.innerText = this.maxCombo
statsModalMaxB2B.innerText = this.maxB2B
this.modal.show()
}
save() {
localStorage['highScore'] = this.highScore;
localStorage["highScore"] = this.highScore
}
}
Stats.prototype.timeFormat = new Intl.DateTimeFormat('fr-FR', {
hour: 'numeric',
minute: '2-digit',
second: '2-digit',
timeZone: 'UTC',
});
Stats.prototype.timeFormat = new Intl.DateTimeFormat("fr-FR", {
hour: "numeric",
minute: "2-digit",
second: "2-digit",
timeZone: "UTC"
})
function playSound(sound, note=0) {
sound.currentTime = 0;
sound.playbackRate = note? Math.pow(5 / 4, note): 1;
sound.play();
sound.currentTime = 0
sound.playbackRate = Math.pow(5/4, note)
sound.play()
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More