refactoring
This commit is contained in:
parent
5b058a58b3
commit
d3f6cf9b71
11
app.js
11
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, 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)
|
||||||
|
18
jsm/Menu.js
18
jsm/Menu.js
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user