Page 1 of 1

help a noob: getting "ghost collisions"

Posted: Tue Aug 10, 2010 9:18 am
by Johann
I have a little breakout clone and now that I begun working on two players instead of just one, I'm getting strange ghost collisions. I'll try to explain...

when spawning a ball:

Code: Select all

	this->b[i].cp_shape->collision_type = BRK_COLLISION_TYPE__BALL;
when spawning a player:

Code: Select all

    this->cp_shape->collision_type = BRK_COLLISION_TYPE__PADDLE;
adding the collision handler:

Code: Select all

    cpSpaceAddCollisionHandler(brk->cp_space,
        BRK_COLLISION_TYPE__BALL,
        BRK_COLLISION_TYPE__PADDLE,
        &BRK_collision__ball_2_paddle, NULL, NULL, NULL, NULL);

when reseting a ball:
(this happens to all balls before and between levels, and naturally cp_body and cp_shape get properly initialized as NULL in the ball constructor)

Code: Select all

	if (this->cp_body != NULL)
	{
		cpSpaceRemoveBody(brk->cp_space, this->cp_body);
		cpBodyFree(this->cp_body);
		this->cp_body = NULL;
	}
	if (this->cp_shape != NULL)
	{
		cpSpaceRemoveShape(brk->cp_space, this->cp_shape);
		cpShapeFree(this->cp_shape);
		this->cp_shape = NULL;
	}
the collision handler function

Code: Select all

int BRK_collision__ball_2_paddle ( cpArbiter *arb, cpSpace *space, void *data )
{
	cpShape *ball_shape, *player_shape;
	cpArbiterGetShapes(arb, &ball_shape, &player_shape);
	brk_ball_c *ball = (brk_ball_c *) ball_shape->data;
	brk_player_c *player= (brk_player_c *) player_shape->data;
	if (ball && player)
		ball->last_touched_by = player->index;
	else
	{
		printf ("WTF?! ");
		if (!ball)
			printf (" no ball ");
		if (!player)
			printf (" no player ");
		printf ("\n");
	}
	return true;
}
(note that paddle and player basically mean the same thing, the player IS the paddle)

I end up with a lot of "WTF?! no ball" in stdout (but never on the first level it seems) That means there is one or more lingering shapes that have collision_type == BRK_COLLISION_TYPE__BALL, right? Otherwise that specific collision handler function wouldn't get called by Chipmunk.

But in the single one place in code in the code where a shape gets that collision_type, which I posted above, I also *always* set the data field as a pointer to the ball itself a few lines later... so how come a shape with collision_type == BRK_COLLISION_TYPE__BALL can have NULL as the data field? I just don't get it. Every ball that has a shape or body gets removed from the space and freed during levels... huh?!

It's probably something silly and simple (since it doesn't occur in single player, it seems like it *has* to be a mistake on my part) but I double checked all the obvious places (and the game is still very simple, so there aren't many places to check), plus Chipmunk 5.3 is not even a day old so maybe there's something weird in the removal/freeing of shapes. Nah, it's likely me, who am I kidding :D

Is there a way to get all bodies and/or shapes in a space, so I can draw them and get a better picture of what is going on? Or any ideas what could cause this?

Re: help a noob: getting "ghost collisions"

Posted: Tue Aug 10, 2010 10:48 am
by slembcke
That sounds very odd. The new sleeping feature did require changing how shapes are removed, so it's possible I've introduced a new bug, but I thought I tested things pretty carefully by this time.

First of all, you should try running it against the debug version of the Chipmunk library (compiled without the NDEBUG flag) to see if it prints out any warnings or errors. The release version of the library disables the error checks as some of them can be pretty expensive. You should also log your shape pointers when you create, destroy, add or remove shapes. Then when you get bogus shape in the callback you can trace where it came from and what was supposed to happen to it.

Re: help a noob: getting "ghost collisions"

Posted: Tue Aug 10, 2010 12:16 pm
by Johann
slembcke wrote:First of all, you should try running it against the debug version of the Chipmunk library (compiled without the NDEBUG flag) to see if it prints out any warnings or errors.
Okay, will do that later today.
The release version of the library disables the error checks as some of them can be pretty expensive. You should also log your shape pointers when you create, destroy, add or remove shapes. Then when you get bogus shape in the callback you can trace where it came from and what was supposed to happen to it.
I'm not sure I understand what you mean by "log your shape pointers"? Each ball and paddle/player has a pointer to a body and to a shape each. In the constructor they are set to NULL, when I spawn them, I create a body/shape and set the pointers, when I remove them, I free the body and shape and set the pointers to NULL. There isn't really anything fancy happening in between, so far the ball can't even go out of bounds for example - the *only* time players and balls get spawned is at start of each level, the only time they get destroyed is at the end of each.. that's why it puzzles me so.
when you get bogus shape in the callback
Is there a way to test this? If a shape pointer is pointing to a valid shape I mean. Right now I'm not sure if I'm getting a bogus shape, or if just its user data pointer is NULL (which it shouldn't be, that shouldn't even be possible as explained above).

Re: help a noob: getting "ghost collisions"

Posted: Tue Aug 10, 2010 1:28 pm
by slembcke
Logging pointers: (just need to use the %p format sequence)

Code: Select all

printf("Oh look I found a pointer %p, somePointer);
By "bogus" I mean one that either you forgot to remove from the space somehow, or a bug in Chipmunk caused it to not be removed. Otherwise, no, there isn't a definitive test you can run to say if something is a valid shape pointer or not.

Re: help a noob: getting "ghost collisions"

Posted: Tue Aug 10, 2010 1:56 pm
by Johann
slembcke wrote:First of all, you should try running it against the debug version of the Chipmunk library (compiled without the NDEBUG flag) to see if it prints out any warnings or errors.
Hmm, can't figure out how to do this using CMake.. (I'm using MSYS/MingW) Is there a compiled .dll available somewhere?
slembcke wrote:Logging pointers: (just need to use the %p format sequence)

Code: Select all

printf("Oh look I found a pointer %p, somePointer);
By "bogus" I mean one that either you forgot to remove from the space somehow, or a bug in Chipmunk caused it to not be removed. Otherwise, no, there isn't a definitive test you can run to say if something is a valid shape pointer or not.
well, putting into the collision handler function posted above

Code: Select all

printf ("%p / %p", ball, player);
results in

00000000 / 045ad490

which kinda is the same, and shouldn't be possible, right? Since there can't be a collision between one shape and a NULL shape.... ?

Re: help a noob: getting "ghost collisions"

Posted: Tue Aug 10, 2010 2:12 pm
by Johann
I now spawned some particles at the current player position whenever that "ghost collision" occurs -- it turns out it happens when a paddle hits a screen boundary! Those boundaries are (non-static, uh) shapes attached to rogue bodies, so I'll attach them to the static body of the space and see if that resolves it...

However, it's still weird/buggy that Chipmunk calls that collision handler function .. those boundaries don't even have a collision_type set!

Re: help a noob: getting "ghost collisions"

Posted: Tue Aug 10, 2010 2:20 pm
by Johann
Johann wrote:I'll attach them to the static body of the space and see if that resolves it...
nope, still the same. oh, and I obviously also was wrong with it not happening on the first level, it happens whenever a paddle hits a boundary period, balls don't seem to have anything to do with it. Weirdness ^ 2!

Re: help a noob: getting "ghost collisions"

Posted: Tue Aug 10, 2010 4:36 pm
by Johann
Johann wrote:However, it's still weird/buggy that Chipmunk calls that collision handler function .. those boundaries don't even have a collision_type set!
And just that turned out to be the problem, or rather, the solution, I created a new enum value for boundaries and now explicitly set collision_type of their shapes to that -- it's not used for any collision handlers, but just setting it made the problem disappear.

I wised up to it when I created a new collision function for balls <-> powerups (since those should not collide, and a collision handler that returns false is simpler than creating a new layer for everything else I want powerups to collide with), because then all of a sudden powerups fell through the boundaries, too (although not paddles or balls = weird!)

Re: help a noob: getting "ghost collisions"

Posted: Tue Aug 10, 2010 5:00 pm
by slembcke
Well, by default shapes have a collision_type of 0. If you don't explicitly set the value of the first enumerant in your enumeration, it will be 0 implicitly.

Re: help a noob: getting "ghost collisions"

Posted: Wed Aug 11, 2010 3:08 am
by Johann
I guess that explains it then! :oops: