@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.
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/
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.
@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
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/
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.
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/
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.
@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.