diff --git a/src/components/beat-loader.js b/src/components/beat-loader.js index 3abc7e6..70bad0b 100644 --- a/src/components/beat-loader.js +++ b/src/components/beat-loader.js @@ -10,16 +10,23 @@ AFRAME.registerComponent('beat-loader', { }, update: function () { - var challengeId = this.data.challengeId; + if (!this.data.challengeId || !this.data.difficulty) { return; } + this.loadBeats(this.data.challengeId, this.data.difficulty); + }, + + /** + * XHR. + */ + loadBeats: function (id, difficulty) { var el = this.el; var xhr; - if (!challengeId || !diffjculty) { return; } - // Load beats. + let url = utils.getS3FileUrl(this.data.challengeId, `${this.data.difficulty}.json`); xhr = new XMLHttpRequest(); el.emit('beatloaderstart'); - xhr.open('GET', utils.getS3FileUrl(challengeId, `${this.data.difficulty}.json`)); + console.log(`Fetching ${url}...`); + xhr.open('GET', url); xhr.addEventListener('load', () => { this.handleBeats(JSON.parse(xhr.responseText)); }); @@ -30,16 +37,7 @@ AFRAME.registerComponent('beat-loader', { * TODO: Load the beat data into the game. */ handleBeats: function (beatData) { - var el = this.el; - - history.pushState( - '', - challenge.songName, - updateQueryParam(window.location.href, 'challenge', this.data.challengeId) - ); - - document.title = `Super Saber - ${challenge.songName}`; - el.emit('beatloaderfinish'); + this.el.sceneEl.emit('beatloaderfinish', beatData, false); console.log('Finished loading challenge data.'); }, }); diff --git a/src/components/console-shortcuts.js b/src/components/console-shortcuts.js index eda2745..75f1ef5 100644 --- a/src/components/console-shortcuts.js +++ b/src/components/console-shortcuts.js @@ -1,6 +1,10 @@ AFRAME.registerComponent('console-shortcuts', { - play: function() { + play: function () { + window.$ = val => document.querySelector(val); + window.$$ = val => document.querySelectorAll(val); + window.$$$ = val => document.querySelector(`[${val}]`).getAttribute(val); + window.$$$$ = val => document.querySelector(`[${val}]`).components[val]; window.scene = this.el; window.state = this.el.systems.state.state; - }, + } }); diff --git a/src/components/discolight.js b/src/components/discolight.js deleted file mode 100644 index 4c3b355..0000000 --- a/src/components/discolight.js +++ /dev/null @@ -1,16 +0,0 @@ -AFRAME.registerComponent('discolight', { - schema: { - color: { type: 'color' }, - speed: { default: 1.0 }, - }, - init: function() { - this.color = new THREE.Color(this.data.color); - this.hsl = this.color.getHSL(); - }, - tick: function(time, delta) { - this.hsl.h += delta * 0.0001 * this.data.speed; - if (this.hsl.l > 1.0) this.hsl.l = 0.0; - this.color.setHSL(this.hsl.h, this.hsl.s, this.hsl.l); - this.el.setAttribute('light', { color: this.color.getHex() }); - }, -}); diff --git a/src/components/discotube.js b/src/components/discotube.js deleted file mode 100644 index 2acdd3a..0000000 --- a/src/components/discotube.js +++ /dev/null @@ -1,14 +0,0 @@ -AFRAME.registerComponent('discotube', { - schema: { - speedX: { default: 1.0 }, - speedY: { default: 0.1 }, - }, - init: function() { - this.material = this.el.object3D.children[0].material; - }, - tick: function(time, delta) { - if (this.material == null) return; - this.material.map.offset.x -= delta * 0.0001 * this.data.speedX; - this.material.map.offset.y -= delta * 0.0001 * this.data.speedY; - }, -}); diff --git a/src/components/history.js b/src/components/history.js new file mode 100644 index 0000000..8fbb3c1 --- /dev/null +++ b/src/components/history.js @@ -0,0 +1,20 @@ +/** + * Update window title and history. + */ +AFRAME.registerComponent('history', { + schema: { + challengeId: {type: 'string'}, + songName: {type: 'string'}, + songSubName: {type: 'string'} + }, + + update: function () { + const data = this.data; + history.pushState( + '', + data.songName, + updateQueryParam(window.location.href, 'challenge', data.challengeId) + ); + document.title = `Super Saber - ${data.songName}`; + } +}); diff --git a/src/components/play-audio.js b/src/components/play-audio.js deleted file mode 100644 index 103281c..0000000 --- a/src/components/play-audio.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Play audio element on event. - */ -AFRAME.registerComponent('play-audio', { - schema: { - audio: { type: 'string' }, - event: { type: 'string' }, - volume: { type: 'number', default: 1 }, - }, - - multiple: true, - - init: function() { - var audio; - audio = document.querySelector(this.data.audio); - audio.volume = this.data.volume; - - this.el.addEventListener(this.data.event, evt => { - if (!audio.paused) { - audio.pause(); - audio.currentTime = 0; - } - audio.play(); - }); - }, -}); diff --git a/src/components/play-button.js b/src/components/play-button.js deleted file mode 100644 index c5721db..0000000 --- a/src/components/play-button.js +++ /dev/null @@ -1,13 +0,0 @@ -AFRAME.registerComponent('play-button', { - init: function() { - var el = this.el; - - el.addEventListener('click', () => { - el.sceneEl.emit('playbuttonclick'); - }); - - el.sceneEl.addEventListener('youtubefinished', evt => { - el.object3D.visible = false; - }); - }, -}); diff --git a/src/components/play-sound.js b/src/components/play-sound.js new file mode 100644 index 0000000..a3ad8bc --- /dev/null +++ b/src/components/play-sound.js @@ -0,0 +1,43 @@ +var SoundPool = require('../lib/soundpool'); + +AFRAME.registerSystem('play-sound', { + init: function () { + this.lastSoundPlayed = ''; + this.lastSoundPlayedTime = 0; + this.pools = {}; + }, + + createPool: function (sound, volume) { + if (this.pools[sound]) { return; } + this.pools[sound] = new SoundPool(sound, volume); + }, + + playSound: function (sound, volume) { + this.createPool(sound, volume); + this.pools[sound].play(); + + this.lastSoundPlayed = sound; + this.lastSoundTime = this.el.time; + } +}); + +/** + * Play sound on event. + */ +AFRAME.registerComponent('play-sound', { + schema: { + enabled: {default: true}, + event: {type: 'string'}, + sound: {type: 'string'}, + volume: {type: 'number', default: 1} + }, + + multiple: true, + + init: function () { + this.el.addEventListener(this.data.event, evt => { + if (!this.data.enabled) { return; } + this.system.playSound(this.data.sound, this.data.volume); + }); + } +}); diff --git a/src/components/preview-song.js b/src/components/preview-song.js index 29414db..026a893 100644 --- a/src/components/preview-song.js +++ b/src/components/preview-song.js @@ -31,6 +31,7 @@ AFRAME.registerComponent('preview-song', { }, update: function (oldData) { + // Stop. if (oldData.challengeId && !this.data.challengeId) { if (this.animation) { this.animation.pause(); } this.audio.pause(); diff --git a/src/components/recenter.js b/src/components/recenter.js index 723d6f1..20660c2 100644 --- a/src/components/recenter.js +++ b/src/components/recenter.js @@ -14,9 +14,7 @@ AFRAME.registerComponent('recenter', { this.checkInViewAfterRecenter = this.checkInViewAfterRecenter.bind(this); // Delay to make sure we have a valid pose. sceneEl.addEventListener('enter-vr', () => { - setTimeout(() => { - this.recenter(); - }, 100); + setTimeout(() => { this.recenter(); }, 100); }); // User can also recenter the menu manually. sceneEl.addEventListener('menudown', () => { @@ -49,7 +47,7 @@ AFRAME.registerComponent('recenter', { checkInViewAfterRecenter: function() { var camera = this.el.sceneEl.camera; var frustum = this.frustum; - var menu = document.querySelector('#menu'); + var menu = this.el; var menuPosition = this.menuPosition; camera.updateMatrix(); camera.updateMatrixWorld(); diff --git a/src/components/song.js b/src/components/song.js new file mode 100644 index 0000000..56420a3 --- /dev/null +++ b/src/components/song.js @@ -0,0 +1,39 @@ +const utils = require('../utils'); + +/** + * Active challenge song / audio. + */ +AFRAME.registerComponent('song', { + schema: { + challengeId: {default: ''}, + isPlaying: {default: false} + }, + + init: function () { + // Use audio element for audioanalyser. + this.audio = document.createElement('audio'); + this.audio.setAttribute('id', 'song'); + this.el.sceneEl.appendChild(this.audio); + }, + + update: function (oldData) { + var el = this.el; + var data = this.data; + + // Changed challenge. + if (data.challengeId !== oldData.challengeId) { + let songUrl = utils.getS3FileUrl(data.challengeId, 'song.ogg'); + this.audio.currentTime = 0; + this.audio.src = data.challengeId ? songUrl : ''; + console.log(`Playing ${songUrl}...`); + } + + // Keep playback state up to date. + if ((data.isPlaying && data.challengeId) && this.audio.paused) { + this.audio.play(); + return; + } else if ((!data.isPlaying || !data.challengeId) && !this.audio.paused) { + this.audio.pause(); + } + } +}); diff --git a/src/index.html b/src/index.html index d2bbdc7..f15cd89 100644 --- a/src/index.html +++ b/src/index.html @@ -5,29 +5,25 @@ -
- - -
-
-