Search code examples
javascriptaframe

Aframe - Select random entity (from 3 options) and set Attribute


Edit: Well thanks to the help of Piotr here is a working example. It takes two random Titles from a JSON array and displays only one at a time (through a process of random selection). Then if the user clicks the Title that belongs to the correct image on the box the font turns green, otherwise if he clicks the Title for a game that doesn't match up with the image then the text turns red. Amazing stuff. Here's some of the code.

  AFRAME.registerComponent('json-text-loader', {
  schema: {},
  init: function () {
    var url = 'json/text.json';
    var parentEL = this.el;

    var request = new XMLHttpRequest();
    request.open( 'GET', url, true );
    request.addEventListener( 'load', function ( event ) {

      var game = JSON.parse( event.target.response )
      var keys = Object.keys(game);
      var random = game[keys.length * Math.random() << 0];
      var trivia = random.Title
      var game2 = JSON.parse( event.target.response )
      var keys2 = Object.keys(game);
      var random2 = game[keys.length * Math.random() << 0];
      var trivia2 = random2.Title
      var textEntity = document.querySelector('#text');
      var gurl = random.Imageurl
      var sceneEl = document.querySelector('a-scene');
      sceneEl.querySelector('a-box').setAttribute('material', {src:gurl}); 
      textEntity.setAttribute("visible", "false")       

    let visibleRandom = Math.floor(Math.random() * 3); // THIS ELEMENT WILL BE VISIBLE
    let anwserRandom = Math.floor(Math.random() * 3); // THIS IS THE ELEMENT WITH THE CORRECT OPTION

  let children = Array.from(parentEL.children); 
  children.forEach((el, index) => {

if (index == visibleRandom) {
  el.setAttribute("visible", "true")
  el.setAttribute("value", trivia2)

} else {
  el.setAttribute("visible", "false")
}
if (index == anwserRandom) {
  el.setAttribute("value", trivia)
} 
 el.addEventListener("click", (e) => {
  if(el.getAttribute("value") == trivia) {
    el.setAttribute("color", "green")
  } else {
    el.setAttribute("color", "red")
  }
});
});
});
    request.send( null );
  }
});

ORIGINAL: Hoping someone can assist with this (if its possible that is). I need a bit of code in my scene to randomly pick one of three var textEntity = document.querySelector('#text'); entities to make visible in my scene, and if that randomly chosen element happens to be the first (textEntity1) and gets clicked on by the user the font color becomes green. The value of textEntity1 is always going to be the same so I don't know if that makes it easier to reference?

textEntity1.setAttribute("value", option1)

The 'Else' part (if this is going to require an 'if statement') is for when the entity made visible is textEntity2 / 3 and gets clicked on, in which case the font color should change to red.

Current (limited) code:

     // select random entity from below and set its attribute as visible                                                   
      var textEntity1 = document.querySelector('#text');
      var textEntity2 = document.querySelector('#text2');
      var textEntity3 = document.querySelector('#text3');

     // trigger event (e.g color change) if visible entity is 'textEntity1' and gets clicked.          
      sceneEl.querySelector('#text').addEventListener('click', function () {
      el.setAttribute('color', '#ffff00');
      });
      } );                                                  

Looking forward to see if there is a solution to this. So far I've learnt how to do random code for setting positions of objects but this seems a bit more complicated than that.


Solution

  • There are a few mechanics here. Let me explain how to do the "quiz" part, and i think it will explain the visibility as well.

    It may not be the best solution, but it seams neat. Lets have our three options inside an empty entity. The parent will handle the logic.

    <a-entity logic>
      <a-box position="0 0 1></a-box>
      <a-box position="0 0 0></a-box>
      <a-box position="0 0 -1></a-box>
    </a-entity>
    

    Cool. Now lets take a look inside the logic component. I need a random integer between 0-2, the Math.random() returns 0-1 (excluding 1), so i need to make Math.floor(Math.random()*3)). Also I need to grab the references. Since they are children of the entity, I don't need a document.querySelector(). I'll grab all the entity's children and convert them into an array:

    AFRAME.registerComponent("logic", {
      init: function() {
         let anwser = Math.floor(Math.random() * 3);
         let children = Array.from(this.el.children);
      }
    });
    

    Now, lets give them event listeners, in which we check which box is clicked:

    children.forEach((el, index) => {
        el.addEventListener("click", (e) => {
          if (index == anwser) {
            el.setAttribute("color", "green")
          } else {
            el.setAttribute("color", "red")
          }
    });
    

    So, I have the boxes, I have a random anwser, and if that anwser is clicked, the box will turn green.

    Moreover You can turn another random anwser invisible, if You put there a el.setAttribute('visibility', 'false')


    Check it out in my fiddle. The anwser is printed in the console.

    UPDATE

    If You already have an anwser from a JSON.parse, You an just check if it fits with the visible entity:

    children.forEach((el, index) => {
        if (index == anwser) {
          el.setAttribute("visible", "true")
        } else {
          el.setAttribute("visible", "false")
        }
        el.addEventListener("click", (e) => {
          if(el.getAttribute("value") == option1) {
            el.setAttribute("color", "green")
          } else {
            el.setAttribute("color", "red")
          }
        });
    }
    

    Check out the updated fiddle.