Jump to content

Implementing an object gravity?


Ido
 Share

Recommended Posts

Hi,
Is it possible to implement a gravity-like pulling force towards an object?
I mean that if I have object X which applies this force, other objects near him will be pulled stronger the closer they are to it?

thanks!

Link to comment
Share on other sites

It seems like what you are describing might be found here: http://phaser.io/docs/2.4.6/Phaser.Physics.P2.Body.html#gravity

However, note that this property of a P2 body is not implemented. Sounds like there might be future support, though.

You could do it yourself by seeing how P2 physics implements actual gravity, and then just apply that logic to local objects. If you do that cleanly, you could probably just contribute your implementation to the P2 Phaser source code!

Link to comment
Share on other sites

Hello,

yes it's possible. It's not even that difficult consult google about newtonian gravity there is an equation which calculates the force between two objects (it's a simple equation in it's basic form). Apply that and you are there.

Here is a simple jsfiddle example which I just put together - I hope I understood what you are looking for correctly.

An here is the code:

console.log('start');
var ctx = document.querySelector('canvas').getContext('2d');
var lastTime = null;
var timeStep;

var obj1 = {};
var obj2 = {};

obj1.x = 20;
obj1.y = 270;
obj1.width = 20;
obj1.height = 20;
obj1.radius = 20;
obj1.velocity = {
  x: 50,
  y: 0
};

obj2.x = 250;
obj2.y = 170;
obj2.width = 150;
obj2.height = 150;
obj2.radius = 50;
obj2.forceRadius = 150;
obj2.mass = 100;

function attract(obj1, obj2)
{
  var dx = obj2.x - obj1.x;
  var dy = obj2.y - obj1.y;

  var radii = obj1.radius + obj2.forceRadius;
  if ((dx < 0 ? -dx : dx) > radii)
  {
    return;
  }
  if ((dy < 0 ? -dy : dy) > radii)
  {
    return;
  }
  var distance = dx * dx + dy * dy;
  if (distance < radii * radii)
  {
    var ratio = (obj2.mass / distance)
    obj1.velocity.x += ratio * dx;
    obj1.velocity.y += ratio * dy;
  }
}

function move(obj, dt)
{
  obj.x += obj.velocity.x * dt;
  obj.y += obj.velocity.y * dt;
}

function draw(obj)
{
  ctx.beginPath();
  ctx.arc(obj.x, obj.y, obj.radius, 0, 2 * Math.PI, false);
  ctx.fill();
  if (obj.forceRadius)
  {
    ctx.beginPath();
    ctx.arc(obj.x, obj.y, obj.forceRadius, 0, 2 * Math.PI, false);
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#ff0000';
    ctx.stroke();
  }
}

function loop(time)
{
	if (lastTime !== null) {
		timeStep = time / 1000 - lastTime;
	}
	lastTime = time / 1000;
 	
  if (timeStep)
  {
  	move(obj1, timeStep);
    attract(obj1, obj2);
    ctx.clearRect(0, 0, 500, 500); 
  	ctx.fillStyle = '#B18247';
    draw(obj2);
    ctx.fillStyle = '#503779';
    draw(obj1);
  }
  
  window.requestAnimationFrame(loop);
}

window.requestAnimationFrame(loop);

I don't know why but code tag or whatever it's called doesn't kinda work for me, I can see it in the preview displayed correctly but not when it's posted, so I gope you can get something from this :-). It's not a phaser example on purpose the implementation in phaser should be straightforward.

 

EDIT: And now it looks perceftly ok in code, I don't know what happened though :).

EDIT2: Oh, when I post or edit the post I can't see code formatting at all unless I go to outside the topic and then come back, weird but at least it works :-).

Link to comment
Share on other sites

For clarity I'm making another post so you can get through the code easier.

Here is slightly adjusted example with both objects attracting each other.

console.log('start');
var ctx = document.querySelector('canvas').getContext('2d');
var lastTime = null;
var timeStep;

var obj1 = {};
var obj2 = {};

obj1.x = 20;
obj1.y = 270;
obj1.radius = 20;
obj1.velocity = {
	x: 50,
  y: 0
};
obj1.mass = 100;
obj1.forceRadius = 150;
obj1.width = 2 * obj1.forceRadius;
obj1.height = 2 * obj1.forceRadius;

obj2.x = 250;
obj2.y = 170;
obj2.radius = 50;
obj2.velocity = {
	x: 0,
  y: 0
};
obj2.forceRadius = 150;
obj2.width = 2 * obj2.forceRadius;
obj2.height = 2 * obj2.forceRadius;
obj2.fRSq = obj2.forceRadius * obj2.forceRadius;
obj2.mass = 100;

function attract(obj1, obj2)
{
  var dx = obj2.x - obj1.x;
  var dy = obj2.y - obj1.y;

  var radii = obj1.forceRadius + obj2.forceRadius;
  if ((dx < 0 ? -dx : dx) > radii)
  {
    return;
  }
  if ((dy < 0 ? -dy : dy) > radii)
  {
    return;
  }
  var distance = dx * dx + dy * dy;
  if (distance < radii * radii)
  {
    var ratio = (obj2.mass / distance)
    obj1.velocity.x += ratio * dx;
    obj1.velocity.y += ratio * dy;
  }
}

function move(obj, dt)
{
	obj.x += obj.velocity.x * dt;
  obj.y += obj.velocity.y * dt;
}

function draw(obj)
{
	ctx.beginPath();
  ctx.arc(obj.x, obj.y, obj.radius, 0, 2 * Math.PI, false);
  ctx.fill();
  if (obj.forceRadius)
  {
  	ctx.beginPath();
    ctx.arc(obj.x, obj.y, obj.forceRadius, 0, 2 * Math.PI, false);
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#ff0000';
    ctx.stroke();
  }
}

function loop(time)
{
	if (lastTime !== null) {
		timeStep = time / 1000 - lastTime;
	}
	lastTime = time / 1000;
 	
  if (timeStep)
  {
  	move(obj1, timeStep);
    move(obj2, timeStep);
    attract(obj1, obj2);
    attract(obj2, obj1);
    ctx.clearRect(0, 0, 500, 500); 
  	ctx.fillStyle = '#B18247';
    draw(obj2);
    ctx.fillStyle = '#503779';
    draw(obj1);
  }
  
  window.requestAnimationFrame(loop);
}

window.requestAnimationFrame(loop);

EDIT: You can play with mass and force radis of both objects however you want to get different results.

Is this what you are looking for?

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...