105 Commits

Author SHA1 Message Date
adrien 6706d60086 more sounds 2026-03-12 02:41:08 +01:00
adrien 040dc5d5e9 round 2026-03-11 19:52:19 +01:00
adrien b8b743871e defaults, round 2026-03-11 18:10:20 +01:00
adrien 018d623143 fix space in url 2026-03-11 16:18:32 +01:00
adrien 54cb17fb88 use https://you.have.fail/tetrioplus/ skins 2026-03-11 15:05:34 +01:00
adrien 7bdb9524ad sanitize input 2026-03-10 03:23:30 +01:00
adrien 923ec9f95d improve jstris skin 2026-03-10 02:06:05 +01:00
adrien 1d9a521595 escapeMarkup 2026-03-09 21:49:02 +01:00
adrien 3bb9f302ed improve jstris skin 2026-03-09 21:03:45 +01:00
adrien 4bac3face1 use https://konsola5.github.io/jstris-customization-database/ 2026-03-09 19:06:48 +01:00
adrien b2601e9c24 tweaks 2026-03-09 01:50:18 +01:00
adrien 89b08832d1 ghost opacity 2026-03-08 05:35:43 +01:00
adrien 7ed61e135b support for jstris skin as well 2026-03-08 05:28:16 +01:00
adrien a49c95f1aa no overlay 2026-03-08 04:08:48 +01:00
adrien d0a2f1b7f9 use external skins 2026-03-07 23:13:45 +01:00
adrien aed0601933 a bit of 3D 2026-03-05 21:14:34 +01:00
adrien 896b26684a sprites 2026-03-05 09:03:17 +01:00
adrien bf18998caa fix paste error 2026-03-05 08:46:10 +01:00
adrien f261f01684 less blinks 2026-03-05 02:01:38 +01:00
adrien 49e56427b1 optimization 2026-03-04 23:54:27 +01:00
adrien b72276b76c neo-classic theme 2026-03-04 19:50:44 +01:00
adrien d4d0dfaf30 merge and rename themes 2026-03-04 08:52:24 +01:00
adrien 5ba379d968 ridge 2026-03-04 00:17:41 +01:00
adrien f6ebe87434 shadow 2026-03-03 16:50:32 +01:00
adrien 24b0e72eab more bounce 2026-03-03 14:51:59 +01:00
adrien ab105bf485 settings reorder 2026-03-01 21:29:21 +01:00
adrien ea8dbff564 pseudo 3d 2026-03-01 21:29:10 +01:00
adrien 9a2989616a top side 2026-03-01 15:32:02 +01:00
adrien d6006e657f ghost 2026-03-01 11:48:18 +01:00
adrien ce758c1e92 update cleared line animation 2026-02-28 10:31:24 +01:00
adrien 8a0590f1b3 hsl 2026-02-23 23:21:11 +01:00
adrien 70caed8fb8 ridge 2026-02-23 18:15:31 +01:00
adrien b6eeae15b9 pop is the new classic 2026-02-23 17:11:34 +01:00
adrien 45c0e090e5 less brilliant 2026-02-21 11:52:26 +01:00
adrien 73ec2015ba more more brilliant 2026-02-21 02:23:48 +01:00
adrien 91e1ea9d3a more brilliant 2026-02-20 21:02:52 +01:00
adrien 798ac21372 pause on fullscreen exit 2026-02-20 09:05:23 +01:00
adrien 2820c42ba8 cover 2026-02-16 00:20:54 +01:00
adrien 8e043b9e8c background position 2026-02-16 00:18:31 +01:00
adrien 136ea4156f fix hold glich; prefered theme pop 2026-02-16 00:07:32 +01:00
adrien c01c6dcf58 new theme 2026-02-01 16:30:01 +01:00
adrien 25826565af bootstrap checkbox 2026-01-27 11:04:09 +01:00
adrien 56b906723c fullscreen checkbox 2026-01-27 08:56:28 +01:00
adrien 20b96da34b fix border 2026-01-23 08:22:58 +01:00
adrien bd195f7da6 softer blink 2026-01-23 08:21:15 +01:00
adrien 06b444c37e more transparency 2026-01-23 00:56:55 +01:00
adrien 71945a7ade clearPiece 2026-01-23 00:54:17 +01:00
adrien 0956e3d6e0 don't close game over modal 2026-01-21 20:45:44 +01:00
adrien cc4c477a10 classic locked-animation box-shadow 2026-01-21 20:36:47 +01:00
adrien e196d931ca speed up css 2026-01-18 05:29:07 +01:00
adrien a4117b782a locked-animation 2026-01-16 21:16:05 +01:00
adrien 3e3fd6d7f4 tweaks 2026-01-16 03:38:58 +01:00
adrien 50a4536994 100px 2026-01-16 03:27:09 +01:00
adrien a4e210526f 3D cleared line animation 2026-01-16 03:23:26 +01:00
adrien cb49d42266 3D cleared line animation 2026-01-16 02:31:13 +01:00
adrien 90b1251ebf restart hard dropped animation 2026-01-16 01:31:15 +01:00
adrien 26a4d113b5 no cleared line animation 2026-01-15 17:55:24 +01:00
adrien b3d012f489 3d trail 2026-01-15 16:51:02 +01:00
adrien 021d67b877 less grab 2026-01-15 16:15:51 +01:00
adrien 3af40de841 scroll backward 2026-01-15 13:39:47 +01:00
adrien 2d700f1927 fix border translation 2026-01-12 08:45:19 +01:00
adrien 280ff0ef9f more light 2026-01-12 01:21:44 +01:00
adrien 8e5b45bf6f fix border translation 2026-01-12 01:19:21 +01:00
adrien 18977dfd1b more light 2026-01-12 00:23:34 +01:00
adrien 334e0e0178 tweaks 2026-01-11 22:38:06 +01:00
adrien 02a24ec1f2 border 2026-01-11 22:26:58 +01:00
adrien 0cb9fd4c27 more shadows 2026-01-11 18:07:00 +01:00
adrien e21f9c7dfa text-shadow 2026-01-11 17:56:25 +01:00
adrien baf5672de8 hold and next light 2026-01-11 00:55:54 +01:00
adrien 9ed62d1e79 hold and next light 2026-01-11 00:51:01 +01:00
adrien 2a5ce8faab more text-shadow 2026-01-10 03:49:30 +01:00
adrien 4f7d44de4b text-shadow 2026-01-10 03:28:11 +01:00
adrien 44e048624a top light 2026-01-10 02:30:12 +01:00
adrien d7fa6c4fe5 Merge branch 'master' of https://git.malingrey.fr/adrien/quatuor 2026-01-10 02:18:05 +01:00
adrien b5ece6f892 stats 2026-01-10 02:15:57 +01:00
adrien 181b6d28f6 stats 2026-01-10 02:01:10 +01:00
adrien 616b364d40 light! 2026-01-09 21:38:04 +01:00
adrien e17517e2eb left always bright, right always dark 2026-01-09 08:15:50 +01:00
adrien e4c0ba5719 floating ghost 2026-01-09 02:32:03 +01:00
adrien a1028cb054 ghost desaturate 2026-01-09 02:28:41 +01:00
adrien 1babf41efe beautifuller 2026-01-09 02:17:45 +01:00
adrien 8d371a52ec 3D light 2026-01-09 01:45:22 +01:00
adrien 743e23d729 nearer 2026-01-08 22:43:50 +01:00
adrien 46ca9f92d3 change side color from orientation 2026-01-08 18:49:41 +01:00
adrien 6d0b93dfdb left face from right neighbour 2026-01-08 18:35:58 +01:00
adrien 97ca770641 left face on first then right face 2026-01-08 18:34:44 +01:00
adrien 3093d880aa border-radius: 2px; 2026-01-07 02:31:33 +01:00
adrien fe77be0381 border-radius 2026-01-07 02:29:09 +01:00
adrien a7fae60a1c 4 faced cubes 2026-01-07 02:18:31 +01:00
adrien 7927038fb2 universal? double backdrop-filters 2026-01-06 21:02:03 +01:00
adrien bb74fbef45 Revert "universal? double backdrop-filters"
This reverts commit 994a7a7f04.
2026-01-06 17:26:45 +01:00
adrien 994a7a7f04 universal? double backdrop-filters 2026-01-06 11:57:25 +01:00
adrien 0c186ccd59 backdrop-filter bug 2026-01-06 09:14:37 +01:00
adrien 44d68d79cc grab cursor on all sceneDiv 2026-01-06 02:16:56 +01:00
adrien 52a7f37eb0 replace synthwave by new wave style 2026-01-06 02:12:32 +01:00
adrien 1f78b2dc10 bout à bout 2026-01-06 01:53:51 +01:00
adrien 491f5c021a corrections 2026-01-03 13:06:28 +01:00
adrien c4d9621551 corrections 2026-01-03 05:17:20 +01:00
adrien 3d8bc0ce11 Merge branch '3729a3762aa6b1aa08a682aea48fb37ab5fe9bd5' 2026-01-03 05:06:08 +01:00
adrien 3729a3762a pop2 style 2026-01-03 02:55:03 +01:00
adrien 4b2cd0e5d2 change minimal ghost piece 2025-08-28 10:40:19 +02:00
adrien 08763c501e change classic ghost piece 2025-08-28 10:32:48 +02:00
adrien bc5de2448d less blink 2025-08-28 02:32:22 +02:00
adrien 67a0f06d03 trail on soft drop 2025-08-28 02:30:17 +02:00
adrien 2f1ec2a6f7 white border 2025-08-28 02:17:10 +02:00
124 changed files with 16022 additions and 1240 deletions
+101 -36
View File
@@ -1,22 +1,28 @@
:root {
--cell-side: 24px;
--rX: -15deg;
--rY: 0;
--tZ: 0;
--cell-size: 25px;
--rX: -15;
--rY: 0;
--tZ: 25px;
}
body {
background: linear-gradient(#212529, #14171a) fixed;
background: linear-gradient(#212529, #14171a) fixed;
}
@supports (backdrop-filter: blur()) {
.modal {
.modal::before {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
backdrop-filter: blur(2px);
}
.modal-content {
background-color: #2125294d;
backdrop-filter: blur(15px);
background-color: #212529b3;
backdrop-filter: blur(10px);
}
}
@@ -25,7 +31,7 @@ body {
}
#matrixCard {
background-image: radial-gradient(#222, #25292d)
background-image: radial-gradient(#222, #25292d);
}
.card-header {
@@ -34,6 +40,7 @@ body {
.modal-title {
text-shadow: 0 0 8px var(--bs-light);
font-weight: 600;
}
#statsTable td,
@@ -41,9 +48,13 @@ body {
text-align: right;
}
td#timeCell {
min-width: 10ch;
}
.minoes-table {
--piece-column: 0;
--piece-row : 0;
--piece-column: 0;
--piece-row: 0;
table-layout: fixed;
border-collapse: separate;
border-spacing: 0;
@@ -51,16 +62,16 @@ body {
}
#matrixTable {
margin-top: calc(-1 * var(--buffer-zone-rows) * var(--cell-side));
margin-top: calc(-1 * var(--buffer-zone-rows) * var(--cell-size));
}
@keyframes hard-dropped-table-animation {
25% {
transform: translateY(2px);
50% {
transform: translate(0, 5px);
}
}
.hard-dropped-table-animation {
animation: hard-dropped-table-animation .2s;
animation: hard-dropped-table-animation ease-in-out 0.2s;
}
tr.buffer-zone td:not(.mino) {
@@ -68,52 +79,73 @@ tr.buffer-zone td:not(.mino) {
}
tr.matrix td:not(.mino) {
border-left : 1px solid #333;
border-right : 1px solid #333;
border-top : 1px solid #303030;
border-left: 1px solid #333;
border-right: 1px solid #333;
border-top: 1px solid #303030;
border-bottom: 1px solid #303030;
}
td {
overflow: hidden;
width: var(--cell-side);
height: var(--cell-side);
width: var(--cell-size);
height: var(--cell-size);
box-sizing: border-box;
}
@keyframes trail-animation {
from {
background-color: #ceffff40;
filter: saturate(50%) brightness(300%);
}
to {
background-color: transparent;
}
}
@keyframes locked-animation {
from {
filter: saturate(50%) brightness(400%);
}
}
.locked.mino {
animation: locked-animation;
animation-duration: 0.2s;
}
td.trail-animation {
animation: trail-animation ease-out .3s;
animation: trail-animation ease-out 0.3s;
}
@keyframes cleared-line-animation {
from {
background-color: #ceffff66;
background-color: white;
filter: saturate(50%) brightness(300%);
box-shadow: -200px 0 5px white, 200px 0 5px white;
box-shadow:
0 0 0 #adb5bd,
0 0 0 #adb5bd;
}
60% {
box-shadow:
-60px 0 2px #adb5bd66,
60px 0 2px #adb5bd66;
}
to {
background-color: transparent;
box-shadow:
-100px 0 5px transparent,
100px 0 5px transparent;
}
}
tr.cleared-line-animation {
animation: cleared-line-animation ease-out .3s;
animation: cleared-line-animation ease-out 0.3s;
}
#holdTable .J,
#holdTable .L,
#holdTable .S,
#holdTable .T,
#holdTable .Z,
#holdTable .Z,
#nextTable .J,
#nextTable .L,
#nextTable .S,
@@ -131,6 +163,7 @@ tr.cleared-line-animation {
text-shadow: 1px 1px #000c;
font-size: 3vmin;
text-align: center;
z-index: 200;
}
#messagesSpan div {
@@ -166,7 +199,6 @@ tr.cleared-line-animation {
opacity: 0;
transform: scale3d(0.3, 0.3, 0.3);
line-height: var(--bs-body-line-height);
}
30% {
opacity: 1;
@@ -186,13 +218,13 @@ tr.cleared-line-animation {
@keyframes rotate-in-animation {
0% {
opacity:0;
transform:rotate(200deg);
opacity: 0;
transform: rotate(200deg);
line-height: var(--bs-body-line-height);
}
30% {
opacity:1;
transform:translateZ(0);
opacity: 1;
transform: translateZ(0);
transform: scale3d(1, 1, 1);
}
80% {
@@ -208,15 +240,15 @@ tr.cleared-line-animation {
}
#messagesSpan div.rotate-in-animation {
animation-name: rotate-in-animation;
animation-timing-function: cubic-bezier(.25,.46,.45,.94);
animation-name: rotate-in-animation;
animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
animation-duration: 1s;
}
#messagesSpan div.zoom-in-animation {
animation-name: zoom-in-animation;
animation-timing-function: cubic-bezier(.25,.46,.45,.94);
transform-origin:center;
animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
transform-origin: center;
animation-duration: 1s;
}
@@ -236,4 +268,37 @@ tr.cleared-line-animation {
animation: game-over-animation;
animation-timing-function: (0.4, 0, 0.6, 1);
animation-duration: 2s;
}
}
#statsModal table {
border-collapse: collapse;
}
#statsModal th {
padding-left: 0;
padding-right: 0.5rem;
padding-bottom: 0.2rem;
border-left: 0.5rem solid transparent;
border-right: 0;
}
#statsModal td {
padding-left: 0.5rem;
padding-right: 0;
padding-bottom: 0.2rem;
border-left: 0;
border-right: 0.5rem solid transparent;
}
#statsModal tr:last-child th,
#statsModal tr:last-child td {
border-bottom: none;
}
.select2-dropdown {
width: min-content !important;
}
.select2-results__group {
display: inline-block;
}
+204
View File
@@ -0,0 +1,204 @@
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);
}
-276
View File
@@ -1,276 +0,0 @@
body {
background-image: url(binaural/bg.jpg),
radial-gradient(
circle at center,
#39444f 0%,
#2c323b 25%,
#293036 28%,
#252b32 34%,
#242930 38%,
#1a1d22 52%,
#191c22 53%,
#151519 63%,
#141418 65%,
#0f0f12 74%,
#0a0c0d 100%
);
background-repeat: round;
}
#sceneDiv {
perspective: 500px;
}
#sceneDiv * {
transform-style: preserve-3d;
}
#screenRow {
display: block;
transform: translateZ(var(--tZ)) rotateX(var(--rX)) rotateY(var(--rY));
cursor: grab;
}
#screenRow:active {
cursor: grabbing;
}
#screenRow * {
display: block;
}
#screenRow .col {
display: inline-block !important;
width: max-content;
height: 100%;
vertical-align: top;
}
.card {
background: #36394180;
}
#matrixCard {
background-image: none;
}
#screenRow .card > * {
transform: translateZ(var(--cell-side));
}
#screenRow .card-header {
background-color: transparent;
border: none;
}
.minoes-table th,
.minoes-table td {
display: inline-block !important;
width: max-content;
}
.minoes-table tr {
width: max-content;
height: var(--cell-side);
}
#statsTable tr {
display: table;
width: 100%;
}
#statsTable th,
#statsTable td {
display: table-cell;
border: 0;
}
tr.matrix td:not(.mino) {
border: 0;
will-change: transform;
transform: translateZ(0);
}
.minoes-table td {
width: var(--cell-side) !important;
height: var(--cell-side);
}
.minoes-table .mino {
background: radial-gradient(circle at -150% -200%, #fffb 0%, var(--background-color) 100%);
overflow: visible;
}
.mino::before,
.mino::after {
content: '';
position: absolute;
display: block;
top: 0;
left: 0;
width: inherit;
height: inherit;
}
.mino::before {
background: var(--light-color);
transform: translateZ(calc(-1 * var(--cell-side))) rotateY(-90deg);
transform-origin: left;
}
.right .mino::before {
background: var(--dark-color);
transform: translateZ(calc(-1 * var(--cell-side))) rotateY(90deg);
transform-origin: right;
}
.mino::after {
background: var(--light-color);
transform: translateZ(calc(-1 * var(--cell-side))) rotateX(90deg);
transform-origin: top;
}
.bottom .mino::after {
background: var(--dark-color);
transform: translateZ(calc(-1 * var(--cell-side))) rotateX(-90deg);
transform-origin: bottom;
}
.I.mino {
--background-color: #42afe1b0;
--light-color: #6ceaff80;
--dark-color: #00a4b0b0;
}
.J.mino {
--background-color: #1165b5b0;
--light-color: #339bff80;
--dark-color: #00009db0;
}
.L.mino {
--background-color: #f38927b0;
--light-color: #ffba5980;
--dark-color: #c54800b0;
}
.O.mino {
--background-color: #f6d03cb0;
--light-color: #ffff7f80;
--dark-color: #ca9501b0;
}
.S.mino {
--background-color: #51b84db0;
--light-color: #84f88080;
--dark-color: #1cbc02b0;
}
.T.mino {
--background-color: #9739a2b0;
--light-color: #d958e980;
--dark-color: #6e019ab0;
}
.Z.mino {
--background-color: #eb4f65b0;
--light-color: #ff7f7980;
--dark-color: #ad1936b0;
}
.ghost.mino {
--background-color: #8886;
--light-color: #ccc6;
--dark-color: #3336;
}
.locking.mino {
--background-color: #eeeb;
--light-color: #fffb;
--dark-color: #dddb;
}
.disabled.mino {
--background-color: #888b;
--light-color: #cccb;
--dark-color: #333b;
}
@keyframes cleared-line-animation {
from {
background-color: #ceffff66;
box-shadow: -200px 0 5px white, 200px 0 5px white;
}
to {
background-color: transparent;
}
}
@keyframes show-level-animation {
from {
opacity: 1;
transform: translateY(200%);
}
50% {
transform: translateY(0) scaleY(1);
line-height: var(--bs-body-line-height);
}
to {
opacity: 1;
transform: translateY(-100%) scaleY(0);
line-height: 0;
}
}
@keyframes zoom-in-animation {
from {
opacity: 1;
transform: scale3d(0.3, 0.3, 0.3);
line-height: var(--bs-body-line-height);
}
30% {
transform: scale3d(1, 1, 1);
}
80% {
transform: scale3d(1, 1, 1);
line-height: var(--bs-body-line-height);
}
to {
opacity: 1;
transform: scale3d(1.5, 0, 1);
line-height: 0;
}
}
@keyframes rotate-in-animation {
0% {
opacity: 1;
transform: rotate(200deg);
line-height: var(--bs-body-line-height);
}
30% {
transform: translateZ(0);
transform: scale3d(1, 1, 1);
}
80% {
transform: scale3d(1, 1, 1);
line-height: var(--bs-body-line-height);
}
to {
opacity: 1;
transform: scale3d(1.5, 0, 1);
line-height: 0;
}
}
@keyframes game-over-animation {
from {
opacity: 1;
transform: translateY(200%);
}
to {
opacity: 1;
transform: translateY(0) scaleY(1);
line-height: var(--bs-body-line-height);
}
}
+69 -104
View File
@@ -1,123 +1,88 @@
.minoes-table tr {
z-index: calc(100 - var(--row));
position: sticky;
}
tr.matrix td:not(.mino) {
border-left: none;
border-bottom: none;
}
.mino {
background: radial-gradient(
ellipse 140% 66% at 122% 88%,
var(--background-color) 100%,
var(--frontier-color) 105%,
var(--light-color) 130%
--color: hsl(var(--hue), var(--saturation), 40%);
--light: hsl(var(--hue), calc(0.66 * var(--saturation)), 84%);
--top: hsl(var(--hue), calc(0.6 * var(--saturation)), 68%);
background-color: var(--color);
background-image:
radial-gradient(
ellipse 22% 8% at 25% 22%,
#ffffff66,
#ffffff33 40%,
transparent 70%
),
radial-gradient(
ellipse 140% 85% at 50% -15%,
var(--light) 0%,
#ffffff77 40%,
#00000005 55%
),
radial-gradient(
ellipse 120% 220% at 50% 140%,
var(--light) 0%,
var(--color) 55%,
#00000066 95%
);
border: 4px solid;
padding: 0;
opacity: 100%;
border-radius: 1px;
box-shadow: 2px 2px 4px #000a;
border: 4px ridge var(--color);
border-top-color: var(--light);
border-radius: 3px;
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;
filter: saturate(1.1) contrast(1.05);
}
.I.mino {
--background-color : #00d6fb;
--frontier-color : #43e7fd;
--light-color : #afeff9;
border-top-color : #7cf2fd;
border-left-color : #2ed5e5;
border-right-color : #01b8ca;
border-bottom-color: #00a4b0;
.I {
--hue: 193;
--saturation: 100%;
}
.J.mino {
--background-color : #2E00FB;
--frontier-color : #7054fb;
--light-color : #b8b4ff;
border-top-color : #4985fd;
border-left-color : #2f36ea;
border-right-color : #0006ca;
border-bottom-color: #00009d;
.J {
--hue: 215;
--saturation: 100%;
}
.L.mino {
--background-color : #FF7900;
--frontier-color : #fe9551;
--light-color : #fdd0b7;
border-top-color : #fd9f6b;
border-left-color : #e76d28;
border-right-color : #e74f00;
border-bottom-color: #c54800;
.L {
--hue: 25;
--saturation: 100%;
}
.O.mino {
--background-color : #FeCB00;
--frontier-color : #fce15c;
--light-color : #ffedac;;
border-top-color : #ffe364;
border-left-color : #e7ba23;
border-right-color : #e3a707;
border-bottom-color: #ca9501;
.O {
--hue: 42;
--saturation: 100%;
}
.S.mino {
--background-color : #67EE12;
--frontier-color : #93f85a;
--light-color : #C8FBA8;
border-top-color : #a4fc6d;
border-left-color : #5ee82b;
border-right-color : #35db00;
border-bottom-color: #1cbc02;
.S {
--hue: 95;
--saturation: 100%;
}
.T.mino {
--background-color : #B000FE;
--frontier-color : #c541fc;
--light-color : #edb2ff;
border-top-color : #d380ff;
border-left-color : #b42deb;
border-right-color : #8000cd;
border-bottom-color: #6e019a;
.T {
--hue: 300;
--saturation: 56%;
}
.Z.mino {
--background-color : #ed2939;
--frontier-color : #fe6483;
--light-color : #ffb8c5;
border-top-color : #fd718d;
border-left-color : #e62250;
border-right-color : #e20332;
border-bottom-color: #ad1936;
.Z {
--hue: 357;
--saturation: 84%;
}
.ghost.mino {
margin: 1px;
opacity: 20%;
filter: brightness(180%) saturate(60%) blur(1px);
}
.moving.mino {
filter: saturate(80%) brightness(150%);
}
.locking.mino {
filter: saturate(50%) brightness(200%);
box-shadow:
-1px -1px 4px #FFF2,
-1px 1px 4px #FFF2,
1px -1px 4px #FFF2,
1px 1px 4px #FFF2;
}
.disabled.mino {
filter: brightness(50%) contrast(80%);
opacity: 70%;
}
@keyframes locked-animation {
from {
filter: saturate(50%) brightness(400%);
box-shadow:
-1px -1px 4px #FFF2,
-1px 1px 4px #FFF2,
1px -1px 4px #FFF2,
1px 1px 4px #FFF2;
}
}
.locked.mino {
animation: locked-animation;
animation-duration: 0.2s;
.ghost {
border: 3px solid #fff2;
padding: 3px;
background-color: #fff2;
background-clip: content-box;
background-image: none;
box-shadow: none;
}
+16 -19
View File
@@ -1,14 +1,14 @@
body {
background-image: url("electro/bg.jpg");
background-image: url('electro/bg.jpg');
background-size: cover;
}
body[data-bs-theme="dark"] {
--bs-body-bg: #2125296b;
body[data-bs-theme='dark'] {
--bs-body-bg: #2125296b;
}
.btn-dark {
--bs-btn-bg: #2125296b;
--bs-btn-bg: #2125296b;
}
.card {
@@ -16,7 +16,7 @@ body[data-bs-theme="dark"] {
}
tr.matrix td:not(.mino) {
border-left : none;
border-left: none;
border-bottom: none;
}
@@ -30,29 +30,30 @@ tr.matrix td:not(.mino) {
}
.mino:not(.ghost):not(.locking):before {
content: "";
content: '';
position: absolute;
z-index: -1;
inset: 0;
margin: 1px 1px 0px 0px;
padding: 2px;
border-radius: 4px;
--glint-x: calc(50% + 50% * (var(--piece-column) - var(--column))/10);
--glint-y: calc(50% + 50% * (var(--piece-row) - var(--row))/25);
--glint-x: calc(50% + 50% * (var(--piece-column) - var(--column)) / 10);
--glint-y: calc(50% + 50% * (var(--piece-row) - var(--row)) / 25);
background: radial-gradient(
at var(--glint-x) var(--glint-y),
rgba(204, 238, 247, 0.9) 0%,
rgba(10, 159, 218, 0.9) 150%);
mask:
linear-gradient(#666 0 0) content-box,
linear-gradient(#fff 0 0);
rgba(204, 238, 247, 0.9) 0%,
rgba(10, 159, 218, 0.9) 150%
);
mask:
linear-gradient(#666 0 0) content-box,
linear-gradient(#fff 0 0);
mask-mode: luminance;
mask-composite: intersect;
}
.ghost.mino {
background: rgba(242, 255, 255, 10%);
border : 2px solid rgba(255, 255, 255, 0.3);
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 3px;
box-shadow: 0px 0px 10px rgba(242, 255, 255, 75%);
}
@@ -78,6 +79,7 @@ tr.matrix td:not(.mino) {
.disabled.mino {
opacity: 60%;
position: relative;
}
.disabled.mino:before {
@@ -92,8 +94,3 @@ tr.matrix td:not(.mino) {
border-color: white;
}
}
.locked.mino {
animation: locked-animation;
animation-duration: 0.2s;
}
+61
View File
@@ -0,0 +1,61 @@
#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%;
}
+217
View File
@@ -0,0 +1,217 @@
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;
}
}
+118
View File
@@ -0,0 +1,118 @@
.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;
}
}
+81
View File
@@ -0,0 +1,81 @@
: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.

After

Width:  |  Height:  |  Size: 5.7 KiB

+23 -26
View File
@@ -5,12 +5,8 @@
.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 {
@@ -26,8 +22,8 @@ tr.matrix td:not(.mino) {
.minoes-table td {
display: inline-block;
width: var(--cell-side);
height: var(--cell-side);
width: var(--cell-size);
height: var(--cell-size);
padding: 0 !important;
z-index: calc(200 - var(--row));
}
@@ -41,43 +37,44 @@ 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 {
opacity: 50%;
opacity: 5%;
box-shadow: none;
transform: translateY(-6px);
}
.moving.mino {
@@ -85,8 +82,8 @@ tr.matrix td:not(.mino) {
}
.locking.mino {
--background-color: white;
--box-shadow-color: #DDD;
--background-color: white;
--box-shadow-color: #ddd;
}
.locked.mino {
@@ -121,4 +118,4 @@ tr.matrix td:not(.mino) {
to {
background-color: transparent;
}
}
}
+89
View File
@@ -0,0 +1,89 @@
.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%;
}
-70
View File
@@ -1,70 +0,0 @@
body {
background-image: url("new-wave/bg.png");
background-size: cover;
}
body[data-bs-theme="dark"] {
--bs-body-bg: #2125296b;
}
.btn-dark {
--bs-btn-bg: #2125296b;
}
.card {
background: #25292d66;
}
#matrixCard {
background-image: radial-gradient(#2226, #25292d66);
}
.minoes-table {
background: transparent;
}
.mino {
background: var(--color);
border: 3px solid var(--border);
box-shadow: 0 0 8px var(--border);
}
.I {
--color: #00eaf888;
--border: #00eaf5;
}
.J {
--color: #00a9f788;
--border: #00a9f7;
}
.L {
--color: #f9b60088;
--border: #f9b600;
}
.O {
--color: #e3e04988;
--border: #e3e049;
}
.S {
--color: #7bd59e88;
--border: #7bd59e;
}
.T {
--color: #d136e288;
--border: #d136e2;
}
.Z {
--color: #E67D8688;
--border: #E67D86;
}
.ghost {
--color: #fff4;
--border: #fff5;
}
+171
View File
@@ -0,0 +1,171 @@
: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;
}

Before

Width:  |  Height:  |  Size: 870 B

After

Width:  |  Height:  |  Size: 870 B

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

+22 -29
View File
@@ -1,5 +1,5 @@
body {
--bs-gutter-x: 0;
--bs-gutter-x: 0;
background: black !important;
}
@@ -7,11 +7,11 @@ body {
gap: 0 !important;
margin: 0;
text-transform: uppercase;
letter-spacing: .1em;
letter-spacing: 0.1em;
}
#screenRow {
--bs-gutter-x: 0;
--bs-gutter-x: 0;
}
.card {
@@ -22,7 +22,7 @@ body {
}
.card-header,
.card-header th{
.card-header th {
background: transparent;
font-weight: 400 !important;
font-size: 1.3em;
@@ -30,7 +30,7 @@ body {
}
#screenRow .table {
--bs-border-width: 0;
--bs-border-width: 0;
}
#holdTable {
@@ -75,6 +75,10 @@ body {
color: white;
}
td#timeCell {
text-align: center;
}
#matrixCard {
background: transparent;
border-top: none;
@@ -91,38 +95,38 @@ body {
}
.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 {
@@ -142,14 +146,3 @@ body {
filter: brightness(50%) contrast(80%);
opacity: 70%;
}
@keyframes locked-animation {
from {
filter: saturate(50%) brightness(400%);
}
}
.locked.mino {
animation: locked-animation;
animation-duration: 0.2s;
}
-156
View File
@@ -1,156 +0,0 @@
:root {
--cell-side: 20px;
}
@font-face {
font-family: "Early GameBoy";
src: url("retro/Early GameBoy.ttf");
}
body {
}
#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;
}
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 {
50% {
opacity: 0;
}
}
.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;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

+436
View File
@@ -0,0 +1,436 @@
: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,
#39444f 0%,
#2c323b 25%,
#293036 28%,
#252b32 34%,
#242930 38%,
#1a1d22 52%,
#191c22 53%,
#151519 63%,
#141418 65%,
#0f0f12 74%,
#0a0c0d 100%
);
background-repeat: space;
background-position: center;
background-size: cover;
}
#sceneDiv {
perspective: 500px;
cursor: grab;
}
#sceneDiv:active {
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,
#screenRow,
#screenRow .col,
#screenRow .card,
#screenRow .card-body,
.minoes-table,
.minoes-table tbody,
.minoes-table tr,
.minoes-table td {
display: block;
transform-style: preserve-3d;
}
#screenRow .col {
display: inline-block !important;
width: max-content;
height: 100%;
vertical-align: top;
}
.card {
background: #36394180;
}
#matrixCard {
background-image: none;
}
#screenRow .card > * {
transform: translateZ(var(--cell-size));
}
#screenRow .card-header {
background-color: transparent;
border: none;
}
.card,
.card-header {
text-shadow: calc(-0.3px * var(--rY)) calc(0.4px * var(--rX)) 5px #0008;
}
#holdTable .mino {
--row: 7;
--column: -5;
}
#nextTable .mino {
--row: 15;
--column: 15;
}
.minoes-table th,
.minoes-table td {
display: inline-block !important;
width: max-content;
}
.minoes-table tr {
width: max-content;
height: var(--cell-size);
}
#statsTable tr {
display: table;
width: 100%;
}
#statsTable th,
#statsTable td {
display: table-cell;
border: 0;
}
tr.matrix td:not(.mino) {
border: 0;
}
.minoes-table td {
width: var(--cell-size);
height: var(--cell-size);
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));
--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: 2px outset var(--center-color);
}
.mino::before,
.mino + :not(.mino)::before,
.mino::after,
td.trail-animation::before,
td.trail-animation::after,
tr.cleared-line-animation td::before,
tr.cleared-line-animation td::after {
content: '';
position: absolute;
top: 0;
left: 0;
display: block;
width: var(--cell-size);
height: var(--cell-size);
}
/* Front face */
.mino,
td.trail-animation {
--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(
circle at var(--center-x) var(--center-y),
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);
}
/* Left face */
.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);
transform-origin: left;
}
/* Right face */
.mino + :not(.mino)::before,
.right .mino + .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));
--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-origin: left;
}
.right .mino:last-child::before {
transform: var(--t3d) rotateY(90deg) !important;
transform-origin: right !important;
}
/* Top face */
.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);
transform-origin: top;
}
/* Bottom face */
.bottom .mino::after,
.bottom td.trail-animation::after,
.bottom tr.cleared-line-animation td::after {
--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-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;
}
.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;
}
#holdTable .J + :not(.mino),
#holdTable .L + :not(.mino),
#holdTable .S + :not(.mino),
#holdTable .T + :not(.mino),
#holdTable .Z + :not(.mino),
#nextTable .J + :not(.mino),
#nextTable .L + :not(.mino),
#nextTable .S + :not(.mino),
#nextTable .T + :not(.mino),
#nextTable .Z + :not(.mino) {
transform: translateX(50%);
}
@keyframes trail-animation {
from {
background-color: hsla(180, 100%, 100%, 0.1);
border-color: hsla(180, 100%, 100%, 0.1);
}
to {
background-color: transparent;
border-color: transparent;
}
}
td.trail-animation::before,
td.trail-animation::after {
animation: trail-animation ease-out 0.3s;
}
@keyframes locked-animation {
from {
--h: 0deg;
--s: 0%;
--l: 100%;
--a: 1;
box-shadow: 0 0 10px hsla(180, 100%, 100%, 0.2);
}
}
.locked.mino::before,
.locked.mino::after {
animation: locked-animation;
animation-duration: 0.2s;
}
@keyframes cleared-line-animation {
from {
background-color: white !important;
box-shadow: 0 0 0 white;
}
to {
background-color: #fff0;
box-shadow: 0 0 100px transparent;
}
}
tr.cleared-line-animation td::before,
tr.cleared-line-animation td::after {
animation: cleared-line-animation ease-out 0.3s;
}
@keyframes show-level-animation {
from {
opacity: 1;
transform: translateY(200%);
}
50% {
transform: translateY(0) scaleY(1);
line-height: var(--bs-body-line-height);
}
to {
opacity: 1;
transform: translateY(-100%) scaleY(0);
line-height: 0;
}
}
@keyframes zoom-in-animation {
from {
opacity: 1;
transform: scale3d(0.3, 0.3, 0.3);
line-height: var(--bs-body-line-height);
}
30% {
transform: scale3d(1, 1, 1);
}
80% {
transform: scale3d(1, 1, 1);
line-height: var(--bs-body-line-height);
}
to {
opacity: 1;
transform: scale3d(1.5, 0, 1);
line-height: 0;
}
}
@keyframes rotate-in-animation {
0% {
opacity: 1;
transform: rotate(200deg);
line-height: var(--bs-body-line-height);
}
30% {
transform: translateZ(0) scale3d(1, 1, 1);
}
80% {
transform: scale3d(1, 1, 1);
line-height: var(--bs-body-line-height);
}
to {
opacity: 1;
transform: scale3d(1.5, 0, 1);
line-height: 0;
}
}
@keyframes game-over-animation {
from {
opacity: 1;
transform: translateY(200%);
}
to {
opacity: 1;
transform: translateY(0) scaleY(1);
line-height: var(--bs-body-line-height);
}
}

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

+43
View File
@@ -0,0 +1,43 @@
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);
}
+50 -84
View File
@@ -1,123 +1,89 @@
body {
background-image: url("new-wave/bg.png");
background-image: url(synthwave/wtCSusF.jpeg);
background-size: cover;
}
body[data-bs-theme="dark"] {
--bs-body-bg: #2125296b;
body[data-bs-theme='dark'] {
--bs-body-bg: #2125296b;
}
.btn-dark {
--bs-btn-bg: #2125296b;
--bs-btn-bg: #2125296b;
}
.card {
background: #25292d66;
}
#matrixCard {
background-image: radial-gradient(#2226, #25292d66);
}
.card,
#matrixCard {
background: repeating-linear-gradient(transparent, #111 1px);
background: repeating-linear-gradient(transparent, transparent 2px, #1114 2px, #1114 5px);
backdrop-filter: blur(3px);
}
.card-header {
background-color: rgba(37, 41, 45, 50%);
.minoes-table {
background: transparent;
border-spacing: 2px;
}
#matrixTable {
border-spacing: 1px;
margin-top: calc(-1 * var(--buffer-zone-rows) * var(--cell-size) - 8px);
}
tr.matrix td:not(.mino) {
border: 1px solid #111;
#matrixTable td:not(.mino) {
border-color: #8881;
border-top: none;
border-bottom: none;
}
.mino {
background: radial-gradient(#fff3 0%, var(--color) 170%);
border: 2px solid var(--color);
border-radius: 0;
outline: 1px solid #0006;
opacity: 100%;
box-shadow: 0 0 12px var(--color);
background: var(--color);
border: 3px solid var(--border);
border-radius: 6px;
box-shadow: 0 0 8px var(--border);
filter: blur(0.5px);
}
.I.mino {
--color: #00eaf5;
.I {
--color: #00eaf866;
--border: #00eaf5;
}
.J.mino {
--color: #00a9f7;
.J {
--color: #00a9f766;
--border: #00a9f7;
}
.L.mino {
--color: #f9b600;
.L {
--color: #f9b60066;
--border: #f9b600;
}
.O.mino {
--color: #f7f200;;
.O {
--color: #e3e04966;
--border: #e3e049;
}
.T.mino {
--color: #d136e2;;
.S {
--color: #7bd59e66;
--border: #7bd59e;
}
.S.mino {
--color: #35da3f;
.T {
--color: #d136e266;
--border: #d136e2;
}
.Z.mino {
--color: #ee3b3a;
.Z {
--color: #e67d8666;
--border: #e67d86;
}
.ghost.mino {
background: transparent;
opacity: 50%;
.ghost {
--color: #fff4;
--border: #fff5;
}
.moving.mino {
filter: brightness(120%);
}
.locking.mino {
--color: white;
box-shadow: 0 0 10px var(--color);
}
@keyframes locked-animation {
from {
background: white;
--color: white;
}
}
.locked.mino {
animation: locked-animation;
animation-duration: 0.2s;
}
.disabled.mino {
outline: 0px;
box-shadow: none;
filter: contrast(40%) brightness(50%);
}
tr.cleared-line-animation {
animation: none;
}
tr.cleared-line-animation::after {
content: "";
width: 100%;
height: var(--cell-side);
position: fixed;
left: 50%;
transform: translateX(-50%);
display: block;
background: repeating-linear-gradient(transparent, #fffb 1px);
opacity: 0;
animation: cleared-line-animation ease-out .3s;
}
@keyframes cleared-line-animation {
25% {
width: 200%;
opacity: 100%;
}
}

Before

Width:  |  Height:  |  Size: 444 KiB

After

Width:  |  Height:  |  Size: 444 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 972 KiB

+68
View File
@@ -0,0 +1,68 @@
:root {
--cell-size: 30px;
--sprite-size: round(100% / 11, 1px);
--skin-url: url(https://you.have.fail/ed/at/tetrioplus/data/content/skin/Haley%20Halcyon/tetrio_gameboy_plus.svg);
}
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);
}
+112 -41
View File
@@ -1,5 +1,5 @@
<!doctype html>
<html lang="fr">
<html lang="fr" data-bs-theme="dark">
<head>
<meta charset="utf-8" />
@@ -8,16 +8,23 @@
<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="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/minimal.css" title="Minimal">
<link rel="alternate stylesheet" href="css/electro.css" title="Électro">
<link rel="alternate stylesheet" href="css/new-wave.css" title="New Wave">
<link rel="alternate stylesheet" href="css/synthwave.css" title="Synthwave">
<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/binaural.css" title="Binaural">
<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/jstris-skin.css" title="Thème sélectionné" id="selectedStyleSheet">
<link rel="alternate stylesheet" href="css/jstris-skin.css" title="Sample...">
<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/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="Stéréo (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="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">
@@ -28,12 +35,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 avec un quatuor de blocs qui tombent."/>
<meta property="og:description" content="Un jeu de quatuors de blocs qui tombent."/>
<meta property="og:locale" content="fr_FR"/>
<meta property="og:site_name" content="adrien.malingrey.fr"/>
</head>
<body data-bs-theme="dark">
<body>
<div class="modal fade" id="settingsModal" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered">
@@ -61,7 +68,8 @@
<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>
@@ -69,18 +77,35 @@
</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" oninput="selectedStyleSheet.href = this.value">
<option value="css/classic.css" selected>Classique</option>
<option value="css/minimal.css">Minimal</option>
<option value="css/new-wave.css">New Wave</option>
<option value="css/synthwave.css">Synthwave</option>
<option value="css/electro.css">Électro</option>
<option value="css/retro.css">Rétro</option>
<option value="css/opera.css">Opéra</option>
<option value="css/binaural.css">Binaural</option>
</select></div>
<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>
<div class="col-4">
<select name="stylesheet" id="stylesheetSelect" class="form-select">
<option value="css/jstris-skin.css" selected>Sample JStris...</option>
<option value="css/tetrio-skin.css">Sample Tetr.io...</option>
<option value="css/classic.css">Classique</option>
<option value="css/neo-classic.css">Néo-classique</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">Stéréo (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">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>
<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">
<label for="fullscreenCheckbox" class="form-check-label">Plein écran</label>
</div>
</div>
<div class="col-2"></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>
@@ -117,9 +142,9 @@
<table id="statsTable" class="table mb-0">
<tr class="card-header fw-bold text-uppercase"><th>Score</th><td id="scoreCell">0</td> </tr>
<tr><th>Meilleur<br/>score</th><td id="highScoreCell"><script>document.write(Number(localStorage["highScore"]) || 0)</script></td></tr>
<tr><th>Niveau</th> <td id="levelCell">0</td> </tr>
<tr><th>But</th> <td id="goalCell">0</td> </tr>
<tr><th>Temps</th> <td id="timeCell">00:00</td> </tr>
<tr><th>Niveau</th><td id="levelCell">0</td> </tr>
<tr><th>But</th> <td id="goalCell">0</td> </tr>
<tr><th>Temps</th> <td id="timeCell">00:00:00</td></tr>
</table>
</div>
</div>
@@ -188,21 +213,21 @@
</div>
<div class="modal fade" id="statsModal" tabindex="-1">
<div class="modal fade" id="statsModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title w-100 text-center">Fin</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
<!-- <button type="button" class="btn-close" data-bs-dismiss="modal"></button> -->
</div>
<div class="modal-body p-0">
<table class="table mb-0">
<tr><th>Score</th> <td id="statsModalScoreCell"></td> <th>Niveau</th> <td id="statsModalLevelCell"></td> </tr>
<tr><th>Meilleur score</th><td id="statsModalHighScoreCell"></td> <th>Temps</th> <td id="statsModalTimeCell"></td> </tr>
<tr><th>Lignes</th> <td id="statsModaltotalClearedLines"></td><th>Lignes par minute</th> <td id="statsModaltotalClearedLinesPM"></td></tr>
<tr><th>Quatuors</th> <td id="statsModalNbQuatuors"></td> <th>Plus long combo</th> <td id="statsModalMaxCombo"></td> </tr>
<tr><th>Pirouettes</th> <td id="statsModalNbTSpin"></td> <th>Plus long bout en bout</th><td id="statsModalMaxB2B"></td> </tr>
<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>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>
</table>
</div>
<div class="modal-footer">
@@ -222,14 +247,60 @@
<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="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>
<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 = "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 = "hyperalert" src = "snd/hyperalert.mp3" preload = "auto" type = "audio/mp3"></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 = "shatter" src = "snd/shatter.mp3" preload = "auto" type = "audio/mp3"></audio>
<audio id = "spin" src = "snd/spin.ogg" preload = "auto" type = "audio/ogg"></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>
+294 -186
View File
@@ -1,188 +1,189 @@
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']")
restart()
}
document.onfullscreenchange = function () {
if (document.fullscreenElement) {
fullscreenCheckbox.checked = true;
} else {
fullscreenCheckbox.checked = false;
if (playing) pauseSettings();
}
};
document.onfullscreenerror = function () {
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()
settings.show();
playSound(menuhover)
}
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
stats.time = stats.pauseTime
scheduler.setInterval(ticktack, 1000)
document.onkeydown = onkeydown;
document.onkeyup = onkeyup;
if (matrix.piece) scheduler.setInterval(fall, stats.fallPeriod)
else generate()
stats.time = stats.pauseTime;
scheduler.setInterval(ticktack, 1000);
if (matrix.piece) scheduler.setInterval(fall, stats.fallPeriod);
else generate();
playSound(menuconfirm)
}
}
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),
moveLeft: () => matrix.piece.move(TRANSLATION.LEFT)? playSound(move) : playSound(hit),
moveRight: () => matrix.piece.move(TRANSLATION.RIGHT),
moveRight: () => matrix.piece.move(TRANSLATION.RIGHT)? playSound(move) : playSound(hit),
rotateClockwise: () => matrix.piece.rotate(ROTATION.CW),
rotateClockwise: () => matrix.piece.rotate(ROTATION.CW)? playSound(rotate) : playSound(hit),
rotateCounterclockwise: () => matrix.piece.rotate(ROTATION.CCW),
rotateCounterclockwise: () => matrix.piece.rotate(ROTATION.CCW)? playSound(rotate) : playSound(hit),
softDrop: () => matrix.piece.move(TRANSLATION.DOWN) && ++stats.score,
softDrop: () => (matrix.piece.move(TRANSLATION.DOWN) && ++stats.score)? playSound(move) : playSound(floor),
hardDrop: function() {
scheduler.clearTimeout(lockDown)
playSound(hardDropSound)
while (matrix.piece.move(TRANSLATION.DOWN, ROTATION.NONE, true)) stats.score += 2
matrixCard.classList.add("hard-dropped-table-animation")
lockDown()
return true
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');
matrixCard.offsetHeight;
matrixCard.classList.add('hard-dropped-table-animation'); // restart animation
lockDown();
return true;
},
hold: function() {
hold: function () {
if (matrix.piece.holdEnabled) {
scheduler.clearInterval(fall)
scheduler.clearTimeout(lockDown)
scheduler.clearInterval(fall);
scheduler.clearTimeout(lockDown);
playSound(hold)
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);
}
}
@@ -194,121 +195,228 @@ 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())
generate()
stats.lockDown(matrix.piece.tSpin, matrix.clearLines());
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()
}
messagesSpan.onanimationend = function (event) {
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()
stats.show();
}
window.onbeforeunload = function(event) {
stats.save()
settings.save()
window.onbeforeunload = function (event) {
stats.save();
settings.save();
if (playing) return false;
}
};
// Play with 3D
let mousedown = false
let rX0 = 0
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
}
sceneDiv.onmousedown = function (event) {
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 - event.clientY + clientY0 + 360) % 360
screenRow.style.setProperty("--rX", rX + "deg")
if (rX <= 180) {
screenRow.classList.remove("top")
screenRow.classList.add("bottom")
sceneDiv.onmousemove = function (event) {
if (mousedown) {
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');
} else {
screenRow.classList.add("top")
screenRow.classList.remove("bottom")
screenRow.classList.add('top');
screenRow.classList.remove('bottom');
}
rY = (rY0 + event.clientX - clientX0 + 360) % 360
screenRow.style.setProperty("--rY", rY + "deg")
if (rY >= 180) {
screenRow.classList.remove("left")
screenRow.classList.add("right")
rY = (rY0 + 0.5 * (event.clientX - clientX0)) % 360;
screenRow.style.setProperty('--rY', rY);
if (rY <= 0) {
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();
}
};
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,
};
}
});
stylesheetSelect.oninput = function (event) {
selectedStyleSheet.href = this.value;
$("#skinURLSelect").empty();
switch (this.value) {
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} (${skin.author})`,
})),
};
data.push(groupData);
}
$('#skinURLSelect').select2({data: data});
});
break;
case 'css/tetrio-skin.css':
skinURLSelect.disabled = false;
fetch("https://you.have.fail/tetrioplus/data/data.json")
.then((resp) => resp.json())
.then((json) => {
const data = json
.filter((item) => (item.type == "skin" && item.format == "tetrioraster"))
.map((skin) => {
return {
id: encodeURI(`https://you.have.fail/tetrioplus/data/${skin.path}`),
text:`${skin.name} (${skin.author})\n${skin.description}`
}
})
.filter((option) => ImageURLPattern.test(option.id))
$('#skinURLSelect').select2({data: data});
})
break;
default:
skinURLSelect.disabled = true;
break;
}
}
sceneDiv.onmouseup = document.onmouseleave = function(event) {
mousedown = false
}
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']");
sceneDiv.onwheel = function(event) {
event.preventDefault()
event.stopPropagation()
let tZ = parseInt(getComputedStyle(screenRow).getPropertyValue("--tZ"))
tZ += event.deltaY
screenRow.style.setProperty("--tZ", tZ + "px")
}
window.onload = function (event) {
restart();
};
+11 -7
View File
@@ -17,7 +17,7 @@ const T_SPIN = {
T_SPIN: "PIROUETTE"
}
// score = AWARDED_LINE_CLEARS[tSpin][nbClearedLines]
// score = AWARDED_LINE_CLEARS[tSpin][clearedLines]
const AWARDED_LINE_CLEARS = {
[T_SPIN.NONE]: [0, 1, 3, 5, 8],
[T_SPIN.MINI]: [1, 2],
@@ -251,8 +251,12 @@ class Matrix extends MinoesTable {
if (piece.locked) className += " locking"
if (piece==this.piece && actionsQueue.length) className += " moving"
super.drawPiece(piece, className)
matrix.table.style.setProperty('--piece-column', this.piece.center.x)
matrix.table.style.setProperty('--piece-row', this.piece.center.y)
this.table.style.setProperty('--piece-column', this.piece.center.x)
this.table.style.setProperty('--piece-row', this.piece.center.y)
}
clearPiece(piece=this.piece, className="") {
super.drawPiece(piece, className)
}
redraw() {
@@ -278,18 +282,18 @@ class Matrix extends MinoesTable {
}
clearLines() {
let nbClearedLines = 0
let clearedLines = 0
for (let y=0; y<this.rows; y++) {
let row = this.blocks[y]
if (row.filter(lockedMino => lockedMino).length == this.columns) {
nbClearedLines++
clearedLines++
this.blocks.splice(y, 1)
this.blocks.unshift(Array(matrix.columns))
this.table.rows[y].classList.add("cleared-line-animation")
}
}
this.redraw()
return nbClearedLines
return clearedLines
}
}
Matrix.prototype.init_center = [4, 4]
@@ -328,7 +332,7 @@ class Tetromino {
let success = this.canMove(translation, rotation)
if (success) {
scheduler.clearTimeout(lockDown)
matrix.drawPiece(this, hardDropped? "trail-animation" : "")
matrix.clearPiece(this, hardDropped? "trail-animation" : "")
this.center = success.center
if (rotation) this.facing = success.facing
this.lastRotation = rotation
+274 -206
View File
@@ -1,334 +1,402 @@
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
}
})
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;
},
},
);
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]
})
window.document.selectedStyleSheetSet = stylesheetSelect.value
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(
'Source externe',
localStorage['skinURL'],
true,
true,
);
$('#skinURLSelect').append(option).trigger('change');
}
skinURLSelect.oninput();
}
}
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({}, {
get: (target, key) => target[key.toLowerCase()],
set: (target, key, value) => target[key.toLowerCase()] = value,
has: (target, key) => key.toLowerCase() in target
})
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,
},
);
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")
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');
}
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 = 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
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;
}
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
if (level <= 20){
this.fallPeriod = 1000 * Math.pow(0.8 - ((level - 1) * 0.007), level - 1)
this._level = level;
this.goal += level * 5;
if (level <= 20) {
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, nbClearedLines) {
this.totalClearedLines += nbClearedLines
if (nbClearedLines == 4) this.nbQuatuors++
if (tSpin == T_SPIN.T_SPIN) this.nbTSpin++
lockDown(tSpin, clearedLines) {
this.totalClearedLines += clearedLines;
if (clearedLines == 4) this.nbQuatuors++;
if (tSpin == T_SPIN.T_SPIN) this.nbTSpin++;
// Cleared lines & T-Spin
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]
})
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],
});
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 (nbClearedLines) {
this.combo++
if (clearedLines) {
this.combo++;
if (this.combo >= 1) {
let comboScore = (nbClearedLines == 1 ? 20 : 50) * this.combo * this.level
let comboScore = (clearedLines == 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 {
this.combo = -1
if (this.combo >= 1) playSound(combobreak)
this.combo = -1;
}
// Back to back sequence
if ((nbClearedLines == 4) || (tSpin && nbClearedLines)) {
this.b2b++
if (clearedLines == 4 || (tSpin && clearedLines)) {
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 EN 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 EN 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 (nbClearedLines && !tSpin ) {
} else if (clearedLines && !tSpin) {
if (this.b2b >= 1) {
messagesSpan.addNewChild("div", {
className: "zoom-in-animation",
style: "animation-delay: .4s",
innerHTML: `FIN DU BOUT EN BOUT`
})
messagesSpan.addNewChild('div', {
className: 'zoom-in-animation',
style: 'animation-delay: .4s',
innerHTML: `FIN DU BOUT À BOUT`,
});
playSound(btb_break)
}
this.b2b = -1
this.b2b = -1;
}
// Sound
if (sfxVolumeRange.value) {
if (nbClearedLines == 4) playSound(quatuorSound, this.combo)
else if (nbClearedLines) playSound(lineClearSound, this.combo)
if (tSpin) playSound(tSpinSound, this.combo)
}
// Sounds
if (clearedLines == 4 || (tSpin && clearedLines)) {
if (this.b2b >= 1) switch(this.b2b) {
case 1: playSound(btb_1); break
case 2: playSound(btb_2); break
default: playSound(btb_3)
} else if (this.combo >= 1) switch(this.combo) {
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 if (clearedLines == 4) playSound(clearbtb);
else playSound(clearspin);
} else if (this.combo >= 1) switch(this.combo) {
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)
} else if (tSpin) {
if (clearedLines) playSound(clearspin);
else playSound(spin);
} else if (clearedLines) playSound(clearline);
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 = Math.pow(5/4, note)
sound.play()
}
function playSound(sound, note = 0) {
sound.currentTime = 0;
sound.playbackRate = Math.pow(5 / 4, note);
sound.play();
}
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
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