simon, voxel painting with saving/sharing via URL hash

in-situ-instructions
Fabien Benetou 6 months ago
parent 9d05fc4b6f
commit 5c09425e47
  1. 201
      index.html

@ -14,8 +14,20 @@
<body> <body>
<script> <script>
/* TODO : /* 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 - 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) - better menu (e.g target with onreleased)
- fix maze/mazemap mismatch (causing emit() error on init) - fix maze/mazemap mismatch (causing emit() error on init)
- game ideas - game ideas
@ -27,20 +39,15 @@ AFRAME.registerComponent('startfunctions', {
addGames() addGames()
// example of adding a game programmatically // example of adding a game programmatically
/*
let newEl = document.createElement('a-entity') let newEl = document.createElement('a-entity')
let gamename = "checkers" //let gamename = "checkers"
let gamename = "carcassone" //let gamename = "carcassone"
//let gamename = "simon"
let gamename = "voxelpaint"
newEl.id = gamename newEl.id = gamename
newEl.setAttribute(gamename, "") newEl.setAttribute(gamename, "")
newEl.classList.add( "game" ) newEl.classList.add( "game" )
AFRAME.scenes[0].appendChild(newEl) 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") 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', { AFRAME.registerComponent('carcassone', {
init: function(){ init: function(){
@ -485,6 +659,11 @@ function overForbiddenSpot(selectorA="#biggu", distanceThreshold=.2){
} }
function moveBigguForward(step=.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 // could also first if within maze boundaries
document.querySelector("#biggu").object3D.translateZ(step) document.querySelector("#biggu").object3D.translateZ(step)
if (overForbiddenSpot()) if (overForbiddenSpot())
@ -685,7 +864,7 @@ AFRAME.registerComponent('idleafterload', {
<a-sky hide-on-enter-ar color="lightgray"></a-sky> <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 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> <a-console position="2 2 0" rotation="0 -45 0" font-size="34" height=1 skip-intro=true></a-console>

Loading…
Cancel
Save