2013-11-19 2 views
2

Я экспериментировал с отличной библиотекой PhysicsJS, особенно с ограничениями и столкновениями. То, что я пытаюсь достичь, - это многоугольник, который может вращаться вокруг фиксированной точки вращения. В качестве примера в реальном мире представьте себе широкую полку, прибитую к стене с одним длинным гвоздем через самый центр, так что он вращается вокруг, возможно, половины или одного оборота, когда что-то не по центру падает сверху.PhysicsJS - как создать тело, которое вращается вокруг фиксированной точки при ударе?

Вот пример скрипка: http://jsfiddle.net/2HRGW/41/

и код:

Physics(function (world) { 
var renderer = Physics.renderer('canvas', { 
    el: 'viewport', 
    width: 500, 
    height: 400 
}); 
world.add(renderer); 

var nail = Physics.body('circle', { 
    x: 250, 
    y: 200, 
    radius: 5, 
    mass: 1, 
    fixed: true 
}); 
world.add(nail); 

var shelf = Physics.body('convex-polygon', { 
    x: 250, 
    y: 200, 
    vertices: [{ 
     x: -100, 
     y: -10 
    }, { 
     x: 100, 
     y: -10 
    }, { 
     x: 100, 
     y: 10 
    }, { 
     x: -100, 
     y: 10 
    }], 
    mass: 100, 
    restitution: 0.5 
}); 
world.add(shelf); 

var ball = Physics.body('circle', { 
    x: 175, 
    y: 50, 
    radius: 20, 
    mass: 10 
}); 
world.add(ball); 

world.add(Physics.integrator('verlet', { 
    drag: 0.003 
})); 

var verletConstraints = Physics.behavior('verlet-constraints', { 
    iterations: 2 
}); 
verletConstraints.distanceConstraint(shelf, nail, 1); 
world.add(verletConstraints); 

world.add(Physics.behavior('constant-acceleration')); 
world.add(Physics.behavior('body-collision-detection')); 
world.add(Physics.behavior('body-impulse-response')); 
world.add(Physics.behavior('sweep-prune')); 
world.add(Physics.behavior('verlet-constraints')); 

var bounds = Physics.aabb(0, 0, 500, 400); 

world.add(Physics.behavior('edge-collision-detection', { 
    aabb: bounds, 
    restitution: 0.01 
})); 

Physics.util.ticker.subscribe(function (time, dt) { 
    world.step(time); 
}); 

world.render(); 

Physics.util.ticker.start(); 

world.subscribe('step', function() { 
    world.render(); 
}); 
}); 

Я определяю фиксированный круг для ногтей и нефиксированного полигона для полки и добавить расстояние ограничения, связывающее многоугольник к кругу. Как вы можете видеть, есть две проблемы. Во-первых, полка сразу немного падает вниз, пока ее верхняя кромка не окажется на одном уровне с верхней частью гвоздя, а не будет равномерно размещена вокруг гвоздя. Во-вторых, когда мяч падает на полку, полка безумно крутится вокруг, несмотря на массу и различные настройки реституции. Приспосабливая свое положение немного, иногда он может даже полностью отсоединиться и улететь.

Я нахожусь на правильном пути, используя ограничения таким образом, или есть более простое решение?

+0

Шельф спиннинг дико, потому что это сталкиваясь с гвоздем и PhysicsJS пытается разрешить коллизию. – Snowball

+0

ОК - но это правильный общий подход? Если да, то что нужно отрегулировать? Если нет, можете ли вы привести пример? –

+1

Вот патч, чтобы условно отключить реакцию столкновения на телах: https://gist.github.com/anonymous/86c0ba8b4f1f85b11f0e. Он также заботится о проблеме «немного вне центра». – Snowball

ответ

7

Как и другие пользователи, это текущее ограничение PhysicsJS. Это прорабатывается:

В то же время, вместо того, чтобы латать библиотеку, почему бы не создать поведение ограничения пользовательских выводов. Для простого поведения ограничения контактов, которое выталкивает центр тяжести тела в целевую позицию, это довольно легко. Вот пример jsFiddle вашего примера с настраиваемым менеджером ограничений контактов, определенным в начале.

http://jsfiddle.net/wellcaffeinated/2HRGW/50/

// create a behavior to handle pin constraints 
Physics.behavior('pin-constraints', function(parent){ 
    return { 
     init: function(opts){ 
      parent.init.call(this, opts); 
      this.pins = []; 
     }, 

     add: function(body, targetPos){ 
      this.pins.push({ 
       body: body, 
       target: Physics.vector(targetPos) 
      }); 
     }, 

     behave: function(data){ 

      var pins = this.pins 
       ,pin 
       ; 

      for (var i = 0, l = pins.length; i < l; i++){ 
       pin = pins[ i ]; 
       // move body to correct position 
       pin.body.state.pos.clone(pin.target); 
      } 
     } 
    }; 
}); 
2

Ваша общая реализация верна. Единственное, что вы ошибаетесь, это масса выпуклого полигона, 100 - дикое значение. Для этого объекта должно быть достаточно массы около 0,2.

+0

Ничего себе, ты прав, это в основном это делает. Как, однако, я могу заставить центр шельфа оставаться неподвижным в центре круга? В настоящее время полка немного опускается, а затем остается нецентральной. –