著名引擎暴力碰撞

Famous Engine Bruteforce collisions

我有一个著名的引擎设置和物理/阻力等工作

但似乎还有其他物理选项,BruteForce、SweepAndPrune 等。 我怀疑这些可能是我需要改进元素之间的碰撞检测的东西。

我试过像这样添加 BruteForce 碰撞检测: this.collision = new collision([rightWall, leftWall, topWall, bottomWall]);

但是我收到关于不正确约束的错误。 this.simulation.addConstraint(this.collision);

有没有人有解决这个问题的经验?

您可以在此处查看演示:

var famous = famous;
var FamousEngine = famous.core.FamousEngine;

var Camera = famous.components.Camera;


var DOMElement = famous.domRenderables.DOMElement;
var Gravity3D = famous.physics.Gravity3D;
var MountPoint = famous.components.MountPoint;
var PhysicsEngine = famous.physics.PhysicsEngine;
var Position = famous.components.Position;
var Size = famous.components.Size;
var Wall = famous.physics.Wall;
var Sphere = famous.physics.Sphere;
var Vec3 = famous.math.Vec3;
var math = famous.math;
var physics = famous.physics;
var collision = famous.physics.Collision;
var gestures = famous.components.GestureHandler;
var Spring = famous.physics.Spring;
console.log(famous)
var anchor = new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0);

//Create Walls
var rightWall = new Wall({
  direction: Wall.LEFT
}).setPosition(window.innerWidth - 20, 0, 0);
var leftWall = new Wall({
  direction: Wall.RIGHT
}).setPosition(window.innerWidth + 20, 0, 0);
var topWall = new Wall({
  direction: Wall.DOWN
}).setPosition(0, 20, 0);
var bottomWall = new Wall({
  direction: Wall.UP
}).setPosition(0, window.innerHeight - 20, 0);

var centerPoint;

function Demo() {
  this.scene = FamousEngine.createScene('body');
  this.collision = new collision([rightWall, leftWall, topWall, bottomWall]);
  console.log(this.collision)
  this.simulation = new PhysicsEngine();
  this.simulation.setOrigin(0.5, 0.5);
  this.simulation.addConstraint(this.collision);
  this.items = [];
  this.walls = [];

  //Create Items
  for (var i = 0; i < 10; i++) {
    var node = this.scene.addChild();
    node.setMountPoint(0.5, 0.5);
    var size = new Size(node).setMode(1, 1);
    var position = new Position(node);
    if (i === 0) {
      createLogo.call(this, node, size, position);

    }
    if (i !== 0 && i !== 9) {
      node.id = i;
      createSatellites.call(this, node, size, position);
    }
    if (i === 9) {
      node.id = i;
      createAlternateShape.call(this, node, size, position);

    }
  }

  //Create Walls
  var node = this.scene.addChild();
  createWalls(node);

  var once = true;

  Demo.prototype.onUpdate = function(time) {
    this.simulation.update(time);
    this.collision.resolve(time, 360)

    //Postition walls
    var wallPosition = topWall.getPosition();
    node.setPosition(wallPosition.x, wallPosition.y);

    //Position elements
    if (this.items.length > 0) {
      for (var i = 0; i < this.items.length; i++) {
        if (once) {
          console.log(this.items[i][1]._node.moving)
          once = false;
        }
        if (this.items[i][1]._node.moving) {
          console.log('moving!')
        } else {
          var itemPosition = this.simulation.getTransform(this.items[i][0]).position;
          this.items[i][1].set(itemPosition[0], itemPosition[1], 0);
        }


      }
    }

    FamousEngine.requestUpdateOnNextTick(this);
  };

  FamousEngine.requestUpdateOnNextTick(this);
}

function createWalls(wallNode) {
  wallNode.setSizeMode('absolute', 'absolute', 'absolute').setAbsoluteSize(window.innerWidth, 10, 0);
  var wallDOMElement = new DOMElement(wallNode, {
    tagName: 'div'
  }).setProperty('background-color', 'lightblue');
}

function createLogo(node, size, position) {
  node.moving = false;
  size.setAbsolute(100, 100);
  var mp = new MountPoint(node).set(0.5, 0.5);
  var el = new DOMElement(node, {
    tagName: 'img',
    attributes: {
      src: 'http://www.denisboudreau.org/presentations/2014/CSUN/Browser%20Zoom%20and%20Low%20Vision/Comps/ToM_EnsoCircle.png'
    }
  });
  centerPoint = new Sphere({
    radius: 50,
    mass: 10000,
    restrictions: ['xy'],
    position: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
  });

  var spring = new Spring(null, centerPoint, {
    stiffness: 95,
    period: 0.6,
    dampingRatio: 1.0,
    anchor: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
  });

  centerPoint.setVelocity(0, 0, 0);
  this.simulation.add(centerPoint, spring);
  this.items.push([centerPoint, position]);
  this.collision.addTarget(centerPoint);
}

function createAlternateShape(node, size, position) {
  node.moving = false;
  size.setAbsolute(100, 100);
  var el = new DOMElement(node, {
    properties: {
      'background-color': 'red',
    }
  });

  var box = new physics.Box({
    size: [100, 100, 100],
    mass: 10,
    position: new Vec3(100, 100, 0)
  });

  // Attach the box to the anchor with a `Spring` force
  var spring = new Spring(null, box, {
    stiffness: 95,
    period: 0.6,
    dampingRatio: 1.0,
    anchor: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
  });

  box.setVelocity(0.5, 0.5, 0);
  this.simulation.add(box, spring);
  this.items.push([box, position]);
  this.collision.addTarget(box);
}

function createSatellites(node, size, position, i) {
  node.moving = false;
  var rand = Math.round(Math.random() * 100 + 30);
  size.setAbsolute(rand, rand);
  var radius = 100;
  var x = Math.floor(Math.random() * radius * 2) - radius;
  var y = (Math.round(Math.random()) * 2 - 1) * Math.sqrt(radius * radius - x * x);
  var color = 'rgb(' + Math.abs(x) + ',' + Math.abs(Math.round(y)) + ',' + (255 - node.id) + ')';
  var el = new DOMElement(node, {
    properties: {
      'background-color': color,
      'border-radius': '50%'
    }
  });

  var satellite = new Sphere({
    radius: rand / 2,
    mass: 10,
    position: new Vec3(x + window.innerWidth / 2, y + window.innerHeight / 2, 0)
  });

  // Attach the box to the anchor with a `Spring` force
  var spring = new Spring(null, satellite, {
    stiffness: 95,
    period: 0.6,
    dampingRatio: 1.0,
    anchor: anchor
  });

  //console.log(color);
  // satellite.setVelocity(-y / Math.PI, -x / Math.PI / 2, y / 2);
  satellite.setVelocity(0.5, 0.5, 0);
  // this.gravity.addTarget(satellite);
  this.simulation.add(satellite, spring);
  this.items.push([satellite, position]);
  this.collision.addTarget(satellite);
  //Drag
  var nodeGesture = new gestures(node);
  nodeGesture.on('drag', function(e, p) {
    if (e.status == "move") {
      node.moving = true;
    }
    var currentPos = node.getPosition()
    var newPosX = currentPos[0] + e.centerDelta.x
    var newPosY = currentPos[1] + e.centerDelta.y
    satellite.setPosition(newPosX, newPosY)
    node.setPosition(newPosX, newPosY)

    if (e.status == "end") {
      node.moving = false;
    }
  });
  //event
  node.addUIEvent('click');
  // node.addComponent({
  //   onReceive:function(event, payload){
  //           if(event==='click'){
  //               // el.setContent('I\'ve been clicked')
  //
  //           }
  //       }
  //   })
}

setTimeout(function() {
  // Boilerplate
  FamousEngine.init();
}, 500);


// App Code
var demo = new Demo();
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Famous :: Seed Project</title>
  <link rel="icon" href="favicon.ico?v=1" type="image/x-icon">
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    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;
      -webkit-perspective: 0;
      perspective: none;
      overflow: hidden;
    }
  </style>
</head>

<body>
  <script src="http://code.famo.us/famous/0.6.2/famous.min.js"></script>
</body>

</html>

这是使用 BruteForceAABB 的解决方案。

var famous = famous;
var FamousEngine = famous.core.FamousEngine;

var Camera = famous.components.Camera;


var DOMElement = famous.domRenderables.DOMElement;
var Gravity3D = famous.physics.Gravity3D;
var MountPoint = famous.components.MountPoint;
var PhysicsEngine = famous.physics.PhysicsEngine;
var Position = famous.components.Position;
var Size = famous.components.Size;
var Wall = famous.physics.Wall;
var Sphere = famous.physics.Sphere;
var Vec3 = famous.math.Vec3;
var math = famous.math;
var physics = famous.physics;
var collision = famous.physics.Collision;
var gestures = famous.components.GestureHandler;
var Spring = famous.physics.Spring;
console.log(famous)
var anchor = new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0);

//Create Walls
var rightWall = new Wall({
  direction: Wall.LEFT
}).setPosition(window.innerWidth - 20, 0, 0);
var leftWall = new Wall({
  direction: Wall.RIGHT
}).setPosition(window.innerWidth + 20, 0, 0);
var topWall = new Wall({
  direction: Wall.DOWN
}).setPosition(0, 20, 0);
var bottomWall = new Wall({
  direction: Wall.UP
}).setPosition(0, window.innerHeight - 20, 0);

var centerPoint;

function Demo() {
  this.scene = FamousEngine.createScene('body');
  // this.collision = new collision.({broadphase: 'BruteForce'});
  var broadPhase = new physics.Collision.BruteForceAABB([rightWall, leftWall, topWall, bottomWall]);
  this.collision = new collision([topWall], {
    'broadPhase': broadPhase
  });

  this.simulation = new PhysicsEngine();
  this.simulation.setOrigin(0.5, 0.5);
  this.simulation.addConstraint(this.collision);
  this.items = [];
  this.walls = [];

  //Create Items
  for (var i = 0; i < 10; i++) {
    var node = this.scene.addChild();
    node.setMountPoint(0.5, 0.5);
    var size = new Size(node).setMode(1, 1);
    var position = new Position(node);
    if (i === 0) {
      createLogo.call(this, node, size, position);

    }
    if (i !== 0 && i !== 9) {
      node.id = i;
      createSatellites.call(this, node, size, position);
    }
    if (i === 9) {
      node.id = i;
      createAlternateShape.call(this, node, size, position);

    }
  }

  //Create Walls
  var node = this.scene.addChild();
  createWalls(node);

  var once = true;

  Demo.prototype.onUpdate = function(time) {
    this.simulation.update(time);
    // this.collision.resolve(time, 360)

    //Postition walls
    var wallPosition = topWall.getPosition();
    node.setPosition(wallPosition.x, wallPosition.y);

    //Position elements
    if (this.items.length > 0) {
      for (var i = 0; i < this.items.length; i++) {
        if (once) {
          console.log(this.items[i][1]._node.moving)
          once = false;
        }
        if (this.items[i][1]._node.moving) {
          console.log('moving!')
        } else {
          var itemPosition = this.simulation.getTransform(this.items[i][0]).position;
          this.items[i][1].set(itemPosition[0], itemPosition[1], 0);
        }


      }
    }

    FamousEngine.requestUpdateOnNextTick(this);
  };

  FamousEngine.requestUpdateOnNextTick(this);
}

function createWalls(wallNode) {
  wallNode.setSizeMode('absolute', 'absolute', 'absolute').setAbsoluteSize(window.innerWidth, 10, 0);
  var wallDOMElement = new DOMElement(wallNode, {
    tagName: 'div'
  }).setProperty('background-color', 'lightblue');
}

function createLogo(node, size, position) {
  node.moving = false;
  size.setAbsolute(100, 100);
  var mp = new MountPoint(node).set(0.5, 0.5);
  var el = new DOMElement(node, {
    tagName: 'img',
    attributes: {
      src: './images/famous_logo.png'
    }
  });
  centerPoint = new Sphere({
    radius: 50,
    mass: 100000,
    restrictions: ['xy'],
    position: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
  });

  var spring = new Spring(null, centerPoint, {
    stiffness: 95,
    period: 0.6,
    dampingRatio: 1.0,
    anchor: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
  });

  centerPoint.setVelocity(0, 0, 0);
  this.simulation.add(centerPoint, spring);
  this.items.push([centerPoint, position]);
  this.collision.addTarget(centerPoint);
}

function createAlternateShape(node, size, position) {
  node.moving = false;
  size.setAbsolute(100, 100);
  var el = new DOMElement(node, {
    properties: {
      'background-color': 'red',
    }
  });

  var box = new physics.Box({
    size: [101, 101, 101],
    mass: 100,
    position: new Vec3(100, 100, 0)
  });

  // Attach the box to the anchor with a `Spring` force
  var spring = new Spring(null, box, {
    period: 1.5,
    dampingRatio: 0.8,
    anchor: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
  });

  box.setVelocity(0.1, 0.1, 0);
  this.simulation.add(box, spring);
  this.items.push([box, position]);
  this.collision.addTarget(box);
}

function createSatellites(node, size, position, i) {
  node.moving = false;
  var rand = Math.round(Math.random() * 100 + 30);
  size.setAbsolute(rand, rand);
  var radius = rand;
  var x = Math.floor(Math.random() * radius * 2) - radius;
  var y = (Math.round(Math.random()) * 2 - 1) * Math.sqrt(radius * radius - x * x);
  var color = 'rgb(' + Math.abs(x) + ',' + Math.abs(Math.round(y)) + ',' + (255 - node.id) + ')';
  var el = new DOMElement(node, {
    properties: {
      'background-color': color,
      'border-radius': '50%'
    }
  });

  var satellite = new Sphere({
    radius: rand / 2,
    mass: 100,
    position: new Vec3(x + window.innerWidth / 2, y + window.innerHeight / 2, 0)
  });

  // Attach the box to the anchor with a `Spring` force
  var spring = new Spring(null, satellite, {
    // stiffness: 10,
    period: 1.5,
    dampingRatio: 0.8,
    anchor: anchor
  });

  //console.log(color);
  // satellite.setVelocity(-y / Math.PI, -x / Math.PI / 2, y / 2);
  satellite.setVelocity(0.1, 0.1, 0);
  // this.gravity.add(satellite);
  this.simulation.add(satellite, spring);
  this.items.push([satellite, position]);
  this.collision.addTarget(satellite);
  //Drag
  var nodeGesture = new gestures(node);
  nodeGesture.on('drag', function(e, p) {
    if (e.status == "move") {
      node.moving = true;
    }
    var currentPos = node.getPosition()
    var newPosX = currentPos[0] + e.centerDelta.x
    var newPosY = currentPos[1] + e.centerDelta.y
    satellite.setPosition(newPosX, newPosY)
    node.setPosition(newPosX, newPosY)

    if (e.status == "end") {
      node.moving = false;
    }
  });
  //event
  node.addUIEvent('click');
  // node.addComponent({
  //   onReceive:function(event, payload){
  //           if(event==='click'){
  //               // el.setContent('I\'ve been clicked')
  //
  //           }
  //       }
  //   })
}

setTimeout(function() {
  // Boilerplate
  FamousEngine.init();
}, 500);


// App Code
var demo = new Demo();
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Famous :: Seed Project</title>
  <link rel="icon" href="favicon.ico?v=1" type="image/x-icon">
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    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;
      -webkit-perspective: 0;
      perspective: none;
      overflow: hidden;
    }
  </style>
</head>

<body>
  <script src="http://code.famo.us/famous/0.6.2/famous.min.js"></script>
</body>

</html>