refactoring

This commit is contained in:
Adrien MALINGREY 2024-10-03 00:18:42 +02:00
parent 5b058a58b3
commit d3f6cf9b71
3 changed files with 105 additions and 120 deletions

11
app.js
View File

@ -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, environment, Mino, Playfield, HoldQueue, NextQueue } from './jsm/Tetrominoes.js' import { TRANSLATION, ROTATION, environment, InstancedMino, 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 { Menu } from './jsm/Menu.js' import { Menu } from './jsm/Menu.js'
@ -30,7 +30,7 @@ let game = {
menu.stats.show() menu.stats.show()
menu.settings.close() menu.settings.close()
Mino.meshes.clear() Mino.instances.clear()
nextQueue.init() nextQueue.init()
holdQueue.piece = undefined holdQueue.piece = undefined
@ -299,7 +299,8 @@ 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)
scene.add(Mino.meshes) const minoes = new InstancedMino()
scene.add(minoes)
const holdQueue = new HoldQueue() const holdQueue = new HoldQueue()
scene.add(holdQueue) scene.add(holdQueue)
const playfield = new Playfield(loadingManager) const playfield = new Playfield(loadingManager)
@ -307,7 +308,7 @@ scene.add(playfield)
const nextQueue = new NextQueue() const nextQueue = new NextQueue()
scene.add(nextQueue) scene.add(nextQueue)
const menu = new Menu(game, settings, stats, scene, controls, playfield) const menu = new Menu(game, settings, stats, scene, minoes, playfield)
menu.load() menu.load()
let fps let fps
@ -328,7 +329,7 @@ function animate() {
scene.updateMatrixWorld() scene.updateMatrixWorld()
scene.update(delta) scene.update(delta)
playfield.update(delta) playfield.update(delta)
Mino.meshes.update() minoes.update()
controls.update() controls.update()
renderer.render(scene, scene.camera) renderer.render(scene, scene.camera)

View File

@ -4,7 +4,7 @@ import { Mino, environment } from './Tetrominoes.js'
export class Menu extends GUI { export class Menu extends GUI {
constructor(game, settings, stats, scene, controls, playfield) { constructor(game, settings, stats, scene, minoes, playfield) {
super({title: "ᵀᴱTᴿᴬ"}) super({title: "ᵀᴱTᴿᴬ"})
this.startButton = this.add(game, "start").name("Jouer").hide() this.startButton = this.add(game, "start").name("Jouer").hide()
@ -28,7 +28,7 @@ export class Menu extends GUI {
this.settings.add(settings, "theme", ["Plasma", "Espace", "Rétro"]).name("Thème").onChange(theme => { this.settings.add(settings, "theme", ["Plasma", "Espace", "Rétro"]).name("Thème").onChange(theme => {
scene.theme = theme scene.theme = theme
Mino.meshes.theme = theme minoes.theme = theme
if (theme == "Rétro") { if (theme == "Rétro") {
playfield.edge.visible = false playfield.edge.visible = false
playfield.retroEdge.visible = true playfield.retroEdge.visible = true
@ -77,10 +77,10 @@ export class Menu extends GUI {
function changeMaterial() { function changeMaterial() {
material?.destroy() material?.destroy()
material = dev.addFolder("minoes material") material = dev.addFolder("minoes material")
material.add(Mino.meshes.material, "constructor", ["MeshBasicMaterial", "MeshStandardMaterial", "MeshPhysicalMaterial"]).listen().onChange(type => { material.add(minoes.material, "constructor", ["MeshBasicMaterial", "MeshStandardMaterial", "MeshPhysicalMaterial"]).listen().onChange(type => {
switch(type) { switch(type) {
case "MeshBasicMaterial": case "MeshBasicMaterial":
Mino.meshes.material = new THREE.MeshBasicMaterial({ minoes.material = new THREE.MeshBasicMaterial({
envMap: environment, envMap: environment,
side: THREE.DoubleSide, side: THREE.DoubleSide,
transparent: true, transparent: true,
@ -89,7 +89,7 @@ export class Menu extends GUI {
}) })
break break
case "MeshStandardMaterial": case "MeshStandardMaterial":
Mino.meshes.material = new THREE.MeshStandardMaterial({ minoes.material = new THREE.MeshStandardMaterial({
envMap: environment, envMap: environment,
side: THREE.DoubleSide, side: THREE.DoubleSide,
transparent: true, transparent: true,
@ -99,7 +99,7 @@ export class Menu extends GUI {
}) })
break break
case "MeshPhysicalMaterial": case "MeshPhysicalMaterial":
Mino.meshes.material = new THREE.MeshPhysicalMaterial({ minoes.material = new THREE.MeshPhysicalMaterial({
envMap: environment, envMap: environment,
side: THREE.DoubleSide, side: THREE.DoubleSide,
transparent: true, transparent: true,
@ -111,11 +111,11 @@ export class Menu extends GUI {
}) })
break break
} }
Mino.meshes.update = Mino.meshes.updateColor minoes.update = minoes.updateColor
changeMaterial() changeMaterial()
}) })
let minoMaterial = Mino.meshes.material instanceof Array ? Mino.meshes.material[0] : Mino.meshes.material let minoMaterial = minoes.material instanceof Array ? minoes.material[0] : minoes.material
if ("opacity" in minoMaterial) material.add(minoMaterial, "opacity" ).min(0).max(1) 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 ("reflectivity" in minoMaterial) material.add(minoMaterial, "reflectivity" ).min(0).max(1)
if ("roughness" in minoMaterial) material.add(minoMaterial, "roughness" ).min(0).max(1) if ("roughness" in minoMaterial) material.add(minoMaterial, "roughness" ).min(0).max(1)
@ -152,7 +152,7 @@ export class Menu extends GUI {
vortex.add(scene.vortex.darkCylinder.material, "opacity").name("dark").min(0).max(1) vortex.add(scene.vortex.darkCylinder.material, "opacity").name("dark").min(0).max(1)
vortex.add(scene.vortex.colorFullCylinder.material, "opacity").name("colorFull").min(0).max(1) vortex.add(scene.vortex.colorFullCylinder.material, "opacity").name("colorFull").min(0).max(1)
changeMaterial(Mino.meshes.material.constructor.name) changeMaterial(minoes.material.constructor.name)
material.close() material.close()
} }
} }

View File

@ -69,107 +69,7 @@ const sideMaterial = new THREE.MeshStandardMaterial({
}) })
class InstancedMino extends THREE.InstancedMesh { export class InstancedMino extends THREE.InstancedMesh {
constructor(geometry, material, count) {
super(geometry, material, count)
this.instances = new Set()
this.count = 0
this.offsets = new Uint8Array(2*count)
this.update = this.updateColor
}
add(instance) {
this.instances.add(instance)
}
delete(instance) {
this.instances.delete(instance)
}
clear() {
this.instances.clear()
}
set theme(theme) {
if (theme == "Rétro") {
this.resetColor()
this.update = this.updateOffset
if (Mino.materials["Rétro"]) {
this.material = Mino.materials["Rétro"]
} else {
Mino.materials["Rétro"] = []
const loadingManager = new THREE.LoadingManager(() => InstancedMino.material = Mino.materials["Rétro"])
new THREE.TextureLoader(loadingManager).load("images/sprites.png", (texture) => {
Mino.materials.Rétro[0] = Mino.materials.Rétro[2] = new TileMaterial({
color: COLORS.RETRO,
map: texture,
bumpMap: texture,
bumpScale: 1.5,
roughness: 0.25,
metalness: 0.9,
transparent: true,
}, 8, 8)
})
new THREE.TextureLoader(loadingManager).load("images/edges.png", (texture) => {
Mino.materials.Rétro[1] = Mino.materials.Rétro[3] = Mino.materials.Rétro[4] = Mino.materials.Rétro[5] = new TileMaterial({
color: COLORS.RETRO,
map: texture,
bumpMap: texture,
bumpScale: 1.5,
roughness: 0.25,
metalness: 0.9,
transparent: true,
}, 1, 1)
})
}
} else {
this.update = this.updateColor
this.material = Mino.materials[theme]
}
}
setOffsetAt(index, offset) {
this.offsets[2*index] = offset.x
this.offsets[2*index + 1] = offset.y
}
resetColor() {
this.instanceColor = null
}
updateColor() {
this.count = 0
this.instances.forEach(mino => {
if (mino.parent?.visible) {
this.setMatrixAt(this.count, mino.matrixWorld)
this.setColorAt(this.count, mino.color)
this.count++
}
})
if (this.count) {
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 {
static materials = { static materials = {
Plasma: new THREE.MeshStandardMaterial({ Plasma: new THREE.MeshStandardMaterial({
envMap: environment, envMap: environment,
@ -188,8 +88,8 @@ class Mino extends THREE.Object3D {
metalness: 0.99, metalness: 0.99,
}) })
} }
static meshes
static { constructor() {
let minoFaceShape = new THREE.Shape() let minoFaceShape = new THREE.Shape()
minoFaceShape.moveTo(.1, .1) minoFaceShape.moveTo(.1, .1)
minoFaceShape.lineTo(.1, .9) minoFaceShape.lineTo(.1, .9)
@ -206,9 +106,93 @@ class Mino extends THREE.Object3D {
bevelSegments: 1 bevelSegments: 1
} }
const geometry = new THREE.ExtrudeGeometry(minoFaceShape, minoExtrudeSettings) const geometry = new THREE.ExtrudeGeometry(minoFaceShape, minoExtrudeSettings)
this.meshes = new InstancedMino(geometry, undefined, 2*ROWS*COLUMNS) super(geometry, undefined, 2*ROWS*COLUMNS)
this.offsets = new Uint8Array(2*this.count)
this.count = 0
} }
set theme(theme) {
if (theme == "Rétro") {
this.resetColor()
this.update = this.updateOffset
if (this.constructor.materials["Rétro"]) {
this.material = this.constructor.materials["Rétro"]
} else {
this.constructor.materials["Rétro"] = []
const loadingManager = new THREE.LoadingManager(() => this.material = this.constructor.materials["Rétro"])
new THREE.TextureLoader(loadingManager).load("images/sprites.png", (texture) => {
this.constructor.materials.Rétro[0] = this.constructor.materials.Rétro[2] = new TileMaterial({
color: COLORS.RETRO,
map: texture,
bumpMap: texture,
bumpScale: 1.4,
roughness: 0.25,
metalness: 0.9,
transparent: true,
}, 8, 8)
})
new THREE.TextureLoader(loadingManager).load("images/edges.png", (texture) => {
this.constructor.materials.Rétro[1] = this.constructor.materials.Rétro[3] = this.constructor.materials.Rétro[4] = this.constructor.materials.Rétro[5] = new TileMaterial({
color: COLORS.RETRO,
map: texture,
bumpMap: texture,
bumpScale: 1.4,
roughness: 0.25,
metalness: 0.9,
transparent: true,
}, 1, 1)
})
}
} else {
this.update = this.updateColor
this.material = this.constructor.materials[theme]
}
}
setOffsetAt(index, offset) {
this.offsets[2*index] = offset.x
this.offsets[2*index + 1] = offset.y
}
resetColor() {
this.instanceColor = null
}
updateColor() {
this.count = 0
Mino.instances.forEach(mino => {
if (mino.parent?.visible) {
this.setMatrixAt(this.count, mino.matrixWorld)
this.setColorAt(this.count, mino.color)
this.count++
}
})
if (this.count) {
this.instanceMatrix.needsUpdate = true
this.instanceColor.needsUpdate = true
}
}
updateOffset() {
this.count = 0
Mino.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 {
static instances = new Set()
constructor(color, offset) { constructor(color, offset) {
super() super()
this.color = color this.color = color
@ -216,7 +200,7 @@ class Mino extends THREE.Object3D {
this.velocity = P(50 - 100 * Math.random(), 60 - 100 * Math.random(), 50 - 100 * Math.random()) this.velocity = P(50 - 100 * Math.random(), 60 - 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.meshes.add(this) this.constructor.instances.add(this)
} }
explode(delta) { explode(delta) {
@ -232,7 +216,7 @@ class Mino extends THREE.Object3D {
} }
dispose() { dispose() {
this.constructor.meshes.delete(this) this.constructor.instances.delete(this)
} }
} }