diff --git a/src/assets.html b/src/assets.html index 600141b..6e312f8 100644 --- a/src/assets.html +++ b/src/assets.html @@ -111,11 +111,10 @@ + wall> { if (!evt.detail || !evt.detail.intersectedEl) { return; } diff --git a/src/components/haptics-wall.js b/src/components/haptics-wall.js index e50a7b7..1eb9554 100644 --- a/src/components/haptics-wall.js +++ b/src/components/haptics-wall.js @@ -5,7 +5,7 @@ AFRAME.registerComponent('haptics-wall', { init: function () { const el = this.el; this.isHittingWall = false; - el.setAttribute('haptics__wall', {dur: 50, force: 0.1}); + el.setAttribute('haptics__wall', {dur: 50, force: 0.075}); this.checkIfHittingWall = this.checkIfHittingWall.bind(this); el.addEventListener('mouseenter', this.checkIfHittingWall); diff --git a/src/components/particleplayer.js b/src/components/particleplayer.js index 2508bf4..a9e6a20 100644 --- a/src/components/particleplayer.js +++ b/src/components/particleplayer.js @@ -326,6 +326,7 @@ AFRAME.registerComponent('particleplayer', { particleSystem.mesh.rotation.copy(rotation); particleSystem.time = 0; this.resetParticles(particleSystem); + return particleSystem; }, doLoop: function (particleSystem) { diff --git a/src/components/saber-intersection.js b/src/components/saber-intersection.js deleted file mode 100644 index adaf233..0000000 --- a/src/components/saber-intersection.js +++ /dev/null @@ -1,67 +0,0 @@ -AFRAME.registerComponent('saber-intersection', { - schema: { - active: {default: true} - }, - - init: function () { - this.hiddenIntersection = {x: 999, y: 0, z: 0}; - this.saberHit = { - rightHand: {active: false, position: null, raycaster: null}, - leftHand: {active: false, position: null, raycaster: null} - }; - this.particles = document.getElementById('sparkParticles'); - this.intersecting = false; - this.saberEnterFunc = this.saberEnter.bind(this); - this.saberLeaveFunc = this.saberLeave.bind(this); - this.particlesPosition = {position: null, rotation: null}; - }, - - pause: function () { - this.el.removeAttribute('raycastable-game'); - this.el.removeEventListener('mouseenter', this.saberEnterFunc); - this.el.removeEventListener('mouseleave', this.saberLeaveFunc); - this.intersecting = false; - }, - - play: function () { - this.el.setAttribute('raycastable-game', ''); - this.el.addEventListener('mouseenter', this.saberEnterFunc); - this.el.addEventListener('mouseleave', this.saberLeaveFunc); - this.material = this.el.getObject3D('mesh').material; - this.saberHit.rightHand.raycaster = document.getElementById('rightHand').components.raycaster__game; - this.saberHit.leftHand.raycaster = document.getElementById('leftHand').components.raycaster__game; - }, - - saberEnter: function (evt) { - if (!this.data.active) { return; } - const saber = this.saberHit[evt.detail.cursorEl.id]; - saber.active = true; - var intersection = saber.raycaster.getIntersection(this.el); - if (intersection) { - this.particlesPosition.position = intersection.point; - this.particles.emit('explode', this.particlesPosition, false); - } - this.intersecting = true; - }, - - saberLeave: function (evt) { - const hand = evt.detail.cursorEl.id; - this.saberHit[hand].active = false; - this.material.uniforms[hand == 'rightHand' ? 'hitRight' : 'hitLeft'].value = this.hiddenIntersection; - this.intersecting = this.saberHit.rightHand.active || this.saberHit.leftHand.active; - }, - - tick: function (time, delta) { - if (this.data.active && this.intersecting) { - var intersection; - if (this.saberHit.rightHand.active) { - intersection = this.saberHit.rightHand.raycaster.getIntersection(this.el); - if (intersection) { this.material.uniforms.hitRight.value = intersection.point; } - } - if (this.saberHit.leftHand.active) { - intersection = this.saberHit.leftHand.raycaster.getIntersection(this.el); - if (intersection) { this.material.uniforms.hitLeft.value = intersection.point; } - } - } - } -}); diff --git a/src/components/saber-particles.js b/src/components/saber-particles.js new file mode 100644 index 0000000..62b8913 --- /dev/null +++ b/src/components/saber-particles.js @@ -0,0 +1,85 @@ +const HIT_LEFT = 'hitLeft'; +const HIT_RIGHT = 'hitRight'; +const LEFT = 'left'; +const RIGHT = 'right'; + +/** + * Show particles when touched by saber. + */ +AFRAME.registerComponent('saber-particles', { + schema: { + enabled: {default: false}, + hand: {type: 'string'} + }, + + init: function () { + this.hiddenIntersection = {x: 999, y: 0, z: 0}; + this.intersectedEl = null; + + this.particles = document.getElementById('sparkParticles'); + this.particleEventDetail = {position: new THREE.Vector3(), rotation: new THREE.Euler()}; + this.particleEvent = {detail: this.particleEventDetail}; + this.particleSystem = null; + + this.saberEnter = this.saberEnter.bind(this); + this.saberLeave = this.saberLeave.bind(this); + + }, + + pause: function () { + this.el.removeEventListener('mouseenter', this.saberEnter); + this.el.removeEventListener('mouseleave', this.saberLeave); + }, + + play: function () { + this.el.addEventListener('mouseenter', this.saberEnter); + this.el.addEventListener('mouseleave', this.saberLeave); + this.particlesDur = this.particles.getAttribute('particleplayer').dur; + }, + + saberEnter: function (evt) { + if (!this.data.enabled) { return; } + if (evt.target !== this.el) { return; } + if (!evt.detail.intersectedEl.hasAttribute('data-saber-particles')) { return; } + this.intersectedEl = evt.detail.intersectedEl; + }, + + saberLeave: function (evt) { + if (evt.detail.target !== this.el) { return; } + + // Hide hit intersection texture. + if (this.intersectedEl.components.wall || this.intersectedEl.id === 'floor') { + const uniform = this.data.hand === RIGHT ? HIT_RIGHT : HIT_LEFT; + const material = this.intersectedEl.getObject3D('mesh').material; + material.uniforms[uniform].value = this.hiddenIntersection; + } + this.intersectedEl = null; + this.particleSystem = null; + }, + + tick: function (time, delta) { + if (!this.data.enabled || !this.intersectedEl) { return; } + + const raycaster = this.el.components.raycaster__game; + const intersection = raycaster.getIntersection(this.intersectedEl); + + if (!intersection) { return; } + + // Update intersection material if necessary. + if (this.intersectedEl.components.wall || this.intersectedEl.id === 'floor') { + const uniform = this.data.hand === RIGHT ? HIT_RIGHT : HIT_LEFT; + const material = this.intersectedEl.getObject3D('mesh').material; + material.uniforms[uniform].value = intersection.point; + } + + if (this.particleSystem && this.particleSystem.active) { + // Update particle position. + this.particleSystem.mesh.position.copy(intersection.point); + } else { + // Start particle system. + this.particleEventDetail.position.copy(intersection.point); + this.particleSystem = this.particles.components.particleplayer.startAfterDelay( + this.particleEvent); + } + } +}); diff --git a/src/index.html b/src/index.html index 4cb4b49..31f5715 100644 --- a/src/index.html +++ b/src/index.html @@ -99,7 +99,7 @@ particleplayer="src: #mineParticlesJSON; pscale: 0.5; scale: 1.4; loop: false; on: explode; img: #sparkImg; count: 20%; animateScale: true; initialScale: 3 1 1; finalScale: 0.2 0.2 1"> + particleplayer="src: #sparksJSON; color: #fcc; pscale: 0.7; on: explode; scale: 0.1; loop: false; img: #spark2Img; dur: 700; count: 50%; animateScale: true; initialScale: 3 0.5 1; finalScale: 0.1 0.5 1">