game over slow down fx (fixes #39)
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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
|
||||
});
|
||||
13
src/components/debug-states.js
Normal file
13
src/components/debug-states.js
Normal file
@@ -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');
|
||||
}
|
||||
});
|
||||
40
src/components/gameover.js
Normal file
40
src/components/gameover.js
Normal file
@@ -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');
|
||||
}
|
||||
});
|
||||
@@ -20,6 +20,7 @@ AFRAME.registerComponent('pauser', {
|
||||
events.forEach(event => {
|
||||
this.el.addEventListener(event, this.pauseGame);
|
||||
});
|
||||
document.addEventListener('keydown', this.pauseGame);
|
||||
},
|
||||
|
||||
pauseGame: function () {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -8,12 +8,15 @@
|
||||
<body>
|
||||
<audio id="introSong" src="assets/sounds/introSong.ogg" loop></audio>
|
||||
|
||||
{% include './templates/debugStates.html' %}
|
||||
|
||||
<a-scene
|
||||
bind__beat-loader="challengeId: challenge.id; difficulty: challenge.difficulty; isPaused: !isPlaying"
|
||||
bind__beat-loader="challengeId: challenge.id; difficulty: challenge.difficulty; isPaused: !isPlaying && !isGameOver"
|
||||
bind__intro-song="isPlaying: menu.active && !menuSelectedChallenge.id"
|
||||
bind__song="challengeId: challenge.id; isPlaying: isPlaying && !challenge.isLoading"
|
||||
bind__song-preview-system="selectedChallengeId: menuSelectedChallenge.id"
|
||||
bind__overlay="enabled: !isPlaying"
|
||||
bind__debug-states="isPlaying: isPlaying; isPaused: isPaused; isGameOver: isGameOver"
|
||||
console-shortcuts
|
||||
debug-controller
|
||||
effect-bloom="strength: 1"
|
||||
@@ -29,6 +32,7 @@
|
||||
proxy-event__cleargame2="event: pausemenurestart; as: cleargame; to: a-scene"
|
||||
search
|
||||
stage-colors="blue"
|
||||
bind__gameover="start: isGameOver; reset: isPlaying && !isGameOver || menu.active"
|
||||
fog="color: #a00; density: 0.035; type: exponential">
|
||||
<a-assets timeout="10000">
|
||||
<a-asset-item id="arrowObj" src="assets/models/arrow.obj"></a-asset-item>
|
||||
|
||||
@@ -296,7 +296,7 @@ function checkGameOver (state) {
|
||||
if (state.damage >= DAMAGE_MAX) {
|
||||
state.damage = 0;
|
||||
state.isGameOver = true;
|
||||
state.isPaused = true;
|
||||
//state.isPaused = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
26
src/templates/debugStates.html
Normal file
26
src/templates/debugStates.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<style type="text/css">
|
||||
#debugStates{
|
||||
position: absolute;
|
||||
z-index: 999999;
|
||||
margin: 0.3rem;
|
||||
font: 14px sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
#debugStates span{
|
||||
display: inline-block;
|
||||
padding: 1rem;
|
||||
margin: 0.3rem;
|
||||
background: #000;
|
||||
color: #fff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
#debugStates span.active{
|
||||
background: #5af;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
<div id="debugStates">
|
||||
<span id="debugIsGameOver">isGameOver</span>
|
||||
<span id="debugIsPaused">isPaused</span>
|
||||
<span id="debugIsPlaying">isPlaying</span>
|
||||
</div>
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
<a-entity id="beams" bind__beams="isPlaying: isPlaying"></a-entity>
|
||||
|
||||
<a-entity mixin="textFont" text="value: READY, STEADY...; align: center; color: #aaf; wrapCount: 18; width: 2" position="0 1.5 -2.5" bind__visible="challenge.isLoading"></a-entity>
|
||||
<a-entity mixin="textFont" text="value: READY, STEADY...; align: center; color: #aaf; wrapCount: 18; width: 2" position="0 1.5 -2.5" bind__visible="challenge.isLoading && !isGameOver"></a-entity>
|
||||
|
||||
<a-entity light="type: directional; intensity: 3" position="0 10 10"></a-entity>
|
||||
|
||||
|
||||
33
test.html
Normal file
33
test.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
let audio = document.createElement('audio');
|
||||
audio.crossOrigin = 'anonymous';
|
||||
audio.setAttribute('src', "https://s3-us-west-2.amazonaws.com/supersaber/106-song.ogg");
|
||||
|
||||
// var ctx = new AudioContext();
|
||||
// var audioSrc = ctx.createMediaElementSource(audio);
|
||||
// var analyser = ctx.createAnalyser();
|
||||
// audioSrc.connect(analyser);
|
||||
// var frequencyData = new Uint8Array(analyser.frequencyBinCount);
|
||||
// analyser.getByteFrequencyData(frequencyData);
|
||||
|
||||
var r = 1;
|
||||
var v = 1;
|
||||
audio.play();
|
||||
setTimeout(rate, 100);
|
||||
function rate(){
|
||||
if (r < 0.5) return;
|
||||
r -= 0.01;
|
||||
v -= 0.02;
|
||||
audio.playbackRate = r;
|
||||
audio.volume = Math.max(0, v);
|
||||
setTimeout(rate, 100);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user