Double collision detection

Official forum for the Chipmunk2D Physics Library.
ucode
Posts: 21
Joined: Tue Oct 09, 2012 1:48 pm
Contact:

Double collision detection

Post by ucode »

I'm using the Ruby port of chipmunk and detect collisions with:

Code: Select all

    @space.add_collision_func(:bullet, :player) do |bullet, player_hit|
      @sound.play
      @player.reset_position
    end
Problem is the block of code gets executed twice whenever there's a collision. I move the player far away, so it's not like the collision happens again because the player is still right next to the bullet.

What's happening and how do I prevent this?
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Double collision detection

Post by slembcke »

Hmm. I assume #add_collision_func is a compatibility function that wraps the now very old Chipmunk API function of the same name. The way that worked is that it would call the callback for every frame that things are overlapping. Without seeing more code (yours and the binding), I can't say either way if this was happening or not.

There should be something that wraps the much newer collision handler functionality (cpSpaceAddCollisionHandler()) which lets you register separate begin, preSolve, postSolve, and separate callbacks. Begin callbacks are guaranteed to be called only once.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
ucode
Posts: 21
Joined: Tue Oct 09, 2012 1:48 pm
Contact:

Re: Double collision detection

Post by ucode »

slembcke wrote:Hmm. I assume #add_collision_func is a compatibility function that wraps the now very old Chipmunk API function of the same name. The way that worked is that it would call the callback for every frame that things are overlapping. Without seeing more code (yours and the binding), I can't say either way if this was happening or not.

There should be something that wraps the much newer collision handler functionality (cpSpaceAddCollisionHandler()) which lets you register separate begin, preSolve, postSolve, and separate callbacks. Begin callbacks are guaranteed to be called only once.
Looks like there is an add collision handler method (http://beoran.github.com/chipmunk/#Callbacks), trying it now. Thanks.
ucode
Posts: 21
Joined: Tue Oct 09, 2012 1:48 pm
Contact:

Re: Double collision detection

Post by ucode »

ucode wrote:Looks like there is an add collision handler method (http://beoran.github.com/chipmunk/#Callbacks), trying it now. Thanks.
Unfortunately, the following code also calls the collision handler twice for every collision :(.

Code: Select all

@space.add_collision_handler(:floor, :player, CollisionHandler.new(@player))
class CollisionHandler
  def initialize(player)
    @player = player
  end
  def begin(a, b, arbiter)
    puts "collided first? #{arbiter.first_contact?}"
    @player.reset_position
  end
end
On every collision I get the following output:

Code: Select all

first contact? true
first contact? true
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Double collision detection

Post by slembcke »

Do you have multiple shapes on your object? Contacts are tracked per pair of shapes. If you have a composite object, you need to increment a counter on begin and decrement it on separate. When you go from 0 -> 1 you know it's the first contact, and when you go from 1 -> 0 you know it's the final contact separating.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
ucode
Posts: 21
Joined: Tue Oct 09, 2012 1:48 pm
Contact:

Re: Double collision detection

Post by ucode »

slembcke wrote:Do you have multiple shapes on your object? Contacts are tracked per pair of shapes. If you have a composite object, you need to increment a counter on begin and decrement it on separate. When you go from 0 -> 1 you know it's the first contact, and when you go from 1 -> 0 you know it's the final contact separating.
wouldn't first_contact? be false if it wasn't the first contact? The player is a simple Circle shape and the floor is a Segment.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Double collision detection

Post by slembcke »

Hmm. Single shape on each object should only produce one callback yeah. Also you don't need to check if it's the first contact in a begin callback. That will always be true.

You should try printing out the shapes on the arbiter to check that it's not the same pair of objects. Also implement the separate callback event to log something as well so you know that isn't happening in between unexpectedly. Is it possible that the object is bouncing?
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
ucode
Posts: 21
Joined: Tue Oct 09, 2012 1:48 pm
Contact:

Re: Double collision detection

Post by ucode »

slembcke wrote:Hmm. Single shape on each object should only produce one callback yeah. Also you don't need to check if it's the first contact in a begin callback. That will always be true.

You should try printing out the shapes on the arbiter to check that it's not the same pair of objects. Also implement the separate callback event to log something as well so you know that isn't happening in between unexpectedly. Is it possible that the object is bouncing?
It shouldn't be possible that the object is bouncing because @player.reset_position moves the player away from the floor.
ucode
Posts: 21
Joined: Tue Oct 09, 2012 1:48 pm
Contact:

Re: Double collision detection

Post by ucode »

ucode wrote:It shouldn't be possible that the object is bouncing because @player.reset_position moves the player away from the floor.
I guess this is part of the issue. In the reset_position method I'm moving the player with:

Code: Select all

@player.shape.body.p.x = 50  # which is far from the other object
That does move my player as expected, but I guess that's also causing my collision callback to be called again. If I remove that resetting of the position, then my callback is called many times but only in the first time is arbiter.first_contact? equal to true.
ucode
Posts: 21
Joined: Tue Oct 09, 2012 1:48 pm
Contact:

Re: Double collision detection

Post by ucode »

So how can I move my player away from the other object when a collision occurs without my collision handler being called twice?
Post Reply

Who is online

Users browsing this forum: No registered users and 11 guests