improved score labels visual feedback (fixes #185)

This commit is contained in:
Diego F. Goberna
2018-11-20 22:35:40 +01:00
parent f0cedba9a5
commit 6845b5df37
5 changed files with 95 additions and 17 deletions

View File

@@ -75,7 +75,6 @@
<a-mixin
id="beatScore"
mixin="font"
score-beat
text="opacity: 0; wrapCount: 19; color: #AAA; width: 1.5"
animation__opacityin="property: components.text.material.uniforms.opacity.value; from: .5; to: 1; dur: 500; startEvents: beatscorestart"
animation__opacityout="property: components.text.material.uniforms.opacity.value; from: 1; to: 0; dur: 500; delay: 700; startEvents: beatscorestart"
@@ -83,6 +82,32 @@
animation__motiony="property: object3D.position.y; to: 0.1; dur: 500; easing: easeOutQuart; startEvents: beatscorestart"
></a-mixin>
<a-mixin
id="beatScoreOk"
score-beat="ok"
mixin="beatScore"
text="value: OK"></a-mixin>
<a-mixin
id="beatScoreGood"
score-beat="good"
mixin="beatScore"
text="value: GOOD; color: #A8E3FF"></a-mixin>
<a-mixin
id="beatScoreExcellent"
score-beat="excellent"
mixin="beatScore"
text="value: EXCELLENT; wrapCount: 16; color: #60CCFF"></a-mixin>
<a-mixin
id="beatScoreSuper"
score-beat="super"
mixin="beatScore"
text="value: SUPER!; wrapCount: 13; color: #00acfc"></a-mixin>
<a-mixin
id="superCut"
geometry="primitive: plane; width: 3; height: 3"
material="shader: superCutFxShader; transparent: true; depthWrite: false"></a-mixin>
<a-mixin
id="wall"
geometry

View File

@@ -8,13 +8,6 @@ const BEAT_WARMUP_ROTATION_TIME = 750;
const ONCE = {once: true};
const SIGN_MATERIAL = {shader: 'flat', color: '#88f'};
const SCORE = {
OK: 'OK',
GOOD: 'GOOD',
EXCELLENT: 'EXCELLENT',
SUPER: 'SUPER'
};
/**
* Bears, beats, Battlestar Galactica.
* Create beat from pool, collision detection, clipping planes, movement, scoring.
@@ -116,6 +109,9 @@ AFRAME.registerComponent('beat', {
this.particles = document.getElementById('saberParticles');
this.mineParticles = document.getElementById('mineParticles');
this.superCuts = document.querySelectorAll('.superCutFx');
this.superCutIdx = 0;
this.explodeEventDetail = {position: null, rotation: null};
this.saberColors = {right: 'blue', left: 'red'};
@@ -747,15 +743,25 @@ AFRAME.registerComponent('beat', {
hitEventDetail.score = score;
this.el.emit('beathit', hitEventDetail, true);
const scoreEl = this.el.sceneEl.components.pool__beatscore.requestEntity();
if (scoreEl) {
if (score < 60) { scoreText = SCORE.OK; }
else if (score < 80) { scoreText = SCORE.GOOD; }
else if (score < 100) { scoreText = SCORE.EXCELLENT; }
else { scoreText = SCORE.SUPER; }
let beatScorePool;
if (score < 60) { beatScorePool = 'pool__beatscoreok'; }
else if (score < 80) { beatScorePool = 'pool__beatscoregood'; }
else if (score < 100) { beatScorePool = 'pool__beatscoreexcellent'; }
else {
beatScorePool = 'pool__beatscoresuper';
const supercut = this.superCuts[this.superCutIdx].getObject3D('mesh');
supercut.position.copy(this.el.object3D.position);
supercut.position.z = -1;
supercut.visible = true;
setTimeout(() => { supercut.visible = false; }, 1000);
supercut.material.uniforms.starttime.value = this.el.sceneEl.time - 50;
this.superCutIdx = (this.superCutIdx + 1) % this.superCuts.length;
}
const scoreEl = this.el.sceneEl.components[beatScorePool].requestEntity();
if (scoreEl) {
scoreEl.object3D.position.copy(this.el.object3D.position);
scoreEl.setAttribute('text', 'value', scoreText);
scoreEl.play();
scoreEl.emit('beatscorestart', null, false);
}

View File

@@ -2,13 +2,18 @@
* Score beat, auto-return to pool in 1.2s.
*/
AFRAME.registerComponent('score-beat', {
schema: {
type: 'string'
},
play: function () {
this.poolComponent = `pool__beatscore${this.data}`;
this.startTime = this.el.sceneEl.time;
},
tick: function (time) {
if (time > this.startTime + 1200) {
this.el.sceneEl.components.pool__beatscore.returnEntity(this.el);
this.el.sceneEl.components[this.poolComponent].returnEntity(this.el);
}
}
});

View File

@@ -0,0 +1,34 @@
AFRAME.registerShader('superCutFxShader', {
schema: {
starttime: {type: 'float', is: 'uniform'},
timems: {type: 'time', is: 'uniform'}
},
vertexShader: `
varying vec2 uvs;
varying vec3 worldPos;
void main() {
uvs.xy = uv.xy;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`,
fragmentShader: `
uniform float starttime;
uniform float timems;
varying vec2 uvs;
varying vec3 worldPos;
#define COLOR vec3(0, 0.67, 0.98)
void main() {
float time = (timems - starttime) / 2000.0;
vec2 p = uvs.xy - 0.5;
float r = p.x * p.x + p.y * p.y;
float alpha = 1.0 - smoothstep(time - 0.01, time, r);
alpha *= smoothstep(time - 0.1, time, r);
alpha *= 1.0 - time * 5.5;
gl_FragColor = vec4(COLOR, alpha);
}
`
});

View File

@@ -42,7 +42,10 @@
pool__beat-dot-blue="mixin: dotBlueBeat; size: 10; container: #beatContainer"
pool__beat-dot-red="mixin: dotRedBeat; size: 10; container: #beatContainer"
pool__beat-mine="mixin: mine; size: 12; container: #beatContainer"
pool__beatscore="mixin: beatScore; size: 5; container: #beatContainer"
pool__beatscoreok="mixin: beatScoreOk; size: 2; container: #beatContainer"
pool__beatscoregood="mixin: beatScoreGood; size: 2; container: #beatContainer"
pool__beatscoreexcellent="mixin: beatScoreExcellent; size: 2; container: #beatContainer"
pool__beatscoresuper="mixin: beatScoreSuper; size: 2; container: #beatContainer"
pool__wall="mixin: wall; size: 10; container: #beatContainer"
proxy-event__cleargame1="event: gamemenuexit; as: cleargame; to: a-scene"
proxy-event__cleargame2="event: gamemenurestart; as: cleargame; to: a-scene"
@@ -78,6 +81,11 @@
{% include './templates/victory.html' %}
{% include './templates/leaderboard.html' %}
<!-- super cut fx rings -->
{% for i in range(1, 5) %}
<a-entity class="superCutFx" mixin="superCut"></a-entity>
{% endfor %}
<!-- Wrong + miss beat visual indicators. -->
<a-entity id="badContainer" bind__visible="isPlaying">
<a-entity id="wrongLeft" mixin='beatWrong'></a-entity>