<SOLVED>Collisions not coliding

Official forum for the Chipmunk2D Physics Library.
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

<SOLVED>Collisions not coliding

Post by jcmeyer5 »

I am trying to set up my collision handlers. I have one set up to test with, but nothing happens. Essentially, this handler handles an inert object being dropped on the player's head (one shape on a complex object). I am using PhysicsEditor to add my bodies and shapes, and the latest Objective-Chipmunk. So... here is the code I have so far.

Code: Select all

// rocks hitting the player
-(void)Begin_Player_Inert:(cpArbiter *)arbiter space:(ChipmunkSpace*)space {
	CCLOG(@"PLAYER INERT COLLISION!");
	CHIPMUNK_ARBITER_GET_SHAPES(arbiter, player, inert);
	applyPlayerDamage(player.data, arbiter, self);
}

-(void)addCollisionHandlers {
    [space addCollisionHandler:self typeA:[Player class] typeB:[Inert class] 
    begin:@selector(Begin_Player_Inert:space:) preSolve:nil postSolve:nil separate:nil];
}
So what happens... is nothing. I am trying to follow the examples in Angry Chipmunk for collision handling while still taking advantage of the relative ease of using Physics Editor. I want the callback when the collision occurs, so I am using the begin: callback. As far as I can tell, the collision isnt making it out of the collision handler as it never calls the callback. I am guessing it has something to do with how I am specifying typeA and typeB. I wanted to use PhysicsEditor collision_type field, but it is an integer incompatible with the Obj-Chip id collision_type field. So... what am I missing?
Last edited by jcmeyer5 on Fri May 11, 2012 7:03 am, edited 1 time in total.
Chipmunk Pro and cocos2D 2.x branch for iOS development
User avatar
slembcke
Site Admin
Posts: 4164
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Collisions... nothing happening

Post by slembcke »

So Objective-Chipmunk uses object references instead of integers as it's much much easier to use unique and accessible values that way.

You can still use integers for collision types though, just cast the integer to id. (Note, this doesn't work with ARC)

Code: Select all

 [space addCollisionHandler:self typeA:(id)5 typeB:(id)6 ...];
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

Re: Collisions... nothing happening

Post by jcmeyer5 »

Okay, I have tossed out my complex scenario for a basic box and circle scenario just so I can learn this. Here is my box class:

Code: Select all

-(id)initAtPos:(cpVect)pos {
	//************************************************************************
	self.position = pos;
	
	hitPoints = 1000;
		
	chassis = [ChipmunkCocosBody bodyWithMass:10.0 andMoment:cpMomentForBox(10.0, 100.0, 30.0)];
	ChipmunkPolyShape* mainShape = [ChipmunkPolyShape boxWithBody:chassis width:100.0 height:30.0];

	// assign body position to GameObject
	chassis.pos = self.position;
	mainShape.collisionType = [Box class];
	mainShape.group = self;
	mainShape.layers = 1;

	chipmunkObjects = [[NSArray alloc] initWithObjects:
							 chassis, mainShape, nil];
	
	return self;
}

+(Box*)boxAtPos:(cpVect)pos {
	return [[Box alloc] initAtPos:pos];
}
And my circle class:

Code: Select all

-(id)initWithName:(NSString*)name atPos:(cpVect)pos {
	
	// set objectType to inert
	self.objectType = kTypeInert;
	
	// load sprite frame cache
	[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"sprites.plist"];
	// load sprite from 
	CCSprite* sprite = [CCSprite spriteWithSpriteFrameName:name];
	// add sprite to array
	objectSprites = [[NSArray alloc] initWithObjects:sprite, nil];
	
	body = [ChipmunkCocosBody bodyWithMass:5.0 andMoment:cpMomentForCircle(5.0, 12, 12, cpvzero)];
	ChipmunkCircleShape* rock = [ChipmunkCircleShape circleWithBody:body	radius:12 offset:cpvzero];
	// set position of body to provided position
	body.pos = pos;
	// assign body position to GameObject
	self.position = body.pos;
	rock.collisionType = [Rock class];
	rock.group = self;
	rock.layers = 1;

	// load sprites array to synced nodes
	body.syncedNodes = objectSprites;
	
	// load chipmunk objects to chipmunkObjects array
	chipmunkObjects = [[NSArray alloc] initWithObjects:body, rock, nil];
	
	return self;
}

+(Rock*)rockWithName:(NSString*)name atPos:(cpVect)pos {
	return [[Rock alloc] initWithName:name atPos:pos];
}
Here are my collision methods (they don't do anything except tell me they are being executed):

Code: Select all


static inline void applyDamage(Box* box, cpArbiter* arb, GameLayer* self) {
	if(cpArbiterIsFirstContact(arb)){
		// Divide the impulse by the timestep to get the collision force.
		cpFloat impact = cpvlength(cpArbiterTotalImpulse(arb))/FIXED_TIMESTEP;
		CCLOG(@"Impact Value: %f",impact);
	}
}

-(void)begin:(cpArbiter*)arbiter space:(ChipmunkSpace*)space {
	CCLOG(@"COLLISION");
	CHIPMUNK_ARBITER_GET_SHAPES(arbiter, box, rock);
	applyDamage(box.data, arbiter, self);
}

-(void)addCollisionHandlers {
	[space addCollisionHandler:self typeA:[SimpleCar class] typeB:[Rock class] begin:@selector(begin:space:) 
	     preSolve:nil postSolve:nil separate:nil];
}
Now, currently, dropping a circle on the box results in a collision call (with impact of 0.000), but the circle drops right through the box. If I don't call the handlers (comment out the [self addCollisionHandlers]), the circles bounce off the box as they should. Again, I am trying to model this off of the Angry Chipmunks demo, but for the life of me, I can't get it to work. What am I missing?
Chipmunk Pro and cocos2D 2.x branch for iOS development
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

Re: Collisions... nothing happening

Post by jcmeyer5 »

Eureka!! I found it. My "begin" callback needed to be a BOOL return and not a void return. Once I fixed that, I started getting impact values and the circles bounced off properly.
Chipmunk Pro and cocos2D 2.x branch for iOS development
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

Re: <SOLVED>Collisions not coliding

Post by jcmeyer5 »

I was able to migrate the collision code back to my original classes without incident. Sweetness!
Chipmunk Pro and cocos2D 2.x branch for iOS development
User avatar
slembcke
Site Admin
Posts: 4164
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: <SOLVED>Collisions not coliding

Post by slembcke »

Also, cpArbiterTotalImpulse() (and other functions that deal with impact values) must be called from a post-solve callback. Otherwise the values you are asking for haven't been calculated yet.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

Re: <SOLVED>Collisions not coliding

Post by jcmeyer5 »

Just figured that out too, as I was getting intermittent values. Moving it to the postSolve gives the results I am looking for. Thanks for the help. I am going to do a search to see if I can find more details on the differences in collision callbacks.
Chipmunk Pro and cocos2D 2.x branch for iOS development
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

Re: <SOLVED>Collisions not coliding

Post by jcmeyer5 »

Okay, another snag...

I am now trying to remove rocks that hit the player. I am trying to do this in the separate callback. Problem is, I am getting a "cannot remove body that was not added to the space (removed twice maybe?)" error. Also, the second rock appears to generate more than one collision before a removal is attempted... could that be part of it? More specifically, here is the console output:

Code: Select all

Initializing cpSpace - Chipmunk v6.0.3 (Debug Enabled)
Compile with -DNDEBUG defined to disable debug mode and runtime assertion checks
2012-05-11 14:36:15.234 ChipTest[26965:10a03] Spawning...
2012-05-11 14:36:15.235 ChipTest[26965:10a03] GameObject added. // player
2012-05-11 14:36:15.236 ChipTest[26965:10a03] cocos2d: Frame interval: 1
2012-05-11 14:36:15.237 ChipTest[26965:10a03] cocos2d: surface size: 1024x768
2012-05-11 14:36:15.394 ChipTest[26965:10a03] Coasting
2012-05-11 14:36:16.453 ChipTest[26965:10a03] cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from [5] to [8].
2012-05-11 14:36:19.353 ChipTest[26965:10a03] GameObject added. // rock#1
2012-05-11 14:36:20.186 ChipTest[26965:10a03] POSTSOLVE // rock#1
2012-05-11 14:36:20.186 ChipTest[26965:10a03] Impact Value: 2782.263916 // rock#1
2012-05-11 14:36:20.203 ChipTest[26965:10a03] GameObject removed. // rock#1
2012-05-11 14:36:25.384 ChipTest[26965:10a03] GameObject added. // rock#2
2012-05-11 14:36:26.186 ChipTest[26965:10a03] POSTSOLVE // rock#2
2012-05-11 14:36:26.187 ChipTest[26965:10a03] Impact Value: 1788.794922 // rock#2
2012-05-11 14:36:26.187 ChipTest[26965:10a03] POSTSOLVE  // still rock#2
2012-05-11 14:36:26.187 ChipTest[26965:10a03] Impact Value: 1373.066650 // still rock#2
2012-05-11 14:36:26.188 ChipTest[26965:10a03] POSTSOLVE // still rock#2
2012-05-11 14:36:26.203 ChipTest[26965:10a03] POSTSOLVE // still rock#2
Chipmunk warning: Adding a post-step callback when the space is not locked is unnecessary. Post-step callbacks will not called until the end of the next call to cpSpaceStep() or the next query.
	Failed condition: space->locked
	Source:/tmp/ChipmunkPro-TMP/Chipmunk/src/cpSpaceStep.c:55
2012-05-11 14:36:26.204 ChipTest[26965:10a03] GameObject removed.
Aborting due to Chipmunk error: Cannot remove a body that was not added to the space. (Removed twice maybe?)
	Failed condition: cpSpaceContainsBody(space, body)
	Source:/tmp/ChipmunkPro-TMP/Chipmunk/src/cpSpace.c:394
Here is my collision stuff:

Code: Select all

//**************************************************************************

static inline void applyDamage(Vehicle* vehicle, cpArbiter* arb, GameLayer* self) {
	if(cpArbiterIsFirstContact(arb)){
		// Divide the impulse by the timestep to get the collision force.
		cpFloat impact = cpvlength(cpArbiterTotalImpulse(arb));
		if (impact > 0.0f) CCLOG(@"Impact Value: %f",impact);
	}
}

-(void)postsolveVehicle:(cpArbiter*)arbiter space:(ChipmunkSpace*)space {
	CCLOG(@"POSTSOLVE");
	CHIPMUNK_ARBITER_GET_SHAPES(arbiter, carShape, rockShape);
	applyDamage(carShape.data, arbiter, self);
}

-(void)separateInert:(cpArbiter*)arbiter space:(ChipmunkSpace*)space {
	CHIPMUNK_ARBITER_GET_SHAPES(arbiter, carShape, rockShape);
	[self->space addPostStepBlock:^{ [self remove:rockShape.data]; } key:rockShape.data];
}

-(void)addCollisionHandlers {
	[space addCollisionHandler:self typeA:[Vehicle class] typeB:[Inert class] 
								begin:nil preSolve:nil postSolve:@selector(postsolveVehicle:space:) separate:@selector(separateInert:space:)];
}

//**************************************************************************

Chipmunk Pro and cocos2D 2.x branch for iOS development
User avatar
slembcke
Site Admin
Posts: 4164
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: <SOLVED>Collisions not coliding

Post by slembcke »

Aha! I think that is the same as a bug that I just fixed. It's... a little complicated to explain why it happens though. It has to do with separate callbacks that can be triggered immediately when removing objects, and scheduling post-step callbacks within them. Try updating to the latest code out of Git and see if your problem goes away.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
jcmeyer5
Posts: 89
Joined: Thu Dec 15, 2011 9:18 am
Contact:

Re: <SOLVED>Collisions not coliding

Post by jcmeyer5 »

I will try the code Monday. I did find a work around with switching the callbacks. I put rock removal as postSolve and damage as separate. Not sure if that switch has ramifications that I have not yet considered, but it appears to be working well.
Chipmunk Pro and cocos2D 2.x branch for iOS development
Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests