Jump to content

Updating P2 body radius


Puzz3l
 Share

Recommended Posts

So I have a group of sprites:

var frameNames = Phaser.Animation.generateFrameNames('explosion', 1, 12);this.explosions = game.add.group();this.explosions.enableBody = true;this.explosions.physicsBodyType = Phaser.Physics.P2JS;for(var i = 0; i < 6; i++) {	var exp = this.explosions.create(0, 0, 'explosionAnim', 'explosion1', false);	exp.lastFrameName = 'explosion1';	exp.anchor.setTo(0.5,0.5);	game.physics.p2.enable(exp);	exp.body.clearShapes();	exp.body.setCircle(10);	exp.body.setCollisionGroup(this.explosionCollisionGroup);	exp.body.collides(this.enemyCollisionGroup, this.killEnemy, this);	exp.body.collideWorldBounds = false;	// Makes immoveable	exp.body.mass = game.physics.p2.walls.bottom.mass;	exp.body.debug = true;	exp.animations.add('explosionAnim', frameNames);}

And every step of their animation I want their body radius to change, so I do this in my update loop:

this.explosions.forEachAlive(function(e) {	e.damage(0.01);	e.body.debugBody.draw();	if(e.frameName != e.lastFrameName) {		var num = parseInt(e.frameName.slice(9)) * 8 + 10;		e.body.setCircle(num);		e.lastFrameName = e.frameName;	}}, this);

Now though, nothing collides with them. Anyone know why this isn't working?

Link to comment
Share on other sites

Hey the same answer was answered before, see here http://www.html5gamedevs.com/topic/5692-p2-increase-body-radius-over-time/?hl=radius

 

I will cite schteppe's important part that also applies to your problem:

 

I think you might be updating the physics shape too fast. They grow to something that cover the whole physics world, and the contact solver goes bananas.

 

Link to comment
Share on other sites

in my game, if i  set a different circle-size with setCircle in the update loop i also have to set collisionGroup in the update loop... otherwise my player wouldn't collide with anything...  same goes for materials for some reason..

player.body.setCircle(radius);player.body.setCollisionGroup(playerCG);player.body.setMaterial(playerMaterial);
Link to comment
Share on other sites

Sorry Puzz3l,

I have to read the question more thoroughly the next time. To reapply the collision group makes sense as you're rebuild the whole circle shape in each animation step- that's what I missed. Although you should not do it in a large scale as it's more expensive than just setting the radius. Maybe you could try updating the radius- just look into the other post.

 

Regards George

Link to comment
Share on other sites

so setCircle(20) is more expensive than setting a new radius for the circle shape? good to know ..  and if i understood right i won't need to reapply the collision group if i change just the radius instead of resetting the whole shape....  ??!

 

 

but how do i get this shape .. or better.. how do i set a new radius for the same shape?

 

player.body.radius ???  

Link to comment
Share on other sites

Hey valueerror, I do not know the exact impact. But it's always better to reuse than to recreate. In this case we would reuse the circle shape instead of creating many many circle instances over time. And yes, by reusing it you wouldn't need to set the other parameters- they remain valid.

 

You get the shape instance returned, use that instance to apply any radius changes.

circleShape = body.addCircle(radius)

See the other post for details on changing the radius.

 

This works for other fixtures like rectangles as well. For complex shapes like a polygon you have to iterate over all created convex shapes to achieve the same result- I only do this to change the mask or make a polygon a sensor.

 

Have a look at this PR I made some weeks ago, https://github.com/photonstorm/phaser/pull/704

It allows you to manage groups of fixtures in a polygon. It's merged in Phaser but not really documented nor does it have examples. That's my duty as I created that feature- but I have not the time to manage this currently. I focus on helping to fix the bugs for now.

 

Regards

George

Link to comment
Share on other sites

hello there.. i've asked this in a separate thread too but i thought it would fit in here and be an important information for everyone setting the radius instead of setCircle()

 

 

with setCircle i can define the radius and the X an Y offset..  how can i do the offset without setCircle?

 

thx

Link to comment
Share on other sites

You mean you want to change the offset ? You would have to access sprite.body.data.shapeOffsets and change them there. They are stored in meter values so don't forget to convert them. By changing the offsets you would change the center of mass. So you may call the method 'updateMassProperties'. I never did this so I can't tell you about other impacts of such a change. If you only want to offset your sprite you are better with overriding the method postUpdate of a sprite.

 

The implementation of phaser looks like this:

postUpdate: function () {    this.sprite.x = this.world.mpxi(this.data.position[0]);    this.sprite.y = this.world.mpxi(this.data.position[1]);    if (!this.fixedRotation)    {        this.sprite.rotation = this.data.angle;    }},

Overwrite it in your own sprite class, call the super method and then adjust your offset. Maybe that's all what you want?

postUpdate: function () {    //call the super method to execute the default postUpdate action    Phaser.Sprite.prototype.postUpdate()        //which offset to apply    var offset = {x: 10, y: 10};    //sprite will have the position of the body, now apply the offset    this.sprite.x = this.sprite.x + offset.x    this.sprite.y = this.sprite.y + offset.y},

Regards

George

Link to comment
Share on other sites

wow thx..     i guess i could avoid the need of a changed circle offset by changing (fixing) the spritesheet  (so the frame where the player ducks matches the updated circle radius instead of the other way around)

 

unfortunately i encountered an other problem..  when setting the circle and the material in the create function..  material settings are not applied..  (my player slides across the world as if there was no friction)  so i reapply the material on every update loop and it works ..  thats why i stick to delete and recreate the circle and reapply the collisiongroup and the material in the update loop for now.. but i'm going to investigate

 

 

edit: investigation complete:  

you need to setCircle() AFTER  player.body.fixedRotation=true;  otherwise later applied materials will not work !  

BUG ??  now i can go back to "doing it right" ^^

Link to comment
Share on other sites

That's weird. Those values should not be affected by a radius change. You should check what's the problem- but you can do this later if you have other thing to implement. It's not performance issue yet.

 

What to check? Is it the material or the collisions group (mask/category bits) that's wrong? You can debug all those values by looking into p2's body (sprite.body.data). Good luck.

Link to comment
Share on other sites

just in case you missed the edit..   i now apply the circle after i set the body to fixedRotation  and now it works.. i do not have to apply materials in the update loop anymore..   this seems like a bug to me.. 

 

now i'm going to use   myshape.radius=''  instead of setCircle() and try to work around the offset issue by changing the spritesheet.. so i'm going to use gimp instead of my texteditor to fix this.. 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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