Jump to content

Implementing an object gravity?


Ido
 Share

Recommended Posts

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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

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