how do i clone a random object from a list and make it visible using A-frame.js

Viewed 109

I'm using Javascript and A-frame. I want to be able to get a random block from the list of blocks and I want it to move down by 1. I can't seem to get any of the blocks to appear randomly on the load current. Below is the code I created to make my tetris board but it's currently giving me slight issues.

I am getting the error

  "message": "Uncaught SyntaxError: Unexpected end of input",

I'm not sure what that means?

var zigZag = document.querySelector("#zigZag");

var fork = document.querySelector("#fork");

var box = document.querySelector("#box");

var line = document.querySelector("#line");

var plane = document.querySelector("#plane");

//timer
// let hour = 0;
// let minute = 0;
// let second = 0;
// let millisecond = 0;

// let cron;

var newBlock, blocks, element, blocksOnPlane, planeBlock;

// Describe this function...

newBlock = [];

blocks = [zigZag, fork, line, box];

blocksOnPlane = [];
document.addEventListener("load", start);

function start() {
  while (true) {
    new Promise((res) => setTimeout(() => res(chooseBlock()), 10));
    console.log(newBlock.length);
    for (var element_index in newBlock) {
      element = newBlock[element_index];
      moveBlock(element);
      plane.detectCollisionsWith(newBlock[element_index], function (
        collidedObject
      ) {
        newBlock = collidedObject;
        newBlock.object3D.position.y = 0;
        blocksOnPlane.unshift(planeBlock);
        newBlock.shift();
      });
      // for (var element_index in blocksOnPlane) {
      //     element = blocksOnPlane[element_index];
      //     newBlock.detectCollisionsWith(planeBlock, function (collidedObject) {
      //         element.setY(element.getY() + 0)
      //         planeBlock = collidedObject;
      //         blocksOnPlane.unshift(planeBlock);
      //         newBlock.shift();

      //     })
      // }
    }
  }
}


document.addEventListener("keydown", function (event) {
  if (event.keyCode === 37) {
    element.object3D.position.x += -1;
  }
  //top
  else if (event.keyCode === 38) {
    element.object3D.position.x += 1;
  }
  //right
  else if (event.keyCode === 39) {
    element.object3D.position.x += 1;
  }
  //bottom
  else if (event.keyCode === 40) {
    element.object3D.position.x += -1;
  }
});

function moveBlock(element) {
  document.createTimer("timer1", 1 * 1000, function () {
    element.object3D.position.y += -1;
  });
}

function listsGetRandomItem(list, remove) {
  var x = Math.floor(Math.random() * list.length);
  if (remove) {
    return list.splice(x, 1)[0];
  } else {
    return list[x];
  }
}

// Describe this function...
function chooseBlock() {
  var tetrisBlock = document.clone(listsGetRandomItem(blocks, false));
  tetrisBlock.visible = true;
  tetrisBlock.object3D.position.x = 0;
  tetrisBlock.object3D.position.y = 7.5;
  tetrisBlock.object3D.position.z = -14;
  newBlock.unshift(tetrisBlock);
}
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<!DOCTYPE html>

    <button type="button" name="start">start</button>
    <button type="button" name="pause">pause</button>
    <button type="button" name="reset">reset</button>
    <a-scene>
      <a-entity
        id="zigZag"
        collide-with-player=""
        hatch-type-shape=""
        data-hatch-type="hatch-type-empty"
        data-icon-type="rectangle"
        physics-scale-fix=""
        hatch-physics=""
        shadow="cast: false; receive: false"
        hatch-cursor-event-detection="enableCursorDetection: true"
        position="-4.0825353394644335 5.15966087923683 -17.160361366799766"
        color="#d5b949"
        class="clickable"
        <!--
        visible="true"
        --
      >
        ><a-box
          id="line6"
          collide-with-player=""
          hatch-type-shape=""
          geometry="primitive: box"
          data-hatch-type="hatch-type-shape"
          data-icon-type="box"
          physics-scale-fix=""
          hatch-physics=""
          shadow=""
          hatch-cursor-event-detection="enableCursorDetection: true"
          position="5.039535339464433 3.3480091207631695 3.1603613667997656"
          color="#f1eaa3"
          material="color: #f1eaa3"
          class="clickable"
          scale="2 1 1"
          rotation="0 0 89.99999999999999"
          child-test="true"
        ></a-box
        ><a-box
          id="line5"
          collide-with-player=""
          hatch-type-shape=""
          geometry="primitive: box"
          data-hatch-type="hatch-type-shape"
          data-icon-type="box"
          physics-scale-fix=""
          hatch-physics=""
          shadow=""
          hatch-cursor-event-detection="enableCursorDetection: true"
          position="4.137505339464433 4.44454912076317 3.1603613667997656"
          color="#f1eaa3"
          material="color: #f1eaa3"
          class="clickable"
          scale="2 1 1"
          rotation="0 0 89.99999999999999"
          child-test="true"
        ></a-box
        ><a-box
          id="line4"
          collide-with-player=""
          hatch-type-shape=""
          geometry="primitive: box"
          data-hatch-type="hatch-type-shape"
          data-icon-type="box"
          physics-scale-fix=""
          hatch-physics=""
          shadow=""
          hatch-cursor-event-detection="enableCursorDetection: true"
          position="4.636015339464434 3.91959912076317 3.1603613667997656"
          color="#f1eaa3"
          material="color: #f1eaa3"
          class="clickable"
          scale="2 1 1"
          rotation="0 0 0"
          child-test="true"
        ></a-box
      ></a-entity>
      <a-entity
        id="fork"
        collide-with-player=""
        hatch-type-shape=""
        data-hatch-type="hatch-type-empty"
        data-icon-type="rectangle"
        physics-scale-fix=""
        hatch-physics=""
        shadow="cast: false; receive: false"
        hatch-cursor-event-detection="enableCursorDetection: true"
        position="1.158747821160648 5.997102835551197 -14.335538215901849"
        color="#617ec2"
        class="clickable"
        rotation="0 0 0"
        scale="1 1 1"
        visible="true"
        ><a-box
          id="line3"
          collide-with-player=""
          hatch-type-shape=""
          geometry="primitive: box"
          data-hatch-type="hatch-type-shape"
          data-icon-type="box"
          physics-scale-fix=""
          hatch-physics=""
          shadow=""
          hatch-cursor-event-detection="enableCursorDetection: true"
          position="-1.158747821160648 1.502897164448803 0.33553821590184896"
          color="#a3eaf1"
          material="color: #a3eaf1"
          class="clickable"
          scale="3 1.0000000000000002 1"
          rotation="0 0 89.99999999999999"
          child-test="true"
        ></a-box
        ><a-box
          id="line2"
          collide-with-player=""
          hatch-type-shape=""
          geometry="primitive: box"
          data-hatch-type="hatch-type-shape"
          data-icon-type="box"
          physics-scale-fix=""
          hatch-physics=""
          shadow=""
          hatch-cursor-event-detection="enableCursorDetection: true"
          position="-0.60527 1.44434 0.33554"
          color="#a3edf1"
          material="color: #a3edf1"
          class="clickable"
          scale="2 1 1"
          rotation="0 0 0"
          child-test="true"
        ></a-box
      ></a-entity>
      <a-box
        hatch-type-shape=""
        data-icon-type="box"
        id="box"
        shadow=""
        displayname="Box"
        position="0 9.09 -14"
        rotation="0 0 0"
        color="#4CC3D9"
        side="front"
        hatch-physics=""
        data-hatch-type="hatch-type-shape"
        material="color: #4CC3D9; side: front"
        geometry="primitive: box"
        physics-scale-fix=""
        hatch-cursor-event-detection="enableCursorDetection: true"
        collide-with-player=""
        class="clickable"
        scale="2 2 1"
        child-test="true"
        visible="true"
      ></a-box>
      <a-box
        id="line"
        collide-with-player=""
        hatch-type-shape=""
        geometry="primitive: box"
        data-hatch-type="hatch-type-shape"
        data-icon-type="box"
        physics-scale-fix=""
        hatch-physics=""
        shadow=""
        hatch-cursor-event-detection="enableCursorDetection: true"
        position="0 7.5 -14"
        color="#a3f1af"
        material="color: #a3f1af"
        class="clickable"
        scale="4 1 1"
        visible="true"
      ></a-box>
      <a-entity
        id="Ground"
        ground="dressing: none; groundSize: 100; ground: flat; groundTexture: none; grid: 1x1; groundColor: #333343; flatShading: true; gridColor: #B5B5B5"
        data-hatch-type="hatch-type-ground"
        data-is-droppable="false"
        data-icon-type="terrain"
        data-is-expandable="false"
        position="0 0 0"
        color="#62E9F7"
        visible="true"
        ><a-entity
          class="environment"
          position=""
          visible=""
          light=""
          data-not-selectable="true"
          data-hide-model="true"
          data-icon-type="light-hemisphere"
        ></a-entity
        ><a-entity
          class="environment"
          position=""
          light=""
          data-hide-model="true"
          visible="true"
          data-icon-type="light-directional"
        ></a-entity
        ><a-entity
          rotation=""
          visible=""
          data-not-selectable="true"
          class="environmentGround environment"
          scale=""
          shadow=""
        ></a-entity
        ><a-entity
          data-not-selectable="true"
          visible=""
          class="environmentDressing environment"
        ></a-entity
      ></a-entity>
      <a-plane
        id="plane"
        collide-with-player=""
        hatch-type-shape=""
        geometry="primitive: plane"
        data-hatch-type="hatch-type-shape"
        data-icon-type="plane"
        physics-scale-fix=""
        hatch-physics=""
        shadow=""
        hatch-cursor-event-detection=""
        position="-0.38406 0 -16.5359"
        color="#975c26"
        material="color: #975c26; shader: flat; side: back"
        rotation="90 0 0"
        scale="17.9 12.9 1"
        visible="true"
      ></a-plane>
    </a-scene>

1 Answers

Not sure where did you get document.clone(element) as the document object doesn't seem to have a cloning utility.

There is a element.cloneNode() method which works fine - we can use it within a custom component, which will also handle the entity lifecycle:

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
  // register new component
  AFRAME.registerComponent("foo", {
    // on init
    init: function() {
      // grab the button, and the entity
      const btn = document.querySelector("button")
      const tmplate = document.getElementById("template")

      // when clicked
      btn.addEventListener("click", evt => {
        // clone the node
        const new_element = tmplate.cloneNode(true);
        // make it smaller, and move it a bit
        new_element.setAttribute("scale", "0.2 0.2 0.2")
        new_element.setAttribute("position", {
          x: Math.random() * 6 - 3,
          y: 0.5,
          z: -1
        })
        // append it to the scene
        this.el.appendChild(new_element)
      })
    }
  })
</script>
<button style="z-index: 9999; position: fixed;">COPY</button>
<a-scene foo>
  <a-entity id="template">
    <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
    <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
    <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
    <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  </a-entity>
  <a-sky color="#ECECEC"></a-sky>
</a-scene>


You can move it down with interval timeouts, or a tick / throttledTick handler. This could be done within a system, which would manage created entities (moving down, collisions).

A simple "moving down" version could look like this:

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
  //register system
  AFRAME.registerSystem("foo", {
    init: function() {
      // array of all registered elements
      this.elements = [];
      // set up the throttled version
      this.tick = AFRAME.utils.throttleTick(this.tick, 250, this);
    },
    register: function(el) {
      // push new element to the registered array
      this.elements.push(el)
    },
    tick: function() {
      // loop through all of the elements, and move them down
      for (el of this.elements) {
        const pos = el.object3D.position // this is more efficient than getAttribute("position")
        pos.y = (pos.y < 0) ? 2 : pos.y - 0.1; // use setAttribute() if you want getAttribute() to work
      }
    }
  })

  // register new component
  AFRAME.registerComponent("foo", {
    // on init
    init: function() {
      //  move it a bit, and make it visible
      this.el.setAttribute("position", {
        x: Math.random() * 6 - 3,
        y: 0.5,
        z: -2
      })
      this.el.setAttribute("visible", "true")

      // register the element in the system
      this.system.register(this.el)
    }
  })

  AFRAME.registerComponent("inserter", {
    init: function() {
      // grab the button, and the entity
      const btn = document.querySelector("button")
      const tmplate = document.getElementById("template")

      // when clicked
      btn.addEventListener("click", evt => {
        // clone the node
        const new_element = tmplate.cloneNode(true);
        new_element.setAttribute("foo", "")
        // append it to the scene
        this.el.appendChild(new_element)
      })
    }
  })
</script>
<button style="z-index: 9999; position: fixed;">NEW</button>
<a-scene inserter>
  <a-entity id="template" visible="false" scale="0.2 0.2 0.2">
    <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
    <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
    <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
    <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  </a-entity>
  <a-sky color="#ECECEC"></a-sky>
</a-scene>


Sooner or later You'll probably run into performance issues (once there are several nodes) and it would be best to dive into mesh instancing (or at least check the performance guidelines)

Related