|
|
|
@ -14,8 +14,20 @@ |
|
|
|
|
<body> |
|
|
|
|
<script> |
|
|
|
|
/* TODO : |
|
|
|
|
- reset (as done for fishinbowl) |
|
|
|
|
- insure scene setup, e.g starting position and orientation of environment and main character (until now assumed unchanged) |
|
|
|
|
- isolate emit('eventname', {test:0}) versus same with onreleased (which does NOT work) and same without event detail (which works) |
|
|
|
|
- add audio instructions |
|
|
|
|
../content/voicesBigguJulia/simon_instructions_fr.mp3 |
|
|
|
|
../content/voicesBigguJulia/labyrinthe_instructions_fr.mp3 |
|
|
|
|
../content/voicesBigguJulia/lettresprenom_instructions_fr.mp3 |
|
|
|
|
../content/voicesBigguJulia/tableauformes_instructions_fr.mp3 |
|
|
|
|
already there |
|
|
|
|
../content/voicesBigguJulia/instructions.mp3 |
|
|
|
|
../content/voicesBigguJulia/bravojulia.mp3 |
|
|
|
|
../content/voicesBigguJulia/continu.mp3 |
|
|
|
|
../content/voicesBigguJulia/biggu-fem.mp3 |
|
|
|
|
|
|
|
|
|
- reset (as done for fishinbowl) |
|
|
|
|
- better menu (e.g target with onreleased) |
|
|
|
|
- fix maze/mazemap mismatch (causing emit() error on init) |
|
|
|
|
- game ideas |
|
|
|
@ -27,20 +39,15 @@ AFRAME.registerComponent('startfunctions', { |
|
|
|
|
addGames() |
|
|
|
|
|
|
|
|
|
// example of adding a game programmatically |
|
|
|
|
/* |
|
|
|
|
let newEl = document.createElement('a-entity') |
|
|
|
|
let gamename = "checkers" |
|
|
|
|
let gamename = "carcassone" |
|
|
|
|
//let gamename = "checkers" |
|
|
|
|
//let gamename = "carcassone" |
|
|
|
|
//let gamename = "simon" |
|
|
|
|
let gamename = "voxelpaint" |
|
|
|
|
newEl.id = gamename |
|
|
|
|
newEl.setAttribute(gamename, "") |
|
|
|
|
newEl.classList.add( "game" ) |
|
|
|
|
AFRAME.scenes[0].appendChild(newEl) |
|
|
|
|
|
|
|
|
|
// move with waddle example |
|
|
|
|
let biggu = document.querySelector("#biggu") |
|
|
|
|
biggu.setAttribute("animation__translation", "property: position; to: 0 0 0.5; dur: 10000;") |
|
|
|
|
biggu.setAttribute("animation__waddle", "property: rotation; from: 0 -20 -10; to: 0 20 10; dur: 1000; loop:true; easing: linear; dir:alternate;") |
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
@ -88,6 +95,173 @@ function showOnlyThisGame(name){ |
|
|
|
|
document.querySelector("["+name+"]").emit("reset") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//___________________________________________________________________________________________________________________________________ |
|
|
|
|
AFRAME.registerComponent('voxelpaint', { |
|
|
|
|
init: function(){ |
|
|
|
|
let generatorName = this.attrName |
|
|
|
|
let el = this.el |
|
|
|
|
this.colors = ["red", "green", "blue", "yellow" ] |
|
|
|
|
this.scale = 1/10 |
|
|
|
|
this.yOffset = 1.5 |
|
|
|
|
let j = 0 |
|
|
|
|
this.colors.map( (color, i) => { |
|
|
|
|
let newEl = document.createElement('a-box') |
|
|
|
|
newEl.setAttribute("scale", ""+this.scale+" "+this.scale+" "+this.scale) |
|
|
|
|
newEl.setAttribute("color",color) |
|
|
|
|
newEl.setAttribute("position", ""+(i%2)*this.scale+" "+(this.yOffset+j*this.scale)+" -.5") |
|
|
|
|
newEl.setAttribute("target","true") |
|
|
|
|
newEl.setAttribute("onpicked", "document.querySelector('["+generatorName+"]').emit('check')") |
|
|
|
|
newEl.setAttribute("onreleased", "document.querySelector('["+generatorName+"]').emit('getVoxelPoses')") |
|
|
|
|
newEl.classList.add( generatorName ) |
|
|
|
|
el.appendChild(newEl) |
|
|
|
|
if (i==1) j++ |
|
|
|
|
}) |
|
|
|
|
// check if data is present, as hash or query parameter, and if so, display accordingly |
|
|
|
|
if (window.location.hash) { |
|
|
|
|
let poses = JSON.parse(decodeURI(window.location.hash.replace("#",'')))[generatorName] |
|
|
|
|
// prefixed by generatorName in order to support saving/sharing of the state of other games |
|
|
|
|
poses.map( p => { |
|
|
|
|
let newEl = document.createElement('a-box') |
|
|
|
|
newEl.setAttribute("scale", ""+this.scale+" "+this.scale+" "+this.scale) |
|
|
|
|
newEl.setAttribute("color",p.color) |
|
|
|
|
newEl.setAttribute("position", p.position) |
|
|
|
|
newEl.setAttribute("rotation", p.rotation) |
|
|
|
|
newEl.setAttribute("target","true") |
|
|
|
|
newEl.setAttribute("onreleased", "document.querySelector('["+generatorName+"]').emit('getVoxelPoses')") |
|
|
|
|
newEl.classList.add( "voxel" ) |
|
|
|
|
newEl.classList.add( generatorName ) |
|
|
|
|
el.appendChild(newEl) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
events: { |
|
|
|
|
reset: function (evt) { |
|
|
|
|
console.log(this.attrName, 'component was resetted!'); |
|
|
|
|
let generatorName = this.attrName |
|
|
|
|
Array.from( this.el.querySelectorAll(".voxel") ).map( el => el.remove() ) |
|
|
|
|
}, |
|
|
|
|
check: function (evt) { |
|
|
|
|
let generatorName = this.attrName |
|
|
|
|
let latest = selectedElements[selectedElements.length-1].element |
|
|
|
|
let newEl = latest.cloneNode(true) // does not seem to properly clone all attributes, e.g color works but not position or scale |
|
|
|
|
// ["scale", "position", "onpicked"].map( prop => console.log( prop)) //newEl.setAttribute(prop, latest.getAttribute(prop) ) |
|
|
|
|
newEl.setAttribute("scale", latest.getAttribute("scale") ) |
|
|
|
|
newEl.setAttribute("position", latest.getAttribute("position") ) |
|
|
|
|
newEl.setAttribute("onpicked", latest.getAttribute("onpicked") ) |
|
|
|
|
latest.removeAttribute("onpicked") |
|
|
|
|
latest.classList.add( "voxel" ) |
|
|
|
|
this.el.appendChild( newEl ) |
|
|
|
|
// could also snap it back, e.g clear rotation, possibily use initially position |
|
|
|
|
}, |
|
|
|
|
getVoxelPoses: function (evt){ |
|
|
|
|
let generatorName = this.attrName |
|
|
|
|
let poses = [] |
|
|
|
|
Array.from( this.el.querySelectorAll(".voxel") ).map( el => { |
|
|
|
|
poses.push( { |
|
|
|
|
position: el.getAttribute("position"), |
|
|
|
|
rotation: el.getAttribute("rotation"), |
|
|
|
|
color: el.getAttribute("color") |
|
|
|
|
} ) |
|
|
|
|
}) |
|
|
|
|
let data = {} |
|
|
|
|
data[generatorName] = poses |
|
|
|
|
window.location.hash = JSON.stringify(data) |
|
|
|
|
// prefixed by generatorName in order to support saving/sharing of the state of other games |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//___________________________________________________________________________________________________________________________________ |
|
|
|
|
AFRAME.registerComponent('simon', { |
|
|
|
|
init: function(){ |
|
|
|
|
let generatorName = this.attrName |
|
|
|
|
let el = this.el |
|
|
|
|
this.colors = ["red", "green", "blue", "yellow" ] |
|
|
|
|
const notePrefix = '../content/notes/t' |
|
|
|
|
const noteSuffix = '.mp3' |
|
|
|
|
this.sequence = [] |
|
|
|
|
this.posInSeq = -1 |
|
|
|
|
this.userSeq = [] |
|
|
|
|
this.scale = 1/10 |
|
|
|
|
let j = 0 |
|
|
|
|
this.colors.map( (color, i) => { |
|
|
|
|
let newEl = document.createElement('a-box') |
|
|
|
|
newEl.setAttribute("scale", ""+this.scale+" "+this.scale+" "+this.scale) |
|
|
|
|
newEl.setAttribute("color",color) |
|
|
|
|
newEl.setAttribute("opacity", .5) |
|
|
|
|
newEl.setAttribute("sound", "src:url("+notePrefix+(i+1)+noteSuffix+")") |
|
|
|
|
newEl.setAttribute("position", ""+(i%2)*this.scale+" 1.1 "+j*this.scale) |
|
|
|
|
newEl.setAttribute("target","true") |
|
|
|
|
newEl.setAttribute("onreleased", "document.querySelector('["+generatorName+"]').emit('check')") |
|
|
|
|
// somehow unable to pass parameters via emit() ?! |
|
|
|
|
//newEl.setAttribute("onreleased", "document.querySelector('["+generatorName+"]').emit('check', {'color':'red'})") |
|
|
|
|
//newEl.setAttribute("onreleased", 'document.querySelector("[simon]").emit("check", {color: "red"})') |
|
|
|
|
//newEl.setAttribute("onreleased", 'document.querySelector("[simon]").emit("check", {color: "green"})') |
|
|
|
|
//newEl.setAttribute("onreleased", 'document.querySelector("['+generatorName+']").emit("check",{color:"'+color+'"})') |
|
|
|
|
newEl.classList.add( generatorName ) |
|
|
|
|
el.appendChild(newEl) |
|
|
|
|
if (i==1) j++ |
|
|
|
|
}) |
|
|
|
|
setTimeout( _ => { document.querySelector("["+generatorName+"]").emit('playSequence') }, 1000) |
|
|
|
|
}, |
|
|
|
|
events: { |
|
|
|
|
reset: function (evt) { |
|
|
|
|
console.log(this.attrName, 'component was resetted!'); |
|
|
|
|
let generatorName = this.attrName |
|
|
|
|
this.sequence = [] |
|
|
|
|
this.posInSeq = -1 |
|
|
|
|
this.userSeq = [] |
|
|
|
|
// could also reposition the boxes |
|
|
|
|
clearInterval( this.interval ) |
|
|
|
|
setTimeout( _ => { document.querySelector("["+generatorName+"]").emit('playSequence') }, 1000) |
|
|
|
|
}, |
|
|
|
|
check: function (evt) { |
|
|
|
|
let latest = selectedElements[selectedElements.length-1].element |
|
|
|
|
// could also snap it back, e.g clear rotation, possibily use initially position |
|
|
|
|
let generatorName = this.attrName |
|
|
|
|
let color = latest.getAttribute("color") |
|
|
|
|
//this.userSeq.push(evt.detail.color) |
|
|
|
|
//let box = this.el.querySelector("a-box[color="+evt.detail.color+"]") |
|
|
|
|
this.userSeq.push(color) |
|
|
|
|
let box = this.el.querySelector("a-box[color="+color+"]") |
|
|
|
|
box.components.sound.playSound() |
|
|
|
|
console.log ('seq:', this.sequence.at( this.userSeq.length-1) ,'user:', this.userSeq.at(-1) ) |
|
|
|
|
if (this.userSeq.at(-1) == this.sequence.at( this.userSeq.length-1) ){ |
|
|
|
|
console.log('same', this.sequence, this.userSeq) |
|
|
|
|
if (this.userSeq.length == this.sequence.length){ |
|
|
|
|
console.log('entire sequence complete', this.sequence, this.userSeq) |
|
|
|
|
animateThenIdle( document.querySelector("#biggu"), 'bigguaction_win') |
|
|
|
|
this.userSeq = [] |
|
|
|
|
document.querySelector("["+generatorName+"]").emit('playSequence') // grow sequence |
|
|
|
|
} else { |
|
|
|
|
console.log('partial sequence only, waiting for new input') |
|
|
|
|
animateThenIdle( document.querySelector("#biggu"), 'bigguaction_yes') |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
document.querySelector("["+generatorName+"]").emit('reset') |
|
|
|
|
animateThenIdle( document.querySelector("#biggu"), 'bigguaction_no') |
|
|
|
|
console.log('failed, should reset') |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
playSequence: function(evt) { |
|
|
|
|
this.interval = setInterval( _ => { |
|
|
|
|
this.posInSeq++ |
|
|
|
|
if (this.posInSeq == this.sequence.length){ |
|
|
|
|
this.sequence.push( this.colors.at( this.colors.length * Math.random() ) ) |
|
|
|
|
clearInterval( this.interval ) |
|
|
|
|
setTimeout( _ => { this.posInSeq=-1 }, 100) |
|
|
|
|
// should also a timeout to start giving answers |
|
|
|
|
} |
|
|
|
|
let box = this.el.querySelector("a-box[color="+ this.sequence[ this.posInSeq ] + "]") |
|
|
|
|
box.setAttribute("opacity", 1) |
|
|
|
|
box.components.sound.playSound() |
|
|
|
|
setTimeout( _ => { box.setAttribute("opacity", .5) }, 700) |
|
|
|
|
}, 1000) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
//___________________________________________________________________________________________________________________________________ |
|
|
|
|
AFRAME.registerComponent('carcassone', { |
|
|
|
|
init: function(){ |
|
|
|
@ -485,6 +659,11 @@ function overForbiddenSpot(selectorA="#biggu", distanceThreshold=.2){ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function moveBigguForward(step=.2){ |
|
|
|
|
/* // move with waddle example |
|
|
|
|
let biggu = document.querySelector("#biggu") |
|
|
|
|
biggu.setAttribute("animation__translation", "property: position; to: 0 0 0.5; dur: 10000;") |
|
|
|
|
biggu.setAttribute("animation__waddle", "property: rotation; from: 0 -20 -10; to: 0 20 10; dur: 1000; loop:true; easing: linear; dir:alternate;") |
|
|
|
|
*/ |
|
|
|
|
// could also first if within maze boundaries |
|
|
|
|
document.querySelector("#biggu").object3D.translateZ(step) |
|
|
|
|
if (overForbiddenSpot()) |
|
|
|
@ -685,7 +864,7 @@ AFRAME.registerComponent('idleafterload', { |
|
|
|
|
<a-sky hide-on-enter-ar color="lightgray"></a-sky> |
|
|
|
|
<a-troika-text anchor=left target value="instructions : \n--right pinch to move\n--left pinch to execute" position="0 1.65 -0.2" scale="0.1 0.1 0.1"></a-troika-text> |
|
|
|
|
|
|
|
|
|
<a-troika-text anchor=left value="jxr location.reload()" target position="-1 1.30 0" rotation="0 40 0" scale="0.1 0.1 0.1"></a-troika-text> |
|
|
|
|
<a-troika-text anchor=left value="jxr location.reload()" target position="-.5 1.30 0" rotation="0 40 0" scale="0.1 0.1 0.1"></a-troika-text> |
|
|
|
|
|
|
|
|
|
<a-console position="2 2 0" rotation="0 -45 0" font-size="34" height=1 skip-intro=true></a-console> |
|
|
|
|
|
|
|
|
|