Daniel Finch
Daniel Finch

Reputation: 443

Attract one set of bodies to another set of bodies, but not to other bodies in the same set

I'm looking to implement a planet-like system, whereby you have large, mostly-fixed objects which have lots of smaller objects around them. The idea is that the smaller objects could orbit around the larger objects, but also change which of the larger objects they're orbiting around. I'm attempting to use the newtonian behaviour type on the smaller objects, but it's making those smaller objects try to orbit around everything, rather than just the large objects. Is there a way to define a behaviour on a set of objects (I have them in an array) and have them only be attracted to objects in another set of objects?

To give you a visual idea, this is how it currently looks (https://i.sstatic.net/5v1cZ.png):

I want the orange objects to orbit the blue objects, but I don't want the orange or blue objects to be attracted to other orange or blue objects respectively. Is this possible with PhysicsJS?

Here is my current progress. To view the script in action, view it on CodePen):

var magnets = []
var particles = []

function rand (from, to) {
  return Math.floor(Math.random() * to) + from
}

function generateMagnet (world, renderer) {
  var magnet = Physics.body('circle', {
    x: rand(0, renderer.width),
    y: rand(0, renderer.height),
    radius: 50,
    mass: 2,
    vx: 0.001,
    vy: 0.001,
    treatment: 'static',
    styles: {
      fillStyle: '#6c71c4'
    }
  })

  magnets.push(magnet)
  world.add(magnet)
}

function generateParticle (world, renderer) {
  var particle = Physics.body('circle', {
    x: rand(0, renderer.width),
    y: rand(0, renderer.height),
    vx: rand(-100, 100) / 1000,
    vy: rand(-100, 100) / 1000,
    mass: 1,
    radius: 5,
    styles: {
      fillStyle: '#cb4b16'
    }
  })

  particles.push(particle)
  world.add(particle)
}

Physics(function (world) {
  // bounds of the window
  var el = document.getElementById('matterContainer')

  var viewportBounds = Physics.aabb(0, 0, el.scrollWidth, el.scrollHeight)
  var edgeBounce
  var renderer

  // create a renderer
  renderer = Physics.renderer('canvas', {
    'el': el
  })
  el.childNodes[0].style.left = 0

  // add the renderer
  world.add(renderer)
  // render on each step
  world.on('step', function () {
    world.render()
  })

  // varrain objects to these bounds
  edgeBounce = Physics.behavior('edge-collision-detection', {
    aabb: viewportBounds,
    restitution: 0.99,
    cof: 0.8
  })

  // resize events
  window.addEventListener('resize', function () {
    // as of 0.7.0 the renderer will auto resize... so we just take the values from the renderer
    viewportBounds = Physics.aabb(0, 0, renderer.width, renderer.height)
    // update the boundaries
    edgeBounce.setAABB(viewportBounds)
  }, true)

  for (var i = 0; i < 5; i++) generateMagnet(world, renderer)
  for (var i = 0; i < 100; i++) generateParticle(world, renderer)

  // add things to the world
  var newton = Physics.behavior('newtonian', { strength: 0.05 })
  // newton.applyTo(particles)

  var attractor = Physics.behavior('attractor', {
    order: 0,
    strength: 0.1
  }).applyTo(magnets);

  world.add([
    Physics.behavior('body-impulse-response'),
    newton,
    edgeBounce
    ])

  // subscribe to ticker to advance the simulation
  Physics.util.ticker.on(function (time) {
    world.step(time)
  })
})
<script src="http://wellcaffeinated.net/PhysicsJS/assets/scripts/vendor/physicsjs-current/physicsjs-full.min.js"></script>
<section id="matterContainer" class="sct-HomepageHero pt-0 pb-0"></section>

<style>
.sct-HomepageHero.pt-0.pb-0 {
  min-height: 600px;
  padding-top: 0;
  padding-bottom: 0;
}
</style>

Upvotes: 0

Views: 112

Answers (0)

Related Questions