How do I use checkpoint controls in A-Frame?

Viewed 539

I am new to A-Frame and still trying to figure everything out! I'm currently constructing a 3D space and would like to create a guided experience for visitors by providing dots on the floor for them to click and be transported to that position. I found this code online which is perfect but I can't get it to work. Here is the link to my project on Glitch: https://glitch.com/~museum-exhibit-demo

This is the code for my camera:

<a-entity position="1.8 -1.1 3" rotation="0 90 0" id="pov">
        <a-camera universal-controls="movementControls: checkpoint" checkpoint-controls="mode: animate">
      <a-entity cursor position="0 0 -1" geometry="primitive: ring; radiusInner: 0.01; radiusOuter: 0.015;" material="color: #CCC; shader: flat;"> </a-entity>
          </a-camera>
    </a-entity>

And this is the code for the cylinder:

<a-cylinder checkpoint radius="0.1.5" height="0.01" position="-0.164 0.111 2.363"  color="#39BB82"></a-cylinder>

Can anyone spot where I'm going wrong?

2 Answers

UPDATE:

I just read the current source of aframe-extra and it seems that nothing is broken! In fact there was a backward-incompatible change in the new versions. Rather than the old syntax of:

universal-controls="movementControls: checkpoint;"

Now this new syntax should be used:

movement-controls="controls: checkpoint;"

But keep in mind that since version 3.2.7, the movement offset is calculated on all 3 XYZ axis and therefore the camera will move to the center of the checkpoint. If you want to preserve the height (y) then simply add the code below above line 83:

targetPosition.y = position.y;

Here is a complete working example:

<html>
  <head>
    <meta charset="utf-8">
    <title>Checkpoint Control with AFrame 1.2.0</title>
    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v6.1.1/dist/aframe-extras.min.js"></script>
  </head>
  <body>
    <a-scene stats>

      <!-- CAMERA -->
      <a-entity position="0 0 0" id="pov">
        <a-camera camera="active: true; spectator: false;" look-controls="pointerLockEnabled:true" movement-controls="controls: checkpoint;" checkpoint-controls="mode: animate; animateSpeed: 10" wasd-controls="enabled: false;" position="0 1.6 22">
          <a-cursor></a-cursor>
        </a-camera>
      </a-entity>

      <!-- CHECKPOINTS -->
      <a-cylinder checkpoint radius="0.5" height="0.01" position="0 0 20" color="#FF0000"></a-cylinder>
      <a-cylinder checkpoint radius="0.5" height="0.01" position="0 0 16" color="#FF0000"></a-cylinder>
      <a-cylinder checkpoint radius="0.5" height="0.01" position="0 0 12" color="#FF0000"></a-cylinder>
      <a-cylinder checkpoint radius="0.5" height="0.01" position="0 0 8" color="#FF0000"></a-cylinder>

    </a-scene>
  </body>
</html>

Information below this line is not valid anymore.


As Piotr already mentioned, the new releases of Aframe-Extra are somehow broken! Using an older version everything will work again.

Below is a working example with Aframe-extra version 3.2.7.

Once the page is fully loaded, click on the screen to lock the cursor, then point the cursor (tiny ring) at a red circle and click.

I also noted few additional options just in case:

  • spectator: false (switch between 1st and 3rd person view)
  • pointerLockEnabled:true (hide the mouse)
  • mode: animate (the other option is teleport)
  • animateSpeed: 10 (well... adjusts the animation speed)
  • wasd-controls="enabled: false;" (otherwise user can move around via WASD/arrow keys)

Code:

<html>
  <head>
    <meta charset="utf-8">
    <title>Checkpoint Control with AFrame 1.2.0</title>
    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v3.2.7/dist/aframe-extras.min.js"></script>
  </head>
  <body>
    <a-scene stats>

      <!-- CAMERA -->
      <a-entity position="0 0 0" id="pov">
        <a-camera camera="active: true; spectator: false;" look-controls="pointerLockEnabled:true" universal-controls="movementControls: checkpoint;" checkpoint-controls="mode: animate; animateSpeed: 10" wasd-controls="enabled: false;" position="0 1.6 22">
          <a-cursor></a-cursor>
        </a-camera>
      </a-entity>

      <!-- CHECKPOINTS -->
      <a-cylinder checkpoint radius="0.5" height="0.01" position="0 0 20" color="#FF0000"></a-cylinder>
      <a-cylinder checkpoint radius="0.5" height="0.01" position="0 0 16" color="#FF0000"></a-cylinder>
      <a-cylinder checkpoint radius="0.5" height="0.01" position="0 0 12" color="#FF0000"></a-cylinder>
      <a-cylinder checkpoint radius="0.5" height="0.01" position="0 0 8" color="#FF0000"></a-cylinder>

    </a-scene>
  </body>
</html>

This won't answer the question, but should solve your problem.

You can substitute the checkpoint-controls with a simple animation system:

  1. you click on a cylinder
  2. you animate the camera from the current position to the cylinder

Which could be implemented like this:

// use a system to keep a global track if we are already moving
AFRAME.registerSystem('goto', {
  init: function() {
    this.isMoving = false
  }
})

// this component will have the actual logic
AFRAME.registerComponent('goto', {
  init: function() {
     let camRig = document.querySelector('#rig')

     // upon click - move the camera
     this.el.addEventListener('click', e => {
        // check if we are already moving
        if (this.system.isMoving) return;

        // lock other attempts to move
        this.system.isMoving = true

        // grab the positions
        let targetPos = this.el.getAttribute("position")
        let rigPos = camRig.getAttribute("position")

        // set the animation attributes. 
        camRig.setAttribute("animation", {
          "from": rigPos,
          "to": AFRAME.utils.coordinates.stringify({x: targetPos.x, y: rigPos.y, z: targetPos.z}),
          "dur": targetPos.distanceTo(rigPos) * 750
        })
        camRig.emit('go')
     })

     // when the animation is finished - update the "shared" variable
     camRig.addEventListener('animationcomplete', e=> {
       this.system.isMoving = false
     })
  }
})

with a setup like this:

<!-- Camera with locked movement --/>
<a-entity id="rig" animation="property: position; startEvents: go">
  <a-camera look-controls wasd-controls-enabled="false"></a-camera>
<a-entity>

<!-- Cylinder node --/>
<a-cylinder goto></a-cylinder>

You can see it working in this glitch.

Related