Compare commits
9 Commits
d3f6cf9b71
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| c52a604f0f | |||
| 8e9a089d34 | |||
| d5893eb8ef | |||
| 1e006d46b9 | |||
| 0f84f90e05 | |||
| 4287edab71 | |||
| 5c2eaca35a | |||
| e7dc780173 | |||
| 9721b311eb |
5
README.md
Normal file
5
README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# teTra
|
||||
|
||||
Falling blocks web game made with three.js librairy
|
||||
|
||||

|
||||
4
app.js
4
app.js
@ -4,7 +4,7 @@ import { TRANSLATION, ROTATION, environment, InstancedMino, Mino, Playfield, Hol
|
||||
import Settings from './jsm/Settings.js'
|
||||
import { Stats } from './jsm/Stats.js'
|
||||
import { Menu } from './jsm/Menu.js'
|
||||
import TetraControls from './jsm/TetraControls.js'
|
||||
import CameraControls from './jsm/CameraControls.js'
|
||||
import { TetraScene } from './jsm/TetraScene.js'
|
||||
import * as FPS from 'three/addons/libs/stats.module.js'
|
||||
|
||||
@ -297,7 +297,7 @@ loadingManager.onStart = function (url, itemsLoaded, itemsTotal) {
|
||||
const stats = new Stats()
|
||||
const settings = new Settings()
|
||||
const scene = new TetraScene(settings, loadingManager)
|
||||
const controls = new TetraControls(scene.camera, renderer.domElement)
|
||||
const controls = new CameraControls(scene.camera, renderer.domElement)
|
||||
|
||||
const minoes = new InstancedMino()
|
||||
scene.add(minoes)
|
||||
|
||||
@ -48,10 +48,10 @@
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.first.mino { top: -0.5em; left: -1em; }
|
||||
.second.mino { top: -0.5em; left: 0em; }
|
||||
.third.mino { top: -0.5em; left: 1em; }
|
||||
.fourth.mino { top: 0.5em; left: 0em; }
|
||||
.T.tetromino .first.mino { top: -0.5em; left: -1em; }
|
||||
.T.tetromino .second.mino { top: -0.5em; left: 0em; }
|
||||
.T.tetromino .third.mino { top: -0.5em; left: 1em; }
|
||||
.T.tetromino .fourth.mino { top: 0.5em; left: 0em; }
|
||||
|
||||
.face {
|
||||
position: absolute;
|
||||
|
||||
11
index.html
11
index.html
@ -8,6 +8,15 @@
|
||||
<link rel="icon" href="favicon.ico">
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<link rel="stylesheet" href="css/loading.css">
|
||||
<meta property="og:title" content="ᵀᴱTᴿᴬ"/>
|
||||
<meta property="og:type" content="game"/>
|
||||
<meta property="og:url" content="https://adrien.malingrey.fr/jeux/tetra/"/>
|
||||
<meta property="og:image" content="https://adrien.malingrey.fr/jeux/tetra/thumbnail.png"/>
|
||||
<meta property="og:image:width" content="250"/>
|
||||
<meta property="og:image:height" content="250"/>
|
||||
<meta property="og:description" content="Des blocs qui tombent en 3D"/>
|
||||
<meta property="og:locale" content="fr_FR"/>
|
||||
<meta property="og:site_name" content="adrien.malingrey.fr"/>
|
||||
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
|
||||
<script type="importmap">
|
||||
{
|
||||
@ -22,7 +31,7 @@
|
||||
<body>
|
||||
<span id="loadingDiv">
|
||||
<div class="scene">
|
||||
<div class="tetromino">
|
||||
<div class="T tetromino">
|
||||
<div class="first mino">
|
||||
<div class="front face"></div>
|
||||
<div class="back face"></div>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
|
||||
|
||||
|
||||
export default class TetraControls extends OrbitControls {
|
||||
export default class CameraControls extends OrbitControls {
|
||||
constructor(camera, domElement) {
|
||||
super(camera, domElement)
|
||||
this.autoRotate
|
||||
22
jsm/Menu.js
22
jsm/Menu.js
@ -1,6 +1,6 @@
|
||||
import * as THREE from 'three'
|
||||
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'
|
||||
import { Mino, environment } from './Tetrominoes.js'
|
||||
import { environment } from './Tetrominoes.js'
|
||||
|
||||
|
||||
export class Menu extends GUI {
|
||||
@ -43,21 +43,21 @@ export class Menu extends GUI {
|
||||
|
||||
this.settings.key = this.settings.addFolder("Commandes").open()
|
||||
let moveLeftKeyController = this.settings.key.add(settings.key, "moveLeft").name('Gauche')
|
||||
moveLeftKeyController.domElement.onclick = this.changeKey.bind(moveLeftKeyController)
|
||||
moveLeftKeyController.domElement.onclick = this.changeKey(moveLeftKeyController)
|
||||
let moveRightKeyController = this.settings.key.add(settings.key, "moveRight").name('Droite')
|
||||
moveRightKeyController.domElement.onclick = this.changeKey.bind(moveRightKeyController)
|
||||
moveRightKeyController.domElement.onclick = this.changeKey(moveRightKeyController)
|
||||
let rotateCWKeyController = this.settings.key.add(settings.key, "rotateCW").name('Rotation horaire')
|
||||
rotateCWKeyController.domElement.onclick = this.changeKey.bind(rotateCWKeyController)
|
||||
rotateCWKeyController.domElement.onclick = this.changeKey(rotateCWKeyController)
|
||||
let rotateCCWKeyController = this.settings.key.add(settings.key, "rotateCCW").name('anti-horaire')
|
||||
rotateCCWKeyController.domElement.onclick = this.changeKey.bind(rotateCCWKeyController)
|
||||
rotateCCWKeyController.domElement.onclick = this.changeKey(rotateCCWKeyController)
|
||||
let softDropKeyController = this.settings.key.add(settings.key, "softDrop").name('Chute lente')
|
||||
softDropKeyController.domElement.onclick = this.changeKey.bind(softDropKeyController)
|
||||
softDropKeyController.domElement.onclick = this.changeKey(softDropKeyController)
|
||||
let hardDropKeyController = this.settings.key.add(settings.key, "hardDrop").name('Chute rapide')
|
||||
hardDropKeyController.domElement.onclick = this.changeKey.bind(hardDropKeyController)
|
||||
hardDropKeyController.domElement.onclick = this.changeKey(hardDropKeyController)
|
||||
let holdKeyController = this.settings.key.add(settings.key, "hold").name('Garder')
|
||||
holdKeyController.domElement.onclick = this.changeKey.bind(holdKeyController)
|
||||
holdKeyController.domElement.onclick = this.changeKey(holdKeyController)
|
||||
let pauseKeyController = this.settings.key.add(settings.key, "pause").name('Pause')
|
||||
pauseKeyController.domElement.onclick = this.changeKey.bind(pauseKeyController)
|
||||
pauseKeyController.domElement.onclick = this.changeKey(pauseKeyController)
|
||||
|
||||
this.settings.delay = this.settings.addFolder("Répétition automatique").open()
|
||||
this.settings.delay.add(settings,"arrDelay").name("ARR (ms)").min(2).max(200).step(1);
|
||||
@ -167,8 +167,8 @@ export class Menu extends GUI {
|
||||
localStorage["teTraSettings"] = JSON.stringify(this.settings.save())
|
||||
}
|
||||
|
||||
changeKey() {
|
||||
let controller = this.settings
|
||||
changeKey(settings) {
|
||||
let controller = settings
|
||||
let input = controller.domElement.getElementsByTagName("input")[0]
|
||||
input.select()
|
||||
input.onkeydown = function (event) {
|
||||
|
||||
@ -70,25 +70,6 @@ const sideMaterial = new THREE.MeshStandardMaterial({
|
||||
|
||||
|
||||
export class InstancedMino extends THREE.InstancedMesh {
|
||||
static materials = {
|
||||
Plasma: new THREE.MeshStandardMaterial({
|
||||
envMap: environment,
|
||||
side: THREE.DoubleSide,
|
||||
transparent: true,
|
||||
opacity: 0.7,
|
||||
roughness: 0.6,
|
||||
metalness: 1,
|
||||
}),
|
||||
Espace: new THREE.MeshStandardMaterial({
|
||||
envMap: environment,
|
||||
side: THREE.DoubleSide,
|
||||
transparent: true,
|
||||
opacity: 0.8,
|
||||
roughness: 0.1,
|
||||
metalness: 0.99,
|
||||
})
|
||||
}
|
||||
|
||||
constructor() {
|
||||
let minoFaceShape = new THREE.Shape()
|
||||
minoFaceShape.moveTo(.1, .1)
|
||||
@ -108,35 +89,34 @@ export class InstancedMino extends THREE.InstancedMesh {
|
||||
const geometry = new THREE.ExtrudeGeometry(minoFaceShape, minoExtrudeSettings)
|
||||
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"]
|
||||
if (this.materials["Rétro"]) {
|
||||
this.material = this.materials["Rétro"]
|
||||
} else {
|
||||
this.constructor.materials["Rétro"] = []
|
||||
const loadingManager = new THREE.LoadingManager(() => this.material = this.constructor.materials["Rétro"])
|
||||
this.materials["Rétro"] = []
|
||||
const loadingManager = new THREE.LoadingManager(() => this.material = this.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({
|
||||
this.materials.Rétro[0] = this.materials.Rétro[2] = new TileMaterial({
|
||||
color: COLORS.RETRO,
|
||||
map: texture,
|
||||
bumpMap: texture,
|
||||
bumpScale: 1.4,
|
||||
bumpScale: 1.5,
|
||||
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({
|
||||
this.materials.Rétro[1] = this.materials.Rétro[3] = this.materials.Rétro[4] = this.materials.Rétro[5] = new TileMaterial({
|
||||
color: COLORS.RETRO,
|
||||
map: texture,
|
||||
bumpMap: texture,
|
||||
bumpScale: 1.4,
|
||||
bumpScale: 1.5,
|
||||
roughness: 0.25,
|
||||
metalness: 0.9,
|
||||
transparent: true,
|
||||
@ -145,7 +125,7 @@ export class InstancedMino extends THREE.InstancedMesh {
|
||||
}
|
||||
} else {
|
||||
this.update = this.updateColor
|
||||
this.material = this.constructor.materials[theme]
|
||||
this.material = this.materials[theme]
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,6 +168,24 @@ export class InstancedMino extends THREE.InstancedMesh {
|
||||
}
|
||||
}
|
||||
}
|
||||
InstancedMino.prototype.materials = {
|
||||
Plasma: new THREE.MeshStandardMaterial({
|
||||
envMap: environment,
|
||||
side: THREE.DoubleSide,
|
||||
transparent: true,
|
||||
opacity: 0.7,
|
||||
roughness: 0.6,
|
||||
metalness: 1,
|
||||
}),
|
||||
Espace: new THREE.MeshStandardMaterial({
|
||||
envMap: environment,
|
||||
side: THREE.DoubleSide,
|
||||
transparent: true,
|
||||
opacity: 0.8,
|
||||
roughness: 0.1,
|
||||
metalness: 0.99,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
class Mino extends THREE.Object3D {
|
||||
|
||||
@ -70,10 +70,10 @@ export class Vortex extends THREE.Group {
|
||||
new THREE.TextureLoader(this.loadingManager).load("./images/dark.jpg", texture => {
|
||||
texture.wrapS = THREE.RepeatWrapping
|
||||
texture.wrapT = THREE.MirroredRepeatWrapping
|
||||
texture.repeat.set(2, 2)
|
||||
texture.repeat.set(2, 4)
|
||||
this.darkCylinder.material.map = texture
|
||||
})
|
||||
this.darkCylinder.material.opacity = 0.05
|
||||
this.darkCylinder.material.opacity = 0.08
|
||||
|
||||
new THREE.TextureLoader(this.loadingManager).load("./images/colorfull.jpg", texture => {
|
||||
texture.wrapS = THREE.RepeatWrapping
|
||||
@ -81,7 +81,7 @@ export class Vortex extends THREE.Group {
|
||||
texture.repeat.set(2, 2)
|
||||
this.colorFullCylinder.material.map = texture
|
||||
})
|
||||
this.colorFullCylinder.material.opacity = 0.14
|
||||
this.colorFullCylinder.material.opacity = 0.15
|
||||
|
||||
this.globalRotation = 0.028
|
||||
this.darkTextureRotation = 0.006
|
||||
|
||||
Reference in New Issue
Block a user