Compare commits
4 Commits
ae8dcb7077
...
90eb3247e0
Author | SHA1 | Date | |
---|---|---|---|
90eb3247e0 | |||
2a25dbe4b0 | |||
d9397c4bcb | |||
ca93423bf8 |
8
app.js
8
app.js
@ -1,10 +1,10 @@
|
||||
import * as THREE from 'three'
|
||||
import { scheduler } from './jsm/scheduler.js'
|
||||
import { TRANSLATION, ROTATION, environment, Mino, Playfield, HoldQueue, NextQueue } from './jsm/Tetrominoes.js'
|
||||
import { Settings } from './jsm/Settings.js'
|
||||
import Settings from './jsm/Settings.js'
|
||||
import { Stats } from './jsm/Stats.js'
|
||||
import { TetraGUI } from './jsm/TetraGUI.js'
|
||||
import { TetraControls } from './jsm/TetraControls.js'
|
||||
import TetraControls from './jsm/TetraControls.js'
|
||||
import { TetraScene } from './jsm/TetraScene.js'
|
||||
|
||||
|
||||
@ -277,7 +277,7 @@ renderer.domElement.tabIndex = 1
|
||||
|
||||
let loadingManager = new THREE.LoadingManager(
|
||||
function() {
|
||||
loaddingCircle.style.display = "none"
|
||||
loadingDiv.style.display = "none"
|
||||
gui.startButton.show()
|
||||
renderer.setAnimationLoop(animate)
|
||||
},
|
||||
@ -290,7 +290,7 @@ let loadingManager = new THREE.LoadingManager(
|
||||
)
|
||||
loadingManager.onStart = function (url, itemsLoaded, itemsTotal) {
|
||||
loadingPercent.innerText = "0%"
|
||||
loaddingCircle.style.display = "block"
|
||||
loadingDiv.style.display = "block"
|
||||
}
|
||||
|
||||
const stats = new Stats()
|
||||
|
311
css/loading.css
311
css/loading.css
@ -1,279 +1,64 @@
|
||||
@-webkit-keyframes outerRotate1 {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
}
|
||||
body { background-color: black; }
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(360deg);
|
||||
}
|
||||
#loadingDiv {
|
||||
box-sizing: border-box;
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-size: 1.4rem;
|
||||
color: hsla(240, 100%, 70%, 0.6);
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@-moz-keyframes outerRotate1 {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(360deg);
|
||||
}
|
||||
.scene {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
margin: auto;
|
||||
perspective: 200px;
|
||||
}
|
||||
|
||||
@-o-keyframes outerRotate1 {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(360deg);
|
||||
}
|
||||
.cube {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
transform-style: preserve-3d;
|
||||
transform: translateZ(20px);
|
||||
left: 80px;
|
||||
top: 80px;
|
||||
}
|
||||
|
||||
@keyframes outerRotate1 {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(360deg);
|
||||
}
|
||||
.cube.is-spinning {
|
||||
animation: spinCube 5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
@-webkit-keyframes outerRotate2 {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(-360deg);
|
||||
}
|
||||
@keyframes spinCube {
|
||||
0% { transform: translateZ(20px) rotateX( 0deg) rotateY( 0deg) rotateZ( 0deg); }
|
||||
100% { transform: translateZ(20px) rotateX(360deg) rotateY( 0deg) rotateZ(360deg); }
|
||||
}
|
||||
|
||||
@-moz-keyframes outerRotate2 {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(-360deg);
|
||||
}
|
||||
.face {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
background: hsla(240, 100%, 0%, 0.4);
|
||||
border: 1px solid hsla(240, 100%, 70%, 0.6);
|
||||
}
|
||||
|
||||
@-o-keyframes outerRotate2 {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
}
|
||||
.front { transform: rotateY( 0deg) translateZ(20px); }
|
||||
.right { transform: rotateY( 90deg) translateZ(20px); }
|
||||
.back { transform: rotateY(180deg) translateZ(20px); }
|
||||
.left { transform: rotateY(-90deg) translateZ(20px); }
|
||||
.top { transform: rotateX( 90deg) translateZ(20px); }
|
||||
.bottom { transform: rotateX(-90deg) translateZ(20px); }
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(-360deg);
|
||||
}
|
||||
.cube.is-backface-hidden .face {
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
@keyframes outerRotate2 {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes textColour {
|
||||
0% {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
100% {
|
||||
color: #3BB2D0;
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes textColour {
|
||||
0% {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
100% {
|
||||
color: #3BB2D0;
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes textColour {
|
||||
0% {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
100% {
|
||||
color: #3BB2D0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes textColour {
|
||||
0% {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
100% {
|
||||
color: #3BB2D0;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #222;
|
||||
}
|
||||
|
||||
#loaddingCircle {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
cursor: progress;
|
||||
}
|
||||
|
||||
.e-loadholder {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-51%, -50%);
|
||||
-moz-transform: translate(-51%, -50%);
|
||||
-ms-transform: translate(-51%, -50%);
|
||||
-o-transform: translate(-51%, -50%);
|
||||
transform: translate(-51%, -50%);
|
||||
width: 240px;
|
||||
height: 240px;
|
||||
border: 5px solid #1B5F70;
|
||||
border-radius: 120px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.e-loadholder:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-51%, -50%);
|
||||
-moz-transform: translate(-51%, -50%);
|
||||
-ms-transform: translate(-51%, -50%);
|
||||
-o-transform: translate(-51%, -50%);
|
||||
transform: translate(-51%, -50%);
|
||||
content: " ";
|
||||
display: block;
|
||||
background: #222;
|
||||
transform-origin: center;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.e-loadholder:after {
|
||||
width: 100px;
|
||||
height: 200%;
|
||||
-webkit-animation: outerRotate2 30s infinite linear;
|
||||
-moz-animation: outerRotate2 30s infinite linear;
|
||||
-o-animation: outerRotate2 30s infinite linear;
|
||||
animation: outerRotate2 30s infinite linear;
|
||||
}
|
||||
|
||||
.e-loadholder .m-loader {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-51%, -50%);
|
||||
-moz-transform: translate(-51%, -50%);
|
||||
-ms-transform: translate(-51%, -50%);
|
||||
-o-transform: translate(-51%, -50%);
|
||||
transform: translate(-51%, -50%);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
color: #888;
|
||||
text-align: center;
|
||||
border: 5px solid #2a93ae;
|
||||
border-radius: 100px;
|
||||
box-sizing: border-box;
|
||||
z-index: 20;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.e-loadholder .m-loader:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-51%, -50%);
|
||||
-moz-transform: translate(-51%, -50%);
|
||||
-ms-transform: translate(-51%, -50%);
|
||||
-o-transform: translate(-51%, -50%);
|
||||
transform: translate(-51%, -50%);
|
||||
content: " ";
|
||||
display: block;
|
||||
background: #222;
|
||||
transform-origin: center;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.e-loadholder .m-loader:after {
|
||||
width: 100px;
|
||||
height: 106%;
|
||||
-webkit-animation: outerRotate1 15s infinite linear;
|
||||
-moz-animation: outerRotate1 15s infinite linear;
|
||||
-o-animation: outerRotate1 15s infinite linear;
|
||||
animation: outerRotate1 15s infinite linear;
|
||||
}
|
||||
|
||||
.e-loadholder .m-loader .e-text {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-size: 10px;
|
||||
font-size: 1rem;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-51%, -50%);
|
||||
-moz-transform: translate(-51%, -50%);
|
||||
-ms-transform: translate(-51%, -50%);
|
||||
-o-transform: translate(-51%, -50%);
|
||||
transform: translate(-51%, -50%);
|
||||
-webkit-animation: textColour 1s alternate linear infinite;
|
||||
-moz-animation: textColour 1s alternate linear infinite;
|
||||
-o-animation: textColour 1s alternate linear infinite;
|
||||
animation: textColour 1s alternate linear infinite;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
text-align: center;
|
||||
border: 5px solid #3bb2d0;
|
||||
border-radius: 70px;
|
||||
box-sizing: border-box;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.e-loadholder .m-loader .e-text:before, .e-loadholder .m-loader .e-text:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-51%, -50%);
|
||||
-moz-transform: translate(-51%, -50%);
|
||||
-ms-transform: translate(-51%, -50%);
|
||||
-o-transform: translate(-51%, -50%);
|
||||
transform: translate(-51%, -50%);
|
||||
content: " ";
|
||||
display: block;
|
||||
background: #222;
|
||||
transform-origin: center;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.e-loadholder .m-loader .e-text:before {
|
||||
width: 110%;
|
||||
height: 40px;
|
||||
-webkit-animation: outerRotate2 3.5s infinite linear;
|
||||
-moz-animation: outerRotate2 3.5s infinite linear;
|
||||
-o-animation: outerRotate2 3.5s infinite linear;
|
||||
animation: outerRotate2 3.5s infinite linear;
|
||||
}
|
||||
|
||||
.e-loadholder .m-loader .e-text:after {
|
||||
width: 40px;
|
||||
height: 110%;
|
||||
-webkit-animation: outerRotate1 8s infinite linear;
|
||||
-moz-animation: outerRotate1 8s infinite linear;
|
||||
-o-animation: outerRotate1 8s infinite linear;
|
||||
animation: outerRotate1 8s infinite linear;
|
||||
}
|
||||
.mino0 { left: -40px; top: -20px; }
|
||||
.mino1 { left: 0px; top: -20px; }
|
||||
.mino2 { left: 40px; top: -20px; }
|
||||
.mino3 { left: 0px; top: 20px; }
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 792 B After Width: | Height: | Size: 761 B |
38
index.html
38
index.html
@ -20,15 +20,39 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="loaddingCircle">
|
||||
<div class="e-loadholder">
|
||||
<div class="m-loader">
|
||||
<span class="e-text">
|
||||
<div id="loadingDiv">
|
||||
<div class="scene">
|
||||
<div class="cube is-spinning">
|
||||
<div class="mino0 front face"></div>
|
||||
<div class="mino0 back face"></div>
|
||||
<div class="mino0 right face"></div>
|
||||
<div class="mino0 left face"></div>
|
||||
<div class="mino0 top face"></div>
|
||||
<div class="mino0 bottom face"></div>
|
||||
<div class="mino1 front face"></div>
|
||||
<div class="mino1 back face"></div>
|
||||
<div class="mino1 right face"></div>
|
||||
<div class="mino1 left face"></div>
|
||||
<div class="mino1 top face"></div>
|
||||
<div class="mino1 bottom face"></div>
|
||||
<div class="mino2 front face"></div>
|
||||
<div class="mino2 back face"></div>
|
||||
<div class="mino2 right face"></div>
|
||||
<div class="mino2 left face"></div>
|
||||
<div class="mino2 top face"></div>
|
||||
<div class="mino2 bottom face"></div>
|
||||
<div class="mino3 front face"></div>
|
||||
<div class="mino3 back face"></div>
|
||||
<div class="mino3 right face"></div>
|
||||
<div class="mino3 left face"></div>
|
||||
<div class="mino3 top face"></div>
|
||||
<div class="mino3 bottom face"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>Chargement</div>
|
||||
<div id="loadingPercent">0%</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span id="messagesSpan"></span>
|
||||
<span id="pauseSpan" tabindex="1">II</span>
|
||||
|
@ -27,7 +27,7 @@ let friendyKeyRenamer = new Proxy({
|
||||
}
|
||||
})
|
||||
|
||||
class Settings {
|
||||
export default class Settings {
|
||||
constructor() {
|
||||
this.startLevel = 1
|
||||
|
||||
@ -79,7 +79,4 @@ class Settings {
|
||||
|
||||
this.theme = "Plasma"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export { Settings }
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
|
||||
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
|
||||
|
||||
|
||||
class TetraControls extends OrbitControls {
|
||||
export default class TetraControls extends OrbitControls {
|
||||
constructor(camera, domElement) {
|
||||
super(camera, domElement)
|
||||
this.autoRotate
|
||||
@ -10,7 +9,7 @@ class TetraControls extends OrbitControls {
|
||||
this.dampingFactor = 0.04
|
||||
this.maxDistance = 21
|
||||
this.keys = {}
|
||||
this.minPolarAngle = 1
|
||||
this.minPolarAngle = 1.05
|
||||
this.maxPolarAngle = 2.1
|
||||
this.minAzimuthAngle = 0.9 - Math.PI / 2
|
||||
this.maxAzimuthAngle = 2.14 - Math.PI / 2
|
||||
@ -19,6 +18,4 @@ class TetraControls extends OrbitControls {
|
||||
this.addEventListener("start", () => domElement.style.cursor = "grabbing")
|
||||
this.addEventListener("end", () => domElement.style.cursor = "grab")
|
||||
}
|
||||
}
|
||||
|
||||
export { TetraControls }
|
||||
}
|
@ -91,7 +91,8 @@ class InstancedMino extends THREE.InstancedMesh {
|
||||
}
|
||||
|
||||
setOffsetAt(index, offset) {
|
||||
this.offsets[index * 2] = offset
|
||||
this.offsets[2*index] = offset.x
|
||||
this.offsets[2*index + 1] = offset.y
|
||||
}
|
||||
|
||||
resetColor() {
|
||||
@ -136,9 +137,9 @@ class Mino extends THREE.Object3D {
|
||||
envMap: environment,
|
||||
side: THREE.DoubleSide,
|
||||
transparent: true,
|
||||
opacity: 0.8,
|
||||
roughness: 0.48,
|
||||
metalness: 0.67,
|
||||
opacity: 0.7,
|
||||
roughness: 0.5,
|
||||
metalness: 1,
|
||||
}),
|
||||
Espace: new THREE.MeshStandardMaterial({
|
||||
envMap: environment,
|
||||
@ -295,7 +296,7 @@ class Tetromino extends THREE.Group {
|
||||
}
|
||||
Tetromino.prototype.lockingColor = new THREE.Color(COLORS.LOCKING)
|
||||
// Super Rotation System
|
||||
// freedom of movement = srs[this.parent.piece.facing][rotation]
|
||||
// freedom of movement = srs[this.facing][rotation]
|
||||
Tetromino.prototype.srs = [
|
||||
{ [ROTATION.CW]: [P(0, 0), P(-1, 0), P(-1, 1), P(0, -2), P(-1, -2)], [ROTATION.CCW]: [P(0, 0), P(1, 0), P(1, 1), P(0, -2), P(1, -2)] },
|
||||
{ [ROTATION.CW]: [P(0, 0), P(1, 0), P(1, -1), P(0, 2), P(1, 2)], [ROTATION.CCW]: [P(0, 0), P(1, 0), P(1, -1), P(0, 2), P(1, 2)] },
|
||||
@ -309,7 +310,7 @@ class Ghost extends Tetromino {
|
||||
copy(piece) {
|
||||
this.position.copy(piece.position)
|
||||
this.minoesPosition = piece.minoesPosition
|
||||
//this.children.forEach(mino => mino.offset = piece.offset)
|
||||
this.children.forEach(mino => {mino.offset = piece.ghostOffset})
|
||||
this.facing = piece.facing
|
||||
this.visible = true
|
||||
while (this.canMove(TRANSLATION.DOWN)) this.position.y--
|
||||
@ -319,7 +320,6 @@ Ghost.prototype.freeColor = new THREE.Color(COLORS.GHOST)
|
||||
Ghost.prototype.minoesPosition = [
|
||||
[P(0, 0, 0), P(0, 0, 0), P(0, 0, 0), P(0, 0, 0)],
|
||||
]
|
||||
Ghost.prototype.offset = 0
|
||||
|
||||
|
||||
class I extends Tetromino { }
|
||||
@ -336,7 +336,8 @@ I.prototype.srs = [
|
||||
{ [ROTATION.CW]: [P(0, 0), P(1, 0), P(-2, 0), P(1, -2), P(-2, 1)], [ROTATION.CCW]: [P(0, 0), P(-2, 0), P(1, 0), P(-2, -1), P(1, 2)] },
|
||||
]
|
||||
I.prototype.freeColor = new THREE.Color(COLORS.I)
|
||||
I.prototype.offset = 1
|
||||
I.prototype.offset = P(0, 1)
|
||||
I.prototype.ghostOffset = P(0, 0)
|
||||
|
||||
class J extends Tetromino { }
|
||||
J.prototype.minoesPosition = [
|
||||
@ -346,7 +347,8 @@ J.prototype.minoesPosition = [
|
||||
[P(0, 1), P(-1, -1), P(0, 0), P(0, -1)],
|
||||
]
|
||||
J.prototype.freeColor = new THREE.Color(COLORS.J)
|
||||
J.prototype.offset = 2
|
||||
J.prototype.offset = P(1, 1)
|
||||
J.prototype.ghostOffset = P(1, 0)
|
||||
|
||||
class L extends Tetromino {
|
||||
}
|
||||
@ -357,7 +359,8 @@ L.prototype.minoesPosition = [
|
||||
[P(0, 1), P(0, 0), P(0, -1), P(-1, 1)],
|
||||
]
|
||||
L.prototype.freeColor = new THREE.Color(COLORS.L)
|
||||
L.prototype.offset = 3
|
||||
L.prototype.offset = P(2, 1)
|
||||
L.prototype.ghostOffset = P(2, 0)
|
||||
|
||||
class O extends Tetromino { }
|
||||
O.prototype.minoesPosition = [
|
||||
@ -367,7 +370,8 @@ O.prototype.srs = [
|
||||
{ [ROTATION.CW]: [], [ROTATION.CCW]: [] }
|
||||
]
|
||||
O.prototype.freeColor = new THREE.Color(COLORS.O)
|
||||
O.prototype.offset = 4
|
||||
O.prototype.offset = P(3, 1)
|
||||
O.prototype.ghostOffset = P(3, 0)
|
||||
|
||||
class S extends Tetromino { }
|
||||
S.prototype.minoesPosition = [
|
||||
@ -377,7 +381,8 @@ S.prototype.minoesPosition = [
|
||||
[P(-1, 1), P(0, 0), P(-1, 0), P(0, -1)],
|
||||
]
|
||||
S.prototype.freeColor = new THREE.Color(COLORS.S)
|
||||
S.prototype.offset = 5
|
||||
S.prototype.offset = P(4, 1)
|
||||
S.prototype.ghostOffset = P(4, 0)
|
||||
|
||||
class T extends Tetromino {
|
||||
get tSpin() {
|
||||
@ -405,7 +410,8 @@ T.prototype.tSlots = [
|
||||
[P(-1, -1), P(-1, 1), P(1, 1), P(1, -1)],
|
||||
]
|
||||
T.prototype.freeColor = new THREE.Color(COLORS.T)
|
||||
T.prototype.offset = 6
|
||||
T.prototype.offset = P(5, 1)
|
||||
T.prototype.ghostOffset = P(5, 0)
|
||||
|
||||
class Z extends Tetromino { }
|
||||
Z.prototype.minoesPosition = [
|
||||
@ -415,7 +421,8 @@ Z.prototype.minoesPosition = [
|
||||
[P(0, 1), P(-1, 0), P(0, 0), P(-1, -1)]
|
||||
]
|
||||
Z.prototype.freeColor = new THREE.Color(COLORS.Z)
|
||||
Z.prototype.offset = 7
|
||||
Z.prototype.offset = P(6, 1)
|
||||
Z.prototype.ghostOffset = P(6, 0)
|
||||
|
||||
|
||||
class Playfield extends THREE.Group {
|
||||
|
@ -33,6 +33,4 @@ class Scheduler {
|
||||
}
|
||||
|
||||
|
||||
const scheduler = new Scheduler()
|
||||
|
||||
export { scheduler }
|
||||
export const scheduler = new Scheduler()
|
Loading…
x
Reference in New Issue
Block a user