Multigrab: how to "z-order" overlapping shapes

Official forum for the Chipmunk2D Physics Library.
Post Reply
SorenToft
Posts: 3
Joined: Sat Feb 23, 2013 8:44 am
Contact:

Multigrab: how to "z-order" overlapping shapes

Post by SorenToft »

Hi

I am using multigrab (objective-c wrapper) to grap the the arm, leg and torso of a person. The person is displayed in profile, so the chipmunk shapes representing the arm and torso overlaps. When i touch the arm multigrab will (most of the time) grab the torso instead. What would be a good way to make sure, the arm always have priority over the torso when grabbing?

Right now my best bet is do some "pre-filtering" in the ccToucedMoved that will determine if the touch is within the arm, then set the MultiGrab grabFilter to filter out all shapes with a lower z sprite index. But I am hoping for a less messy solution.

Regards.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Multigrab: how to "z-order" overlapping shapes

Post by slembcke »

Sorry, trying to catch up on missed posts this morning.

Unfortunately there is not a way to z-order them without modifying the ChipmunkMultiGrab source itself. It's implemented to grab the closest non-filtered shape to the touch location. In the case where you touch a spot where two shapes are overlapping, it will grab the one that the touch is deepest into. I assume "displayed in profile" means from the side? In that case if the arm and torso are overlapping and the torso is thicker, then you are pretty likely to touch deeper into the torso than the arm.

The changes to ChipmunkMultiGrab would be relatively simple to make. In the "beginLocation:" method, when it compares the distance change it to fall back on your z-order if the distance is negative (meaning inside the touched shape).

An idea for the next version of ChipmunkMultiGrab would be to have a sorting callback. In the case of ties (multiple shapes under the touch location), it breaks them with the return value of the sorting callback. The default one could just return the touch depth to keep the current behavior. For z-ordered stuff you could override the callback to return the z-value. It might be a while before I get to this though. I'm already sort of backlogged right now. :-\
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
SorenToft
Posts: 3
Joined: Sat Feb 23, 2013 8:44 am
Contact:

Re: Multigrab: how to "z-order" overlapping shapes

Post by SorenToft »

Hi - thank you for your answer.

Yes, when I say in profile I mean "from the side". Writing displayed in profile is probably speaking Danglish (Danish-English). ;)

I did make a work-around. In my ccToucesBegan I look at the distance from the touch point to the arm, and if it is <= 0, I filter out the torso before calling [Multigrab beginLocation].

I may subclass Multigrab to make a more generic solution along the line you suggested.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Multigrab: how to "z-order" overlapping shapes

Post by slembcke »

I just pushed the custom sort ordering feature I described above to the git repository. This test should illustrate what I mean.

Code: Select all

-(void)testMultiGrabSort
{
	ChipmunkSpace *space = [[ChipmunkSpace alloc] init];
	ChipmunkMultiGrab *multiGrab = [[ChipmunkMultiGrab alloc] initForSpace:space withSmoothing:0.0 withGrabForce:1.0];
	
	ChipmunkBody *body = [space add:[ChipmunkBody bodyWithMass:1.0 andMoment:1.0]];
	ChipmunkShape *big = [space add:[ChipmunkCircleShape circleWithBody:body radius:10.0 offset:cpvzero]];
	ChipmunkShape *small = [space add:[ChipmunkCircleShape circleWithBody:body radius:5.0 offset:cpvzero]];
	
	// Used for the custom sorting orders.
	big.data = @0;
	small.data = @1;
	
	ChipmunkGrab *grab1 = [multiGrab beginLocation:cpvzero];
	GHAssertEquals(grab1.grabbedShape, big, @"Should have grabbed 'big' since it has the largest penetration depth.");
	
	multiGrab.grabSort = ^(ChipmunkShape *shape, cpFloat depth){
		NSNumber *n = shape.data;
		return (cpFloat)n.floatValue;
	};
	
	// Should grab small since it's sorting order will be the largest;
	ChipmunkGrab *grab2 = [multiGrab beginLocation:cpvzero];
	GHAssertEquals(grab2.grabbedShape, small, @"Should have grabbed 'small' since it has the highest custom sort value.");
	
	[multiGrab release];
	[space release];
}
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
SorenToft
Posts: 3
Joined: Sat Feb 23, 2013 8:44 am
Contact:

Re: Multigrab: how to "z-order" overlapping shapes

Post by SorenToft »

Thank you - I will check it out and clean up my code :-)
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 33 guests