Jump to content

P2 physics - RevoluteConstraint problem


jloa
 Share

Recommended Posts

So, i'm trying to make a top-view car game prototype using the P2 physics engine and i've faced some weird bug? with the RevoluteConstraints.
The idea is simple: create a car body sprite, create two tires and attach them to the car body, then apply car physics simulation on those tires and let the body follow. And the problem is that when tires are joint to the car, they are positioned wrong (which is weird) + the car starts rotating and the reason for that i just can't understand as: tires are positioned symmetrically + both RevoluteConstraints have the same forces that should be applied to constrain the bodies. May be i'm getting something wrong?
I wouldn't make this topic if there were more advanced examples covering the P2 physics or at least examples in the docs/source code (yep, i've already googled for a solution).
 
Here's a picture
post-9831-0-66848700-1406290075.png
 
And here's the code (also available here http://pastebin.com/qjqeF5bc):

var ns = ns || {}; (function(ns){         // ref to the engine's keyboard cursors        var cursors;         // world info        var worldInfo = {                'w': 10000,                'h': 5980,                'friction': 0.3,                'restitution': 0.5,                'stiffness': 1e7,                'relaxation': 5,                'frictionStiffness': 1e7,                'frictionRelaxation': 5,                'surfaceVelocity': 0.0,                'material': null        };        // car reference        var raceCar;         /**         * RaceCar class         * @param x:int                         init x position of the car         * @param y:int                         init y position of the car         * @param worldInfo:object      world info object         */        var RaceCar = function(x, y, worldInfo)        {                // debug sprites                this.debug = false;                this.damping = 0.5;                this.angularDamping = 0.5;                // car material ref                this.material = null;                // contact material ref                this.contactMaterial = null;                // world info ref                this.worldInfo = worldInfo;                // car sprite ref                this.car = null;                // tire sprites ref                this.tires = {                        'left': null,                        'right': null                };                // sprite ids for car parts                this.spriteIds = {                        'car': 'car',                        'tire': 'tire'                };                // tire offets (relative to the car's center of mass offsets used for positioning the tires and for constrait points)                // mind that the 'x' get sum/subs with the car.width/2, so that the x be dynamic                // so the real x offset will be offsetRealX = car.width/2 + x                this.tireOffsets = {                        'left': { x:2, y:-16 },                        'right': { x:-2, y:-16 }                };                 // create sprites                this.createSprites(x, y);                // enable physics                this.enablePhysics();                // create materials                this.createMaterials();        };        /**         * Creates car part sprites (should be call before other methods)         * @param x:int  init x position of the car         * @param y:int  init y position of the car         */        RaceCar.prototype.createSprites = function(x, y)        {                // create sprites                this.car = game.add.sprite(x, y, this.spriteIds['car'], 0);                this.tires.left = game.add.sprite(x - this.car.width/2 + this.tireOffsets.left.x, y + this.tireOffsets.left.y, this.spriteIds['tire']);                this.tires.right = game.add.sprite(x + this.car.width/2 + this.tireOffsets.right.x, y + this.tireOffsets.right.y, this.spriteIds['tire']);                this.car.bringToTop();        };        /**         * Enables physics for the car (should be called after @see this.createSprites())         */        RaceCar.prototype.enablePhysics = function()        {                // enable physics                game.physics.p2.enable(this.car, this.debug);                game.physics.p2.enable(this.tires.left, this.debug);                game.physics.p2.enable(this.tires.right, this.debug);                          // revolutes                //                // @TODO now this is the bug place                // when we create revolutes there are 2 problems need to be solved:                // - tires are wrong positioned (even thought the force is 200 000)                // - car starts rotating despite that the tires are positioned symmetrically relative to the car's center of mass which is 50% 50% by default                //                game.physics.p2.createRevoluteConstraint(this.tires.left, [0,0], this.car, [-this.car.width/2 + this.tireOffsets.left.x, this.tireOffsets.left.y], 20000);                game.physics.p2.createRevoluteConstraint(this.tires.right, [0,0], this.car, [this.car.width/2 + this.tireOffsets.right.x, this.tireOffsets.right.y], 20000);                // set damping                this.tires.left.body.damping = this.damping;                this.tires.right.body.damping = this.damping;                this.car.body.damping = this.damping;                // set angularDamping;                this.tires.left.body.angularDamping = this.angularDamping;                this.tires.right.body.angularDamping = this.angularDamping;                this.car.body.angularDamping = this.angularDamping;                // allow sleep                         this.tires.left.body.allowSleep = true;                this.tires.right.body.allowSleep = true;                this.car.body.allowSleep = true;                // collide with world                this.tires.left.body.collideWorldBounds = true;                this.tires.right.body.collideWorldBounds = true;                this.car.body.collideWorldBounds = true;                // revolutes seem work only if the tires' mass is significantly less than the car's                this.tires.left.body.mass = 1;  // .01 seems to work, kind of, still buggy coz tires get rotated like +1 degree why?!                this.tires.right.body.mass = 1; // .01 seems to work, kind of, still buggy coz tires get rotated like +1 degree why?!                this.car.body.mass = 1;        };        /**         * Creates the car material + the contact material with the world (should be called after @see this.enablePhysics())         */        RaceCar.prototype.createMaterials = function()        {                this.material = game.physics.p2.createMaterial('carMaterial');                // assign material                this.car.body.setMaterial(this.material);                this.tires.left.body.setMaterial(this.material);                this.tires.right.body.setMaterial(this.material);                // create contactMaterial                this.contactMaterial = game.physics.p2.createContactMaterial(this.material, this.worldInfo['material']);                this.contactMaterial.friction = this.worldInfo['friction'];                                             // Friction to use in the contact of these two materials.                this.contactMaterial.restitution = this.worldInfo['restitution'];                               // Restitution (i.e. how bouncy it is!) to use in the contact of these two materials.                this.contactMaterial.stiffness = this.worldInfo['stiffness'];                                   // упругость - Stiffness of the resulting ContactEquation that this ContactMaterial generate.                this.contactMaterial.relaxation = this.worldInfo['relaxation'];                                 // Relaxation of the resulting ContactEquation that this ContactMaterial generate.                this.contactMaterial.frictionStiffness = this.worldInfo['frictionStiffness'];   // Stiffness of the resulting FrictionEquation that this ContactMaterial generate.                this.contactMaterial.frictionRelaxation = this.worldInfo['frictionRelaxation']; // Relaxation of the resulting FrictionEquation that this ContactMaterial generate.                this.contactMaterial.surfaceVelocity = this.worldInfo['surfaceVelocity'];               // Will add surface velocity to this material. If bodyA rests on top if bodyB, and the surface velocity is positive, bodyA will slide to the right.        };         var preload = function()        {                game.load.image('car', 'assets/i/car.png');                game.load.image('tire', 'assets/i/tire.png');                game.load.image('map', 'assets/i/map.jpg');        };        var create = function()        {                // resize our game world to be                game.world.setBounds(0, 0, worldInfo.w, worldInfo.h);                game.stage.backgroundColor = '#ffffff';                game.stage.disableVisibilityChange = true;                 // physics                game.physics.startSystem(Phaser.Physics.P2JS);                game.physics.p2.setBounds(0, 0, worldInfo.w, worldInfo.h, true, true, true, true, false);                game.physics.p2.friction = worldInfo['friction'];                game.physics.p2.restitution = worldInfo['restitution'];                game.physics.p2.applyDamping = true;                 // world material                worldInfo['material'] = game.physics.p2.createMaterial('worldMaterial');                game.physics.p2.setWorldMaterial(worldInfo['material'], true, true, true, true);                 // create a race car                raceCar = new RaceCar(200, 200, worldInfo);                 // camera follow car                game.camera.follow(raceCar.car, Phaser.Camera.FOLLOW_LOCKON);                 // input controls                cursors = game.input.keyboard.createCursorKeys();        };        var update = function()        {                // do nothing for now        };        var render = function()        {                // do nothing for now        };         // start the game        var game = new Phaser.Game(800, 600, Phaser.AUTO, 'game', { preload: preload, create: create, update: update, render: render });})(ns);

Link to comment
Share on other sites

Fixed!

Ok, i've figured it out now.

In case anyone else stumbles upon this problem: "what to do when revolute constaraint overlap and apply force to each other and what them to ignore each other".

The answer took me a while, because there's nothing said in the docs http://docs.phaser.io/Phaser.Physics.P2.RevoluteConstraint.html

The things is that the docs are totally incomplete. The p2 RevoluteContraint class has lots of other methods/props http://schteppe.github.io/p2.js/docs/classes/RevoluteConstraint.html

And the property that solves the issue is

collideConnected:Boolean// Set to true if you want the connected bodies to collide.Default: true

So when you create an instance of revolute costraint (in phaser game.physics.p2.createRevoluteConstraint() method will return the instance reference), don't forget to set the property to false.

And finally, if you are working with p2 physics better use the p2 docs @ http://schteppe.github.io/p2.js/docs/

 

ps: how do i close the thread?

Link to comment
Share on other sites

  • 1 month later...

sorry if this is a dump question but..

 

aren't you pulling the tires 4px inside the car with you constraints?  that would mean they constantly would try to get closer but they collide so they start acting weird..

 

 

-this.car.width/2 + this.tireOffsets.left.x

 

-15 + 2  = -13

 

shouldn't this be:

 

-(15+2) = -17

 

??  then you wouldn't need to deactivate the collision between those two..

 

and here comes another question: 

this is a very interesting find.. does this disable the collision only between those two objects connected to each other but still allows collisions with other objects??

and how would the code look like if i want to use those extra options in phaser..  i would also like to use lowerlimit and upperlimit to keep the constraint in place..

 

thx

Link to comment
Share on other sites

  • 1 year later...
 Share

  • Recently Browsing   0 members

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