From b7e36bf760b6a37bc4d32c43c5427cf86f9f8c1f Mon Sep 17 00:00:00 2001 From: "Diego F. Goberna" Date: Tue, 9 Oct 2018 21:36:35 +0200 Subject: [PATCH] game over slow down fx (fixes #39) --- src/components/beams.js | 2 +- src/components/beat-loader.js | 9 ++++++++ src/components/beat.js | 29 +++++++++++++++++++++--- src/components/debug-states.js | 13 +++++++++++ src/components/gameover.js | 40 ++++++++++++++++++++++++++++++++++ src/components/pauser.js | 1 + src/components/song.js | 15 +++++++++++++ src/components/stage-colors.js | 29 ++++++++++++++++++++++-- src/index.html | 6 ++++- src/state/index.js | 2 +- src/templates/debugStates.html | 26 ++++++++++++++++++++++ src/templates/stage.html | 2 +- test.html | 33 ++++++++++++++++++++++++++++ 13 files changed, 198 insertions(+), 9 deletions(-) create mode 100644 src/components/debug-states.js create mode 100644 src/components/gameover.js create mode 100644 src/templates/debugStates.html create mode 100644 test.html diff --git a/src/components/beams.js b/src/components/beams.js index 64fd1bd..723d6c7 100644 --- a/src/components/beams.js +++ b/src/components/beams.js @@ -26,7 +26,7 @@ AFRAME.registerComponent('beams', { blending: THREE.AdditiveBlending }; redMaterial = new THREE.MeshBasicMaterial(materialOptions); - materialOptions.color = 0x4444cc; + materialOptions.color = 0x3333aa; blueMaterial = new THREE.MeshBasicMaterial(materialOptions); geo = new THREE.PlaneBufferGeometry(0.4, 50).translate(0, 25, 0); diff --git a/src/components/beat-loader.js b/src/components/beat-loader.js index 06d83ed..f6f0a32 100644 --- a/src/components/beat-loader.js +++ b/src/components/beat-loader.js @@ -24,8 +24,10 @@ AFRAME.registerComponent('beat-loader', { this.bpm = undefined; this.first = null; this.lastTime = undefined; + this.speed = 1.0; // for slowing down on gameover this.el.addEventListener('cleargame', this.clearBeats.bind(this)); + this.el.addEventListener('slowdown', this.slowDown.bind(this)); }, update: function (oldData) { @@ -84,6 +86,8 @@ AFRAME.registerComponent('beat-loader', { var msPerBeat; var noteTime; + delta *= this.speed; + if (this.data.isPaused || !this.data.challengeId || !this.beatData || !audioEl) { return; } notes = this.beatData._notes; @@ -195,8 +199,13 @@ AFRAME.registerComponent('beat-loader', { this.audioSync = null; this.first = null; this.lastTime = 0; + this.speed = 1.0; for (let i = 0; i < this.beatContainer.children.length; i++) { this.beatContainer.children[i].components.beat.returnToPool(true); } + }, + + slowDown: function (ev) { + this.speed = ev.detail.progress; } }); diff --git a/src/components/beat.js b/src/components/beat.js index b08a7ed..bb9f1d2 100644 --- a/src/components/beat.js +++ b/src/components/beat.js @@ -76,6 +76,10 @@ AFRAME.registerComponent('beat', { var blockEl = this.blockEl = document.createElement('a-entity'); var signEl = this.signEl = document.createElement('a-entity'); + this.el.object3D.visible = true; + blockEl.setAttribute('material', {opacity: 1}); + signEl.setAttribute('material', {opacity: 1}); + // Small offset to prevent z-fighting when the blocks are far away signEl.object3D.position.z += 0.02; blockEl.appendChild(signEl); @@ -430,20 +434,30 @@ AFRAME.registerComponent('beat', { } } - this.el.object3D.position.z += this.data.speed * (timeDelta / 1000); + this.el.object3D.position.z += this.data.speed * this.system.speed * (timeDelta / 1000); this.backToPool = this.el.object3D.position.z >= 2; + + if (this.system.speed < 1.0) { + if (this.system.speed <= 0){ + this.el.object3D.visible = false; + } + else { + this.blockEl.setAttribute('material', {opacity: this.system.speed}); + this.signEl.setAttribute('material', {opacity: this.system.speed}); + } + } } else { // Update gravity velocity. this.gravityVelocity = getGravityVelocity(this.gravityVelocity, timeDelta); this.el.object3D.position.y += this.gravityVelocity * (timeDelta / 1000); - rightCutNormal.copy(this.rightCutPlane.normal).multiplyScalar((this.data.speed / 2) * (timeDelta / 500)); + rightCutNormal.copy(this.rightCutPlane.normal).multiplyScalar((this.data.speed * this.system.speed / 2) * (timeDelta / 500)); rightCutNormal.y = 0; // Y handled by gravity. this.partRightEl.object3D.position.add(rightCutNormal); this.partRightEl.object3D.setRotationFromAxisAngle(this.rotationAxis, rightRotation); rightRotation = rightRotation >= 2 * Math.PI ? 0 : rightRotation + rotationStep; - leftCutNormal.copy(this.leftCutPlane.normal).multiplyScalar((this.data.speed / 2) * (timeDelta / 500)); + leftCutNormal.copy(this.leftCutPlane.normal).multiplyScalar((this.data.speed * this.system.speed / 2) * (timeDelta / 500)); leftCutNormal.y = 0; // Y handled by gravity. this.partLeftEl.object3D.position.add(leftCutNormal); this.partLeftEl.object3D.setRotationFromAxisAngle(this.rotationAxis, leftRotation); @@ -489,3 +503,12 @@ function getGravityVelocity (velocity, timeDelta) { const GRAVITY = -9.8; return velocity + (GRAVITY * (timeDelta / 1000)); } + + +/** + * Beat system to coordinate the speed down of all beats on game over + */ + +AFRAME.registerSystem('beat', { + speed: 1.0 +}); \ No newline at end of file diff --git a/src/components/debug-states.js b/src/components/debug-states.js new file mode 100644 index 0000000..89aeba1 --- /dev/null +++ b/src/components/debug-states.js @@ -0,0 +1,13 @@ +AFRAME.registerComponent('debug-states', { + schema: { + isPlaying: {default: false}, + isPaused: {default: false}, + isGameOver: {default: false} + }, + update: function(){ + document.getElementById('debugIsGameOver').className = this.data.isGameOver ? 'active': ''; + document.getElementById('debugIsPaused').className = this.data.isPaused ? 'active': ''; + document.getElementById('debugIsPlaying').className = this.data.isPlaying ? 'active': ''; + console.log(`%c gameover: ${this.data.isGameOver}, paused: ${this.data.isPaused}, playing: ${this.data.isPlaying}`, 'background: #222; color: #bada55'); + } +}); \ No newline at end of file diff --git a/src/components/gameover.js b/src/components/gameover.js new file mode 100644 index 0000000..adefc6e --- /dev/null +++ b/src/components/gameover.js @@ -0,0 +1,40 @@ +AFRAME.registerComponent('gameover', { + schema: { + start: {default: false}, + reset: {default: false} + }, + init: function () { + this.beatContainer = document.getElementById('beatContainer'); + }, + update: function (oldData) { + var data = this.data; + if (data.start){ + console.log('starting slow down...'); + this.el.sceneEl.setAttribute('stage-colors', 'red'); + this.countDown = 1; + this.lastTime = performance.now(); + } + if (data.reset && data.reset !== oldData.reset){ + this.resetStage(); + } + }, + tick: function (time, delta) { + if (!this.data.start) return; + if (this.countDown >= 0){ + this.el.sceneEl.emit('slowdown', {progress: this.countDown}); + //this.beatContainer.object3D.position.z = -Math.pow(1 - this.countDown, 2) * 1.5; + this.countDown -= delta / 1000; + this.el.sceneEl.systems.beat.speed = this.countDown; + } + else { + this.data.start = false; + setTimeout(()=>{ this.el.sceneEl.emit('pausegame'); }, 1000); + } + }, + resetStage: function () { + this.data.start = false; + this.beatContainer.object3D.position.z = 0; + this.el.sceneEl.systems.beat.speed = 1.0; + this.el.sceneEl.setAttribute('stage-colors', 'blue'); + } +}); \ No newline at end of file diff --git a/src/components/pauser.js b/src/components/pauser.js index c98275c..001a76a 100644 --- a/src/components/pauser.js +++ b/src/components/pauser.js @@ -20,6 +20,7 @@ AFRAME.registerComponent('pauser', { events.forEach(event => { this.el.addEventListener(event, this.pauseGame); }); + document.addEventListener('keydown', this.pauseGame); }, pauseGame: function () { diff --git a/src/components/song.js b/src/components/song.js index 364805b..230cd14 100644 --- a/src/components/song.js +++ b/src/components/song.js @@ -31,6 +31,8 @@ AFRAME.registerComponent('song', { audio.currentTime = 0; } }); + + this.el.addEventListener('slowdown', this.slowDown.bind(this)); }, update: function (oldData) { @@ -48,10 +50,23 @@ AFRAME.registerComponent('song', { if (data.isPlaying && data.challengeId && this.audio.paused) { console.log(`Playing ${this.audio.src}...`); this.data.analyserEl.setAttribute('audioanalyser', 'src', audio); + audio.playbackRate = 1; + audio.volume = 1; audio.play(); return; } else if ((!data.isPlaying || !data.challengeId) && !audio.paused) { audio.pause(); } + }, + + slowDown: function (ev) { + var progress = ev.detail.progress; + if (progress > 0.01){ + this.audio.playbackRate = 0.5 + progress / 2.0; + this.audio.volume = progress; + } + else { + this.audio.pause(); + } } }); diff --git a/src/components/stage-colors.js b/src/components/stage-colors.js index 87fa2b4..b80e817 100644 --- a/src/components/stage-colors.js +++ b/src/components/stage-colors.js @@ -22,12 +22,18 @@ AFRAME.registerComponent('stage-colors', { emissive: this.mineEmission[this.data], envMap: this.mineEnvMap[this.data] }); + this.sky = document.getElementById('sky'); + this.backglow = document.getElementById('backglow'); + this.smoke1 = document.getElementById('smoke1'); + this.smoke2 = document.getElementById('smoke2'); + this.auxColor = new THREE.Color(); + this.el.addEventListener('slowdown', this.slowDown.bind(this)); }, update: function () { const red = this.data === 'red'; - document.getElementById('backglow').setAttribute('material', 'color', red ? '#f10' : '#00acfc'); - document.getElementById('sky').setAttribute('material', 'color', red ? '#f10' : '#00acfc'); + this.backglow.setAttribute('material', {color: red ? '#f10' : '#00acfc', opacity: 0.8}); + this.sky.setAttribute('material', 'color', red ? '#f10' : '#00acfc'); this.el.setAttribute('background', 'color', red ? '#770100': '#15252d'); this.el.sceneEl.setAttribute('fog', 'color', red ? '#a00' : '#007cb9'); this.el.sceneEl.systems.materials.neon.color = red ? this.neonRed : this.neonBlue; @@ -35,6 +41,25 @@ AFRAME.registerComponent('stage-colors', { this.mineMaterial.color = this.mineColor[this.data]; this.mineMaterial.emissive = this.mineEmission[this.data]; this.mineMaterial.envMap = this.mineEnvMap[this.data]; + this.smoke1.setAttribute('material', 'opacity', 1); + this.smoke2.setAttribute('material', 'opacity', 1); + }, + + slowDown: function (ev) { + var progress = Math.max(0, ev.detail.progress); + + this.auxColor.setRGB(0.2 + progress * 0.46, 0, 0); + this.el.sceneEl.setAttribute('fog', 'color', '#' + this.auxColor.getHexString()); + + this.auxColor.setHSL(0.0014, 1, 0.23 * progress); + this.el.sceneEl.setAttribute('background', 'color', '#' + this.auxColor.getHexString()); + + this.auxColor.setRGB(0.1 + progress * 0.9, 0.066 * progress, 0); + this.sky.setAttribute('material', 'color', '#' + this.auxColor.getHexString()); + + this.backglow.setAttribute('material', 'opacity', 0.2 + progress * 0.5); + this.smoke1.setAttribute('material', 'opacity', progress); + this.smoke2.setAttribute('material', 'opacity', progress); } }); diff --git a/src/index.html b/src/index.html index 17be5e6..d401427 100644 --- a/src/index.html +++ b/src/index.html @@ -8,12 +8,15 @@ + {% include './templates/debugStates.html' %} + diff --git a/src/state/index.js b/src/state/index.js index 6314546..74cce30 100644 --- a/src/state/index.js +++ b/src/state/index.js @@ -296,7 +296,7 @@ function checkGameOver (state) { if (state.damage >= DAMAGE_MAX) { state.damage = 0; state.isGameOver = true; - state.isPaused = true; + //state.isPaused = true; } } diff --git a/src/templates/debugStates.html b/src/templates/debugStates.html new file mode 100644 index 0000000..96cc58a --- /dev/null +++ b/src/templates/debugStates.html @@ -0,0 +1,26 @@ + +
+ isGameOver + isPaused + isPlaying +
\ No newline at end of file diff --git a/src/templates/stage.html b/src/templates/stage.html index a7270e3..cf15e89 100644 --- a/src/templates/stage.html +++ b/src/templates/stage.html @@ -55,7 +55,7 @@ - + diff --git a/test.html b/test.html new file mode 100644 index 0000000..0d3f9fc --- /dev/null +++ b/test.html @@ -0,0 +1,33 @@ + + + + + + + + + \ No newline at end of file