Wavertron Posted April 7, 2014 Share Posted April 7, 2014 So I've been getting a problem with my P2 player sprite, where it triggers the collision callback two or three times, for a single collision. Basically, when to Flat Edges collide, its firing the collision callback twice You can replicate it by editing the "collision groups" master example First, modify the "hitPanda" method so we can see a hit count that increments with every collision callback:hitCount = 0;function hitPanda(body1, body2) { // body1 is the space ship (as it's the body that owns the callback) // body2 is the body it impacted with, in this case our panda // As body2 is a Phaser.Physics.P2.Body object, you access its own (the sprite) via the sprite property: body2.sprite.alpha -= 0.1; hitCount++ console.log("hitCount=" + hitCount);}Then modify the Ship's body to something non-circle, non-pointy, like 1 or 2 or 3 below: game.physics.p2.enable(ship, true); //true so we can see the physics body //ship.body.setCircle(28);1. ship.body.addPolygon(null, 0,0, 50,0, 50,50, 0,50); //simple square2. ship.body.setRectangleFromSprite();3. ship.body.setRectangle(50,50);Then, when you collide the ship into a panda, you very often get a double collision. The callback fires twice. Initially I thought it might be a problem with using a polygon body, as that's what I have in my current WIP.But setRectangle has the same problem. Then I thought it was the rotation, causing a tiny second hit as an objects start to rotate next to each other.And that would have explained why a circle worked ok in the example, because when it rotates it not going to hit anything twice. So I disabled all the rotation:panda.body.fixedRotation = true;ship.body.fixedRotation = true;But that didn't help. I think I've finally found the answer via the humble triangle. Here's a pic to better explain. - When I jab a panda with the right-side pointy end, I don't get the multiple hits. Just get a nice clean 1 hit.- Slap into a panda with the left-side flat edge. The Panda have rectangle bodies also. When the two flat edges hit together, bingo, two collision callbacks instead of one. Here's the triangle body code:ship.body.addPolygon(null, 0,0, 50,25, 0,50); //triangle with a point on the right side and flat edge on the left side.//btw, set pandas to show their body:panda.body.debug = true;So.... how to fix this issue? (I've attached my testing code with the .txt extension added to allow it to be attached to this post)collision groups.js.txt Link to comment Share on other sites More sharing options...
JP91 Posted April 7, 2014 Share Posted April 7, 2014 I do not think this is a problem. Link to comment Share on other sites More sharing options...
Wavertron Posted April 7, 2014 Author Share Posted April 7, 2014 Hmmm it is when you only want a collision callback to execute once. Right now I've had to put in a 100ms timer based switch to filter out the second and third callbacks (I'm not sure its working perfectly either).As a very simple example, imagine a game where every crash deducts a point or health. Well this bug will mean the crash gets penalised twice. Link to comment Share on other sites More sharing options...
JP91 Posted April 7, 2014 Share Posted April 7, 2014 hey... you're right about that, but I think what happens is that there is a collision with multiple contacts, then you can use onBeginContact to when a first contact. Link to comment Share on other sites More sharing options...
Wavertron Posted April 8, 2014 Author Share Posted April 8, 2014 Nice. Just tested in the example. Removed the collisionGroups stuff, and just using ship.body.onBeginContact.add(...) method, and its working as expected. Just the single hit, even with two flat edges colliding. That will have to do. EDIT: dang.... just tried it in my game, no good. It does seems a bit more reliable, but still getting double/triple hits Link to comment Share on other sites More sharing options...
valueerror Posted April 8, 2014 Share Posted April 8, 2014 did you find a method to get both bodies to the function you trigger with the onbegincontact signal? i mean if you run into an enemy you would probably do something with the player and the enemy in your function but onbegincontact just sends the enemy.. Link to comment Share on other sites More sharing options...
Wavertron Posted April 8, 2014 Author Share Posted April 8, 2014 valueerror,That part's easy. Just pass in the object you want as the second parameter when defining the callback function. The second param is the context, it will be accessible as the "this" object in the function. ship.body.onBeginContact.add(hitPanda2, ship); //pass in "ship" as second param here, //to make it available as the "this" object when function hitPanda2 executes. So then over in "hitPanda2" function, I can for example access the ship's name via this.namefunction hitPanda2(body2, shapeA, shapeB, equation) { //This callback is sent: //body2 the Body it collides with //shapeA the shape in the calling Body involved in the collision //shapeB the shape in the Body it hit //equation an array with the contact equation data in it // //this the Ship sprite I chose to pass as the context for this function body2.sprite.alpha -= 0.1; console.log(this.name);} Link to comment Share on other sites More sharing options...
valueerror Posted April 8, 2014 Share Posted April 8, 2014 @Rudy THANK YOU so much... i was searching for this for days... rich said "onbegincontact" is better because calculating impact events (collisiongroups and callbacks) is very expensive and we should not use them until absolutely necessary.. now i can change everything and see if the performance on mobile will finally be acceptable... Link to comment Share on other sites More sharing options...
JP91 Posted April 8, 2014 Share Posted April 8, 2014 @Rudy I think you can use onEndContact, after the last contact life decreases, etc. Link to comment Share on other sites More sharing options...
Wavertron Posted April 9, 2014 Author Share Posted April 9, 2014 No luck. Same deal, you just get two end contact events. I'm playing around with some ideas on how to short circuit the secondary collision. Its a bit hit and miss though and I'd like to avoid a timer approach is possible. Frustrating, I think I might work on the Player States pattern I've been meaning to get around to. It should at least clean up my code, perhaps I'll have some inspiration from that... Link to comment Share on other sites More sharing options...
schteppe Posted April 17, 2014 Share Posted April 17, 2014 I think that Phaser uses the p2 impact event internally, which fires once per *contact point*, not per *body pair*. If you get two contact points, you will get two events. I agree this is a bit weird and I might even change to the less weird behavior in future p2 versions. However, you can keep track of the body pairs yourself and prevent duplicates by looking at the body id's. Something like this will print the body id's. Do it and you'll see what I mean.function hitPanda(body1, body2) { console.log(body1.data.id, body2.data.id)The two numbers are unique per body collision. During one frame, make sure the current number combination didn't occur more than once. Stefan multiplegeorges 1 Link to comment Share on other sites More sharing options...
Recommended Posts