how to add walls to a famo.us physics simulation?

别等时光非礼了梦想. 提交于 2020-01-03 05:06:06

问题


I have a simple physics sim with some bouncing balls. I'm trying to add a bounding box of "walls" but having problems.

any examples would be great :) meantime

looking at the cool ascii art docs here

 *    (wall)
 *      |
 *      | (normal)     (origin)
 *      | --->            *
 *      |
 *      |    (distance)
 *      ...................
 *            (100px)
 *
 *      e.g., Wall({normal : [1,0,0], distance : 100})

my guess is that adding a wall of

@walls.push = new Wall({normal : [1,0,0], distance : 5})

should be a wall of just 5 pixels left of the origin.

my questions are: - how do we set the origin of the physics engine? I don't see an origin property here in the PhysicsEngine should i attach a modifier to it?

  • are engine coords in a 0~1 range? ie 0.5? or screen pixels?

  • since walls only take a single distance (effectively like a radius), with direction being set by the normals, are they always facing inwards to the origin? ie you can't have a wall facing outwards?

  • default Walls() looking at the source this should create a bounding box the size of the viewport but doesn't seem to work...

  • Here's a public repo with the code/demo so far

  • and here's a running demo with no walls :(

回答1:


The physics engine defaults with the origin centered and the walls must be defined relative to the center using the context size. I have not played around with changing the origin of the PhysicsEngine itself, but it's just going to be relative anyway to the modifiers on your surfaces.

Here is a working wall example.. just click the ball to give it some initial velocity!

Hope you can derive some help from this example!

Good Luck!

var Engine          = require('famous/core/Engine');
var Surface         = require('famous/core/Surface');
var EventHandler    = require('famous/core/EventHandler');
var View            = require('famous/core/View');
var Transform       = require('famous/core/Transform');

var StateModifier   = require('famous/modifiers/StateModifier');

var PhysicsEngine   = require('famous/physics/PhysicsEngine');
var Body            = require('famous/physics/bodies/Body');
var Circle          = require('famous/physics/bodies/Circle');
var Wall            = require('famous/physics/constraints/Wall');

var context = Engine.createContext();

var handler = new EventHandler();

var physicsEngine = new PhysicsEngine();

var ball = new Surface ({
  size: [200,200],
  properties: {
    backgroundColor: 'red',
    borderRadius: '100px'
  }
})

ball.state = new StateModifier({origin:[0.5,0.5]});

ball.particle = new Circle({radius:100});

physicsEngine.addBody(ball.particle);

ball.on("click",function(){
  ball.particle.setVelocity([1,1,0]);
});

context.add(ball.state).add(ball)

var leftWall    = new Wall({normal : [1,0,0],  distance : window.innerWidth/2.0, restitution : 0.5});
var rightWall   = new Wall({normal : [-1,0,0], distance : window.innerWidth/2.0, restitution : 0.5});
var topWall     = new Wall({normal : [0,1,0],  distance : window.innerHeight/2.0, restitution : 0.5});
var bottomWall  = new Wall({normal : [0,-1,0], distance : window.innerHeight/2.0, restitution : 0.5});

physicsEngine.attach( leftWall,  [ball.particle]);
physicsEngine.attach( rightWall, [ball.particle]);
physicsEngine.attach( topWall,   [ball.particle]);
physicsEngine.attach( bottomWall,[ball.particle]);

Engine.on('prerender', function(){
  ball.state.setTransform(ball.particle.getTransform())
});



回答2:


I found johntraver's answer above and it answered all of my questions re: implementing the physics engine. The one minor hiccup was that it didn't work for me (0.2.0). This was due to the fact that the contextSize was getting set to [0,0] so all of the walls were located at the center of the screen. This led me to turn the wall setup into a function and call it with Engine.nextTick(). This way the context has size when the walls are put into place. Then just for kicks I added another call to the same function on Engine resize. This also required that the walls be detached before being recreated to avoid creating an endless number of walls with a field that only got smaller.

Here is my tweak of the above answer:

/* globals define */
define(function(require, exports, module) {
    'use strict';
    // import dependencies
var Engine          = require('famous/core/Engine');
var Surface         = require('famous/core/Surface');
var EventHandler    = require('famous/core/EventHandler');
var View            = require('famous/core/View');
var Transform       = require('famous/core/Transform');

var StateModifier   = require('famous/modifiers/StateModifier');

var PhysicsEngine   = require('famous/physics/PhysicsEngine');
var Body            = require('famous/physics/bodies/Body');
var Circle          = require('famous/physics/bodies/Circle');
var Wall            = require('famous/physics/constraints/Wall');


    function wallBounce() {
        var context = Engine.createContext();

        var contextSize;// = context.getSize();

        var handler = new EventHandler();

        var physicsEngine = new PhysicsEngine();

        var ball = new Surface ({
          size: [200,200],
          properties: {
            backgroundColor: 'red',
            borderRadius: '100px'
          }
        })

        ball.state = new StateModifier({origin:[0.5,0.5]});

        ball.particle = new Circle({radius:100});

        physicsEngine.addBody(ball.particle);

        ball.on("click",function(){
          ball.particle.setVelocity([.1,.13,0]);
        });

        context.add(ball.state).add(ball);
        function setWalls() {
            //console.log(contextSize[0]);
            contextSize = context.getSize();
            var leftWall    = new Wall({normal : [1,0,0],  distance : contextSize[0]/2.0, restitution : .5});
            var rightWall   = new Wall({normal : [-1,0,0], distance : contextSize[0]/2.0, restitution : .5});
            var topWall     = new Wall({normal : [0,1,0],  distance : contextSize[1]/2.0, restitution : .5});
            var bottomWall  = new Wall({normal : [0,-1,0], distance : contextSize[1]/2.0, restitution : .5});

            physicsEngine.detachAll();
            physicsEngine.attach( leftWall,  [ball.particle]);
            physicsEngine.attach( rightWall, [ball.particle]);
            physicsEngine.attach( topWall,   [ball.particle]);
            physicsEngine.attach( bottomWall,[ball.particle]);
        };
        Engine.nextTick(setWalls);
        Engine.on('resize',setWalls);

        Engine.on('prerender', function(){
          ball.state.setTransform(ball.particle.getTransform())
        });
    };

    new wallBounce();

});


来源:https://stackoverflow.com/questions/23399011/how-to-add-walls-to-a-famo-us-physics-simulation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!