12 Commits

Author SHA1 Message Date
cf2420d544 spinend sound 2026-03-27 08:29:13 +01:00
06100377c9 speak 2026-03-27 01:07:52 +01:00
df0944f309 countdown 2026-03-27 00:56:09 +01:00
f87af4fa7e swap stats th and td 2026-03-18 01:56:27 +01:00
980715c72f save both skins 2026-03-18 01:38:43 +01:00
81b243bd85 hard drop rotation 2026-03-16 13:30:20 +01:00
4320b46e37 group tetr.io skins by authors 2026-03-14 17:53:56 +01:00
b2738f6923 game over sound 2026-03-12 09:32:37 +01:00
7730d72315 improve sounds 2026-03-12 09:25:51 +01:00
56ed3b5c13 if (sfxVolumeRange.value) 2026-03-12 03:13:28 +01:00
6706d60086 more sounds 2026-03-12 02:41:08 +01:00
040dc5d5e9 round 2026-03-11 19:52:19 +01:00
101 changed files with 751 additions and 14116 deletions

View File

@@ -11,7 +11,7 @@ body {
@supports (backdrop-filter: blur()) {
.modal::before {
content: "";
content: '';
position: absolute;
top: 0;
bottom: 0;
@@ -30,8 +30,12 @@ body {
background-color: #25292d;
}
#statsTable th {
text-align: right;
}
#matrixCard {
background-image: radial-gradient(#222, #25292d)
background-image: radial-gradient(#222, #25292d);
}
.card-header {
@@ -43,18 +47,13 @@ body {
font-weight: 600;
}
#statsTable td,
#statsModal td {
text-align: right;
}
td#timeCell {
min-width: 10ch;
}
.minoes-table {
--piece-column: 0;
--piece-row : 0;
--piece-row: 0;
table-layout: fixed;
border-collapse: separate;
border-spacing: 0;
@@ -71,7 +70,7 @@ td#timeCell {
}
}
.hard-dropped-table-animation {
animation: hard-dropped-table-animation ease-in-out .2s;
animation: hard-dropped-table-animation ease-in-out 0.2s;
}
tr.buffer-zone td:not(.mino) {
@@ -79,9 +78,9 @@ 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;
}
@@ -113,26 +112,32 @@ td {
}
td.trail-animation {
animation: trail-animation ease-out .3s;
animation: trail-animation ease-out 0.3s;
}
@keyframes cleared-line-animation {
from {
background-color: white;
filter: saturate(50%) brightness(300%);
box-shadow: 0 0 0 #adb5bd, 0 0 0 #adb5bd;
box-shadow:
0 0 0 #adb5bd,
0 0 0 #adb5bd;
}
60% {
box-shadow: -60px 0 2px #adb5bd66, 60px 0 2px #adb5bd66;
box-shadow:
-60px 0 2px #adb5bd66,
60px 0 2px #adb5bd66;
}
to {
background-color: transparent;
box-shadow: -100px 0 5px transparent, 100px 0 5px transparent;
box-shadow:
-100px 0 5px transparent,
100px 0 5px transparent;
}
}
tr.cleared-line-animation {
animation: cleared-line-animation ease-out .3s;
animation: cleared-line-animation ease-out 0.3s;
}
#holdTable .J,
@@ -150,9 +155,12 @@ tr.cleared-line-animation {
#messagesSpan {
position: absolute;
top: 5%;
top: 0;
left: 50%;
transform: translate(-50%, 0);
padding-top: 5%;
width: 100%;
height: 100%;
color: #fffc;
text-shadow: 1px 1px #000c;
font-size: 3vmin;
@@ -165,6 +173,31 @@ tr.cleared-line-animation {
overflow: hidden;
}
@keyframes countdown-animation {
from {
opacity: 0;
}
50% {
opacity: 100%;
}
to {
opacity: 0;
font-size: 20vmin;
}
}
#messagesSpan div.countdown-animation {
animation: countdown-animation;
animation-timing-function: ease-in-out;
animation-duration: .5s;
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: -5%;
align-content: center;
}
@keyframes show-level-animation {
from {
opacity: 0;
@@ -177,7 +210,7 @@ tr.cleared-line-animation {
}
to {
opacity: 0;
transform: translateY(-100%) scaleY(0);
transform: translateY(-50%) scaleY(0);
line-height: 0;
}
}
@@ -193,7 +226,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;
@@ -213,13 +245,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% {
@@ -236,14 +268,14 @@ tr.cleared-line-animation {
#messagesSpan div.rotate-in-animation {
animation-name: rotate-in-animation;
animation-timing-function: cubic-bezier(.25,.46,.45,.94);
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;
}
@@ -269,20 +301,22 @@ tr.cleared-line-animation {
border-collapse: collapse;
}
#statsModal th {
#statsModal td {
padding-left: 0;
padding-right: 0.5rem;
padding-bottom: 0.2rem;
border-left: 0.5rem solid transparent;
border-right: 0;
width: max-content;
}
#statsModal td {
#statsModal th {
padding-left: 0.5rem;
padding-right: 0;
padding-bottom: 0.2rem;
border-left: 0;
border-right: 0.5rem solid transparent;
text-align: right;
}
#statsModal tr:last-child th,

View File

@@ -1,9 +1,9 @@
body {
background-image: url("electro/bg.jpg");
background-image: url('electro/bg.jpg');
background-size: cover;
}
body[data-bs-theme="dark"] {
body[data-bs-theme='dark'] {
--bs-body-bg: #2125296b;
}
@@ -16,7 +16,7 @@ body[data-bs-theme="dark"] {
}
tr.matrix td:not(.mino) {
border-left : none;
border-left: none;
border-bottom: none;
}
@@ -30,19 +30,20 @@ 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%);
rgba(10, 159, 218, 0.9) 150%
);
mask:
linear-gradient(#666 0 0) content-box,
linear-gradient(#fff 0 0);
@@ -52,7 +53,7 @@ tr.matrix td:not(.mino) {
.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%);
}

View File

@@ -7,7 +7,7 @@ body {
gap: 0 !important;
margin: 0;
text-transform: uppercase;
letter-spacing: .1em;
letter-spacing: 0.1em;
}
#screenRow {
@@ -26,7 +26,7 @@ body {
}
.card-header,
.card-header th{
.card-header th {
background: transparent;
font-weight: 400 !important;
font-size: 1.3em;
@@ -40,12 +40,7 @@ body {
.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(5px 8px 0 rgba(9, 9, 9, 22%));
}
.minoes-table tr {
@@ -104,16 +99,13 @@ td#timeCell {
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));
border: none !important;
}
.mino {
@@ -122,59 +114,47 @@ tr.matrix td:not(.mino) {
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;
background-color: #42afe1;
--box-shadow-color: #6ceaff;
}
.J.mino {
background-color: #1165B5;
border-color: #339BFF;
--box-shadow-color: #339BFF;
background-color: #1165b5;
--box-shadow-color: #339bff;
}
.L.mino {
background-color: #F38927;
border-color: #FFBA59;
--box-shadow-color: #FFBA59;
background-color: #f38927;
--box-shadow-color: #ffba59;
}
.O.mino {
background-color: #F6D03C;
border-color: #FFFF7F;
--box-shadow-color: #FFFF7F;
background-color: #f6d03c;
--box-shadow-color: #ffff7f;
}
.S.mino {
background-color: #32ee3e;
border-color: #84F880;
--box-shadow-color: #84F880;
--box-shadow-color: #84f880;
}
.T.mino {
background-color: #9739A2;
border-color: #D958E9;
--box-shadow-color: #D958E9;
background-color: #9739a2;
--box-shadow-color: #d958e9;
}
.Z.mino {
background-color: #EB4F65;
border-color: #FF7F79;
--box-shadow-color: #FF7F79;
background-color: #eb4f65;
--box-shadow-color: #ff7f79;
}
.ghost.mino {
background-color: #fff4;
border: none;
opacity: 5%;
box-shadow: none;
transform: translateY(-3px);
}
.moving.mino {
@@ -192,7 +172,6 @@ tr.matrix td:not(.mino) {
.disabled.mino {
filter: brightness(50%) contrast(65%);
opacity: 70%;
}
@keyframes locked-animation {
@@ -200,22 +179,3 @@ tr.matrix td:not(.mino) {
filter: saturate(50%) brightness(300%);
}
}
@keyframes cleared-line-animation {
from {
background-color: #eeeeee;
}
to {
background-color: transparent;
}
}
@keyframes trail-animation {
from {
background-color: #ceffff05;
filter: saturate(50%) brightness(110%);
}
to {
background-color: transparent;
}
}

View File

@@ -46,7 +46,7 @@ tr.matrix td:not(.mino) {
.L.mino {
background-color: #fa9b23;
--box-shadow-color: #FFBA59;
--box-shadow-color: #ffba59;
}
.O.mino {
@@ -56,7 +56,7 @@ tr.matrix td:not(.mino) {
.S.mino {
background-color: #01a493;
--box-shadow-color: #03e7d3;;
--box-shadow-color: #03e7d3;
}
.T.mino {
@@ -66,7 +66,7 @@ tr.matrix td:not(.mino) {
.Z.mino {
background-color: #ee2b58;
--box-shadow-color: #fd4487;;
--box-shadow-color: #fd4487;
}
.ghost.mino {

View File

@@ -1,6 +1,6 @@
:root {
--cell-size: 24px;
--sprite-size: calc(100% / 8);
--sprite-size: round(100% / 8, 1px);
--skin-url: url(https://i.imgur.com/HqGYC5G.png);
}
@@ -75,21 +75,7 @@ tr.matrix td:not(.mino) {
box-shadow: 4px 4px 10px #0002;
}
.option {
display: inline-block;
.preview {
--cell-size: 24px;
height: var(--cell-size);
}
.result {
--nb-sprites: 9;
}
.select2-container:not(.select2-container--disabled) .selection {
--nb-sprites: 4;
--sprite-pos: 4;
width: calc(var(--nb-sprites) * var(--cell-size));
background-position-x: calc(-1 * var(--sprite-pos) * var(--cell-size));
background-image: var(--skin-url);
background-size: cover;
background-repeat: no-repeat;
}

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 {
@@ -41,38 +37,38 @@ tr.matrix td:not(.mino) {
}
.I.mino {
--background-color: #42AFE1;
--box-shadow-color: #6CEAFF;
--background-color: #42afe1;
--box-shadow-color: #6ceaff;
}
.J.mino {
--background-color: #1165B5;
--box-shadow-color: #339BFF;
--background-color: #1165b5;
--box-shadow-color: #339bff;
}
.L.mino {
--background-color: #F38927;
--box-shadow-color: #FFBA59;
--background-color: #f38927;
--box-shadow-color: #ffba59;
}
.O.mino {
--background-color: #F6D03C;
--box-shadow-color: #FFFF7F;
--background-color: #f6d03c;
--box-shadow-color: #ffff7f;
}
.S.mino {
--background-color: #51B84D;
--box-shadow-color: #84F880;
--background-color: #51b84d;
--box-shadow-color: #84f880;
}
.T.mino {
--background-color: #9739A2;
--box-shadow-color: #D958E9;
--background-color: #9739a2;
--box-shadow-color: #d958e9;
}
.Z.mino {
--background-color: #EB4F65;
--box-shadow-color: #FF7F79;
--background-color: #eb4f65;
--box-shadow-color: #ff7f79;
}
.ghost.mino {
@@ -87,7 +83,7 @@ tr.matrix td:not(.mino) {
.locking.mino {
--background-color: white;
--box-shadow-color: #DDD;
--box-shadow-color: #ddd;
}
.locked.mino {

View File

@@ -4,12 +4,12 @@
}
@font-face {
font-family: "Early GameBoy";
src: url("old-school/Early GameBoy.ttf");
font-family: 'Early GameBoy';
src: url('old-school/Early GameBoy.ttf');
}
#screenRow {
background-image: url("old-school/bg.png");
background-image: url('old-school/bg.png');
background-size: 10px;
padding: 40px 20px;
border: 3px inset black;
@@ -21,9 +21,9 @@
}
.card {
background: #8D8E04;
background: #8d8e04;
border-radius: 0;
border-image-source: url("old-school/border-sm.png");
border-image-source: url('old-school/border-sm.png');
border-image-slice: 25;
border-image-width: 13px;
border-image-repeat: repeat;
@@ -33,12 +33,12 @@
}
.card-header {
background: #8D8E04;
background: #8d8e04;
}
#matrixCard {
background: #808302;
border-image-source: url("old-school/border-lg.png");
border-image-source: url('old-school/border-lg.png');
border-image-slice: 30;
border-image-width: 15px;
border-image-outset: 15px;
@@ -48,16 +48,18 @@
.card,
.card-header,
#messagesSpan div {
font-family: "Early GameBoy", monospace;
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%);
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;
font-size: 0.7em;
letter-spacing: -0.1em;
}
#statsTable tr {
@@ -68,7 +70,7 @@
#statsTable th,
#statsTable td {
border: 0;
padding: 0 .2rem;
padding: 0 0.2rem;
}
#statsTable td {
@@ -77,7 +79,11 @@
}
#messagesSpan {
text-shadow: -2px -2px #808302, -2px 2px #808302, 2px -2px #808302, 2px 2px #808302;
text-shadow:
-2px -2px #808302,
-2px 2px #808302,
2px -2px #808302,
2px 2px #808302;
}
.minoes-table td {
@@ -85,9 +91,11 @@
}
.mino {
box-shadow: -2px -2px 5px rgba(0, 0, 0, 40%), 1px 1px 2px rgba(0, 0, 0, 40%);
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-image: url('old-school/sprites.png');
background-position: calc(var(--sprite-pos) * var(--sprite-size)) 0px;
}
@@ -139,18 +147,25 @@
}
.hard-dropped-table-animation {
animation: hard-dropped-table-animation steps(1) .2s;
animation: hard-dropped-table-animation steps(1) 0.2s;
}
@keyframes cleared-line-animation {
10%, 30%, 50%, 70%, 90% {
10%,
30%,
50%,
70%,
90% {
opacity: 0;
}
20%, 40%, 60%, 80% {
20%,
40%,
60%,
80% {
opacity: 100%;
}
}
tr.cleared-line-animation {
animation: cleared-line-animation ease-out .4s;
animation: cleared-line-animation ease-out 0.4s;
}

View File

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

View File

@@ -6,8 +6,10 @@
}
body {
background-image: url(stereo/bg.jpg),
radial-gradient(circle at center,
background-image:
url(stereo/bg.jpg),
radial-gradient(
circle at center,
#39444f 0%,
#2c323b 25%,
#293036 28%,
@@ -18,7 +20,8 @@ body {
#151519 63%,
#141418 65%,
#0f0f12 74%,
#0a0c0d 100%);
#0a0c0d 100%
);
background-repeat: space;
background-position: center;
background-size: cover;
@@ -37,7 +40,8 @@ body {
--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));
transform: translateZ(var(--tZ)) rotateX(calc((var(--rX)) * 1deg))
rotateY(calc((var(--rY)) * 1deg));
}
#sceneDiv,
@@ -66,9 +70,10 @@ body {
#matrixCard {
background-image: none;
transform-origin: bottom;
}
#screenRow .card>* {
#screenRow .card > * {
transform: translateZ(var(--cell-size));
}
@@ -79,8 +84,7 @@ body {
.card,
.card-header {
text-shadow:
calc(-0.3px * var(--rY)) calc(0.4px * var(--rX)) 5px #0008;
text-shadow: calc(-0.3px * var(--rY)) calc(0.4px * var(--rX)) 5px #0008;
}
#holdTable .mino {
@@ -160,11 +164,7 @@ tr.cleared-line-animation td::after {
/* Front face */
.mino,
td.trail-animation {
--light: calc(
1
+ (var(--light-y) * 0.3)
+ (var(--light-x) * 0.2)
);
--light: calc(1 + (var(--light-y) * 0.3) + (var(--light-x) * 0.2));
--center-x: calc(35% + var(--light-x) * 10%);
--center-y: calc(35% + var(--light-y) * 10%);
background: radial-gradient(
@@ -182,11 +182,7 @@ td.trail-animation {
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)
);
--light: calc(1.1 + (var(--light-x) * -0.2) + (var(--light-y) * 0.15));
transform: var(--t3d) rotateY(-90deg);
transform-origin: left;
}
@@ -196,11 +192,7 @@ tr.cleared-line-animation td::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)
);
--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);
@@ -217,10 +209,7 @@ tr.cleared-line-animation td::before,
.mino::after,
td.trail-animation::after,
tr.cleared-line-animation td::after {
--light: calc(
1.5
+ (var(--light-y) * 0.2)
);
--light: calc(1.5 + (var(--light-y) * 0.2));
transform: var(--t3d) rotateX(90deg);
transform-origin: top;
}
@@ -229,10 +218,7 @@ tr.cleared-line-animation td::after {
.bottom .mino::after,
.bottom td.trail-animation::after,
.bottom tr.cleared-line-animation td::after {
--light: calc(
1.1
+ (var(--light-y) * -0.3)
);
--light: calc(1.1 + (var(--light-y) * -0.3));
--center-x: calc(65% + var(--light-x) * 10%);
--center-y: calc(65% + var(--light-y) * 10%);
filter: saturate(0.95);
@@ -240,17 +226,77 @@ tr.cleared-line-animation td::after {
transform-origin: bottom;
}
.J, .J + :not(.mino) { --h: 210deg; --s: 78%; --l: 52%; --a: 0.75; }
.L, .L + :not(.mino) { --h: 28deg; --s: 85%; --l: 52%; --a: 0.75; }
.O, .O + :not(.mino) { --h: 48deg; --s: 88%; --l: 52%; --a: 0.75; }
.I, .I + :not(.mino) { --h: 200deg; --s: 70%; --l: 52%; --a: 0.75; }
.S, .S + :not(.mino) { --h: 118deg; --s: 45%; --l: 52%; --a: 0.75; }
.T, .T + :not(.mino) { --h: 293deg; --s: 48%; --l: 52%; --a: 0.75; }
.Z, .Z + :not(.mino) { --h: 352deg; --s: 75%; --l: 52%; --a: 0.75; }
.J,
.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.40; }
.locking.mino, .locking.mino + :not(.mino) { --h: 0deg; --s: 0%; --l: 92%; --a: 0.72; }
.disabled.mino, .disabled.mino + :not(.mino) { --h: 0deg; --s: 0%; --l: 45%; --a: 0.72; }
.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),
@@ -278,12 +324,21 @@ tr.cleared-line-animation td::after {
td.trail-animation::before,
td.trail-animation::after {
animation: trail-animation ease-out .3s;
animation: trail-animation ease-out 0.3s;
}
@keyframes hard-dropped-table-animation {
50% {
transform: translateY(10px) rotateX(-3deg);
}
}
@keyframes locked-animation {
from {
--h: 0deg; --s: 0%; --l: 100%; --a: 1;
--h: 0deg;
--s: 0%;
--l: 100%;
--a: 1;
box-shadow: 0 0 10px hsla(180, 100%, 100%, 0.2);
}
}
@@ -291,7 +346,7 @@ td.trail-animation::after {
.locked.mino::before,
.locked.mino::after {
animation: locked-animation;
animation-duration: .2s;
animation-duration: 0.2s;
}
@keyframes cleared-line-animation {
@@ -307,7 +362,7 @@ td.trail-animation::after {
tr.cleared-line-animation td::before,
tr.cleared-line-animation td::after {
animation: cleared-line-animation ease-out .3s;
animation: cleared-line-animation ease-out 0.3s;
}
@keyframes show-level-animation {

View File

@@ -3,7 +3,7 @@ body {
background-size: cover;
}
body[data-bs-theme="dark"] {
body[data-bs-theme='dark'] {
--bs-body-bg: #2125296b;
}
@@ -79,8 +79,8 @@ body[data-bs-theme="dark"] {
}
.Z {
--color: #E67D8666;
--border: #E67D86;
--color: #e67d8666;
--border: #e67d86;
}
.ghost {

View File

@@ -1,7 +1,7 @@
: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);
--skin-url: url(tetrio-skin/a_forest.png);
}
tr.matrix td:not(.mino) {
@@ -62,23 +62,7 @@ tr.matrix td:not(.mino) {
box-shadow: 4px 4px 10px #0002;
}
.option {
.preview {
--cell-size: 24px;
display: inline-block;
height: var(--cell-size);
}
.result {
--nb-sprites: 9;
}
.select2-container:not(.select2-container--disabled) .selection {
--padded-cell-size: calc(var(--cell-size) + 1px);
--nb-sprites: 4;
--sprite-pos: 2;
width: calc(var(--nb-sprites) * var(--padded-cell-size) - 1px);
background-position-x: calc(-1 * var(--sprite-pos) * var(--padded-cell-size));
background-image: var(--skin-url);
background-size: cover;
background-repeat: no-repeat;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -12,8 +12,9 @@
<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="stylesheet" href="css/tetrio-skin.css" title="Thème sélectionné" id="selectedStyleSheet">
<link rel="alternate stylesheet" href="css/tetrio-skin.css" title="Sample Tetr.io...">
<link rel="alternate stylesheet" href="css/jstris-skin.css" title="Sample JStris...">
<link rel="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">
@@ -21,7 +22,7 @@
<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)">
<link rel="alternate stylesheet" href="css/stereo.css" title="3D">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.1.0-rc.0/js/select2.min.js"></script>
@@ -79,8 +80,8 @@
<label for="stylesheetSelect" class="col-2 col-form-label">Thème</label>
<div class="col-4">
<select name="stylesheet" id="stylesheetSelect" class="form-select">
<option value="css/jstris-skin.css" selected>Sample JStris...</option>
<option value="css/tetrio-skin.css">Sample Tetr.io...</option>
<option value="css/tetrio-skin.css" selected>Sample Tetr.io...</option>
<option value="css/jstris-skin.css">Sample JStris...</option>
<option value="css/classic.css">Classique</option>
<option value="css/neo-classic.css">Néo-classique</option>
<option value="css/synthwave.css">Synthwave</option>
@@ -88,17 +89,19 @@
<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>
<option value="css/stereo.css">3D</option>
</select>
</div>
<div class="col-4">
<select name="skinURL" id="skinURLSelect" class="form-select"
oninput="document.documentElement.style.setProperty('--skin-url', `url(${encodeURI(this.value)})`)">
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>
<label for="sfxVolumeRange" class="col-2 col-form-label"><abbr title="Auteur des effets sonores : 25Pi25">Volume</abbr></label>
<div class="col-4 d-flex align-items-baseline">
<input name="sfxVolumeRange" id="sfxVolumeRange" class="form-range" type="range" min="0" max="1" step="any" value="0.7">
</div>
<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">
@@ -140,11 +143,11 @@
</div>
<div class="card shadow">
<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:00</td></tr>
<tr class="card-header fw-bold text-uppercase"><td>Score</td><th id="scoreCell">0</th> </tr>
<tr><td>Meilleur<br/>score</td><th id="highScoreCell"><script>document.write(Number(localStorage["highScore"]) || 0)</script></th></tr>
<tr><td>Niveau</td><th id="levelCell">0</th> </tr>
<tr><td>But</td> <th id="goalCell">0</th> </tr>
<tr><td>Temps</td> <th id="timeCell">00:00:00</th></tr>
</table>
</div>
</div>
@@ -223,11 +226,16 @@
</div>
<div class="modal-body p-0">
<table class="table mb-0">
<tr><th>Score</th> <td id="statsModalScoreCell"></td> <th>Quatuors</th> <td id="statsModalNbQuatuors"></td> </tr>
<tr><th>Meilleur score</th><td id="statsModalHighScoreCell"></td> <th>Pirouettes</th> <td id="statsModalNbTSpin"></td> </tr>
<tr><th>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>
<tr><td>Score</td> <th id="statsModalScoreCell"></th> </tr>
<tr><td>Meilleur score</td> <th id="statsModalHighScoreCell"></th> </tr>
<tr><td>Niveau</td> <th id="statsModalLevelCell"></th> </tr>
<tr><td>Temps</td> <th id="statsModalTimeCell"></th> </tr>
<tr><td>Lignes</td> <th id="statsModaltotalClearedLines"></th> </tr>
<tr><td>Lignes par minute</td> <th id="statsModaltotalClearedLinesPM"><htd></tr>
<tr><td>Quatuors</td> <th id="statsModalNbQuatuors"></th> </tr>
<tr><td>Pirouettes</td> <th id="statsModalNbTSpin"></th> </tr>
<tr><td>Plus long combo</td> <th id="statsModalMaxCombo"></th> </tr>
<tr><td>Plus long bout à bout</td><th id="statsModalMaxB2B"></th> </tr>
</table>
</div>
<div class="modal-footer">
@@ -247,11 +255,58 @@
<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="gameover" src="snd/topout.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="harddrop" src="snd/harddrop.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="hit" src="snd/hit.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="hold" src="snd/hold.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="menuconfirm" src="snd/menuconfirm.mp3" preload="auto" type="audio/mp3"></audio>
<audio id="menuhover" src="snd/menuhover.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="move" src="snd/move.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="rotate" src="snd/rotate.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="spin" src="snd/spin.ogg" preload="auto" type="audio/ogg"></audio>
<audio id="spinend" src="snd/spinend.mp3" preload="auto" type="audio/ogg"></audio>
</span>
<script src="js/game_logic.js" language="Javascript" type="text/javascript"></script>

138
js/app.js
View File

@@ -32,6 +32,7 @@ function pauseSettings() {
document.onkeydown = null;
settings.show();
playSound(menuhover)
}
function newGame(event) {
@@ -71,9 +72,31 @@ function resume(event) {
for (const sound of document.getElementsByTagName('audio'))
sound.volume = sfxVolumeRange.value;
playSound(menuconfirm)
settings.modal.hide();
settings.getInputs();
messagesSpan.addNewChild('div', {
className: 'countdown-animation',
innerHTML: "3",
})
setTimeout(() => messagesSpan.addNewChild('div', {
className: 'countdown-animation',
innerHTML: "2",
}), 1000);
setTimeout(() => messagesSpan.addNewChild('div', {
className: 'countdown-animation',
innerHTML: "1",
}), 2000);
setTimeout(() => {
messagesSpan.addNewChild('div', {
className: 'countdown-animation',
innerHTML: "GO",
})
document.onkeydown = onkeydown;
document.onkeyup = onkeyup;
@@ -82,6 +105,7 @@ function resume(event) {
if (matrix.piece) scheduler.setInterval(fall, stats.fallPeriod);
else generate();
}, 3000);
}
}
@@ -103,19 +127,19 @@ function generate(piece) {
}
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(spinend),
rotateCounterclockwise: () => matrix.piece.rotate(ROTATION.CCW),
rotateCounterclockwise: () => matrix.piece.rotate(ROTATION.CCW)? playSound(rotate) : playSound(spinend),
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);
playSound(harddrop);
while (matrix.piece.move(TRANSLATION.DOWN, ROTATION.NONE, true)) stats.score += 2;
matrixCard.classList.remove('hard-dropped-table-animation');
matrixCard.offsetHeight;
@@ -128,6 +152,7 @@ let playerActions = {
if (matrix.piece.holdEnabled) {
scheduler.clearInterval(fall);
scheduler.clearTimeout(lockDown);
playSound(hold)
let piece = matrix.piece;
piece.facing = FACING.NORTH;
@@ -250,6 +275,17 @@ function gameOver() {
playing = false;
stats.show();
playSound(gameover)
speak("Game over")
}
function speak(text) {
if (!window.speechSynthesis) return;
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = 'fr-FR';
utterance.volume = sfxVolumeRange.value;
speechSynthesis.speak(utterance);
}
window.onbeforeunload = function (event) {
@@ -318,14 +354,20 @@ sceneDiv.onwheel = function (event) {
screenRow.style.setProperty('--tZ', tZ + 'px');
};
// Skins
$.fn.select2.defaults.set("templateResult", (state) =>
state.id
? $(`<img class="option result" src="${state.id}" title="${state.text}" loading="lazy"/>`)
? $(`<img class="preview" src="${state.id}" title="${state.text}" loading="lazy"/>`)
: state.text
)
$.fn.select2.defaults.set("templateSelection", (state) =>
state.id
? $(`<span class="option selection" style="--skin-url: url(${state.id})" title="${state.text}" alt="${state.id}" loading="lazy"></span>`)
? $(`
<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")
@@ -347,12 +389,57 @@ $.fn.select2.defaults.set("createTag", function (params) {
stylesheetSelect.oninput = function (event) {
selectedStyleSheet.href = this.value;
var skinURL = skinURLSelect.value
$("#skinURLSelect").empty();
switch (this.value) {
case 'css/jstris-skin.css':
skinURLSelect.disabled = false;
case 'css/tetrio-skin.css':
localStorage[skinURLSelect.name] = skinURLSelect.value
skinURLSelect.name = "tetrioSkinURL"
$("#skinURLSelect").empty();
const baseURL = "https://you.have.fail/tetrioplus/data"
fetch(`${baseURL}/data.json`)
.then((resp) => resp.json())
.then((json) => {
json = json.filter((item) => (item.type == "skin" && item.format == "tetrioraster" && /\.(?:png|jpg|jpeg|gif|bmp|webp|svg)$/i.test(item.path)))
const groups = Map.groupBy(json, (skin) => skin.author)
var data = groups.entries().map(([author, skins]) => {
return {
text: author,
children: skins.map((skin) => {
return {
id: `${baseURL}/${encodeURI(skin.path)}`,
text: skin.description? `${skin.name}\n${skin.description}` : `${skin.name}`
}
})
}
}).toArray()
data.push({
text: "AdrienMalin",
children: [{
id: `${document.location.href}/css/tetrio-skin/a_forest.png`,
text: "A forest"
}]
})
data.sort((group1, group2) => group1.text > group2.text)
skinURLSelect.disabled = false;
$('#skinURLSelect').select2({data: data})
if (skinURL = localStorage['tetrioSkinURL']) {
if ($('#skinURLSelect').find(`option[value='${skinURL}']`).length) {
$('#skinURLSelect').val(skinURL).trigger('change');
} else {
var option = new Option('Sample sauvegardé', skinURL);
$('#skinURLSelect').append(option).trigger('change');
}
}
skinURLSelect.oninput();
})
break;
case 'css/jstris-skin.css':
localStorage[skinURLSelect.name] = skinURLSelect.value
skinURLSelect.name = "jstrisSkinURL"
$("#skinURLSelect").empty();
fetch('https://konsola5.github.io/jstris-customization-database/jstrisCustomizationDatabase.json')
.then(response => response.json())
.then(json => {
@@ -362,31 +449,24 @@ stylesheetSelect.oninput = function (event) {
text: group,
children: json[group].map(skin => ({
id: skin.link,
text: `${skin.name} (${skin.author})\n${skin.description}`,
text: `${skin.name} by ${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: `https://you.have.fail/tetrioplus/data/${skin.path}`,
text:`${skin.name} (${skin.author})`
$('#skinURLSelect').select2({data: data})
if (skinURL = localStorage['jstrisSkinURL']) {
if ($('#skinURLSelect').find(`option[value='${skinURL}']`).length) {
$('#skinURLSelect').val(skinURL).trigger('change');
} else {
var option = new Option('Sample sauvegardé', skinURL);
$('#skinURLSelect').append(option).trigger('change');
}
})
$('#skinURLSelect').select2({data: data});
})
}
skinURLSelect.oninput();
});
break;
default:

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],
@@ -282,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]

View File

@@ -37,20 +37,6 @@ class Settings {
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() {
@@ -144,8 +130,8 @@ class Stats {
levelInput.value = localStorage['startLevel'] || 1;
this.score = 0;
this.goal = 0;
this.combo = 0;
this.b2b = 0;
this.combo = -1;
this.b2b = -1;
this.startTime = new Date();
this.lockDelay = DELAY.LOCK;
this.totalClearedLines = 0;
@@ -177,6 +163,7 @@ class Stats {
}
set level(level) {
speak(`Niveau ${level}`)
this._level = level;
this.goal += level * 5;
if (level <= 20) {
@@ -231,23 +218,23 @@ class Stats {
return new Date() - this.startTime;
}
lockDown(tSpin, nbClearedLines) {
this.totalClearedLines += nbClearedLines;
if (nbClearedLines == 4) this.nbQuatuors++;
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 awardedLineClears = AWARDED_LINE_CLEARS[tSpin][clearedLines];
let patternScore = 100 * this.level * awardedLineClears;
if (tSpin)
messagesSpan.addNewChild('div', {
className: 'rotate-in-animation',
innerHTML: tSpin,
});
if (nbClearedLines)
if (clearedLines)
messagesSpan.addNewChild('div', {
className: 'zoom-in-animation',
innerHTML: CLEARED_LINES_NAMES[nbClearedLines],
innerHTML: CLEARED_LINES_NAMES[clearedLines],
});
if (patternScore) {
messagesSpan.addNewChild('div', {
@@ -259,10 +246,10 @@ class Stats {
}
// Combo
if (nbClearedLines) {
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',
@@ -279,11 +266,12 @@ class Stats {
this.score += comboScore;
}
} else {
if (this.combo >= 1) playSound(combobreak)
this.combo = -1;
}
// Back to back sequence
if (nbClearedLines == 4 || (tSpin && nbClearedLines)) {
if (clearedLines == 4 || (tSpin && clearedLines)) {
this.b2b++;
if (this.b2b >= 1) {
let b2bScore = patternScore / 2;
@@ -302,22 +290,65 @@ class Stats {
}
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 À BOUT`,
});
playSound(btb_break)
}
this.b2b = -1;
}
// Sound
// Sounds
if (sfxVolumeRange.value) {
if (nbClearedLines == 4) playSound(quatuorSound, this.combo);
else if (nbClearedLines) playSound(lineClearSound, this.combo);
if (tSpin) playSound(tSpinSound, this.combo);
if (clearedLines == 4 || (tSpin && clearedLines)) switch(this.b2b) {
case -1:
case 0: playSound(clearbtb); break
case 1: playSound(btb_1); break
case 2: playSound(btb_2); break
default: playSound(btb_3)
} else if (tSpin) switch(this.combo) {
case -1: playSound(spin); break
case 0: playSound(clearspin); break
case 1: playSound(combo_1_power); break
case 2: playSound(combo_2_power); break
case 3: playSound(combo_3_power); break
case 4: playSound(combo_4_power); break
case 5: playSound(combo_5_power); break
case 6: playSound(combo_6_power); break
case 7: playSound(combo_7_power); break
case 8: playSound(combo_8_power); break
case 9: playSound(combo_9_power); break
case 10: playSound(combo_10_power); break
case 11: playSound(combo_11_power); break
case 12: playSound(combo_12_power); break
case 13: playSound(combo_13_power); break
case 14: playSound(combo_14_power); break
case 15: playSound(combo_15_power); break
default: playSound(combo_16_power)
} else switch(this.combo) {
case -1: break;
case 0: playSound(clearline); break
case 1: playSound(combo_1); break
case 2: playSound(combo_2); break
case 3: playSound(combo_3); break
case 4: playSound(combo_4); break
case 5: playSound(combo_5); break
case 6: playSound(combo_6); break
case 7: playSound(combo_7); break
case 8: playSound(combo_8); break
case 9: playSound(combo_9); break
case 10: playSound(combo_10); break
case 11: playSound(combo_11); break
case 12: playSound(combo_12); break
case 13: playSound(combo_13); break
case 14: playSound(combo_14); break
case 15: playSound(combo_15); break
default: playSound(combo_16)
}
}
this.goal -= awardedLineClears;
@@ -355,6 +386,6 @@ Stats.prototype.timeFormat = new Intl.DateTimeFormat('fr-FR', {
function playSound(sound, note = 0) {
sound.currentTime = 0;
sound.playbackRate = Math.pow(5 / 4, note);
sound.playbackRate = note? Math.pow(5 / 4, note): 1;
sound.play();
}

File diff suppressed because it is too large Load Diff

BIN
snd/allclear.ogg Normal file

Binary file not shown.

BIN
snd/btb_1.ogg Normal file

Binary file not shown.

BIN
snd/btb_2.ogg Normal file

Binary file not shown.

BIN
snd/btb_3.ogg Normal file

Binary file not shown.

BIN
snd/btb_break.ogg Normal file

Binary file not shown.

BIN
snd/clearbtb.ogg Normal file

Binary file not shown.

BIN
snd/clearline.ogg Normal file

Binary file not shown.

BIN
snd/clearquad.ogg Normal file

Binary file not shown.

BIN
snd/clearspin.ogg Normal file

Binary file not shown.

BIN
snd/clutch.mp3 Normal file

Binary file not shown.

BIN
snd/combo_1.mp3 Normal file

Binary file not shown.

BIN
snd/combo_10.mp3 Normal file

Binary file not shown.

BIN
snd/combo_10_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_11.mp3 Normal file

Binary file not shown.

BIN
snd/combo_11_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_12.mp3 Normal file

Binary file not shown.

BIN
snd/combo_12_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_13.mp3 Normal file

Binary file not shown.

BIN
snd/combo_13_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_14.mp3 Normal file

Binary file not shown.

BIN
snd/combo_14_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_15.mp3 Normal file

Binary file not shown.

BIN
snd/combo_15_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_16.ogg Normal file

Binary file not shown.

BIN
snd/combo_16_power.ogg Normal file

Binary file not shown.

BIN
snd/combo_1_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_2.mp3 Normal file

Binary file not shown.

BIN
snd/combo_2_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_3.mp3 Normal file

Binary file not shown.

BIN
snd/combo_3_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_4.mp3 Normal file

Binary file not shown.

BIN
snd/combo_4_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_5.mp3 Normal file

Binary file not shown.

BIN
snd/combo_5_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_6.mp3 Normal file

Binary file not shown.

BIN
snd/combo_6_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_7.mp3 Normal file

Binary file not shown.

BIN
snd/combo_7_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_8.mp3 Normal file

Binary file not shown.

BIN
snd/combo_8_power.mp3 Normal file

Binary file not shown.

BIN
snd/combo_9.mp3 Normal file

Binary file not shown.

BIN
snd/combo_9_power.mp3 Normal file

Binary file not shown.

BIN
snd/combobreak.mp3 Normal file

Binary file not shown.

BIN
snd/counter.ogg Normal file

Binary file not shown.

BIN
snd/damage_alert.ogg Normal file

Binary file not shown.

BIN
snd/damage_large.ogg Normal file

Binary file not shown.

BIN
snd/damage_medium.ogg Normal file

Binary file not shown.

BIN
snd/damage_small.ogg Normal file

Binary file not shown.

BIN
snd/death.mp3 Normal file

Binary file not shown.

BIN
snd/elim.mp3 Normal file

Binary file not shown.

BIN
snd/exchange.ogg Normal file

Binary file not shown.

BIN
snd/floor.ogg Normal file

Binary file not shown.

BIN
snd/garbage_in_large.ogg Normal file

Binary file not shown.

BIN
snd/garbage_in_medium.ogg Normal file

Binary file not shown.

BIN
snd/garbage_in_small.ogg Normal file

Binary file not shown.

BIN
snd/garbage_out_large.ogg Normal file

Binary file not shown.

BIN
snd/garbage_out_medium.ogg Normal file

Binary file not shown.

BIN
snd/garbage_out_small.ogg Normal file

Binary file not shown.

BIN
snd/garbagerise.ogg Normal file

Binary file not shown.

BIN
snd/garbagesmash.ogg Normal file

Binary file not shown.

BIN
snd/harddrop.ogg Normal file

Binary file not shown.

BIN
snd/hit.mp3 Normal file

Binary file not shown.

BIN
snd/hold.ogg Normal file

Binary file not shown.

BIN
snd/hyperalert.mp3 Normal file

Binary file not shown.

BIN
snd/menuconfirm.mp3 Normal file

Binary file not shown.

BIN
snd/menuhit1.mp3 Normal file

Binary file not shown.

BIN
snd/menuhit2.mp3 Normal file

Binary file not shown.

BIN
snd/menuhit3.mp3 Normal file

Binary file not shown.

BIN
snd/menuhover.ogg Normal file

Binary file not shown.

BIN
snd/move.ogg Normal file

Binary file not shown.

BIN
snd/offset.ogg Normal file

Binary file not shown.

BIN
snd/rotate.ogg Normal file

Binary file not shown.

BIN
snd/shatter.mp3 Normal file

Binary file not shown.

BIN
snd/spin.ogg Normal file

Binary file not shown.

BIN
snd/spinend.mp3 Normal file

Binary file not shown.

BIN
snd/topout.ogg Normal file

Binary file not shown.

BIN
snd/warning.ogg Normal file

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