game texts glow, tweaked ui buttons
|
Before Width: | Height: | Size: 906 KiB After Width: | Height: | Size: 916 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 903 B After Width: | Height: | Size: 4.6 KiB |
@@ -222,3 +222,25 @@ f 78/73 74/75 76/83
|
|||||||
f 75/76 77/74 78/73
|
f 75/76 77/74 78/73
|
||||||
f 80/78 84/80 82/84
|
f 80/78 84/80 82/84
|
||||||
f 83/79 81/82 84/80
|
f 83/79 81/82 84/80
|
||||||
|
v -2.335000 1.285000 -4.010000
|
||||||
|
v -1.285000 1.285000 -4.010000
|
||||||
|
v -2.335000 1.735000 -4.010000
|
||||||
|
v -1.285000 1.735000 -4.010000
|
||||||
|
vt 0.875776 0.376339
|
||||||
|
vt 0.906624 0.499321
|
||||||
|
vt 0.875776 0.499321
|
||||||
|
vt 0.906624 0.376339
|
||||||
|
s off
|
||||||
|
f 86/85 87/86 85/87
|
||||||
|
f 86/85 88/88 87/86
|
||||||
|
v 1.621500 1.202500 -4.013000
|
||||||
|
v 1.978500 1.202500 -4.013000
|
||||||
|
v 1.621500 1.577500 -4.013000
|
||||||
|
v 1.978500 1.577500 -4.013000
|
||||||
|
vt 0.875776 0.376339
|
||||||
|
vt 0.906624 0.499321
|
||||||
|
vt 0.875776 0.499321
|
||||||
|
vt 0.906624 0.376339
|
||||||
|
s off
|
||||||
|
f 90/89 91/90 89/91
|
||||||
|
f 90/89 92/92 91/90
|
||||||
|
|||||||
13
assets/models/textglow.obj
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Blender v2.79 (sub 0) OBJ File: 'stage.blend'
|
||||||
|
# www.blender.org
|
||||||
|
v -0.150000 -0.150000 0.000000
|
||||||
|
v 0.150000 -0.150000 0.000000
|
||||||
|
v -0.150000 0.150000 -0.000000
|
||||||
|
v 0.150000 0.150000 -0.000000
|
||||||
|
vt 0.875776 0.376339
|
||||||
|
vt 0.906624 0.499321
|
||||||
|
vt 0.875776 0.499321
|
||||||
|
vt 0.906624 0.376339
|
||||||
|
s off
|
||||||
|
f 2/1 3/2 1/3
|
||||||
|
f 2/1 4/4 3/2
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
vertexShader : `
|
|
||||||
varying vec2 uvs;
|
|
||||||
varying vec3 worldPos;
|
|
||||||
void main() {
|
|
||||||
uvs.xy = uv.xy;
|
|
||||||
vec4 p = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
||||||
worldPos = (modelMatrix * vec4( position, 1.0 )).xyz;
|
|
||||||
gl_Position = p;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
|
|
||||||
fragmentShader: `
|
|
||||||
varying vec2 uvs;
|
|
||||||
varying vec3 worldPos;
|
|
||||||
uniform vec3 tunnelNeon;
|
|
||||||
uniform vec3 leftLaser;
|
|
||||||
uniform vec3 rightLaser;
|
|
||||||
uniform vec3 floorNeon;
|
|
||||||
uniform sampler2D src;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float mask;
|
|
||||||
vec4 col = texture2D(src, uvs);
|
|
||||||
|
|
||||||
// tunnel neon
|
|
||||||
mask = step(0.87, uvs.x) * step(0.5, uvs.y) * (1.0 - step(0.935, uvs.x)) * ( 1.0 - step(0.75, uvs.y));
|
|
||||||
col.xyz = mix(col.xyz, col.xyz * tunnelNeon, mask);
|
|
||||||
|
|
||||||
// floor & corridor neons
|
|
||||||
mask = step(0.935, uvs.x) * step(0.5, uvs.y) * ( 1.0 - step(0.75, uvs.y));
|
|
||||||
col.xyz = mix(col.xyz, col.xyz * floorNeon, mask);
|
|
||||||
|
|
||||||
// left laser
|
|
||||||
mask = step(0.5, uvs.x) * (1.0 - step(0.625, uvs.x)) * (1.0 - step(0.5, uvs.y));
|
|
||||||
col.xyz = mix(col.xyz, col.xyz * leftLaser, mask);
|
|
||||||
|
|
||||||
// right laser
|
|
||||||
mask = step(0.625, uvs.x) * (1.0 - step(0.75, uvs.x)) * (1.0 - step(0.5, uvs.y));
|
|
||||||
col.xyz = mix(col.xyz, col.xyz * rightLaser, mask);
|
|
||||||
|
|
||||||
gl_FragColor = col;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
};
|
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
<img id="floorNormalsImg" src="assets/img/floornormals.png">
|
<img id="floorNormalsImg" src="assets/img/floornormals.png">
|
||||||
<img id="atlasImg" src="assets/img/atlas.png">
|
<img id="atlasImg" src="assets/img/atlas.png">
|
||||||
|
|
||||||
<a-mixin id="slice" slice9="color: #050505; transparent: true; opacity: 0.7; src: #sliceImg; left: 50; right: 52; top: 50; bottom: 52; padding: 0.18"></a-mixin>
|
<a-mixin id="slice" slice9="color: #050505; transparent: true; opacity: 0.9; src: #sliceImg; left: 50; right: 52; top: 50; bottom: 52; padding: 0.18"></a-mixin>
|
||||||
<a-mixin id="font" text="font: assets/fonts/Teko-Bold.json; shader: msdf; letterSpacing: 1"></a-mixin>
|
<a-mixin id="font" text="font: assets/fonts/Teko-Bold.json; shader: msdf; letterSpacing: 1"></a-mixin>
|
||||||
<a-mixin id="superKeyboardTextInput" mixin="font"></a-mixin>
|
<a-mixin id="superKeyboardTextInput" mixin="font"></a-mixin>
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
<a-mixin
|
<a-mixin
|
||||||
id="beatScore"
|
id="beatScore"
|
||||||
mixin="font"
|
mixin="font"
|
||||||
text="opacity: 0; wrapCount: 19; color: #AAA; width: 1.5"
|
text="opacity: 0; wrapCount: 19; color: #FFF; width: 1.5"
|
||||||
animation__opacityin="property: components.text.material.uniforms.opacity.value; from: .5; to: 1; dur: 500; startEvents: beatscorestart"
|
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"
|
animation__opacityout="property: components.text.material.uniforms.opacity.value; from: 1; to: 0; dur: 500; delay: 700; startEvents: beatscorestart"
|
||||||
animation__motionz="property: object3D.position.z; from: -2; to: -6; dur: 500; easing: easeOutQuart; startEvents: beatscorestart"
|
animation__motionz="property: object3D.position.z; from: -2; to: -6; dur: 500; easing: easeOutQuart; startEvents: beatscorestart"
|
||||||
@@ -149,11 +149,11 @@
|
|||||||
<a-mixin
|
<a-mixin
|
||||||
id="bigMenuButton"
|
id="bigMenuButton"
|
||||||
mixin="slice"
|
mixin="slice"
|
||||||
slice9="src: #slicebtnImg; color: #999; width: 1; left: 70; top: 70; height: 0.2; padding: 0.1"
|
slice9="src: #slicebtnImg; color: #999; width: 1; right: 52; bottom: 47; left: 77; top: 73; height: 0.22; padding: 0.1"
|
||||||
animation__mouseenter1="property: components.slice9.material.color; type: color; from: #999; to: #FFF; startEvents: mouseenter; pauseEvents: mouseleave; dur: 150"
|
animation__mouseenter1="property: components.slice9.material.color; type: color; from: #CCC; to: #FFF; startEvents: mouseenter; pauseEvents: mouseleave; dur: 150"
|
||||||
animation__mouseleave1="property: components.slice9.material.color; type: color; from: #FFF; to: #999; startEvents: mouseleave; pauseEvents: mouseenter; dur: 150"
|
animation__mouseleave1="property: components.slice9.material.color; type: color; from: #FFF; to: #CCC; startEvents: mouseleave; pauseEvents: mouseenter; dur: 150"
|
||||||
animation__mouseenter2="property: scale; from: 1 1 1; to: 1.1 1.1 1.1; startEvents: mouseenter; pauseEvents: mouseleave; dur: 150"
|
animation__mouseenter2="property: scale; from: 1 1 1; to: 1.04 1.04 1.04; startEvents: mouseenter; pauseEvents: mouseleave; dur: 80"
|
||||||
animation__mouseleave2="property: scale; to: 1 1 1; from: 1.1 1.1 1.1; startEvents: mouseleave; pauseEvents: mouseenter; dur: 150"></a-mixin>
|
animation__mouseleave2="property: scale; to: 1 1 1; from: 1.04 1.04 1.04; startEvents: mouseleave; pauseEvents: mouseenter; dur: 80"></a-mixin>
|
||||||
|
|
||||||
|
|
||||||
<!-- stage, neons, etc animations launched from beat-loader events -->
|
<!-- stage, neons, etc animations launched from beat-loader events -->
|
||||||
@@ -189,3 +189,10 @@
|
|||||||
animation__rightlasercolorred="isRawProperty: true; property: systems.materials.stageAdditive.uniforms.rightLaser.value; type: color; to: {{ COLORS.NEON_RED }}; dur: 5; easing: linear; startEvents: rightlasercolorred"
|
animation__rightlasercolorred="isRawProperty: true; property: systems.materials.stageAdditive.uniforms.rightLaser.value; type: color; to: {{ COLORS.NEON_RED }}; dur: 5; easing: linear; startEvents: rightlasercolorred"
|
||||||
animation__rightlasercolorredfade="isRawProperty: true; property: systems.materials.stageAdditive.uniforms.rightLaser.value; type: color; from: {{ COLORS.NEON_BRIGHTRED }}; to: {{ COLORS.NEON_RED }}; dur: 500; easing: linear; startEvents: rightlasercolorredfade"
|
animation__rightlasercolorredfade="isRawProperty: true; property: systems.materials.stageAdditive.uniforms.rightLaser.value; type: color; from: {{ COLORS.NEON_BRIGHTRED }}; to: {{ COLORS.NEON_RED }}; dur: 500; easing: linear; startEvents: rightlasercolorredfade"
|
||||||
></a-mixin>
|
></a-mixin>
|
||||||
|
|
||||||
|
|
||||||
|
<a-mixin id="textGlowColorAnimation"
|
||||||
|
animation__textglowoff="isRawProperty: true; property: systems.materials.stageAdditive.uniforms.textGlow.value; type: color; to: {{ COLORS.TEXT_OFF }}; dur: 5; easing: easeInOutCubic; startEvents: textglowoff"
|
||||||
|
animation__textglownormal="isRawProperty: true; property: systems.materials.stageAdditive.uniforms.textGlow.value; type: color; to: {{ COLORS.TEXT_NORMAL }}; dur: 750; easing: easeInOutCubic; delay: 100; startEvents: textglownormal"
|
||||||
|
animation__textglowbold="isRawProperty: true; property: systems.materials.stageAdditive.uniforms.textGlow.value; type: color; from: {{ COLORS.TEXT_BOLD }}; to: {{ COLORS.TEXT_NORMAL }}; dur: 500; easing: easeInOutCubic; startEvents: textglowbold"
|
||||||
|
></a-mixin>
|
||||||
|
|||||||
@@ -1,855 +0,0 @@
|
|||||||
import {BEAT_WARMUP_OFFSET, BEAT_WARMUP_SPEED, BEAT_WARMUP_TIME} from '../constants/beat';
|
|
||||||
|
|
||||||
const auxObj3D = new THREE.Object3D();
|
|
||||||
const collisionZThreshold = -1.65;
|
|
||||||
const BEAT_WARMUP_ROTATION_CHANGE = Math.PI / 5;
|
|
||||||
const BEAT_WARMUP_ROTATION_OFFSET = 0.4;
|
|
||||||
const BEAT_WARMUP_ROTATION_TIME = 750;
|
|
||||||
const ONCE = {once: true};
|
|
||||||
|
|
||||||
const SCORE_POOL = {
|
|
||||||
OK : 'pool__beatscoreok',
|
|
||||||
GOOD : 'pool__beatscoregood',
|
|
||||||
GREAT : 'pool__beatscoregreat',
|
|
||||||
SUPER : 'pool__beatscoresuper'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bears, beats, Battlestar Galactica.
|
|
||||||
* Create beat from pool, collision detection, clipping planes, movement, scoring.
|
|
||||||
*/
|
|
||||||
AFRAME.registerComponent('beat', {
|
|
||||||
schema: {
|
|
||||||
anticipationPosition: {default: 0},
|
|
||||||
color: {default: 'red', oneOf: ['red', 'blue']},
|
|
||||||
cutDirection: {default: 'down'},
|
|
||||||
debug: {default: false},
|
|
||||||
horizontalPosition: {default: 'middleleft', oneOf: ['left', 'middleleft', 'middleright', 'right']},
|
|
||||||
size: {default: 0.40},
|
|
||||||
speed: {default: 1.0},
|
|
||||||
type: {default: 'arrow', oneOf: ['arrow', 'dot', 'mine']},
|
|
||||||
verticalPosition: {default: 'middle', oneOf: ['bottom', 'middle', 'top']},
|
|
||||||
warmupPosition: {default: 0},
|
|
||||||
},
|
|
||||||
|
|
||||||
materialColor: {
|
|
||||||
blue: '#08083E',
|
|
||||||
red: '#290404'
|
|
||||||
},
|
|
||||||
|
|
||||||
cutColor: {
|
|
||||||
blue: '#b3dcff',
|
|
||||||
red: '#ffb3ca'
|
|
||||||
},
|
|
||||||
|
|
||||||
models: {
|
|
||||||
arrow: 'beatObjTemplate',
|
|
||||||
dot: 'beatObjTemplate',
|
|
||||||
mine: 'mineObjTemplate'
|
|
||||||
},
|
|
||||||
|
|
||||||
signModels: {
|
|
||||||
arrowred: 'arrowRedObjTemplate',
|
|
||||||
arrowblue: 'arrowBlueObjTemplate',
|
|
||||||
dotred: 'dotRedObjTemplate',
|
|
||||||
dotblue: 'dotBlueObjTemplate'
|
|
||||||
},
|
|
||||||
|
|
||||||
orientations: [180, 0, 270, 90, 225, 135, 315, 45, 0],
|
|
||||||
|
|
||||||
rotations: {
|
|
||||||
up: 180,
|
|
||||||
down: 0,
|
|
||||||
left: 270,
|
|
||||||
right: 90,
|
|
||||||
upleft: 225,
|
|
||||||
upright: 135,
|
|
||||||
downleft: 315,
|
|
||||||
downright: 45
|
|
||||||
},
|
|
||||||
|
|
||||||
horizontalPositions: {
|
|
||||||
left: -0.75,
|
|
||||||
middleleft: -0.25,
|
|
||||||
middleright: 0.25,
|
|
||||||
right: 0.75
|
|
||||||
},
|
|
||||||
|
|
||||||
verticalPositions: {
|
|
||||||
bottom: 0.70,
|
|
||||||
middle: 1.20,
|
|
||||||
top: 1.70
|
|
||||||
},
|
|
||||||
|
|
||||||
init: function () {
|
|
||||||
this.backToPool = false;
|
|
||||||
this.beams = document.getElementById('beams').components.beams;
|
|
||||||
this.beatBoundingBox = new THREE.Box3();
|
|
||||||
this.currentRotationWarmupTime = 0;
|
|
||||||
this.cutDirection = new THREE.Vector3();
|
|
||||||
this.destroyed = false;
|
|
||||||
this.gravityVelocity = 0;
|
|
||||||
this.hitEventDetail = {};
|
|
||||||
this.hitBoundingBox = new THREE.Box3();
|
|
||||||
this.poolName = undefined;
|
|
||||||
this.returnToPoolTimer = 800;
|
|
||||||
this.rotationAxis = new THREE.Vector3();
|
|
||||||
this.saberEls = this.el.sceneEl.querySelectorAll('[saber-controls]');
|
|
||||||
this.scoreEl = null;
|
|
||||||
this.scoreElTime = undefined;
|
|
||||||
this.startPositionZ = undefined;
|
|
||||||
this.rightCutPlanePoints = [
|
|
||||||
new THREE.Vector3(),
|
|
||||||
new THREE.Vector3(),
|
|
||||||
new THREE.Vector3()
|
|
||||||
];
|
|
||||||
this.leftCutPlanePoints = [
|
|
||||||
new THREE.Vector3(),
|
|
||||||
new THREE.Vector3(),
|
|
||||||
new THREE.Vector3()
|
|
||||||
];
|
|
||||||
|
|
||||||
this.mineParticles = document.getElementById('mineParticles');
|
|
||||||
this.wrongElLeft = document.getElementById('wrongLeft');
|
|
||||||
this.wrongElRight = document.getElementById('wrongRight');
|
|
||||||
this.missElLeft = document.getElementById('missLeft');
|
|
||||||
this.missElRight = document.getElementById('missRight');
|
|
||||||
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'};
|
|
||||||
|
|
||||||
this.onEndStroke = this.onEndStroke.bind(this);
|
|
||||||
|
|
||||||
this.initBlock();
|
|
||||||
this.initColliders();
|
|
||||||
if (this.data.type === 'mine') {
|
|
||||||
this.initMineFragments();
|
|
||||||
} else {
|
|
||||||
this.initFragments();
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
updatePosition: function () {
|
|
||||||
const el = this.el;
|
|
||||||
const data = this.data;
|
|
||||||
|
|
||||||
el.object3D.position.set(
|
|
||||||
this.horizontalPositions[data.horizontalPosition],
|
|
||||||
this.verticalPositions[data.verticalPosition],
|
|
||||||
data.anticipationPosition + data.warmupPosition
|
|
||||||
);
|
|
||||||
|
|
||||||
el.object3D.rotation.z = THREE.Math.degToRad(this.rotations[data.cutDirection]);
|
|
||||||
},
|
|
||||||
|
|
||||||
update: function () {
|
|
||||||
this.updatePosition();
|
|
||||||
this.updateBlock();
|
|
||||||
this.updateFragments();
|
|
||||||
|
|
||||||
if (this.data.type === 'mine') {
|
|
||||||
this.poolName = `pool__beat-mine`;
|
|
||||||
} else {
|
|
||||||
this.poolName = `pool__beat-${this.data.type}-${this.data.color}`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
pause: function () {
|
|
||||||
this.el.object3D.visible = false;
|
|
||||||
if (this.data.type !== 'mine') {
|
|
||||||
this.partLeftEl.object3D.visible = false;
|
|
||||||
this.partRightEl.object3D.visible = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
play: function () {
|
|
||||||
this.blockEl.object3D.visible = true;
|
|
||||||
this.destroyed = false;
|
|
||||||
this.el.object3D.visible = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
tock: function (time, timeDelta) {
|
|
||||||
const el = this.el;
|
|
||||||
const data = this.data;
|
|
||||||
const position = el.object3D.position;
|
|
||||||
const rotation = el.object3D.rotation;
|
|
||||||
|
|
||||||
if (this.destroyed) {
|
|
||||||
this.tockDestroyed(timeDelta);
|
|
||||||
// Check to remove score entity from pool.
|
|
||||||
} else {
|
|
||||||
// Only check collisions when close.
|
|
||||||
if (position.z > collisionZThreshold) { this.checkCollisions(); }
|
|
||||||
|
|
||||||
// Move.
|
|
||||||
if (position.z < data.anticipationPosition) {
|
|
||||||
let newPositionZ = position.z + BEAT_WARMUP_SPEED * (timeDelta / 1000);
|
|
||||||
// Warm up / warp in.
|
|
||||||
if (newPositionZ < data.anticipationPosition) {
|
|
||||||
position.z = newPositionZ;
|
|
||||||
} else {
|
|
||||||
position.z = data.anticipationPosition;
|
|
||||||
this.beams.newBeam(this.data.color, position);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Standard moving.
|
|
||||||
position.z += this.data.speed * (timeDelta / 1000);
|
|
||||||
rotation.z = this.startRotationZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position.z > (data.anticipationPosition - BEAT_WARMUP_ROTATION_OFFSET) &&
|
|
||||||
this.currentRotationWarmupTime < BEAT_WARMUP_ROTATION_TIME) {
|
|
||||||
const progress = AFRAME.ANIME.easings.easeOutBack(
|
|
||||||
this.currentRotationWarmupTime / BEAT_WARMUP_ROTATION_TIME);
|
|
||||||
el.object3D.rotation.z = this.rotationZStart + (progress * this.rotationZChange);
|
|
||||||
this.currentRotationWarmupTime += timeDelta;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check.
|
|
||||||
this.backToPool = position.z >= 2;
|
|
||||||
if (this.backToPool) { this.missHit(); }
|
|
||||||
}
|
|
||||||
this.returnToPool();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when summoned by beat-loader.
|
|
||||||
*/
|
|
||||||
onGenerate: function () {
|
|
||||||
this.startRotationZ = this.el.object3D.rotation.z;
|
|
||||||
|
|
||||||
// Set up rotation warmup.
|
|
||||||
this.currentRotationWarmupTime = 0;
|
|
||||||
this.rotationZChange = BEAT_WARMUP_ROTATION_CHANGE;
|
|
||||||
if (Math.random > 0.5) { this.rotationZChange *= -1; }
|
|
||||||
this.el.object3D.rotation.z -= this.rotationZChange;
|
|
||||||
this.rotationZStart = this.el.object3D.rotation.z;
|
|
||||||
// Reset mine.
|
|
||||||
if (this.data.type == 'mine') { this.resetMineFragments(); }
|
|
||||||
},
|
|
||||||
|
|
||||||
initBlock: function () {
|
|
||||||
var el = this.el;
|
|
||||||
var blockEl = this.blockEl = document.createElement('a-entity');
|
|
||||||
var signEl = this.signEl = document.createElement('a-entity');
|
|
||||||
|
|
||||||
blockEl.setAttribute('mixin', 'beatBlock');
|
|
||||||
blockEl.setAttribute('mixin', 'beatSign');
|
|
||||||
|
|
||||||
// Small offset to prevent z-fighting when the blocks are far away
|
|
||||||
signEl.object3D.position.z += 0.02;
|
|
||||||
blockEl.appendChild(signEl);
|
|
||||||
el.appendChild(blockEl);
|
|
||||||
},
|
|
||||||
|
|
||||||
updateBlock: function () {
|
|
||||||
const blockEl = this.blockEl;
|
|
||||||
const signEl = this.signEl;
|
|
||||||
if (!blockEl) { return; }
|
|
||||||
|
|
||||||
blockEl.setAttribute('material', {
|
|
||||||
metalness: 0.9,
|
|
||||||
roughness: 0.10,
|
|
||||||
sphericalEnvMap: '#envmapTexture',
|
|
||||||
color: this.materialColor[this.data.color]
|
|
||||||
});
|
|
||||||
this.setObjModelFromTemplate(blockEl, this.models[this.data.type]);
|
|
||||||
|
|
||||||
// Model is 0.29 size. We make it 1.0 so we can easily scale based on 1m size.
|
|
||||||
blockEl.object3D.scale.set(1, 1, 1);
|
|
||||||
blockEl.object3D.scale.multiplyScalar(3.45).multiplyScalar(this.data.size);
|
|
||||||
|
|
||||||
if (this.data.type === 'mine') {
|
|
||||||
const model = blockEl.getObject3D('mesh');
|
|
||||||
if (model) {
|
|
||||||
model.material = this.el.sceneEl.components['stage-colors'].mineMaterial;
|
|
||||||
} else {
|
|
||||||
blockEl.addEventListener('model-loaded', () => {
|
|
||||||
model.material = this.el.sceneEl.components['stage-colors'].mineMaterial;
|
|
||||||
}, ONCE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
signEl.setAttribute('materials', {name: 'stageAdditive'});
|
|
||||||
this.setObjModelFromTemplate(signEl, this.signModels[this.data.type + this.data.color]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
initColliders: function () {
|
|
||||||
var data = this.data;
|
|
||||||
var hitColliderConfiguration;
|
|
||||||
var hitColliderEl;
|
|
||||||
|
|
||||||
if (this.data.type === 'dot' || this.data.type === 'mine') { return; }
|
|
||||||
|
|
||||||
// Hit colliders are 40% larger than the block.
|
|
||||||
hitColliderConfiguration = {
|
|
||||||
position: {x: 0, y: data.size / 2, z: 0},
|
|
||||||
size: {width: data.size * 1.4, height: data.size / 3.0, depth: data.size* 1.4}
|
|
||||||
};
|
|
||||||
|
|
||||||
hitColliderEl = this.hitColliderEl = document.createElement('a-entity');
|
|
||||||
hitColliderEl.setAttribute('geometry', {
|
|
||||||
primitive: 'box',
|
|
||||||
height: hitColliderConfiguration.size.height,
|
|
||||||
width: hitColliderConfiguration.size.width,
|
|
||||||
depth: hitColliderConfiguration.size.depth
|
|
||||||
});
|
|
||||||
|
|
||||||
hitColliderEl.object3D.position.copy(hitColliderConfiguration.position);
|
|
||||||
hitColliderEl.object3D.visible = false;
|
|
||||||
this.el.appendChild(hitColliderEl);
|
|
||||||
|
|
||||||
if (data.debug) {
|
|
||||||
hitColliderEl.object3D.visible = true;
|
|
||||||
hitColliderEl.setAttribute('material', 'color', 'purple');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
initFragments: function () {
|
|
||||||
var cutEl;
|
|
||||||
var partEl;
|
|
||||||
|
|
||||||
partEl = this.partLeftEl = document.createElement('a-entity');
|
|
||||||
cutEl = this.cutLeftEl = document.createElement('a-entity');
|
|
||||||
|
|
||||||
partEl.appendChild(cutEl);
|
|
||||||
this.el.appendChild(partEl);
|
|
||||||
|
|
||||||
partEl = this.partRightEl = document.createElement('a-entity');
|
|
||||||
cutEl = this.cutRightEl = document.createElement('a-entity');
|
|
||||||
|
|
||||||
partEl.appendChild(cutEl);
|
|
||||||
this.el.appendChild(partEl);
|
|
||||||
|
|
||||||
this.initCuttingClippingPlanes();
|
|
||||||
},
|
|
||||||
|
|
||||||
initMineFragments: function () {
|
|
||||||
var fragment;
|
|
||||||
var fragments = this.el.sceneEl.systems['mine-fragments-loader'].fragments.children;
|
|
||||||
var material = this.el.sceneEl.components['stage-colors'].mineMaterial;
|
|
||||||
|
|
||||||
this.randVec = new THREE.Vector3(
|
|
||||||
Math.random() * Math.PI,
|
|
||||||
Math.random() * Math.PI,
|
|
||||||
Math.random() * Math.PI);
|
|
||||||
|
|
||||||
this.mineFragments = [];
|
|
||||||
this.mineBroken = document.createElement('a-entity');
|
|
||||||
this.el.appendChild(this.mineBroken);
|
|
||||||
|
|
||||||
for (var i = 0; i < fragments.length; i++) {
|
|
||||||
fragment = new THREE.Mesh(fragments[i].geometry, material);
|
|
||||||
fragment.speed = new THREE.Vector3();
|
|
||||||
fragment.speed.set(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5);
|
|
||||||
this.mineFragments.push(fragment);
|
|
||||||
this.mineBroken.object3D.add(fragment);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
updateFragments: function () {
|
|
||||||
var cutLeftEl = this.cutLeftEl;
|
|
||||||
var cutRightEl = this.cutRightEl;
|
|
||||||
var partLeftEl = this.partLeftEl;
|
|
||||||
var partRightEl = this.partRightEl;
|
|
||||||
var fragment;
|
|
||||||
if (!partLeftEl) { return; }
|
|
||||||
if (this.data.type === 'mine') {
|
|
||||||
this.resetMineFragments();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
partLeftEl.setAttribute('material', {
|
|
||||||
metalness: 0.8,
|
|
||||||
roughness: 0.12,
|
|
||||||
sphericalEnvMap: '#envmapTexture',
|
|
||||||
color: this.materialColor[this.data.color],
|
|
||||||
side: 'double'
|
|
||||||
});
|
|
||||||
this.setObjModelFromTemplate(partLeftEl, this.models.dot);
|
|
||||||
partLeftEl.object3D.visible = false;
|
|
||||||
|
|
||||||
cutLeftEl.setAttribute('material', {
|
|
||||||
shader: 'flat',
|
|
||||||
color: this.data.cutColor,
|
|
||||||
side: 'double'
|
|
||||||
});
|
|
||||||
this.setObjModelFromTemplate(cutLeftEl, this.models.dot);
|
|
||||||
|
|
||||||
partRightEl.setAttribute('material', {
|
|
||||||
metalness: 0.8,
|
|
||||||
roughness: 0.12,
|
|
||||||
sphericalEnvMap: '#envmapTexture',
|
|
||||||
color: this.materialColor[this.data.color],
|
|
||||||
side: 'double'
|
|
||||||
});
|
|
||||||
this.setObjModelFromTemplate(partRightEl, this.models.dot);
|
|
||||||
partRightEl.object3D.visible = false;
|
|
||||||
|
|
||||||
cutRightEl.setAttribute('material', {
|
|
||||||
shader: 'flat',
|
|
||||||
color: this.data.cutColor,
|
|
||||||
side: 'double'
|
|
||||||
});
|
|
||||||
this.setObjModelFromTemplate(cutRightEl, this.models.dot);
|
|
||||||
},
|
|
||||||
|
|
||||||
resetMineFragments: function () {
|
|
||||||
if (this.data.type !== 'mine') { return; }
|
|
||||||
for (let i = 0; i < this.mineFragments.length; i++) {
|
|
||||||
let fragment = this.mineFragments[i];
|
|
||||||
fragment.visible = false;
|
|
||||||
fragment.position.set(0, 0, 0);
|
|
||||||
fragment.scale.set(1, 1, 1);
|
|
||||||
fragment.speed.set(
|
|
||||||
Math.random() * 5 - 2.5,
|
|
||||||
Math.random() * 5 - 2.5,
|
|
||||||
Math.random() * 5 - 2.5);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
wrongHit: function (hand) {
|
|
||||||
var wrongEl = hand === 'left' ? this.wrongElLeft : this.wrongElRight;
|
|
||||||
if (!wrongEl) { return; }
|
|
||||||
wrongEl.object3D.position.copy(this.el.object3D.position);
|
|
||||||
wrongEl.object3D.position.y += 0.2;
|
|
||||||
wrongEl.object3D.position.z -= 0.5;
|
|
||||||
wrongEl.object3D.visible = true;
|
|
||||||
wrongEl.emit('beatwrong', null, true);
|
|
||||||
this.destroyed = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
missHit: function (hand) {
|
|
||||||
var missEl = hand === 'left' ? this.missElLeft : this.missElRight;
|
|
||||||
if (!missEl || this.data.type === 'mine') { return; }
|
|
||||||
missEl.object3D.position.copy(this.el.object3D.position);
|
|
||||||
missEl.object3D.position.y += 0.2;
|
|
||||||
missEl.object3D.position.z -= 0.5;
|
|
||||||
missEl.object3D.visible = true;
|
|
||||||
missEl.emit('beatmiss', null, true);
|
|
||||||
if (AFRAME.utils.getUrlParameter('synctest')) {
|
|
||||||
console.log(this.el.sceneEl.components.song.getCurrentTime());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
destroyBeat: (function () {
|
|
||||||
var parallelPlaneMaterial = new THREE.MeshBasicMaterial({
|
|
||||||
color: '#00008b',
|
|
||||||
side: THREE.DoubleSide
|
|
||||||
});
|
|
||||||
var planeMaterial = new THREE.MeshBasicMaterial({color: 'grey', side: THREE.DoubleSide});
|
|
||||||
var point1 = new THREE.Vector3();
|
|
||||||
var point2 = new THREE.Vector3();
|
|
||||||
var point3 = new THREE.Vector3();
|
|
||||||
|
|
||||||
return function (saberEl) {
|
|
||||||
var coplanarPoint;
|
|
||||||
var cutThickness = this.cutThickness = 0.02;
|
|
||||||
var direction = this.cutDirection;
|
|
||||||
var leftBorderInnerPlane = this.leftBorderInnerPlane;
|
|
||||||
var leftBorderOuterPlane = this.leftBorderOuterPlane;
|
|
||||||
var leftCutPlane = this.leftCutPlane;
|
|
||||||
var planeGeometry;
|
|
||||||
var planeMesh;
|
|
||||||
var rightBorderInnerPlane = this.rightBorderInnerPlane;
|
|
||||||
var rightBorderOuterPlane = this.rightBorderOuterPlane;
|
|
||||||
var rightCutPlane = this.rightCutPlane;
|
|
||||||
var trailPoints = saberEl.components.trail.saberTrajectory;
|
|
||||||
|
|
||||||
point1.copy(trailPoints[0].top);
|
|
||||||
point2.copy(trailPoints[0].center);
|
|
||||||
point3.copy(trailPoints[trailPoints.length - 1].top);
|
|
||||||
direction.copy(point1).sub(point3);
|
|
||||||
|
|
||||||
this.partRightEl.object3D.position.set(0, 0, 0);
|
|
||||||
this.partRightEl.object3D.rotation.set(0, 0, 0);
|
|
||||||
this.partRightEl.object3D.updateMatrixWorld();
|
|
||||||
|
|
||||||
this.partRightEl.object3D.worldToLocal(this.rightCutPlanePoints[0].copy(point1));
|
|
||||||
this.partRightEl.object3D.worldToLocal(this.rightCutPlanePoints[1].copy(point2));
|
|
||||||
this.partRightEl.object3D.worldToLocal(this.rightCutPlanePoints[2].copy(point3));
|
|
||||||
|
|
||||||
this.partLeftEl.object3D.position.set(0, 0, 0);
|
|
||||||
this.partLeftEl.object3D.rotation.set(0, 0, 0);
|
|
||||||
this.partLeftEl.object3D.updateMatrixWorld();
|
|
||||||
|
|
||||||
this.partLeftEl.object3D.worldToLocal(this.leftCutPlanePoints[0].copy(point3));
|
|
||||||
this.partLeftEl.object3D.worldToLocal(this.leftCutPlanePoints[1].copy(point2));
|
|
||||||
this.partLeftEl.object3D.worldToLocal(this.leftCutPlanePoints[2].copy(point1));
|
|
||||||
|
|
||||||
this.generateCutClippingPlanes();
|
|
||||||
|
|
||||||
if (this.data.debug) {
|
|
||||||
coplanarPoint = new THREE.Vector3();
|
|
||||||
planeGeometry = new THREE.PlaneGeometry(4.0, 4.0, 1.0, 1.0);
|
|
||||||
|
|
||||||
rightCutPlane.coplanarPoint(coplanarPoint);
|
|
||||||
planeGeometry.lookAt(rightCutPlane.normal);
|
|
||||||
planeGeometry.translate(coplanarPoint.x, coplanarPoint.y, coplanarPoint.z);
|
|
||||||
|
|
||||||
planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
|
|
||||||
this.el.sceneEl.setObject3D('rightCutPlane', planeMesh);
|
|
||||||
|
|
||||||
planeGeometry = new THREE.PlaneGeometry(4.0, 4.0, 1.0, 1.0);
|
|
||||||
|
|
||||||
rightBorderOuterPlane.coplanarPoint(coplanarPoint);
|
|
||||||
planeGeometry.lookAt(rightBorderOuterPlane.normal);
|
|
||||||
planeGeometry.translate(coplanarPoint.x, coplanarPoint.y, coplanarPoint.z);
|
|
||||||
|
|
||||||
const parallelPlaneMesh = new THREE.Mesh(planeGeometry, parallelPlaneMaterial);
|
|
||||||
this.el.sceneEl.setObject3D('planeParallel', parallelPlaneMesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.blockEl.object3D.visible = false;
|
|
||||||
|
|
||||||
const partRightMaterial = this.partRightEl.getObject3D('mesh').material;
|
|
||||||
partRightMaterial.clippingPlanes = partRightMaterial.clippingPlanes || [];
|
|
||||||
partRightMaterial.clippingPlanes.length = 0;
|
|
||||||
partRightMaterial.clippingPlanes.push(rightCutPlane);
|
|
||||||
|
|
||||||
const cutRightMaterial = this.cutRightEl.getObject3D('mesh').material;
|
|
||||||
cutRightMaterial.clippingPlanes = cutRightMaterial.clippingPlanes || [];
|
|
||||||
cutRightMaterial.clippingPlanes.length = 0;
|
|
||||||
cutRightMaterial.clippingPlanes.push(rightBorderOuterPlane);
|
|
||||||
cutRightMaterial.clippingPlanes.push(rightBorderInnerPlane);
|
|
||||||
|
|
||||||
const partLeftMaterial = this.partLeftEl.getObject3D('mesh').material;
|
|
||||||
partLeftMaterial.clippingPlanes = partLeftMaterial.clippingPlanes || [];
|
|
||||||
partLeftMaterial.clippingPlanes.length = 0;
|
|
||||||
partLeftMaterial.clippingPlanes.push(leftCutPlane);
|
|
||||||
|
|
||||||
const cutLeftMaterial = this.cutLeftEl.getObject3D('mesh').material;
|
|
||||||
cutLeftMaterial.clippingPlanes = cutLeftMaterial.clippingPlanes || [];
|
|
||||||
cutLeftMaterial.clippingPlanes.length = 0;
|
|
||||||
cutLeftMaterial.clippingPlanes.push(leftBorderInnerPlane);
|
|
||||||
cutLeftMaterial.clippingPlanes.push(leftBorderOuterPlane);
|
|
||||||
|
|
||||||
this.partLeftEl.object3D.visible = true;
|
|
||||||
this.partRightEl.object3D.visible = true;
|
|
||||||
|
|
||||||
this.el.sceneEl.renderer.localClippingEnabled = true;
|
|
||||||
this.destroyed = true;
|
|
||||||
this.gravityVelocity = 0.1;
|
|
||||||
|
|
||||||
this.rotationAxis.copy(this.rightCutPlanePoints[0]).sub(this.rightCutPlanePoints[1]);
|
|
||||||
|
|
||||||
this.returnToPoolTimer = 800;
|
|
||||||
|
|
||||||
auxObj3D.up.copy(rightCutPlane.normal);
|
|
||||||
auxObj3D.lookAt(direction);
|
|
||||||
this.explodeEventDetail.position = this.el.object3D.position;
|
|
||||||
this.explodeEventDetail.rotation = auxObj3D.rotation;
|
|
||||||
this.particles.emit('explode', this.explodeEventDetail, false);
|
|
||||||
};
|
|
||||||
})(),
|
|
||||||
|
|
||||||
destroyMine: function () {
|
|
||||||
for (let i = 0; i < this.mineFragments.length; i++) {
|
|
||||||
this.mineFragments[i].visible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.blockEl.object3D.visible = false;
|
|
||||||
this.destroyed = true;
|
|
||||||
this.gravityVelocity = 0.1;
|
|
||||||
this.returnToPoolTimer = 800;
|
|
||||||
|
|
||||||
this.explodeEventDetail.position = this.el.object3D.position;
|
|
||||||
this.explodeEventDetail.rotation = this.randVec;
|
|
||||||
this.mineParticles.emit('explode', this.explodeEventDetail, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
initCuttingClippingPlanes: function () {
|
|
||||||
this.leftCutPlanePointsWorld = [
|
|
||||||
new THREE.Vector3(),
|
|
||||||
new THREE.Vector3(),
|
|
||||||
new THREE.Vector3()
|
|
||||||
];
|
|
||||||
this.rightCutPlanePointsWorld = [
|
|
||||||
new THREE.Vector3(),
|
|
||||||
new THREE.Vector3(),
|
|
||||||
new THREE.Vector3()
|
|
||||||
];
|
|
||||||
|
|
||||||
this.rightCutPlane = new THREE.Plane();
|
|
||||||
this.rightBorderOuterPlane = new THREE.Plane();
|
|
||||||
this.rightBorderInnerPlane = new THREE.Plane();
|
|
||||||
|
|
||||||
this.leftCutPlane = new THREE.Plane();
|
|
||||||
this.leftBorderOuterPlane = new THREE.Plane();
|
|
||||||
this.leftBorderInnerPlane = new THREE.Plane();
|
|
||||||
},
|
|
||||||
|
|
||||||
generateCutClippingPlanes: function () {
|
|
||||||
var leftBorderInnerPlane = this.leftBorderInnerPlane;
|
|
||||||
var leftBorderOuterPlane = this.leftBorderOuterPlane;
|
|
||||||
var leftCutPlane = this.leftCutPlane;
|
|
||||||
var leftCutPlanePointsWorld = this.leftCutPlanePointsWorld;
|
|
||||||
var partLeftEl = this.partLeftEl;
|
|
||||||
var partRightEl = this.partRightEl;
|
|
||||||
var rightBorderInnerPlane = this.rightBorderInnerPlane;
|
|
||||||
var rightBorderOuterPlane = this.rightBorderOuterPlane;
|
|
||||||
var rightCutPlane = this.rightCutPlane;
|
|
||||||
var rightCutPlanePointsWorld = this.rightCutPlanePointsWorld;
|
|
||||||
|
|
||||||
partRightEl.object3D.updateMatrixWorld();
|
|
||||||
partRightEl.object3D.localToWorld(
|
|
||||||
rightCutPlanePointsWorld[0].copy(this.rightCutPlanePoints[0]));
|
|
||||||
partRightEl.object3D.localToWorld(
|
|
||||||
rightCutPlanePointsWorld[1].copy(this.rightCutPlanePoints[1]));
|
|
||||||
partRightEl.object3D.localToWorld(
|
|
||||||
rightCutPlanePointsWorld[2].copy(this.rightCutPlanePoints[2]));
|
|
||||||
|
|
||||||
partLeftEl.object3D.updateMatrixWorld();
|
|
||||||
partLeftEl.object3D.localToWorld(
|
|
||||||
leftCutPlanePointsWorld[0].copy(this.leftCutPlanePoints[0]));
|
|
||||||
partLeftEl.object3D.localToWorld(
|
|
||||||
leftCutPlanePointsWorld[1].copy(this.leftCutPlanePoints[1]));
|
|
||||||
partLeftEl.object3D.localToWorld(
|
|
||||||
leftCutPlanePointsWorld[2].copy(this.leftCutPlanePoints[2]));
|
|
||||||
|
|
||||||
rightCutPlane.setFromCoplanarPoints(
|
|
||||||
rightCutPlanePointsWorld[0], rightCutPlanePointsWorld[1], rightCutPlanePointsWorld[2]);
|
|
||||||
rightBorderOuterPlane.set(rightCutPlane.normal,
|
|
||||||
rightCutPlane.constant + this.cutThickness);
|
|
||||||
|
|
||||||
leftCutPlane.setFromCoplanarPoints(
|
|
||||||
leftCutPlanePointsWorld[0], leftCutPlanePointsWorld[1], leftCutPlanePointsWorld[2]);
|
|
||||||
leftBorderOuterPlane.set(leftCutPlane.normal, leftCutPlane.constant + this.cutThickness);
|
|
||||||
|
|
||||||
rightBorderInnerPlane.setFromCoplanarPoints(
|
|
||||||
rightCutPlanePointsWorld[2], rightCutPlanePointsWorld[1], rightCutPlanePointsWorld[0]);
|
|
||||||
leftBorderInnerPlane.setFromCoplanarPoints(
|
|
||||||
leftCutPlanePointsWorld[2], leftCutPlanePointsWorld[1], leftCutPlanePointsWorld[0]);
|
|
||||||
},
|
|
||||||
|
|
||||||
returnToPool: function (force) {
|
|
||||||
if (!this.backToPool && !force) { return; }
|
|
||||||
this.el.sceneEl.components[this.poolName].returnEntity(this.el);
|
|
||||||
},
|
|
||||||
|
|
||||||
checkCollisions: function () {
|
|
||||||
const cutDirection = this.data.cutDirection;
|
|
||||||
const saberColors = this.saberColors;
|
|
||||||
const saberEls = this.saberEls;
|
|
||||||
const hitBoundingBox = this.hitColliderEl && this.hitBoundingBox.setFromObject(
|
|
||||||
this.hitColliderEl.getObject3D('mesh'));
|
|
||||||
const beatBoundingBox = this.beatBoundingBox.setFromObject(
|
|
||||||
this.blockEl.getObject3D('mesh'));
|
|
||||||
|
|
||||||
for (let i = 0; i < saberEls.length; i++) {
|
|
||||||
let saberBoundingBox = saberEls[i].components['saber-controls'].boundingBox;
|
|
||||||
let saberControls;
|
|
||||||
let maxAngle;
|
|
||||||
|
|
||||||
if (!saberBoundingBox) { break; }
|
|
||||||
|
|
||||||
const hand = saberEls[i].getAttribute('saber-controls').hand;
|
|
||||||
|
|
||||||
if (hitBoundingBox && saberBoundingBox.intersectsBox(hitBoundingBox)) {
|
|
||||||
if (saberEls[i].components['saber-controls'].swinging &&
|
|
||||||
this.data.color === saberColors[hand]) {
|
|
||||||
saberControls = saberEls[i].components['saber-controls'];
|
|
||||||
this.hitHand = hand;
|
|
||||||
this.hitSaberEl = saberEls[i];
|
|
||||||
this.hitSaberEl.addEventListener('strokeend', this.onEndStroke, ONCE);
|
|
||||||
if (cutDirection === 'up' || cutDirection === 'down') {
|
|
||||||
maxAngle = saberControls.maxAnglePlaneX;
|
|
||||||
} else if (cutDirection === 'left' || cutDirection === 'right') {
|
|
||||||
maxAngle = saberControls.maxAnglePlaneY;
|
|
||||||
} else {
|
|
||||||
maxAngle = saberControls.maxAnglePlaneXY;
|
|
||||||
}
|
|
||||||
this.angleBeforeHit = maxAngle;
|
|
||||||
saberControls.maxAnglePlaneX = 0;
|
|
||||||
saberControls.maxAnglePlaneY = 0;
|
|
||||||
saberControls.maxAnglePlaneXY = 0;
|
|
||||||
} else {
|
|
||||||
this.wrongHit(hand);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify for haptics.
|
|
||||||
this.el.emit(`beatcollide${hand}`, null, true);
|
|
||||||
|
|
||||||
// Sound.
|
|
||||||
this.el.parentNode.components['beat-hit-sound'].playSound(
|
|
||||||
this.el, this.data.cutDirection);
|
|
||||||
|
|
||||||
if (this.data.type === 'mine') {
|
|
||||||
this.destroyMine();
|
|
||||||
} else {
|
|
||||||
this.destroyBeat(saberEls[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (saberBoundingBox.intersectsBox(beatBoundingBox)) {
|
|
||||||
// Notify for haptics.
|
|
||||||
this.el.emit(`beatcollide${hand}`, null, true);
|
|
||||||
|
|
||||||
// Sound.
|
|
||||||
this.el.parentNode.components['beat-hit-sound'].playSound(this.el);
|
|
||||||
|
|
||||||
if (this.data.type === 'mine') {
|
|
||||||
this.el.emit('minehit', null, true);
|
|
||||||
this.destroyMine();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.destroyBeat(saberEls[i]);
|
|
||||||
|
|
||||||
if (this.data.type === 'dot' && saberEls[i].components['saber-controls'].swinging &&
|
|
||||||
this.data.color === saberColors[hand]) {
|
|
||||||
this.hitSaberEl = saberEls[i];
|
|
||||||
this.hitSaberEl.addEventListener('strokeend', this.onEndStroke, ONCE);
|
|
||||||
saberControls = saberEls[i].components['saber-controls'];
|
|
||||||
maxAngle = Math.max(saberControls.maxAnglePlaneX, saberControls.maxAnglePlaneY,
|
|
||||||
saberControls.maxAnglePlaneXY);
|
|
||||||
this.hitHand = hand;
|
|
||||||
this.angleBeforeHit = maxAngle;
|
|
||||||
saberControls.maxAnglePlaneX = 0;
|
|
||||||
saberControls.maxAnglePlaneY = 0;
|
|
||||||
saberControls.maxAnglePlaneXY = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.wrongHit(hand);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onEndStroke: function () {
|
|
||||||
var cutDirection = this.data.cutDirection;
|
|
||||||
var hitEventDetail = this.hitEventDetail;
|
|
||||||
var maxAngle;
|
|
||||||
var saberControls = this.hitSaberEl.components['saber-controls'];
|
|
||||||
var scoreText;
|
|
||||||
|
|
||||||
// Harcoded temporarily.
|
|
||||||
const saberRotation = 3.14 / 12;
|
|
||||||
|
|
||||||
if (cutDirection === 'up' || cutDirection === 'down') {
|
|
||||||
maxAngle = saberControls.maxAnglePlaneX;
|
|
||||||
} else if (cutDirection === 'left' || cutDirection === 'right') {
|
|
||||||
maxAngle = saberControls.maxAnglePlaneY;
|
|
||||||
} else {
|
|
||||||
maxAngle = saberControls.maxAnglePlaneXY;
|
|
||||||
}
|
|
||||||
|
|
||||||
const angleBeforeHit = Math.max(0, (this.angleBeforeHit - saberRotation) * 180 / Math.PI);
|
|
||||||
const angleAfterHit = Math.max(0, (maxAngle - saberRotation) * 180 / Math.PI);
|
|
||||||
|
|
||||||
let score = 0;
|
|
||||||
score += angleBeforeHit >= 85 ? 70 : (angleBeforeHit / 80) * 70;
|
|
||||||
score += angleAfterHit >= 60 ? 30 : (angleAfterHit / 60) * 30;
|
|
||||||
|
|
||||||
hitEventDetail.score = score;
|
|
||||||
this.el.emit('beathit', hitEventDetail, true);
|
|
||||||
|
|
||||||
let beatScorePool;
|
|
||||||
if (score < 60) { beatScorePool = SCORE_POOL.OK; }
|
|
||||||
else if (score < 80) { beatScorePool = SCORE_POOL.GOOD; }
|
|
||||||
else if (score < 100) { beatScorePool = SCORE_POOL.GREAT; }
|
|
||||||
else {
|
|
||||||
beatScorePool = SCORE_POOL.SUPER;
|
|
||||||
|
|
||||||
this.superCuts[this.superCutIdx].components.supercutfx.createSuperCut(this.el.object3D.position);
|
|
||||||
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.play();
|
|
||||||
scoreEl.emit('beatscorestart', null, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroyed animation.
|
|
||||||
*/
|
|
||||||
tockDestroyed: (function () {
|
|
||||||
var leftCutNormal = new THREE.Vector3();
|
|
||||||
var leftRotation = 0;
|
|
||||||
var rightCutNormal = new THREE.Vector3();
|
|
||||||
var rightRotation = 0;
|
|
||||||
var rotationStep = 2 * Math.PI / 150;
|
|
||||||
var fragment;
|
|
||||||
|
|
||||||
return function (timeDelta) {
|
|
||||||
// Update gravity velocity.
|
|
||||||
this.gravityVelocity = getGravityVelocity(this.gravityVelocity, timeDelta);
|
|
||||||
this.el.object3D.position.y += this.gravityVelocity * (timeDelta / 1000);
|
|
||||||
|
|
||||||
if (this.data.type == 'mine') {
|
|
||||||
for (var i = 0; i < this.mineFragments.length; i++) {
|
|
||||||
fragment = this.mineFragments[i];
|
|
||||||
if (!fragment.visible) { continue; }
|
|
||||||
fragment.position.addScaledVector(fragment.speed, timeDelta / 1000);
|
|
||||||
fragment.scale.multiplyScalar(0.97)
|
|
||||||
if (fragment.scale.y < 0.1){
|
|
||||||
fragment.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rightCutNormal.copy(this.rightCutPlane.normal)
|
|
||||||
.multiplyScalar((this.data.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.y = 0; // Y handled by gravity.
|
|
||||||
this.partLeftEl.object3D.position.add(leftCutNormal);
|
|
||||||
this.partLeftEl.object3D.setRotationFromAxisAngle(this.rotationAxis, leftRotation);
|
|
||||||
leftRotation = leftRotation >= 2 * Math.PI ? 0 : leftRotation + rotationStep;
|
|
||||||
|
|
||||||
this.generateCutClippingPlanes();
|
|
||||||
|
|
||||||
this.returnToPoolTimer -= timeDelta;
|
|
||||||
this.backToPool = this.returnToPoolTimer <= 0;
|
|
||||||
};
|
|
||||||
})(),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load OBJ from already parsed and loaded OBJ template.
|
|
||||||
*/
|
|
||||||
setObjModelFromTemplate: (function () {
|
|
||||||
const geometries = {};
|
|
||||||
|
|
||||||
return function (el, templateId) {
|
|
||||||
if (!geometries[templateId]) {
|
|
||||||
const templateEl = document.getElementById(templateId);
|
|
||||||
if (templateEl.getObject3D('mesh')) {
|
|
||||||
geometries[templateId] = templateEl.getObject3D('mesh').children[0].geometry;
|
|
||||||
} else {
|
|
||||||
templateEl.addEventListener('model-loaded', () => {
|
|
||||||
geometries[templateId] = templateEl.getObject3D('mesh').children[0].geometry;
|
|
||||||
this.setObjModelFromTemplate(el, templateId);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!el.getObject3D('mesh')) { el.setObject3D('mesh', new THREE.Mesh()); }
|
|
||||||
el.getObject3D('mesh').geometry = geometries[templateId];
|
|
||||||
};
|
|
||||||
})()
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get velocity given current velocity using gravity acceleration.
|
|
||||||
*/
|
|
||||||
function getGravityVelocity (velocity, timeDelta) {
|
|
||||||
const GRAVITY = -9.8;
|
|
||||||
return velocity + (GRAVITY * (timeDelta / 1000));
|
|
||||||
}
|
|
||||||
@@ -36,5 +36,6 @@ AFRAME.registerComponent('gameover', {
|
|||||||
for (let i = 0; i < this.gameOverEls.length; i++) {
|
for (let i = 0; i < this.gameOverEls.length; i++) {
|
||||||
this.gameOverEls[i].emit('gameover', null, false);
|
this.gameOverEls[i].emit('gameover', null, false);
|
||||||
}
|
}
|
||||||
|
this.el.emit('textglowoff', null, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ AFRAME.registerSystem('materials', {
|
|||||||
floorNeon: {value: new THREE.Color(COLORS.NEON_BLUE)},
|
floorNeon: {value: new THREE.Color(COLORS.NEON_BLUE)},
|
||||||
leftLaser: {value: new THREE.Color(COLORS.NEON_BLUE)},
|
leftLaser: {value: new THREE.Color(COLORS.NEON_BLUE)},
|
||||||
rightLaser: {value: new THREE.Color(COLORS.NEON_BLUE)},
|
rightLaser: {value: new THREE.Color(COLORS.NEON_BLUE)},
|
||||||
|
textGlow: {value: new THREE.Color(COLORS.TEXT_OFF)},
|
||||||
src: {value: new THREE.TextureLoader().load(document.getElementById('atlasImg').src)},
|
src: {value: new THREE.TextureLoader().load(document.getElementById('atlasImg').src)},
|
||||||
},
|
},
|
||||||
vertexShader: stageAdditiveShaders.vertexShader,
|
vertexShader: stageAdditiveShaders.vertexShader,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ AFRAME.registerComponent('score-texts', {
|
|||||||
for (let i = 0; i < this.textEls.length; i++) {
|
for (let i = 0; i < this.textEls.length; i++) {
|
||||||
this.textEls[i].components['animation__fadein'].beginAnimation();
|
this.textEls[i].components['animation__fadein'].beginAnimation();
|
||||||
}
|
}
|
||||||
|
this.el.sceneEl.emit('textglownormal', null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Started loading.
|
// Started loading.
|
||||||
@@ -35,6 +36,7 @@ AFRAME.registerComponent('score-texts', {
|
|||||||
for (let i = 0; i < this.textEls.length; i++) {
|
for (let i = 0; i < this.textEls.length; i++) {
|
||||||
this.textEls[i].components.text.material.uniforms.opacity.value = 0;
|
this.textEls[i].components.text.material.uniforms.opacity.value = 0;
|
||||||
}
|
}
|
||||||
|
this.el.sceneEl.emit('textglowoff', null, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ AFRAME.registerComponent('twister', {
|
|||||||
|
|
||||||
pulse: function (twist) {
|
pulse: function (twist) {
|
||||||
if (!this.data.enabled) { return; }
|
if (!this.data.enabled) { return; }
|
||||||
console.log('PULSE');
|
|
||||||
if (twist == 0) { twist = 0.03 + Math.random() * 0.25; }
|
if (twist == 0) { twist = 0.03 + Math.random() * 0.25; }
|
||||||
else twist = Math.min(twist * 0.4, 0.4);
|
else twist = Math.min(twist * 0.4, 0.4);
|
||||||
twist *= Math.random() < 0.5 ? -1 : 1; // random direction
|
twist *= Math.random() < 0.5 ? -1 : 1; // random direction
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
OFF: '#111',
|
|
||||||
RED: '#f00',
|
|
||||||
BLUE: '#00f',
|
|
||||||
|
|
||||||
BG_OFF: '#222',
|
|
||||||
BG_BLUE: '#007AB8',
|
|
||||||
BG_BRIGHTBLUE: '#5FCCFF',
|
|
||||||
BG_RED: '#B80000',
|
|
||||||
BG_BRIGHTRED: '#FF4343',
|
|
||||||
|
|
||||||
NEON_OFF: '#000',
|
|
||||||
NEON_BLUE: '#00f',
|
|
||||||
NEON_BRIGHTBLUE: '#aaf',
|
|
||||||
NEON_RED: '#f00',
|
|
||||||
NEON_BRIGHTRED: '#faa',
|
|
||||||
};
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<a-mixin
|
<a-mixin
|
||||||
id="gameMenuButton"
|
id="gameMenuButton"
|
||||||
mixin="slice"
|
mixin="bigMenuButton"
|
||||||
animation__mouseenter="property: components.slice9.material.color; type: color; from: #050505; to: #067197; startEvents: mouseenter; pauseEvents: mouseleave; dur: 150"
|
animation__mouseenter="property: components.slice9.material.color; type: color; from: #050505; to: #067197; startEvents: mouseenter; pauseEvents: mouseleave; dur: 150"
|
||||||
animation__mouseleave="property: components.slice9.material.color; type: color; from: #067197; to: #050505; startEvents: mouseleave; pauseEvents: mouseenter; dur: 150"
|
animation__mouseleave="property: components.slice9.material.color; type: color; from: #067197; to: #050505; startEvents: mouseleave; pauseEvents: mouseenter; dur: 150"
|
||||||
slice9="width: 1; height: 0.27; padding: 0.04"></a-mixin>
|
slice9="width: 1; height: 0.27; padding: 0.04"></a-mixin>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
id="gameMenuButtonText"
|
id="gameMenuButtonText"
|
||||||
mixin="font"
|
mixin="font"
|
||||||
position="0 -0.07 0.01"
|
position="0 -0.07 0.01"
|
||||||
text="align: center; wrapCount: 17; color: #F0F0F0"></a-mixin>
|
text="align: center; wrapCount: 17; color: #FFF"></a-mixin>
|
||||||
|
|
||||||
<!-- Titles. -->
|
<!-- Titles. -->
|
||||||
<a-entity id="inGameMenuTitles" position="0 1.7 -2.3">
|
<a-entity id="inGameMenuTitles" position="0 1.7 -2.3">
|
||||||
|
|||||||
@@ -229,13 +229,13 @@
|
|||||||
id="playButton"
|
id="playButton"
|
||||||
play-sound="event: mouseenter; sound: #hoverSound; volume: 0.03"
|
play-sound="event: mouseenter; sound: #hoverSound; volume: 0.03"
|
||||||
play-sound__click="event: click; sound: #confirmSound; volume: 0.25"
|
play-sound__click="event: click; sound: #confirmSound; volume: 0.25"
|
||||||
position="0 -0.51 0"
|
position="0 -0.561 0"
|
||||||
proxy-event="event: click; to: a-scene; as: playbuttonclick"
|
proxy-event="event: click; to: a-scene; as: playbuttonclick"
|
||||||
material="shader: flat; src: #playImg; transparent: true; color: #CCC"
|
material="shader: flat; src: #playImg; transparent: true; color: #DDD"
|
||||||
width="0.4"
|
width="0.5"
|
||||||
height="0.2"
|
height="0.25"
|
||||||
animation__mouseenter1="property: components.material.material.color; type: color; from: #CCC; to: #FFF; startEvents: mouseenter; pauseEvents: mouseleave; dur: 150"
|
animation__mouseenter1="property: components.material.material.color; type: color; from: #DDD; to: #FFF; startEvents: mouseenter; pauseEvents: mouseleave; dur: 150"
|
||||||
animation__mouseleave1="property: components.material.material.color; type: color; from: #FFF; to: #CCC; startEvents: mouseleave; pauseEvents: mouseenter; dur: 150"
|
animation__mouseleave1="property: components.material.material.color; type: color; from: #FFF; to: #DDD; startEvents: mouseleave; pauseEvents: mouseenter; dur: 150"
|
||||||
animation__mouseenter2="property: scale; from: 1 1 1; to: 1.1 1.1 1.1; startEvents: mouseenter; pauseEvents: mouseleave; dur: 150"
|
animation__mouseenter2="property: scale; from: 1 1 1; to: 1.1 1.1 1.1; startEvents: mouseenter; pauseEvents: mouseleave; dur: 150"
|
||||||
animation__mouseleave2="property: scale; to: 1 1 1; from: 1.1 1.1 1.1; startEvents: mouseleave; pauseEvents: mouseenter; dur: 150"
|
animation__mouseleave2="property: scale; to: 1 1 1; from: 1.1 1.1 1.1; startEvents: mouseleave; pauseEvents: mouseenter; dur: 150"
|
||||||
bind-toggle__raycastable="menuActive && !!menuSelectedChallenge.id && !genreMenuOpen"
|
bind-toggle__raycastable="menuActive && !!menuSelectedChallenge.id && !genreMenuOpen"
|
||||||
@@ -315,7 +315,7 @@
|
|||||||
bind-toggle__raycastable="menuActive && !genreMenuOpen && !isSearching && !genre"
|
bind-toggle__raycastable="menuActive && !genreMenuOpen && !isSearching && !genre"
|
||||||
bind__visible="menuActive && !genreMenuOpen && !isSearching && !genre"
|
bind__visible="menuActive && !genreMenuOpen && !isSearching && !genre"
|
||||||
proxy-event="event: click; to: a-scene; as: genremenuopen">
|
proxy-event="event: click; to: a-scene; as: genremenuopen">
|
||||||
<a-entity mixin="font" text="align: center; color: #AAA; wrapCount: 20; value: BROWSE GENRES" position="0 -0.07 0.01"></a-entity>
|
<a-entity mixin="font" text="align: center; color: #FFF; wrapCount: 20; value: BROWSE GENRES" position="0 -0.07 0.01"></a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
|
|
||||||
<a-entity id="clearGenreButton"
|
<a-entity id="clearGenreButton"
|
||||||
@@ -323,7 +323,7 @@
|
|||||||
bind-toggle__raycastable="menuActive && !!genre"
|
bind-toggle__raycastable="menuActive && !!genre"
|
||||||
bind__visible="menuActive && !!genre"
|
bind__visible="menuActive && !!genre"
|
||||||
proxy-event="event: click; to: a-scene; as: searchclear">
|
proxy-event="event: click; to: a-scene; as: searchclear">
|
||||||
<a-entity mixin="font" text="align: center; color: #AAA; wrapCount: 20; value: CLEAR GENRE" position="0 -0.07 0.01"></a-entity>
|
<a-entity mixin="font" text="align: center; color: #FFF; wrapCount: 20; value: CLEAR GENRE" position="0 -0.07 0.01"></a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
|
|
||||||
@@ -334,7 +334,7 @@
|
|||||||
bind__visible="genreMenuOpen"
|
bind__visible="genreMenuOpen"
|
||||||
position="0 0.2 -1.9"
|
position="0 0.2 -1.9"
|
||||||
proxy-event="event: click; to: a-scene; as: genremenuclose">
|
proxy-event="event: click; to: a-scene; as: genremenuclose">
|
||||||
<a-entity mixin="font" text="align: center; color: #AAA; wrapCount: 20; value: BACK" position="0 -0.07 0.01"></a-entity>
|
<a-entity mixin="font" text="align: center; color: #FFF; wrapCount: 20; value: BACK" position="0 -0.07 0.01"></a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
|
|
||||||
<a-entity id="searchButtons" position="0.55 0.2 -1.9">
|
<a-entity id="searchButtons" position="0.55 0.2 -1.9">
|
||||||
@@ -343,7 +343,7 @@
|
|||||||
bind-toggle__raycastable="menuActive && !genreMenuOpen && !isSearching && !search.query"
|
bind-toggle__raycastable="menuActive && !genreMenuOpen && !isSearching && !search.query"
|
||||||
bind__visible="menuActive && !genreMenuOpen && !isSearching && !search.query"
|
bind__visible="menuActive && !genreMenuOpen && !isSearching && !search.query"
|
||||||
proxy-event="event: click; to: a-scene; as: keyboardopen">
|
proxy-event="event: click; to: a-scene; as: keyboardopen">
|
||||||
<a-entity mixin="font" text="align: center; color: #AAA; wrapCount: 20; value: SEARCH SONGS" position="0 -0.07 0.01"></a-entity>
|
<a-entity mixin="font" text="align: center; color: #FFF; wrapCount: 20; value: SEARCH SONGS" position="0 -0.07 0.01"></a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
|
|
||||||
<a-entity id="searchClearButton"
|
<a-entity id="searchClearButton"
|
||||||
@@ -351,6 +351,6 @@
|
|||||||
bind-toggle__raycastable="menuActive && !!search.query && !isSearching"
|
bind-toggle__raycastable="menuActive && !!search.query && !isSearching"
|
||||||
bind__visible="menuActive && !!search.query && !isSearching"
|
bind__visible="menuActive && !!search.query && !isSearching"
|
||||||
proxy-event="event: click; to: a-scene; as: searchclear">
|
proxy-event="event: click; to: a-scene; as: searchclear">
|
||||||
<a-entity mixin="font" text="align: center; color: #AAA; wrapCount: 20; value: CLEAR SEARCH" position="0 -0.07 0.01"></a-entity>
|
<a-entity mixin="font" text="align: center; color: #FFF; wrapCount: 20; value: CLEAR SEARCH" position="0 -0.07 0.01"></a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<a-mixin
|
<a-mixin
|
||||||
id="scoreText"
|
id="scoreText"
|
||||||
mixin="font"
|
mixin="font"
|
||||||
text="color: #88A; letterSpacing: -2; align: center"></a-mixin>
|
text="color: #FFF; letterSpacing: -2; align: center"></a-mixin>
|
||||||
|
|
||||||
<a-entity
|
<a-entity
|
||||||
id="scoreContainer"
|
id="scoreContainer"
|
||||||
|
|||||||