3

I'm new to the 'Physics Engine world'. I decided to use Famo.us for experimenting and trying to learn how to use the Physics Engine.

How do you make balls bounce when hitting each other? I managed to add the balls and create the walls. The balls bounce when hitting the walls, but not when hitting each other, they just pass through. I've been trying anything I could find, but unfortunately, the lack of information on the famo.us doc is being a little bit of obstacle for me (as I'm still learning the concepts).

Another concept I don't quite understand in practice is how to add gravity to the balls.

This is what I'm trying to achieve: http://mrdoob.com/projects/chromeexperiments/ball-pool/

Here is the code I have so far:

define(function(require, exports, module) {
    var Engine          = require('famous/core/Engine');
    var Surface         = require('famous/core/Surface');
    var ContainerSurface         = require('famous/surfaces/ContainerSurface');
    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 Vector          = require('famous/math/Vector');

    var Collision       = require('famous/physics/constraints/Collision');


    var context = Engine.createContext();

    var contextSize;

    var mainSurface = new ContainerSurface ({
        size: [undefined,undefined],
        properties: {
            backgroundColor: '#dddddd'
        }
    });

    mainSurface.on("click",function(){
        addNewBall(1);
        setWalls();
    });


    var handler = new EventHandler();

    var physicsEngine = new PhysicsEngine();

    var balls = [];
    var collision = new Collision();
    function addNewBall(number){
        if(number == undefined) var number = 1;
        for(var i=0; i<number; i++){
            var index = balls.length;
            balls[index] = new Surface ({
              size: [50,50],
              properties: {
                backgroundColor: 'red',
                borderRadius: '50px'
              }
            })

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

            balls[index].particle = new Circle({radius:25});

            //Attempting to add collision
            physicsEngine.attach( collision,  [balls[index]]);

            balls[index].particle.applyForce(new Vector(Math.random(), 1, 0));

            physicsEngine.addBody(balls[index].particle);


            mainSurface.add(balls[index].state).add(balls[index]);
        }
    }

    context.add(mainSurface);
    addNewBall(1);

    //Function to loop through all balls and set the walls
    function setWalls() {
        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});

        for(var i=0; i < balls.length; i++){
            physicsEngine.attach( leftWall,  [balls[i].particle]);
            physicsEngine.attach( rightWall, [balls[i].particle]);
            physicsEngine.attach( topWall,   [balls[i].particle]);
            physicsEngine.attach( bottomWall,[balls[i].particle]);
        }
    }


    Engine.nextTick(setWalls);
    Engine.on('resize',setWalls);

    Engine.on('prerender', function(){
        for(var i=0; i < balls.length; i++){
            balls[i].state.setTransform(balls[i].particle.getTransform())
        }
    });
});
user229044
  • 232,980
  • 40
  • 330
  • 338
  • Did you figure it out? I am unable to add collision to your example using the answers here... Would love to see how you did it. Can you share the source? – Luca Feb 21 '15 at 23:29

2 Answers2

2

The problem is this line:

physicsEngine.attach( collision,  [balls[index]]);

The .attach method takes a physics agent (Collision), array of targets (balls), and an [optional] source. Since a collision is between two balls, you will need to define a source of the collision. Similarly, you can connect a Spring or Repulsion between two particles. Drag, Gravity, etc don't need this.

To define a collision between all pairs of particles, you would do:

for (var i = 0; i < balls.length; i++) {
    physicsEngine.attach(collision, balls, balls[i]);
}

equivalently (thought slightly less optimally), you can use a double for loop to be explicit

for (var i = 0; i < balls.length; i++) {
    for (var j = 0; j < balls.length; j++) {
        if (i !== j) physicsEngine.attach(collision, balls[j], balls[i]);
    }
}
dmvaldman
  • 413
  • 2
  • 13
  • Thanks for your help @dmvaldman . It works fine now. That was the part I was not quite getting. I still need to work out the Gravity thing... I found an example on the internet that is working (http://hbsand.com/HappyBoxes/), but I can't implement it on my own code. I must be missing something... But I'm not giving up yet. I will carry on investigating. :) – user3794206 Jul 03 '14 at 09:32
0

team doob? doing famous :)

checking your demo it seems you got it working now, and also DMV pointed out the specifics. but just as another approach... I put a demo together (with famous guys help at a hackathon) of balls bouncing off each other, with walls etc.

http://famfiziks.meteor.com/battle

source is here: https://github.com/dcsan/fambot

dcsan
  • 11,333
  • 15
  • 77
  • 118