RETRO THEME
This commit is contained in:
parent
8ed998f255
commit
7f6795109b
17
app.js
17
app.js
@ -1,6 +1,6 @@
|
|||||||
import * as THREE from 'three'
|
import * as THREE from 'three'
|
||||||
import { scheduler } from './jsm/scheduler.js'
|
import { scheduler } from './jsm/scheduler.js'
|
||||||
import { TRANSLATION, ROTATION, environnement, Mino, Playfield, HoldQueue, NextQueue } from './jsm/gamelogic.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 { Stats } from './jsm/Stats.js'
|
||||||
import { TetraGUI } from './jsm/TetraGUI.js'
|
import { TetraGUI } from './jsm/TetraGUI.js'
|
||||||
@ -29,7 +29,7 @@ let game = {
|
|||||||
gui.settings.close()
|
gui.settings.close()
|
||||||
gui.stats.show()
|
gui.stats.show()
|
||||||
|
|
||||||
Mino.mesh.clear()
|
Mino.meshes.clear()
|
||||||
|
|
||||||
nextQueue.init()
|
nextQueue.init()
|
||||||
holdQueue.piece = undefined
|
holdQueue.piece = undefined
|
||||||
@ -298,17 +298,18 @@ const stats = new Stats()
|
|||||||
const settings = new Settings()
|
const settings = new Settings()
|
||||||
const scene = new TetraScene(settings, loadingManager)
|
const scene = new TetraScene(settings, loadingManager)
|
||||||
const controls = new TetraControls(scene.camera, renderer.domElement)
|
const controls = new TetraControls(scene.camera, renderer.domElement)
|
||||||
const gui = new TetraGUI(game, settings, stats, scene, controls)
|
|
||||||
|
|
||||||
scene.add(Mino.mesh)
|
|
||||||
|
|
||||||
|
scene.add(Mino.meshes)
|
||||||
const holdQueue = new HoldQueue()
|
const holdQueue = new HoldQueue()
|
||||||
scene.add(holdQueue)
|
scene.add(holdQueue)
|
||||||
const playfield = new Playfield()
|
const playfield = new Playfield(loadingManager)
|
||||||
scene.add(playfield)
|
scene.add(playfield)
|
||||||
const nextQueue = new NextQueue()
|
const nextQueue = new NextQueue()
|
||||||
scene.add(nextQueue)
|
scene.add(nextQueue)
|
||||||
|
|
||||||
|
const gui = new TetraGUI(game, settings, stats, scene, controls, playfield)
|
||||||
|
gui.load()
|
||||||
|
|
||||||
messagesSpan.onanimationend = function (event) {
|
messagesSpan.onanimationend = function (event) {
|
||||||
event.target.remove()
|
event.target.remove()
|
||||||
}
|
}
|
||||||
@ -321,12 +322,12 @@ function animate() {
|
|||||||
scene.updateMatrixWorld()
|
scene.updateMatrixWorld()
|
||||||
scene.update(delta)
|
scene.update(delta)
|
||||||
playfield.update(delta)
|
playfield.update(delta)
|
||||||
Mino.mesh.update()
|
Mino.meshes.update()
|
||||||
controls.update()
|
controls.update()
|
||||||
gui.update()
|
gui.update()
|
||||||
|
|
||||||
renderer.render(scene, scene.camera)
|
renderer.render(scene, scene.camera)
|
||||||
environnement.camera.update(renderer, scene)
|
environment.camera.update(renderer, scene)
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("resize", () => {
|
window.addEventListener("resize", () => {
|
||||||
|
BIN
audio/Tetris_MkVaffQuasi_Ultimix_OC_ReMix.mp3
Normal file
BIN
audio/Tetris_MkVaffQuasi_Ultimix_OC_ReMix.mp3
Normal file
Binary file not shown.
BIN
images/edge.png
Normal file
BIN
images/edge.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
BIN
images/sprites.png
Normal file
BIN
images/sprites.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 792 B |
@ -6,8 +6,8 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>teTra</title>
|
<title>teTra</title>
|
||||||
<link rel="icon" href="favicon.ico">
|
<link rel="icon" href="favicon.ico">
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="css/style.css">
|
||||||
<link rel="stylesheet" href="loading.css">
|
<link rel="stylesheet" href="css/loading.css">
|
||||||
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
|
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
|
||||||
<script type="importmap">
|
<script type="importmap">
|
||||||
{
|
{
|
||||||
@ -35,6 +35,6 @@
|
|||||||
<audio id="music" src="audio/benevolence.m4a" loop></audio>
|
<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 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>
|
<script type="module" src="app.js"></script>
|
||||||
<script>navigator?.serviceWorker.register('./jsm/service-worker.js')</script>
|
<script>navigator?.serviceWorker?.register('./jsm/service-worker.js')</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,5 +1,5 @@
|
|||||||
import { Clock } from 'three'
|
import { Clock } from 'three'
|
||||||
import { T_SPIN } from './gamelogic.js'
|
import { T_SPIN } from './Tetrominoes.js'
|
||||||
|
|
||||||
|
|
||||||
// score = AWARDED_LINE_CLEARS[tSpin][nbClearedLines]
|
// score = AWARDED_LINE_CLEARS[tSpin][nbClearedLines]
|
||||||
|
@ -10,8 +10,8 @@ class TetraControls extends OrbitControls {
|
|||||||
this.dampingFactor = 0.04
|
this.dampingFactor = 0.04
|
||||||
this.maxDistance = 21
|
this.maxDistance = 21
|
||||||
this.keys = {}
|
this.keys = {}
|
||||||
this.minPolarAngle = 0.9
|
this.minPolarAngle = 1
|
||||||
this.maxPolarAngle = 2.14
|
this.maxPolarAngle = 2.1
|
||||||
this.minAzimuthAngle = 0.9 - Math.PI / 2
|
this.minAzimuthAngle = 0.9 - Math.PI / 2
|
||||||
this.maxAzimuthAngle = 2.14 - Math.PI / 2
|
this.maxAzimuthAngle = 2.14 - Math.PI / 2
|
||||||
this.target.set(5, 7, 0)
|
this.target.set(5, 7, 0)
|
||||||
|
159
jsm/TetraGUI.js
159
jsm/TetraGUI.js
@ -1,92 +1,15 @@
|
|||||||
import * as THREE from 'three'
|
import * as THREE from 'three'
|
||||||
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'
|
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'
|
||||||
import * as FPS from 'three/addons/libs/stats.module.js'
|
import * as FPS from 'three/addons/libs/stats.module.js'
|
||||||
import { Mino, environnement } from './gamelogic.js'
|
import { Mino, environment } from './Tetrominoes.js'
|
||||||
|
|
||||||
|
|
||||||
let jsKeyRenamer = new Proxy({
|
|
||||||
["←"]: "ArrowLeft",
|
|
||||||
["→"]: "ArrowRight",
|
|
||||||
["↑"]: "ArrowUp",
|
|
||||||
["↓"]: "ArrowDown",
|
|
||||||
["Espace"]: " ",
|
|
||||||
["Échap."]: "Escape",
|
|
||||||
["Ret. arrière"]: "Backspace",
|
|
||||||
["Entrée"]: "Enter",
|
|
||||||
}, {
|
|
||||||
get(obj, keyName) {
|
|
||||||
return keyName in obj ? obj[keyName] : keyName
|
|
||||||
}
|
|
||||||
})
|
|
||||||
let friendyKeyRenamer = new Proxy({
|
|
||||||
["ArrowLeft"]: "←",
|
|
||||||
["ArrowRight"]: "→",
|
|
||||||
["ArrowUp"]: "↑",
|
|
||||||
["ArrowDown"]: "↓",
|
|
||||||
[" "]: "Espace",
|
|
||||||
["Escape"]: "Échap.",
|
|
||||||
["Backspace"]: "Ret. arrière",
|
|
||||||
["Enter"]: "Entrée",
|
|
||||||
}, {
|
|
||||||
get(obj, keyName) {
|
|
||||||
return keyName in obj ? obj[keyName] : keyName.toUpperCase()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
export class TetraGUI extends GUI {
|
export class TetraGUI extends GUI {
|
||||||
constructor(game, settings, stats, scene, controls) {
|
constructor(game, settings, stats, scene, controls, playfield, loadingManager) {
|
||||||
super({title: "teTra"})
|
super({title: "teTra"})
|
||||||
this.startLevel = 1
|
|
||||||
|
this.startButton = this.add(game, "start").name("Jouer").hide()
|
||||||
let keyMaps = {
|
this.pauseButton = this.add(game, "pause").name("Pause").hide()
|
||||||
key: {},
|
|
||||||
action: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.key = new Proxy(keyMaps, {
|
|
||||||
set(km, action, key) {
|
|
||||||
key = jsKeyRenamer[key]
|
|
||||||
km.action[key.toLowerCase()] = action
|
|
||||||
return km.key[action] = key
|
|
||||||
},
|
|
||||||
has(km, action) {
|
|
||||||
return action in km.key
|
|
||||||
},
|
|
||||||
get(km, action) {
|
|
||||||
return friendyKeyRenamer[km.key[action]]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.action = new Proxy(keyMaps, {
|
|
||||||
set(km, key, action) {
|
|
||||||
km.key[action] = key
|
|
||||||
return km.action[key.toLowerCase()] = action
|
|
||||||
},
|
|
||||||
has(km, key) {
|
|
||||||
return key.toLowerCase() in km.action
|
|
||||||
},
|
|
||||||
get(km, key) {
|
|
||||||
return km.action[key.toLowerCase()]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.key.moveLeft = "ArrowLeft"
|
|
||||||
this.key.moveRight = "ArrowRight"
|
|
||||||
this.key.rotateCCW = "w"
|
|
||||||
this.key.rotateCW = "ArrowUp"
|
|
||||||
this.key.softDrop = "ArrowDown"
|
|
||||||
this.key.hardDrop = " "
|
|
||||||
this.key.hold = "c"
|
|
||||||
this.key.pause = "Escape"
|
|
||||||
|
|
||||||
this.arrDelay = 50
|
|
||||||
this.dasDelay = 300
|
|
||||||
|
|
||||||
this.musicVolume = 50
|
|
||||||
this.sfxVolume = 50
|
|
||||||
|
|
||||||
this.startButton = this.add(game, "start").name("Jouer").hide()
|
|
||||||
this.pauseButton = this.add(game, "pause").name("Pause").hide()
|
|
||||||
this.resumeButton = this.add(game, "resume").name("Reprendre").hide()
|
this.resumeButton = this.add(game, "resume").name("Reprendre").hide()
|
||||||
|
|
||||||
this.stats = this.addFolder("Stats").hide()
|
this.stats = this.addFolder("Stats").hide()
|
||||||
@ -104,25 +27,21 @@ export class TetraGUI extends GUI {
|
|||||||
this.settings = this.addFolder("Options").open()
|
this.settings = this.addFolder("Options").open()
|
||||||
|
|
||||||
this.settings.add(settings, "startLevel").name("Niveau initial").min(1).max(15).step(1)
|
this.settings.add(settings, "startLevel").name("Niveau initial").min(1).max(15).step(1)
|
||||||
this.settings.add(settings, "theme", ["Plasma", "Espace"]).name("Thème").onChange(theme => {
|
|
||||||
scene.vortex.theme = theme
|
this.settings.add(settings, "theme", ["Plasma", "Espace", "Rétro"]).name("Thème").onChange(theme => {
|
||||||
switch (theme) {
|
scene.theme = theme
|
||||||
case "Plasma":
|
Mino.meshes.material = Mino.materials[theme]
|
||||||
scene.ambientLight.intensity = 0.6
|
if (theme == "Rétro") {
|
||||||
scene.directionalLight.intensity = 5
|
playfield.edge.visible = false
|
||||||
|
playfield.retroEdge.visible = true
|
||||||
Mino.mesh.material.opacity = 0.7
|
Mino.meshes.resetColor()
|
||||||
Mino.mesh.material.roughness = 0.48
|
Mino.meshes.update = Mino.meshes.updateOffset
|
||||||
Mino.mesh.material.metalness = 0.9
|
music.src = "audio/Tetris_MkVaffQuasi_Ultimix_OC_ReMix.mp3"
|
||||||
break
|
} else {
|
||||||
case "Espace":
|
playfield.edge.visible = true
|
||||||
scene.ambientLight.intensity = 20
|
playfield.retroEdge.visible = false
|
||||||
scene.directionalLight.intensity = 10
|
Mino.meshes.update = Mino.meshes.updateColor
|
||||||
|
music.src = "audio/benevolence.m4a"
|
||||||
Mino.mesh.material.opacity = 0.6
|
|
||||||
Mino.mesh.material.roughness = 0.05
|
|
||||||
Mino.mesh.material.metalness = 0.997
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -184,11 +103,11 @@ export class TetraGUI extends GUI {
|
|||||||
function changeMaterial(type) {
|
function changeMaterial(type) {
|
||||||
material?.destroy()
|
material?.destroy()
|
||||||
material = dev.addFolder("minoes material")
|
material = dev.addFolder("minoes material")
|
||||||
material.add(Mino.mesh.material, "constructor", ["MeshBasicMaterial", "MeshStandardMaterial", "MeshPhysicalMaterial"]).name("type").onChange(changeMaterial)
|
material.add(Mino.meshes.material, "constructor", ["MeshBasicMaterial", "MeshStandardMaterial", "MeshPhysicalMaterial"]).name("type").onChange(changeMaterial)
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case "MeshBasicMaterial":
|
case "MeshBasicMaterial":
|
||||||
Mino.mesh.material = new THREE.MeshBasicMaterial({
|
Mino.meshes.material = new THREE.MeshBasicMaterial({
|
||||||
envMap: environnement,
|
envMap: environment,
|
||||||
side: THREE.DoubleSide,
|
side: THREE.DoubleSide,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
@ -196,8 +115,8 @@ export class TetraGUI extends GUI {
|
|||||||
})
|
})
|
||||||
break
|
break
|
||||||
case "MeshStandardMaterial":
|
case "MeshStandardMaterial":
|
||||||
Mino.mesh.material = new THREE.MeshStandardMaterial({
|
Mino.meshes.material = new THREE.MeshStandardMaterial({
|
||||||
envMap: environnement,
|
envMap: environment,
|
||||||
side: THREE.DoubleSide,
|
side: THREE.DoubleSide,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
opacity: 0.7,
|
opacity: 0.7,
|
||||||
@ -206,8 +125,8 @@ export class TetraGUI extends GUI {
|
|||||||
})
|
})
|
||||||
break
|
break
|
||||||
case "MeshPhysicalMaterial":
|
case "MeshPhysicalMaterial":
|
||||||
Mino.mesh.material = new THREE.MeshPhysicalMaterial({
|
Mino.meshes.material = new THREE.MeshPhysicalMaterial({
|
||||||
envMap: environnement,
|
envMap: environment,
|
||||||
side: THREE.DoubleSide,
|
side: THREE.DoubleSide,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
opacity: 0.6,
|
opacity: 0.6,
|
||||||
@ -223,17 +142,17 @@ export class TetraGUI extends GUI {
|
|||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if ("opacity" in Mino.mesh.material) material.add(Mino.mesh.material, "opacity" ).min(0).max(1).listen()
|
if ("opacity" in Mino.meshes.material) material.add(Mino.meshes.material, "opacity" ).min(0).max(1).listen()
|
||||||
if ("reflectivity" in Mino.mesh.material) material.add(Mino.mesh.material, "reflectivity" ).min(0).max(1).listen()
|
if ("reflectivity" in Mino.meshes.material) material.add(Mino.meshes.material, "reflectivity" ).min(0).max(1).listen()
|
||||||
if ("roughness" in Mino.mesh.material) material.add(Mino.mesh.material, "roughness" ).min(0).max(1).listen()
|
if ("roughness" in Mino.meshes.material) material.add(Mino.meshes.material, "roughness" ).min(0).max(1).listen()
|
||||||
if ("metalness" in Mino.mesh.material) material.add(Mino.mesh.material, "metalness" ).min(0).max(1).listen()
|
if ("metalness" in Mino.meshes.material) material.add(Mino.meshes.material, "metalness" ).min(0).max(1).listen()
|
||||||
if ("attenuationDistance" in Mino.mesh.material) material.add(Mino.mesh.material, "attenuationDistance").min(0).listen()
|
if ("attenuationDistance" in Mino.meshes.material) material.add(Mino.meshes.material, "attenuationDistance").min(0).listen()
|
||||||
if ("ior" in Mino.mesh.material) material.add(Mino.mesh.material, "ior" ).min(1).max(2).listen()
|
if ("ior" in Mino.meshes.material) material.add(Mino.meshes.material, "ior" ).min(1).max(2).listen()
|
||||||
if ("sheen" in Mino.mesh.material) material.add(Mino.mesh.material, "sheen" ).min(0).max(1).listen()
|
if ("sheen" in Mino.meshes.material) material.add(Mino.meshes.material, "sheen" ).min(0).max(1).listen()
|
||||||
if ("sheenRoughness" in Mino.mesh.material) material.add(Mino.mesh.material, "sheenRoughness" ).min(0).max(1).listen()
|
if ("sheenRoughness" in Mino.meshes.material) material.add(Mino.meshes.material, "sheenRoughness" ).min(0).max(1).listen()
|
||||||
if ("specularIntensity" in Mino.mesh.material) material.add(Mino.mesh.material, "specularIntensity" ).min(0).max(1).listen()
|
if ("specularIntensity" in Mino.meshes.material) material.add(Mino.meshes.material, "specularIntensity" ).min(0).max(1).listen()
|
||||||
if ("thickness" in Mino.mesh.material) material.add(Mino.mesh.material, "thickness" ).min(0).max(5).listen()
|
if ("thickness" in Mino.meshes.material) material.add(Mino.meshes.material, "thickness" ).min(0).max(5).listen()
|
||||||
if ("transmission" in Mino.mesh.material) material.add(Mino.mesh.material, "transmission" ).min(0).max(1).listen()
|
if ("transmission" in Mino.meshes.material) material.add(Mino.meshes.material, "transmission" ).min(0).max(1).listen()
|
||||||
}
|
}
|
||||||
changeMaterial(this.materialType)
|
changeMaterial(this.materialType)
|
||||||
material.close()
|
material.close()
|
||||||
@ -250,8 +169,6 @@ export class TetraGUI extends GUI {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.load()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load() {
|
||||||
|
@ -44,6 +44,24 @@ export class TetraScene extends THREE.Scene {
|
|||||||
}.bind(this))
|
}.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set theme(theme) {
|
||||||
|
switch (theme) {
|
||||||
|
case "Plasma":
|
||||||
|
this.ambientLight.intensity = 0.6
|
||||||
|
this.directionalLight.intensity = 5
|
||||||
|
break
|
||||||
|
case "Espace":
|
||||||
|
this.ambientLight.intensity = 20
|
||||||
|
this.directionalLight.intensity = 10
|
||||||
|
break
|
||||||
|
case "Rétro":
|
||||||
|
this.ambientLight.intensity = 1
|
||||||
|
this.directionalLight.intensity = 10
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.vortex.theme = theme
|
||||||
|
}
|
||||||
|
|
||||||
update(delta) {
|
update(delta) {
|
||||||
this.vortex.update(delta)
|
this.vortex.update(delta)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as THREE from 'three'
|
import * as THREE from 'three'
|
||||||
import { scheduler } from './scheduler.js'
|
import { scheduler } from './scheduler.js'
|
||||||
|
import { TileMaterial } from './TileMaterial.js'
|
||||||
|
|
||||||
|
|
||||||
Array.prototype.pick = function () { return this.splice(Math.floor(Math.random() * this.length), 1)[0] }
|
Array.prototype.pick = function () { return this.splice(Math.floor(Math.random() * this.length), 1)[0] }
|
||||||
@ -54,10 +55,17 @@ const COLUMNS = 10
|
|||||||
|
|
||||||
|
|
||||||
const envRenderTarget = new THREE.WebGLCubeRenderTarget(256)
|
const envRenderTarget = new THREE.WebGLCubeRenderTarget(256)
|
||||||
const environnement = envRenderTarget.texture
|
const environment = envRenderTarget.texture
|
||||||
environnement.type = THREE.HalfFloatType
|
environment.type = THREE.HalfFloatType
|
||||||
environnement.camera = new THREE.CubeCamera(1, 1000, envRenderTarget)
|
environment.camera = new THREE.CubeCamera(1, 1000, envRenderTarget)
|
||||||
environnement.camera.position.set(5, 10, 0)
|
environment.camera.position.set(5, 10, 0)
|
||||||
|
|
||||||
|
|
||||||
|
const sideMaterial = new THREE.MeshStandardMaterial({
|
||||||
|
color: 0x222222,
|
||||||
|
roughness: 0.8,
|
||||||
|
metalness: 0.8,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class InstancedMino extends THREE.InstancedMesh {
|
class InstancedMino extends THREE.InstancedMesh {
|
||||||
@ -65,6 +73,8 @@ class InstancedMino extends THREE.InstancedMesh {
|
|||||||
super(geometry, material, count)
|
super(geometry, material, count)
|
||||||
this.instances = new Set()
|
this.instances = new Set()
|
||||||
this.count = 0
|
this.count = 0
|
||||||
|
this.offsets = new Uint8Array(2*count)
|
||||||
|
this.update = this.updateColor
|
||||||
}
|
}
|
||||||
|
|
||||||
add(instance) {
|
add(instance) {
|
||||||
@ -79,26 +89,83 @@ class InstancedMino extends THREE.InstancedMesh {
|
|||||||
this.instances.clear()
|
this.instances.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
setOffsetAt(index, offset) {
|
||||||
|
this.offsets[index * 2] = offset
|
||||||
|
}
|
||||||
|
|
||||||
|
resetColor() {
|
||||||
|
if (this.instanceColor) {
|
||||||
|
this.instanceColor.array.fill(0xffffff)
|
||||||
|
this.instanceColor.needsUpdate = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateColor() {
|
||||||
this.count = 0
|
this.count = 0
|
||||||
this.instances.forEach(mino => {
|
this.instances.forEach(mino => {
|
||||||
if (mino.parent?.visible) {
|
if (mino.parent?.visible) {
|
||||||
this.setColorAt(this.count, mino.color)
|
|
||||||
this.setMatrixAt(this.count, mino.matrixWorld)
|
this.setMatrixAt(this.count, mino.matrixWorld)
|
||||||
|
this.setColorAt(this.count, mino.color)
|
||||||
this.count++
|
this.count++
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (this.count) {
|
if (this.count) {
|
||||||
this.instanceColor.needsUpdate = true
|
|
||||||
this.instanceMatrix.needsUpdate = true
|
this.instanceMatrix.needsUpdate = true
|
||||||
|
this.instanceColor.needsUpdate = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOffset() {
|
||||||
|
this.count = 0
|
||||||
|
this.instances.forEach(mino => {
|
||||||
|
if (mino.parent?.visible) {
|
||||||
|
this.setMatrixAt(this.count, mino.matrixWorld)
|
||||||
|
this.setOffsetAt(this.count, mino.offset)
|
||||||
|
this.count++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (this.count) {
|
||||||
|
this.instanceMatrix.needsUpdate = true
|
||||||
|
this.geometry.setAttribute('offset', new THREE.InstancedBufferAttribute(this.offsets, 2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Mino extends THREE.Object3D {
|
class Mino extends THREE.Object3D {
|
||||||
static instances = new Set()
|
static materials = {
|
||||||
static mesh
|
Plasma: new THREE.MeshStandardMaterial({
|
||||||
|
envMap: environment,
|
||||||
|
side: THREE.DoubleSide,
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.7,
|
||||||
|
roughness: 0.48,
|
||||||
|
metalness: 0.67,
|
||||||
|
}),
|
||||||
|
Espace: new THREE.MeshStandardMaterial({
|
||||||
|
envMap: environment,
|
||||||
|
side: THREE.DoubleSide,
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.8,
|
||||||
|
roughness: 0.05,
|
||||||
|
metalness: 0.997,
|
||||||
|
}),
|
||||||
|
Rétro: [sideMaterial, sideMaterial, sideMaterial, sideMaterial, sideMaterial, sideMaterial]
|
||||||
|
}
|
||||||
|
static {
|
||||||
|
new THREE.TextureLoader().load("images/sprites.png", (texture) => {
|
||||||
|
this.materials.Rétro[0] = new TileMaterial({
|
||||||
|
color: 0xd0d4c1,
|
||||||
|
map: texture,
|
||||||
|
bumpMap: texture,
|
||||||
|
bumpScale: 4,
|
||||||
|
roughness: 0.25,
|
||||||
|
metalness: 0.8,
|
||||||
|
transparent: true,
|
||||||
|
}, 8, 8)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
static meshes
|
||||||
static {
|
static {
|
||||||
let minoFaceShape = new THREE.Shape()
|
let minoFaceShape = new THREE.Shape()
|
||||||
minoFaceShape.moveTo(.1, .1)
|
minoFaceShape.moveTo(.1, .1)
|
||||||
@ -116,24 +183,17 @@ class Mino extends THREE.Object3D {
|
|||||||
bevelSegments: 1
|
bevelSegments: 1
|
||||||
}
|
}
|
||||||
let minoGeometry = new THREE.ExtrudeGeometry(minoFaceShape, minoExtrudeSettings)
|
let minoGeometry = new THREE.ExtrudeGeometry(minoFaceShape, minoExtrudeSettings)
|
||||||
let minoMaterial = new THREE.MeshStandardMaterial({
|
this.meshes = new InstancedMino(minoGeometry, this.materials.Plasma, 2*ROWS*COLUMNS)
|
||||||
envMap: environnement,
|
|
||||||
side: THREE.DoubleSide,
|
|
||||||
transparent: true,
|
|
||||||
opacity: 0.7,
|
|
||||||
roughness: 0.48,
|
|
||||||
metalness: 0.67,
|
|
||||||
})
|
|
||||||
this.mesh = new InstancedMino(minoGeometry, minoMaterial, 2*ROWS*COLUMNS)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(color) {
|
constructor(color, offset) {
|
||||||
super()
|
super()
|
||||||
this.color = color
|
this.color = color
|
||||||
|
this.offset = offset
|
||||||
this.velocity = P(50 - 100 * Math.random(), 50 - 100 * Math.random(), 50 - 100 * Math.random())
|
this.velocity = P(50 - 100 * Math.random(), 50 - 100 * Math.random(), 50 - 100 * Math.random())
|
||||||
this.rotationAngle = P(Math.random(), Math.random(), Math.random()).normalize()
|
this.rotationAngle = P(Math.random(), Math.random(), Math.random()).normalize()
|
||||||
this.angularVelocity = 5 - 10 * Math.random()
|
this.angularVelocity = 5 - 10 * Math.random()
|
||||||
this.constructor.mesh.add(this)
|
this.constructor.meshes.add(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
explode(delta) {
|
explode(delta) {
|
||||||
@ -149,7 +209,7 @@ class Mino extends THREE.Object3D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this.constructor.mesh.delete(this)
|
this.constructor.meshes.delete(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +224,7 @@ class Tetromino extends THREE.Group {
|
|||||||
constructor(position) {
|
constructor(position) {
|
||||||
super()
|
super()
|
||||||
if (position) this.position.copy(position)
|
if (position) this.position.copy(position)
|
||||||
this.minoesPosition[FACING.NORTH].forEach(() => this.add(new Mino(this.freeColor)))
|
this.minoesPosition[FACING.NORTH].forEach(() => this.add(new Mino(this.freeColor, this.offset)))
|
||||||
this.facing = FACING.NORTH
|
this.facing = FACING.NORTH
|
||||||
this.rotatedLast = false
|
this.rotatedLast = false
|
||||||
this.rotationPoint4Used = false
|
this.rotationPoint4Used = false
|
||||||
@ -251,6 +311,7 @@ class Ghost extends Tetromino {
|
|||||||
copy(piece) {
|
copy(piece) {
|
||||||
this.position.copy(piece.position)
|
this.position.copy(piece.position)
|
||||||
this.minoesPosition = piece.minoesPosition
|
this.minoesPosition = piece.minoesPosition
|
||||||
|
//this.children.forEach(mino => mino.offset = piece.offset)
|
||||||
this.facing = piece.facing
|
this.facing = piece.facing
|
||||||
this.visible = true
|
this.visible = true
|
||||||
while (this.canMove(TRANSLATION.DOWN)) this.position.y--
|
while (this.canMove(TRANSLATION.DOWN)) this.position.y--
|
||||||
@ -260,6 +321,7 @@ Ghost.prototype.freeColor = new THREE.Color(COLORS.GHOST)
|
|||||||
Ghost.prototype.minoesPosition = [
|
Ghost.prototype.minoesPosition = [
|
||||||
[P(0, 0, 0), P(0, 0, 0), P(0, 0, 0), P(0, 0, 0)],
|
[P(0, 0, 0), P(0, 0, 0), P(0, 0, 0), P(0, 0, 0)],
|
||||||
]
|
]
|
||||||
|
Ghost.prototype.offset = 0
|
||||||
|
|
||||||
|
|
||||||
class I extends Tetromino { }
|
class I extends Tetromino { }
|
||||||
@ -276,6 +338,7 @@ 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)] },
|
{ [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.freeColor = new THREE.Color(COLORS.I)
|
||||||
|
I.prototype.offset = 1
|
||||||
|
|
||||||
class J extends Tetromino { }
|
class J extends Tetromino { }
|
||||||
J.prototype.minoesPosition = [
|
J.prototype.minoesPosition = [
|
||||||
@ -285,8 +348,10 @@ J.prototype.minoesPosition = [
|
|||||||
[P(0, 1), P(-1, -1), P(0, 0), P(0, -1)],
|
[P(0, 1), P(-1, -1), P(0, 0), P(0, -1)],
|
||||||
]
|
]
|
||||||
J.prototype.freeColor = new THREE.Color(COLORS.J)
|
J.prototype.freeColor = new THREE.Color(COLORS.J)
|
||||||
|
J.prototype.offset = 2
|
||||||
|
|
||||||
class L extends Tetromino { }
|
class L extends Tetromino {
|
||||||
|
}
|
||||||
L.prototype.minoesPosition = [
|
L.prototype.minoesPosition = [
|
||||||
[P(-1, 0), P(0, 0), P(1, 0), P(1, 1)],
|
[P(-1, 0), P(0, 0), P(1, 0), P(1, 1)],
|
||||||
[P(0, 1), P(0, 0), P(0, -1), P(1, -1)],
|
[P(0, 1), P(0, 0), P(0, -1), P(1, -1)],
|
||||||
@ -294,6 +359,7 @@ L.prototype.minoesPosition = [
|
|||||||
[P(0, 1), P(0, 0), P(0, -1), P(-1, 1)],
|
[P(0, 1), P(0, 0), P(0, -1), P(-1, 1)],
|
||||||
]
|
]
|
||||||
L.prototype.freeColor = new THREE.Color(COLORS.L)
|
L.prototype.freeColor = new THREE.Color(COLORS.L)
|
||||||
|
L.prototype.offset = 3
|
||||||
|
|
||||||
class O extends Tetromino { }
|
class O extends Tetromino { }
|
||||||
O.prototype.minoesPosition = [
|
O.prototype.minoesPosition = [
|
||||||
@ -303,6 +369,7 @@ O.prototype.srs = [
|
|||||||
{ [ROTATION.CW]: [], [ROTATION.CCW]: [] }
|
{ [ROTATION.CW]: [], [ROTATION.CCW]: [] }
|
||||||
]
|
]
|
||||||
O.prototype.freeColor = new THREE.Color(COLORS.O)
|
O.prototype.freeColor = new THREE.Color(COLORS.O)
|
||||||
|
O.prototype.offset = 4
|
||||||
|
|
||||||
class S extends Tetromino { }
|
class S extends Tetromino { }
|
||||||
S.prototype.minoesPosition = [
|
S.prototype.minoesPosition = [
|
||||||
@ -312,6 +379,7 @@ S.prototype.minoesPosition = [
|
|||||||
[P(-1, 1), P(0, 0), P(-1, 0), P(0, -1)],
|
[P(-1, 1), P(0, 0), P(-1, 0), P(0, -1)],
|
||||||
]
|
]
|
||||||
S.prototype.freeColor = new THREE.Color(COLORS.S)
|
S.prototype.freeColor = new THREE.Color(COLORS.S)
|
||||||
|
S.prototype.offset = 5
|
||||||
|
|
||||||
class T extends Tetromino {
|
class T extends Tetromino {
|
||||||
get tSpin() {
|
get tSpin() {
|
||||||
@ -339,6 +407,7 @@ T.prototype.tSlots = [
|
|||||||
[P(-1, -1), P(-1, 1), P(1, 1), P(1, -1)],
|
[P(-1, -1), P(-1, 1), P(1, 1), P(1, -1)],
|
||||||
]
|
]
|
||||||
T.prototype.freeColor = new THREE.Color(COLORS.T)
|
T.prototype.freeColor = new THREE.Color(COLORS.T)
|
||||||
|
T.prototype.offset = 6
|
||||||
|
|
||||||
class Z extends Tetromino { }
|
class Z extends Tetromino { }
|
||||||
Z.prototype.minoesPosition = [
|
Z.prototype.minoesPosition = [
|
||||||
@ -348,18 +417,19 @@ Z.prototype.minoesPosition = [
|
|||||||
[P(0, 1), P(-1, 0), P(0, 0), P(-1, -1)]
|
[P(0, 1), P(-1, 0), P(0, 0), P(-1, -1)]
|
||||||
]
|
]
|
||||||
Z.prototype.freeColor = new THREE.Color(COLORS.Z)
|
Z.prototype.freeColor = new THREE.Color(COLORS.Z)
|
||||||
|
Z.prototype.offset = 7
|
||||||
|
|
||||||
|
|
||||||
class Playfield extends THREE.Group {
|
class Playfield extends THREE.Group {
|
||||||
constructor() {
|
constructor(loadingManager) {
|
||||||
super()
|
super()
|
||||||
//this.visible = false
|
//this.visible = false
|
||||||
|
|
||||||
const edgeMaterial = new THREE.MeshStandardMaterial({
|
const edgeMaterial = new THREE.MeshStandardMaterial({
|
||||||
color: COLORS.EDGE,
|
color: COLORS.EDGE,
|
||||||
envMap: environnement,
|
envMap: environment,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
opacity: 0.2,
|
opacity: 0.3,
|
||||||
roughness: 0.1,
|
roughness: 0.1,
|
||||||
metalness: 0.67,
|
metalness: 0.67,
|
||||||
})
|
})
|
||||||
@ -373,14 +443,56 @@ class Playfield extends THREE.Group {
|
|||||||
.lineTo(COLUMNS + .3, -.3)
|
.lineTo(COLUMNS + .3, -.3)
|
||||||
.lineTo(-.3, -.3)
|
.lineTo(-.3, -.3)
|
||||||
.moveTo(-.3, SKYLINE)
|
.moveTo(-.3, SKYLINE)
|
||||||
const edge = new THREE.Mesh(
|
this.edge = new THREE.Mesh(
|
||||||
new THREE.ExtrudeGeometry(edgeShape, {
|
new THREE.ExtrudeGeometry(edgeShape, {
|
||||||
depth: 1,
|
depth: 1,
|
||||||
bevelEnabled: false,
|
bevelEnabled: false,
|
||||||
}),
|
}),
|
||||||
edgeMaterial
|
edgeMaterial
|
||||||
)
|
)
|
||||||
this.add(edge)
|
this.add(this.edge)
|
||||||
|
|
||||||
|
const retroEdgeShape = new THREE.Shape()
|
||||||
|
.moveTo(-1, SKYLINE)
|
||||||
|
.lineTo(0, SKYLINE)
|
||||||
|
.lineTo(0, 0)
|
||||||
|
.lineTo(COLUMNS, 0)
|
||||||
|
.lineTo(COLUMNS, SKYLINE)
|
||||||
|
.lineTo(COLUMNS + 1, SKYLINE)
|
||||||
|
.lineTo(COLUMNS + 1, -1)
|
||||||
|
.lineTo(-1, -1)
|
||||||
|
.moveTo(-1, SKYLINE)
|
||||||
|
const retroEdgeTexture = new THREE.TextureLoader(loadingManager).load("images/edge.png", (texture) => {
|
||||||
|
texture.wrapS = THREE.RepeatWrapping
|
||||||
|
texture.wrapT = THREE.RepeatWrapping
|
||||||
|
})
|
||||||
|
const retroEdgeMaterial = new THREE.MeshStandardMaterial({
|
||||||
|
color: 0xd0d4c1,
|
||||||
|
map: retroEdgeTexture,
|
||||||
|
bumpMap: retroEdgeTexture,
|
||||||
|
bumpScale: 0.5,
|
||||||
|
roughness: 0.25,
|
||||||
|
metalness: 0.8,
|
||||||
|
})
|
||||||
|
this.retroEdge = new THREE.Mesh(
|
||||||
|
new THREE.ExtrudeGeometry(retroEdgeShape, {
|
||||||
|
depth: 1,
|
||||||
|
bevelEnabled: false,
|
||||||
|
}),
|
||||||
|
[retroEdgeMaterial, sideMaterial, sideMaterial, sideMaterial, sideMaterial, sideMaterial],
|
||||||
|
)
|
||||||
|
this.add(this.retroEdge)
|
||||||
|
const back = new THREE.Mesh(
|
||||||
|
new THREE.PlaneGeometry(COLUMNS, SKYLINE),
|
||||||
|
new THREE.MeshStandardMaterial({
|
||||||
|
color: 0xc5d0a1,
|
||||||
|
roughness: 0.9,
|
||||||
|
metalness: 0.9,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
back.position.set(COLUMNS/2, SKYLINE/2, 0)
|
||||||
|
this.retroEdge.add(back)
|
||||||
|
this.retroEdge.visible = false
|
||||||
|
|
||||||
const positionKF = new THREE.VectorKeyframeTrack('.position', [0, 1, 2], [0, 0, 0, 0, -0.2, 0, 0, 0, 0])
|
const positionKF = new THREE.VectorKeyframeTrack('.position', [0, 1, 2], [0, 0, 0, 0, -0.2, 0, 0, 0, 0])
|
||||||
const clip = new THREE.AnimationClip('HardDrop', 3, [positionKF])
|
const clip = new THREE.AnimationClip('HardDrop', 3, [positionKF])
|
||||||
@ -515,4 +627,4 @@ class NextQueue extends THREE.Group {
|
|||||||
NextQueue.prototype.positions = [P(0, 0), P(0, -3), P(0, -6), P(0, -9), P(0, -12), P(0, -15), P(0, -18)]
|
NextQueue.prototype.positions = [P(0, 0), P(0, -3), P(0, -6), P(0, -9), P(0, -12), P(0, -15), P(0, -18)]
|
||||||
|
|
||||||
|
|
||||||
export { T_SPIN, FACING, TRANSLATION, ROTATION, COLORS, environnement, Mino, Tetromino, Playfield, HoldQueue, NextQueue }
|
export { T_SPIN, FACING, TRANSLATION, ROTATION, COLORS, environment, Mino, Tetromino, Playfield, HoldQueue, NextQueue }
|
93
jsm/TileMaterial.js
Normal file
93
jsm/TileMaterial.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import { MeshStandardMaterial, Texture, Vector2 } from 'three';
|
||||||
|
|
||||||
|
export class TileMaterial extends MeshStandardMaterial {
|
||||||
|
constructor(params, tileSizeX, tileSizeY) {
|
||||||
|
super(params);
|
||||||
|
this.tileSize = { value: new Vector2(tileSizeX / this.map.image.width, tileSizeY / this.map.image.height) };
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeCompile(shader) {
|
||||||
|
shader.uniforms.tileSize = this.tileSize
|
||||||
|
shader.vertexShader = shader.vertexShader.replace(
|
||||||
|
`void main() {`,
|
||||||
|
`varying vec2 vUv;
|
||||||
|
varying vec2 vOffset;
|
||||||
|
attribute vec2 offset;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vUv = uv;
|
||||||
|
vOffset = offset;
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position, 1.0);`
|
||||||
|
)
|
||||||
|
shader.fragmentShader = `varying vec2 vUv;
|
||||||
|
varying vec2 vOffset;
|
||||||
|
//uniform sampler2D map;
|
||||||
|
uniform vec2 tileSize;
|
||||||
|
varying vec2 vBumpMapUvOffset;
|
||||||
|
` + shader.fragmentShader
|
||||||
|
shader.fragmentShader = shader.fragmentShader.replace(
|
||||||
|
`#include <map_fragment>`,
|
||||||
|
`#ifdef USE_MAP
|
||||||
|
|
||||||
|
vec4 sampledDiffuseColor = texture2D(map, vUv * tileSize + vOffset * tileSize);
|
||||||
|
|
||||||
|
#ifdef DECODE_VIDEO_TEXTURE
|
||||||
|
|
||||||
|
// use inline sRGB decode until browsers properly support SRGB8_ALPHA8 with video textures (#26516)
|
||||||
|
|
||||||
|
sampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
diffuseColor *= sampledDiffuseColor;
|
||||||
|
|
||||||
|
#endif`
|
||||||
|
)
|
||||||
|
shader.fragmentShader = shader.fragmentShader.replace(
|
||||||
|
`#include <bumpmap_pars_fragment>`,
|
||||||
|
`#ifdef USE_BUMPMAP
|
||||||
|
|
||||||
|
uniform sampler2D bumpMap;
|
||||||
|
uniform float bumpScale;
|
||||||
|
|
||||||
|
// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
|
||||||
|
// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
|
||||||
|
|
||||||
|
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
|
||||||
|
|
||||||
|
vec2 dHdxy_fwd() {
|
||||||
|
|
||||||
|
vec2 vBumpMapUvOffset = vBumpMapUv * tileSize + vOffset * tileSize;
|
||||||
|
|
||||||
|
vec2 dSTdx = dFdx( vBumpMapUvOffset );
|
||||||
|
vec2 dSTdy = dFdy( vBumpMapUvOffset );
|
||||||
|
|
||||||
|
float Hll = bumpScale * texture2D( bumpMap, vBumpMapUvOffset ).x;
|
||||||
|
float dBx = bumpScale * texture2D( bumpMap, vBumpMapUvOffset + dSTdx ).x - Hll;
|
||||||
|
float dBy = bumpScale * texture2D( bumpMap, vBumpMapUvOffset + dSTdy ).x - Hll;
|
||||||
|
|
||||||
|
return vec2( dBx, dBy );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {
|
||||||
|
|
||||||
|
// normalize is done to ensure that the bump map looks the same regardless of the texture's scale
|
||||||
|
vec3 vSigmaX = normalize( dFdx( surf_pos.xyz ) );
|
||||||
|
vec3 vSigmaY = normalize( dFdy( surf_pos.xyz ) );
|
||||||
|
vec3 vN = surf_norm; // normalized
|
||||||
|
|
||||||
|
vec3 R1 = cross( vSigmaY, vN );
|
||||||
|
vec3 R2 = cross( vN, vSigmaX );
|
||||||
|
|
||||||
|
float fDet = dot( vSigmaX, R1 ) * faceDirection;
|
||||||
|
|
||||||
|
vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );
|
||||||
|
return normalize( abs( fDet ) * surf_norm - vGrad );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@ export class Vortex extends THREE.Group {
|
|||||||
this.colorFullTextureRotation = 0.006
|
this.colorFullTextureRotation = 0.006
|
||||||
this.colorFullMoveForward = 0.025
|
this.colorFullMoveForward = 0.025
|
||||||
|
|
||||||
const commonCylinderGeometry = new THREE.CylinderGeometry(35, 35, 500, 12, 1, true)
|
const commonCylinderGeometry = new THREE.CylinderGeometry(35, 35, 1000, 12, 1, true)
|
||||||
|
|
||||||
this.darkCylinder = new THREE.Mesh(
|
this.darkCylinder = new THREE.Mesh(
|
||||||
commonCylinderGeometry,
|
commonCylinderGeometry,
|
||||||
@ -24,6 +24,7 @@ export class Vortex extends THREE.Group {
|
|||||||
blending: THREE.AdditiveBlending,
|
blending: THREE.AdditiveBlending,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
this.darkCylinder.position.y = -100
|
||||||
this.add(this.darkCylinder)
|
this.add(this.darkCylinder)
|
||||||
|
|
||||||
this.colorFullCylinder = new THREE.Mesh(
|
this.colorFullCylinder = new THREE.Mesh(
|
||||||
@ -33,6 +34,7 @@ export class Vortex extends THREE.Group {
|
|||||||
blending: THREE.AdditiveBlending,
|
blending: THREE.AdditiveBlending,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
this.colorFullCylinder.position.y = -100
|
||||||
this.add(this.colorFullCylinder)
|
this.add(this.colorFullCylinder)
|
||||||
|
|
||||||
this.position.set(5, 10, -10)
|
this.position.set(5, 10, -10)
|
||||||
@ -44,7 +46,7 @@ export class Vortex extends THREE.Group {
|
|||||||
new THREE.TextureLoader(this.loadingManager).load("./images/plasma.jpg", texture => {
|
new THREE.TextureLoader(this.loadingManager).load("./images/plasma.jpg", texture => {
|
||||||
texture.wrapS = THREE.RepeatWrapping
|
texture.wrapS = THREE.RepeatWrapping
|
||||||
texture.wrapT = THREE.MirroredRepeatWrapping
|
texture.wrapT = THREE.MirroredRepeatWrapping
|
||||||
texture.repeat.set(1, 1)
|
texture.repeat.set(1, 2)
|
||||||
this.darkCylinder.material.map = texture
|
this.darkCylinder.material.map = texture
|
||||||
})
|
})
|
||||||
this.darkCylinder.material.opacity = 0.17
|
this.darkCylinder.material.opacity = 0.17
|
||||||
@ -52,7 +54,7 @@ export class Vortex extends THREE.Group {
|
|||||||
new THREE.TextureLoader(this.loadingManager).load("./images/plasma2.jpg", texture => {
|
new THREE.TextureLoader(this.loadingManager).load("./images/plasma2.jpg", texture => {
|
||||||
texture.wrapS = THREE.RepeatWrapping
|
texture.wrapS = THREE.RepeatWrapping
|
||||||
texture.wrapT = THREE.MirroredRepeatWrapping
|
texture.wrapT = THREE.MirroredRepeatWrapping
|
||||||
texture.repeat.set(2, 1)
|
texture.repeat.set(2, 2)
|
||||||
this.colorFullCylinder.material.map = texture
|
this.colorFullCylinder.material.map = texture
|
||||||
})
|
})
|
||||||
this.colorFullCylinder.material.opacity = 0.7
|
this.colorFullCylinder.material.opacity = 0.7
|
||||||
@ -62,6 +64,8 @@ export class Vortex extends THREE.Group {
|
|||||||
this.darkMoveForward = 0.009
|
this.darkMoveForward = 0.009
|
||||||
this.colorFullTextureRotation = 0.006
|
this.colorFullTextureRotation = 0.006
|
||||||
this.colorFullMoveForward = 0.025
|
this.colorFullMoveForward = 0.025
|
||||||
|
|
||||||
|
this.visible = true
|
||||||
break
|
break
|
||||||
|
|
||||||
case "Espace":
|
case "Espace":
|
||||||
@ -86,17 +90,29 @@ export class Vortex extends THREE.Group {
|
|||||||
this.darkMoveForward = 0.03
|
this.darkMoveForward = 0.03
|
||||||
this.colorFullTextureRotation = 0.006
|
this.colorFullTextureRotation = 0.006
|
||||||
this.colorFullMoveForward = 0.012
|
this.colorFullMoveForward = 0.012
|
||||||
|
|
||||||
|
this.visible = true
|
||||||
|
break
|
||||||
|
|
||||||
|
case "Rétro":
|
||||||
|
this.visible = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(delta) {
|
update(delta) {
|
||||||
this.rotation.y += this.globalRotation * delta
|
if (this.visible) {
|
||||||
|
this.rotation.y += this.globalRotation * delta
|
||||||
this.darkCylinder.material.map.offset.y += this.darkMoveForward * delta
|
|
||||||
this.darkCylinder.material.map.offset.x += this.darkTextureRotation * delta
|
if (this.darkCylinder.material.map) {
|
||||||
|
this.darkCylinder.material.map.offset.y += this.darkMoveForward * delta
|
||||||
this.colorFullCylinder.material.map.offset.y += this.colorFullMoveForward * delta
|
this.darkCylinder.material.map.offset.x += this.darkTextureRotation * delta
|
||||||
this.colorFullCylinder.material.map.offset.x += this.colorFullTextureRotation * delta
|
}
|
||||||
|
|
||||||
|
if (this.colorFullCylinder.material.map) {
|
||||||
|
this.colorFullCylinder.material.map.offset.y += this.colorFullMoveForward * delta
|
||||||
|
this.colorFullCylinder.material.map.offset.x += this.colorFullTextureRotation * delta
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -33,7 +33,7 @@ class Scheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const scheduler = new Scheduler
|
const scheduler = new Scheduler()
|
||||||
|
|
||||||
|
|
||||||
export { scheduler }
|
export { scheduler }
|
Loading…
x
Reference in New Issue
Block a user