menu selected challenge state
This commit is contained in:
49
src/components/preview-song.js
Normal file
49
src/components/preview-song.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
var utils = require('../utils');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle song preview play, pause, fades.
|
||||||
|
*/
|
||||||
|
AFRAME.registerComponent('preview-song', {
|
||||||
|
schema: {
|
||||||
|
challengeId: {type: 'string'},
|
||||||
|
previewStartTime: {type: 'number'}
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
var el = this.el;
|
||||||
|
this.audio = new Audio();
|
||||||
|
this.audio.volume = 0;
|
||||||
|
|
||||||
|
// anime.js animation.
|
||||||
|
this.volumeTarget = {volume: 0};
|
||||||
|
this.animation = AFRAME.anime({
|
||||||
|
targets: this.volumeTarget,
|
||||||
|
delay: 250,
|
||||||
|
duration: 1500,
|
||||||
|
easing: 'easeInQuad',
|
||||||
|
volume: 0.5,
|
||||||
|
autoplay: false,
|
||||||
|
loop: false,
|
||||||
|
update: () => {
|
||||||
|
this.audio.volume = this.volumeTarget.volume;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function (oldData) {
|
||||||
|
if (oldData.challengeId && !this.data.challengeId) {
|
||||||
|
if (this.animation) { this.animation.pause(); }
|
||||||
|
this.audio.pause();
|
||||||
|
this.audio.src = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play preview.
|
||||||
|
this.audio.currentTime = this.data.previewStartTime;
|
||||||
|
this.audio.src = utils.getS3FileUrl(this.data.challengeId, 'song.ogg');
|
||||||
|
this.audio.volume = 0;
|
||||||
|
this.volumeTarget.volume = 0;
|
||||||
|
this.audio.play();
|
||||||
|
this.animation.restart();
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
var algoliasearch = require('algoliasearch/lite');
|
var algoliasearch = require('algoliasearch/lite');
|
||||||
var bindEvent = require('aframe-event-decorators').bindEvent;
|
var bindEvent = require('aframe-event-decorators').bindEvent;
|
||||||
var utils = require('../utils');
|
|
||||||
|
|
||||||
var client = algoliasearch('QULTOY3ZWU', 'be07164192471df7e97e6fa70c1d041d');
|
var client = algoliasearch('QULTOY3ZWU', 'be07164192471df7e97e6fa70c1d041d');
|
||||||
var index = client.initIndex('supersaber');
|
var index = client.initIndex('supersaber');
|
||||||
@@ -34,56 +33,9 @@ AFRAME.registerComponent('search', {
|
|||||||
/**
|
/**
|
||||||
* Click listener for search result.
|
* Click listener for search result.
|
||||||
*/
|
*/
|
||||||
AFRAME.registerComponent('search-result', {
|
AFRAME.registerComponent('search-result-list', {
|
||||||
init: function() {
|
click: bindEvent(function (evt) {
|
||||||
var el = this.el;
|
this.el.sceneEl.emit('menuchallengeclick', evt.target.closest('.searchResult').dataset.id,
|
||||||
this.audio = new Audio();
|
false);
|
||||||
this.audio.currentTime = el.getAttribute('data-preview-start-time');
|
|
||||||
this.audio.src = utils.getS3FileUrl(el.getAttribute('data-id'), 'song.ogg');
|
|
||||||
this.audio.volume = 0;
|
|
||||||
this.eventDetail = {};
|
|
||||||
|
|
||||||
this.volumeTarget = {volume: 0};
|
|
||||||
this.animation = AFRAME.anime({
|
|
||||||
targets: this.volumeTarget,
|
|
||||||
delay: 250,
|
|
||||||
duration: 1500,
|
|
||||||
easing: 'easeInQuad',
|
|
||||||
volume: 0.5,
|
|
||||||
autoplay: false,
|
|
||||||
loop: false,
|
|
||||||
update: () => {
|
|
||||||
this.audio.volume = this.volumeTarget.volume;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
remove: function () {
|
|
||||||
if (this.animation) { this.animation.pause(); }
|
|
||||||
this.audio.pause();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preview song.
|
|
||||||
*/
|
|
||||||
mouseenter: bindEvent(function () {
|
|
||||||
this.audio.volume = 0;
|
|
||||||
this.volumeTarget.volume = 0;
|
|
||||||
this.audio.play();
|
|
||||||
this.animation.restart();
|
|
||||||
}),
|
|
||||||
|
|
||||||
mouseleave: bindEvent(function () {
|
|
||||||
if (this.animation) { this.animation.pause(); }
|
|
||||||
this.audio.pause();
|
|
||||||
}),
|
|
||||||
|
|
||||||
click: bindEvent(function () {
|
|
||||||
var el = this.el;
|
|
||||||
this.eventDetail.id = el.getAttribute('data-id');
|
|
||||||
this.eventDetail.title = el.getAttribute('data-title');
|
|
||||||
|
|
||||||
// Tell application we are starting a challenge and initiate beat-loader.
|
|
||||||
el.sceneEl.emit('challengeset', this.eventDetail);
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<audio id="hoverSound" src="/assets/sounds/hover.ogg"></audio>
|
<audio id="hoverSound" src="/assets/sounds/hover.ogg"></audio>
|
||||||
|
|
||||||
<a-scene bind__beat-loader="challengeId: challenge.id"
|
<a-scene bind__beat-loader="challengeId: challenge.id"
|
||||||
bind__embedded="embedded"
|
bind__preview-song="challengeId: menuSelectedChallenge.id"
|
||||||
challenge-loader
|
challenge-loader
|
||||||
console-shortcuts
|
console-shortcuts
|
||||||
search>
|
search>
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
var hasInitialChallenge = !!AFRAME.utils.getUrlParameter('challenge');
|
var hasInitialChallenge = !!AFRAME.utils.getUrlParameter('challenge');
|
||||||
|
|
||||||
|
var challengeDataStore = {};
|
||||||
|
|
||||||
AFRAME.registerState({
|
AFRAME.registerState({
|
||||||
initialState: {
|
initialState: {
|
||||||
challenge: {
|
challenge: {
|
||||||
id: AFRAME.utils.getUrlParameter('challenge'),
|
id: AFRAME.utils.getUrlParameter('challenge'),
|
||||||
isLoading: false
|
isLoading: false,
|
||||||
},
|
},
|
||||||
discoLightsOn: true,
|
|
||||||
discotube: {speedX: -0.05, speedY: -0.1},
|
|
||||||
inVR: false,
|
inVR: false,
|
||||||
maxStreak: 0,
|
maxStreak: 0,
|
||||||
menuActive: true,
|
menu: {
|
||||||
|
active: true
|
||||||
|
},
|
||||||
|
menuSelectedChallenge: {
|
||||||
|
id: '',
|
||||||
|
difficulties: []
|
||||||
|
},
|
||||||
playButtonText: 'Play',
|
playButtonText: 'Play',
|
||||||
score: 0,
|
score: 0,
|
||||||
scoreText: '',
|
scoreText: '',
|
||||||
@@ -35,10 +41,23 @@ AFRAME.registerState({
|
|||||||
state.score = 0;
|
state.score = 0;
|
||||||
state.streak = 0;
|
state.streak = 0;
|
||||||
state.maxStreak = 0;
|
state.maxStreak = 0;
|
||||||
state.menuActive = false;
|
state.menu.active = false;
|
||||||
|
state.menuSelectedChallenge.id = '';
|
||||||
setScreen(state, 'challenge');
|
setScreen(state, 'challenge');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Song clicked from menu.
|
||||||
|
*/
|
||||||
|
menuchallengeclick: function (state, id) {
|
||||||
|
let challengeData = challengeDataStore[id];
|
||||||
|
state.menuSelectedChallenge.id = id;
|
||||||
|
state.menuSelectedChallenge.difficulties.length = 0;
|
||||||
|
for (let i = 0; i < challengeData.difficulties.length; i++) {
|
||||||
|
state.menuSelectedChallenge.difficulties.push(challengeData.difficulties[i]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
playbuttonclick: function (state) {
|
playbuttonclick: function (state) {
|
||||||
state.menuActive = false;
|
state.menuActive = false;
|
||||||
},
|
},
|
||||||
@@ -51,15 +70,12 @@ AFRAME.registerState({
|
|||||||
state.searchResults.length = 0;
|
state.searchResults.length = 0;
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
if (!payload.results[i]) { continue; }
|
if (!payload.results[i]) { continue; }
|
||||||
|
challengeDataStore[payload.results[i].id] = payload.results[i];
|
||||||
state.searchResults.push(payload.results[i]);
|
state.searchResults.push(payload.results[i]);
|
||||||
}
|
}
|
||||||
state.searchResults.__dirty = true;
|
state.searchResults.__dirty = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
togglediscolights: function (state, payload) {
|
|
||||||
state.discoLightsOn = !state.discoLightsOn;
|
|
||||||
},
|
|
||||||
|
|
||||||
togglemenu: function (state) {
|
togglemenu: function (state) {
|
||||||
state.menuActive = !state.menuActive;
|
state.menuActive = !state.menuActive;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,42 +1,22 @@
|
|||||||
<a-entity id="sky"
|
<a-entity id="sky" cubemap="folder: /assets/img/env/space/"></a-entity>
|
||||||
cubemap="folder: /assets/img/env/space/"></a-entity>
|
|
||||||
|
|
||||||
<a-entity id="skyFade"
|
<a-entity id="skyFade"
|
||||||
bind__visible="menuActive"
|
bind__visible="menu.active"
|
||||||
bind__isPlaying="menuActive"
|
bind__isPlaying="menu.active"
|
||||||
geometry="primitive: box; width: 50; height: 50; depth: 50"
|
geometry="primitive: box; width: 50; height: 50; depth: 50"
|
||||||
material="shader: flat; color: #111; opacity: 0.6; side: back"></a-entity>
|
material="shader: flat; color: #111; opacity: 0.6; side: back"></a-entity>
|
||||||
|
|
||||||
<a-entity id="tube"
|
|
||||||
geometry="primitive:cylinder;radius:3;height:100;openEnded:true"
|
|
||||||
material="fog: false; depthWrite: false; src:#tubeImg;transparent:true;side:back;repeat:1 5"
|
|
||||||
position="0 1.5 -40"
|
|
||||||
rotation="90 0 0"
|
|
||||||
bind__discotube="speedX: discotube.speedX; speedY: discotube.speedY"></a-entity>
|
|
||||||
|
|
||||||
<a-plane id="floor"
|
<a-plane id="floor"
|
||||||
width="40"
|
width="40"
|
||||||
height="40"
|
height="40"
|
||||||
rotation="-90 0 0"
|
rotation="-90 0 0"
|
||||||
material="src:#gridImg; transparent: true; color: #f9e3fb; repeat: 80 80; depthWrite:false">
|
material="src: #gridImg; transparent: true; color: #f9e3fb; repeat: 80 80; depthWrite: false">
|
||||||
<a-plane position="0 0 -0.01"
|
<a-plane position="0 0 -0.01"
|
||||||
width="2"
|
width="2"
|
||||||
height="2"
|
height="2"
|
||||||
material="color: #000; transparent: true; opacity: 0.7"></a-plane>
|
material="color: #000; transparent: true; opacity: 0.7"></a-plane>
|
||||||
</a-plane>
|
</a-plane>
|
||||||
|
|
||||||
<!-- Disco lights -->
|
|
||||||
<a-entity light="type: directional; intensity: 1"
|
|
||||||
position="0 -2 1"
|
|
||||||
discolight="color: #fda6f7; speed: 2.0"
|
|
||||||
bind__visible="discoLightsOn"></a-entity>
|
|
||||||
<a-entity light="type: directional; intensity: 1.6"
|
|
||||||
position="-0 2 .6"
|
|
||||||
discolight="color: #7a9efc; speed: 0.01"
|
|
||||||
bind__visible="discoLightsOn"></a-entity>
|
|
||||||
<!-- Default lights -->
|
<!-- Default lights -->
|
||||||
<a-entity light="type: ambient; color: #BBB"
|
<a-entity light="type: ambient; color: #BBB"></a-entity>
|
||||||
bind__visible="!discoLightsOn"></a-entity>
|
<a-entity light="type: directional; color: #FFF; intensity: 0.6" position="-0.5 1 1"></a-entity>
|
||||||
<a-entity light="type: directional; color: #FFF; intensity: 0.6"
|
|
||||||
position="-0.5 1 1"
|
|
||||||
bind__visible="!discoLightsOn"></a-entity>
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
{% macro searchResults () %}
|
{% macro searchResults () %}
|
||||||
<a-entity id="searchResultList"
|
<a-entity id="searchResultList"
|
||||||
|
bind-for="for: item; in: searchResults; key: id; template: #searchResultTemplate"
|
||||||
layout="type: box; columns: 1; marginRow: 0.125"
|
layout="type: box; columns: 1; marginRow: 0.125"
|
||||||
bind-for="for: item; in: searchResults; key: id; template: #searchResultTemplate">
|
search-result-list>
|
||||||
</a-entity>
|
</a-entity>
|
||||||
|
|
||||||
{% raw %}
|
{% raw %}
|
||||||
<template id="searchResultTemplate">
|
<template id="searchResultTemplate">
|
||||||
<a-entity class="searchResult" search-result
|
<a-entity class="searchResult" data-id="{{ item.id }}">
|
||||||
data-id="{{ item.id }}" data-title="{{ item.songName }}"
|
|
||||||
data-preview-start-time="{{ item.previewStartTime }}">
|
|
||||||
<a-entity class="searchResultSlice"
|
<a-entity class="searchResultSlice"
|
||||||
geometry="primitive: plane; width: 0.8; height: 0.1"
|
geometry="primitive: plane; width: 0.8; height: 0.1"
|
||||||
material="shader: flat; transparent: true; src: #resultImg; color: #BBB"
|
material="shader: flat; transparent: true; src: #resultImg; color: #BBB"
|
||||||
@@ -28,7 +27,7 @@
|
|||||||
{% endraw %}
|
{% endraw %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
<a-entity id="menu" bind__visible="menuActive" position="0 1 -1">
|
<a-entity id="menu" bind__visible="menu.active" position="0 1 -1">
|
||||||
<a-entity id="keyboard" super-keyboard="hand: {{ DEBUG_KEYBOARD and '#mouseCursor' or '#rightHand' }}; imagePath: assets/img/keyboard/; injectToRaycasterObjects: false" position="0 0.2 0.02" keyboard-raycastable search></a-entity>
|
<a-entity id="keyboard" super-keyboard="hand: {{ DEBUG_KEYBOARD and '#mouseCursor' or '#rightHand' }}; imagePath: assets/img/keyboard/; injectToRaycasterObjects: false" position="0 0.2 0.02" keyboard-raycastable search></a-entity>
|
||||||
|
|
||||||
<a-plane id="play"
|
<a-plane id="play"
|
||||||
|
|||||||
Reference in New Issue
Block a user