Compare commits

...

5 Commits

Author SHA1 Message Date
adrien a4f7ba0e08 spinend sound 2026-03-27 08:32:43 +01:00
adrien 81c49ed4ae countdown 2026-03-27 01:22:08 +01:00
adrien 18d302732c pause on fullscreen exit 2026-03-26 20:58:56 +01:00
adrien 27978c2b32 tweaks 2026-03-24 21:29:43 +01:00
adrien fc5ff692b8 move sounds 2026-03-24 08:56:19 +01:00
11 changed files with 116 additions and 83 deletions
+44 -29
View File
@@ -46,25 +46,31 @@ let game = {
},
resume: function() {
document.onkeydown = onkeydown
document.onkeyup = onkeyup
window.onblur = game.pause
menu.settings.domElement.onclick = game.pause
document.body.classList.remove("pause")
menu.resumeButton.hide()
menu.pauseButton.show()
stats.clock.start()
stats.clock.elapsedTime = stats.elapsedTime
if (settings.musicVolume) scene.music.play()
if (scene.playfield.piece) {
scheduler.resetInterval(game.fall, stats.fallPeriod)
} else {
this.generate()
}
pauseSpan.innerHTML = "3"
setTimeout(() => pauseSpan.innerHTML = "2", 1000)
setTimeout(() => pauseSpan.innerHTML = "1", 2000)
setTimeout(() => {
pauseSpan.innerHTML = ""
document.onkeydown = onkeydown
document.onkeyup = onkeyup
window.onblur = game.pause
menu.settings.domElement.onclick = game.pause
document.body.classList.remove("pause")
menu.resumeButton.hide()
menu.pauseButton.show()
stats.clock.start()
stats.clock.elapsedTime = stats.elapsedTime
if (settings.musicVolume) scene.music.play()
if (scene.playfield.piece) {
scheduler.resetInterval(game.fall, stats.fallPeriod)
} else {
this.generate()
}
}, 3000)
},
generate: function(nextPiece=nextQueue.shift()) {
@@ -122,6 +128,7 @@ let game = {
window.onblur = null
pauseSpan.onfocus = game.resume
pauseSpan.innerHTML = "II"
document.body.classList.add("pause")
menu.pauseButton.hide()
menu.resumeButton.show()
@@ -148,19 +155,20 @@ let game = {
fullscreen: function() {
if (document.fullscreenElement) {
if (document.exitFullscreen) {
document.exitFullscreen();
document.exitFullscreen()
}
} else {
document.body.requestFullscreen();
document.body.requestFullscreen()
}
}
}
document.onfullscreenchange = function() {
if (document.fullscreenElement) {
menu.settings.fullscreenButton.name("Quitter le plein écran");
menu.settings.fullscreenButton.name("Quitter le plein écran")
} else {
menu.settings.fullscreenButton.name("Plein écran");
menu.settings.fullscreenButton.name("Plein écran")
game.pause()
}
}
@@ -175,16 +183,23 @@ function playSound(sound, note=0) {
/* Handle player inputs */
let playerActions = {
moveLeft: () => scene.playfield.piece.move(TRANSLATION.LEFT),
moveLeft: () => scene.playfield.piece.move(TRANSLATION.LEFT)? scene.moveSound.play() : scene.hitSound.stop() && scene.hitSound.play(),
moveRight: () => scene.playfield.piece.move(TRANSLATION.RIGHT),
moveRight: () => scene.playfield.piece.move(TRANSLATION.RIGHT)? scene.moveSound.play() : scene.hitSound.stop() && scene.hitSound.play(),
rotateCW: () => scene.playfield.piece.rotate(ROTATION.CW),
rotateCW: () => scene.playfield.piece.rotate(ROTATION.CW)? scene.rotateSound.stop() && scene.rotateSound.play() : scene.spinEndSound.stop() && scene.spinEndSound.play(),
rotateCCW: () => scene.playfield.piece.rotate(ROTATION.CCW),
rotateCCW: () => scene.playfield.piece.rotate(ROTATION.CCW)? scene.rotateSound.stop() && scene.rotateSound.play() : scene.spinEndSound.stop() && scene.spinEndSound.play(),
softDrop: function () {
if (scene.playfield.piece.move(TRANSLATION.DOWN)) stats.score++
if (scene.playfield.piece.move(TRANSLATION.DOWN)) {
stats.score++
scene.moveSound.stop()
scene.moveSound.play()
} else {
scene.floorSound.stop()
scene.floorSound.play()
}
},
hardDrop: function () {
@@ -285,7 +300,7 @@ function resumeOnKeyDown(event) {
let loadingManager = new THREE.LoadingManager(
function() {
loadingDiv.style.display = "none"
menu.startButton.show()
if (!game.playing) menu.startButton.show()
scene.renderer.setAnimationLoop(animate)
},
function (url, itemsLoaded, itemsTotal) {
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.
+2 -2
View File
@@ -28,7 +28,7 @@
</script>
</head>
<body>
<body class="pause">
<span id="loadingDiv">
<div class="scene">
<div class="T tetromino">
@@ -72,7 +72,7 @@
</div>
</span>
<span id="messagesSpan"></span>
<span id="pauseSpan" tabindex="1">II</span>
<span id="pauseSpan" tabindex="1"></span>
<audio id="music" src="audio/benevolence.m4a" loop></audio>
<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 type="module" src="app.js"></script>
+1
View File
@@ -111,6 +111,7 @@ export class Menu extends GUI {
})
let minoMaterial = scene.minoes.material instanceof Array ? scene.minoes.material[0] : scene.minoes.material
if ("color" in minoMaterial) material.addColor(minoMaterial, "color" )
if ("opacity" in minoMaterial) material.add(minoMaterial, "opacity" ).min(0).max(1)
if ("reflectivity" in minoMaterial) material.add(minoMaterial, "reflectivity" ).min(0).max(1)
if ("roughness" in minoMaterial) material.add(minoMaterial, "roughness" ).min(0).max(1)
+31 -6
View File
@@ -47,17 +47,42 @@ export class TetraScene extends THREE.Scene {
this.lineClearSound = new THREE.Audio(listener)
audioLoader.load('audio/line-clear.ogg', function( buffer ) {
this.lineClearSound.setBuffer(buffer)
this.lineClearSound.setVolume(settings.sfxVolume/100)
}.bind(this))
this.tetrisSound = new THREE.Audio(listener)
audioLoader.load('audio/tetris.ogg', function( buffer ) {
this.tetrisSound.setBuffer(buffer)
this.lineClearSound.setVolume(settings.sfxVolume/100)
this.tetrisSound.setVolume(settings.sfxVolume/100)
this.hardDropSound.setVolume(settings.sfxVolume/100)
}.bind(this))
this.hardDropSound = new THREE.Audio(listener)
audioLoader.load('audio/hard-drop.wav', function( buffer ) {
this.hardDropSound.setBuffer(buffer)
this.hardDropSound.setVolume(settings.sfxVolume/100)
}.bind(this))
this.hitSound = new THREE.Audio(listener)
audioLoader.load('audio/hit.mp3', function( buffer ) {
this.hitSound.setBuffer(buffer)
this.hitSound.setVolume(settings.sfxVolume/100)
}.bind(this))
this.floorSound = new THREE.Audio(listener)
audioLoader.load('audio/floor.ogg', function( buffer ) {
this.floorSound.setBuffer(buffer)
this.floorSound.setVolume(settings.sfxVolume/100)
}.bind(this))
this.moveSound = new THREE.Audio(listener)
audioLoader.load('audio/move.ogg', function( buffer ) {
this.moveSound.setBuffer(buffer)
this.moveSound.setVolume(settings.sfxVolume/100)
}.bind(this))
this.rotateSound = new THREE.Audio(listener)
audioLoader.load('audio/rotate.ogg', function( buffer ) {
this.rotateSound.setBuffer(buffer)
this.rotateSound.setVolume(settings.sfxVolume/100)
}.bind(this))
this.spinEndSound = new THREE.Audio(listener)
audioLoader.load('audio/spinend.mp3', function( buffer ) {
this.spinEndSound.setBuffer(buffer)
this.spinEndSound.setVolume(settings.sfxVolume/100)
}.bind(this))
this.playfield = new Playfield(loadingManager)
@@ -72,8 +97,8 @@ export class TetraScene extends THREE.Scene {
switch (theme) {
case "Plasma":
this.ambientLight.intensity = 1
this.directionalLight.intensity = 1
this.directionalLight.position.set(5, -20, 20)
this.directionalLight.intensity = 3
this.directionalLight.position.set(5, 50, -20)
this.music.src = "audio/Moon-Over-Moscow-DJ-ResiDance-Mix-2022.mp3"
this.background = new THREE.Color(0xffffff)
this.fog.color.set(0xffffff)
@@ -82,8 +107,8 @@ export class TetraScene extends THREE.Scene {
break
case "Space":
this.ambientLight.intensity = 3
this.directionalLight.intensity = 1
this.directionalLight.position.set(2, 15, 20)
this.directionalLight.intensity = 10
this.directionalLight.position.set(2, 15, -20)
this.music.src = "audio/benevolence.m4a"
this.background = new THREE.Color(0x000000)
this.fog.color.set(0x000000)
+25 -34
View File
@@ -93,10 +93,10 @@ export class InstancedMino extends THREE.InstancedMesh {
color: COLORS.RETRO,
map: texture,
bumpMap: texture,
bumpScale: 1.5,
bumpScale: 1,
envMap: environment,
envMapIntensity: 5,
roughness: 0.07,
roughness: 0.03,
metalness: 1,
transparent: true,
}, 8, 8)
@@ -109,10 +109,10 @@ export class InstancedMino extends THREE.InstancedMesh {
color: COLORS.RETRO,
map: texture,
bumpMap: texture,
bumpScale: 1.5,
bumpScale: 1,
envMap: environment,
envMapIntensity: 5,
roughness: 0.07,
roughness: 0.03,
metalness: 1,
transparent: true,
}, 1, 1)
@@ -168,35 +168,26 @@ InstancedMino.prototype.materials = {
envMap: environment,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.55,
opacity: 0.66,
roughness: 0.1,
metalness: 0.95,
}),
Space: new THREE.MeshStandardMaterial({
envMap: environment,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.66,
roughness: 0.01,
metalness: 0.99,
metalness: 0.6,
onBeforeCompile: shader => {
shader.vertexShader = `
varying vec3 vPos;
${shader.vertexShader}
`.replace(
'#include <begin_vertex>',
`
#include <begin_vertex>
vPos = position;
float n = sin(position.x*3.1 + position.y*5.2 + position.z*7.3) * 0.03;
transformed += normal * n;
`
);
}
})
}
InstancedMino.prototype.materials['Plasma'].onBeforeCompile = shader => {
shader.vertexShader = `
varying vec3 vPos;
${shader.vertexShader}
`.replace(
'#include <begin_vertex>',
`
#include <begin_vertex>
vPos = position;
// Bruit basé sur la position du sommet pour irrégularité
float n = sin(position.x*3.1 + position.y*5.2 + position.z*7.3) * 0.03;
transformed += normal * n;
`
);
};
class Mino extends THREE.Object3D {
@@ -487,8 +478,8 @@ class Playfield extends THREE.Group {
.lineTo(COLUMNS, 0)
.lineTo(COLUMNS, SKYLINE)
.lineTo(COLUMNS + 1, SKYLINE)
.lineTo(COLUMNS + 1, -1)
.lineTo(-1, -1)
.lineTo(COLUMNS + 1, -6/8)
.lineTo(-1, -6/8)
.moveTo(-1, SKYLINE)
const retroEdgeTexture = new THREE.TextureLoader(loadingManager).load("images/edge.png", (texture) => {
texture.wrapS = THREE.RepeatWrapping
@@ -498,10 +489,10 @@ class Playfield extends THREE.Group {
color: COLORS.RETRO,
map: retroEdgeTexture,
bumpMap: retroEdgeTexture,
bumpScale: 1,
envMap: environment,
envMapIntensity: 5,
bumpScale: 1.5,
roughness: 0.07,
roughness: 0.03,
metalness: 1
})
this.retroEdge = new THREE.Mesh(
+13 -12
View File
@@ -57,39 +57,40 @@ export class Vortex extends THREE.Group {
this.add(this.opaqueCylinder)
})
this.globalRotation = 0.028
this.transparentTextureRotation = 0.005
this.transparentMoveForward = 0.009
this.opaqueTextureRotation = 0.006
this.opaqueMoveForward = 0.025
this.globalRotation = 0.028
this.transparentTextureRotation = 0.005
this.transparentMoveForward = 0.009
this.opaqueTextureRotation = 0.006
this.opaqueMoveForward = 0.025
this.visible = true
break
case "Space":
loader.load("./images/colorfull.jpg", texture => {
texture.wrapS = THREE.RepeatWrapping
texture.wrapS = THREE.MirroredRepeatWrapping
texture.wrapT = THREE.MirroredRepeatWrapping
texture.repeat.set(1, 4)
texture.repeat.set(1, 8)
this.transparentCylinder.material.map = texture
this.transparentCylinder.material.opacity = 0.3
this.add(this.transparentCylinder)
})
loader.load("./images/stars_space.jpg", texture => {
texture.wrapS = THREE.RepeatWrapping
texture.wrapS = THREE.MirroredRepeatWrapping
texture.wrapT = THREE.MirroredRepeatWrapping
texture.repeat.set(3, 6)
this.opaqueCylinder.material.map = texture
this.opaqueCylinder.material.map.offset.x = 5
this.opaqueCylinder.material.blending = THREE.AdditiveBlending
this.add(this.opaqueCylinder)
})
this.globalRotation = 0.028
this.opaqueTextureRotation = 0.006
this.opaqueMoveForward = 0.06
this.globalRotation = 0.028
this.opaqueTextureRotation = 0.006
this.opaqueMoveForward = 0.04
this.transparentTextureRotation = 0
this.transparentMoveForward = 0.01
this.transparentMoveForward = 0.02
this.visible = true
break