如何在 Famous Engine 中将球体从墙上弹开?

How to bounce a sphere off of a wall in Famous Engine?

我创建了一个球体和一个墙并将其添加到物理引擎中。球体也被赋予了起始速度。

然后我创建了一个圆和墙节点,添加了 DOMElement 组件,并设置了一些尺寸和颜色。

在更新循环中,节点将它们的位置与它们的物理对应物——球体和墙同步。

我预计球体会与墙碰撞,但动画显示球体只是继续穿过墙。我想知道发生这种情况的代码有什么问题。

'use strict';

var famous = require('famous');
var DOMElement = famous.domRenderables.DOMElement;
var FamousEngine = famous.core.FamousEngine;
var Node = famous.core.Node;
var math = famous.math;
var physics = famous.physics;
var Particle = physics.Particle;
var Sphere = physics.Sphere;
var Vec3 = math.Vec3;
var Box = physics.Box;
var Wall = physics.Wall;

// Create Simulation.
var simulation = new physics.PhysicsEngine();

// Create Scene.
var scene = FamousEngine.createScene();

/***************************************
 * Add Bodies
 ***************************************/

// Create Sphere.
var mySphere = new Sphere({ mass: 10, radius: 50 });

// Give the sphere some velocity.
mySphere.setVelocity(100, 0)
    .setPosition(0, 250, 0);

// Create Wall.
var rightWall = new Wall({ 
    direction: Wall.LEFT,
    size: [10, 500, 100]
});

rightWall.setPosition(500, 0, 0);

simulation.addBody(rightWall);
simulation.addBody(mySphere);

/***************************************
 * Add Nodes + Components
 ***************************************/

// Create circleNode, which updates its position based on mySphere's position.
var circleNode = scene.addChild();

circleNode
    .setSizeMode('absolute', 'absolute', 'absolute')
    // Match size of sphere
    .setAbsoluteSize(100, 100)
    .setPosition(0, 250, 0)
    .setMountPoint(0, 0);

// Add DOMElement component to circleNode.
var circleDOMElement = new DOMElement(circleNode, { tagName: 'div' })
    .setProperty('background-color', 'pink')
    .setProperty('border-radius', '50px');

// Create a wallNode, which will update its position based on rightWall's position.
var wallNode = scene.addChild();

wallNode
    .setSizeMode('absolute', 'absolute', 'absolute')
    .setAbsoluteSize(10, 500, 100);

var wallDOMElement = new DOMElement(wallNode, { tagName: 'div' })
    .setProperty('background-color', 'lightblue');

/***************************************
 * Create an Update Loop
 ***************************************/

var updateLoop = scene.addComponent({
    onUpdate: function (time) {
        // During update, sync cirlceNode position with sphere,
        // and wallNode position with wall.
        var spherePosition = mySphere.getPosition();
        var wallPosition = rightWall.getPosition();

        circleNode.setPosition(spherePosition.x, spherePosition.y);
        wallNode.setPosition(wallPosition.x, wallPosition.y);

        simulation.update(time);

        scene.requestUpdateOnNextTick(updateLoop);
    }
});

// Kick off loop.
scene.requestUpdate(updateLoop);
FamousEngine.init();

需要将约束应用于墙和球体。在这种情况下,您可以使用 Collision

var Collision = physics.Collision;

替换

rightWall.setPosition(500, 0, 0);

simulation.addBody(rightWall);
simulation.addBody(mySphere);

rightWall.setPosition(500, 0, 0);

simulation.addBody(mySphere);

var collision = new Collision([mySphere,rightWall]);
simulation.addConstraint(collision);

另外,将圆的挂载点固定在圆心

circleNode
  .setSizeMode('absolute', 'absolute', 'absolute')
  // Match size of sphere
  .setAbsoluteSize(100, 100)
  .setPosition(0, 250, 0)
  .setMountPoint(0.5, 0.5);

奖励:添加左墙以使粒子保持在屏幕上

// Create Walls.
var rightWall = new Wall({ 
  direction: Wall.LEFT
});
var leftWall = new Wall({ 
  direction: Wall.RIGHT
});

leftWall.setPosition(0, 0, 0);
rightWall.setPosition(500, 0, 0);

simulation.addBody(mySphere);
var collision = new Collision([mySphere,rightWall,leftWall]);
simulation.addConstraint(collision);

示例工作代码段

var FamousEngine = famous.core.FamousEngine;
var DOMElement = famous.domRenderables.DOMElement;
var Node = famous.core.Node;
var math = famous.math;
var physics = famous.physics;
var Sphere = physics.Sphere;
var Wall = physics.Wall;
var Collision = physics.Collision;

// Create Scene.
var scene = FamousEngine.createScene();
var rootNode = scene.addChild();

// Create Simulation.
var simulation = new physics.PhysicsEngine();


/***************************************
 * Add Bodies
 ***************************************/

// Create Sphere.
var mySphere = new Sphere({
  mass: 100,
  radius: 50
});

// Give the sphere some velocity.
mySphere.setVelocity(500, 0)
  .setPosition(0, 70, 0);

// Create Wall.
var rightWall = new Wall({
  direction: Wall.LEFT
});
var leftWall = new Wall({
  direction: Wall.RIGHT
});

leftWall.setPosition(0, 0, 0);
rightWall.setPosition(300, 0, 0);

//simulation.addBody(rightWall);
simulation.addBody(mySphere);
var collision = new Collision([mySphere, rightWall, leftWall]);
simulation.addConstraint(collision);

/***************************************
 * Add Nodes + Components
 ***************************************/

// Create circleNode, which updates its position based on mySphere's position.
var circleNode = scene.addChild();

circleNode
  .setSizeMode('absolute', 'absolute', 'absolute')
  // Match size of sphere
  .setAbsoluteSize(100, 100)
  .setPosition(0, 70, 0)
  .setMountPoint(0.5, 0.5);
circleNode.addUIEvent('click');
circleNode.addComponent({
  onReceive: function(type, event) {
    if (type === 'click') {
      console.log('setting velocity');
      mySphere.setVelocity(1000, 0);
    }
  },
});

// Add DOMElement component to circleNode.
var circleDOMElement = new DOMElement(circleNode, {
    tagName: 'div'
  })
  .setProperty('background-color', 'lightblue')
  .setProperty('text-align', 'center')
  .setProperty('line-height', '100px')
  .setProperty('border-radius', '50px');
circleDOMElement.setContent('click');
// Create a wallNode, which will update its position based on rightWall's position.
var wallNode = scene.addChild();

wallNode
  .setSizeMode('absolute', 'absolute', 'absolute')
  .setAbsoluteSize(10, 130, 0);

var wallDOMElement = new DOMElement(wallNode, {
    tagName: 'div'
  })
  .setProperty('background-color', 'lightblue');

/***************************************
 * Create an Update Loop
 ***************************************/
var updateLoop = rootNode.addComponent({
  onUpdate: function(time) {
    // During update, sync cirlceNode position with sphere,
    // and wallNode position with wall.
    var spherePosition = mySphere.getPosition();
    var wallPosition = rightWall.getPosition();

    circleNode.setPosition(spherePosition.x, spherePosition.y);
    wallNode.setPosition(wallPosition.x, wallPosition.y);

    simulation.update(time);

    rootNode.requestUpdateOnNextTick(updateLoop);
  }
});

// Kick off loop.
rootNode.requestUpdate(updateLoop);
FamousEngine.init();
            html,
            body {
              width: 100%;
              height: 100%;
              margin: 0px;
              padding: 0px;
            }
            body {
              position: absolute;
              -webkit-transform-style: preserve-3d;
              transform-style: preserve-3d;
              -webkit-font-smoothing: antialiased;
              -webkit-tap-highlight-color: transparent;
              background-color: black;
              -webkit-perspective: 0;
              perspective: none;
              overflow: hidden;
            }
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Physics Famous0.6.2</title>
  <link rel="icon" href="favicon.ico?v=1" type="image/x-icon">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="http://code.famo.us/famous/0.6.2/famous.min.js"></script>
  <style>
  </style>
</head>

<body>
</body>

</html>