Search code examples
collision-detectiongame-physicsaframecannon.js

Aframe physics sphere breaks into smaller spheres on collision


In my game, I make a sphere (created using a-sphere), a dynamic body, collide with another dynamic body (a-box).

Upon collision, the sphere breaks into multiple smaller spheres. I need to stop this disintegration

Here is the codepen - sphere breaks on collision with dynamic body

Here is the accompanying code -

HTML

<a-scene physics="debug: true; gravity: -5.0">
  <a-entity camera="userHeight: 1.6"
                look-controls
                kinematic-body>
        <a-entity cursor
                  position="0 0 -1"
                  geometry="primitive: circle; radius: 0.01; segments: 4;"
                  material="color: #FF4444; shader: flat"></a-entity>
    <a-entity position="0 0 1" id="attachment"></a-entity>
  </a-entity>

  <a-entity geometry="primitive: box; height:2" material="color: black; shader: flat" position="0 2 -5" dynamic-body></a-entity>

  <a-plane static-body color="#ccc" height="100" width="100" position="0 -0.1 0" rotation="-90 0 0"></a-plane>
</a-scene>

and JS

const scene = document.querySelector('a-scene');
const camera = document.querySelector('[camera]');
const attachment = document.querySelector('#attachment');

function spawnBullet() {
    let entity = document.createElement('a-sphere');
    let impulseAmount = 8;

    entity.setAttribute('radius', 1);
    // Set initial position of projectile to that of the camera.
    entity.setAttribute('position', camera.getAttribute('position'));
    entity.setAttribute('color', '#00FFCC');
    entity.setAttribute('shader', 'flat');
    entity.setAttribute('mass', 10);

    // Append projectile to the scene, not to the camera, to
    // avoid all sorts of complications. Most notably, CANNON.js
    // has no scene graph or nesting.
    scene.appendChild(entity);

    entity.setAttribute('dynamic-body', true);  

    entity.addEventListener('body-loaded', function(){
      // Can't apply forces during the same tick that attaches the body, because
      // it hasn't been fully synced to the physics sim. (bug)
      setTimeout(function () {
        let pStart = new CANNON.Vec3();
        // Use an origin point behind the head, not at the head, so
        // there's a useful vector between the origin and the projectile.
        pStart.copy(attachment.object3D.getWorldPosition());
        let force = entity.body.position.vsub(pStart);
        force.normalize(); 
        force.scale(impulseAmount, force);
        entity.body.applyImpulse(force, entity.body.position);
      }, 0);

      entity.addEventListener('collide', function(e){
        console.log("hit");
      })
    });
}

if (scene.hasLoaded) init(); // change 2
else scene.addEventListener('loaded', init);

function init () {
  // any code that appends things to the scene
  scene.addEventListener('click', spawnBullet);
}

Is there a way that this can be stopped and the sphere remains intact after collision?


Solution

  • Listening for the click event on the scene is backfiring, because you get three events
    - the cursor emits one when clicked on something
    - the target emits one when clicked
    - the canvas emits one (mouse clicking, not the a-frame cursor - on the DOM canvas element).

    You can see it in this example, click on any object on the scene, and check out the console.


    You can listen for the mousedown event which is emitted by the cursor everytime its "clicked". Check it out here
    Provided you're on a PC, you can also listen for the click on the aframe canvas. If you're on a vive then just call the shootBullet when a trigger is pulled.

    Check it out working properly here.