I'm using Cocos2d 2.0 with Chipmunk. I have a sprite A that moves across the screen, can rotate to change direction arbitrarily and move again.
Orbiting A is a child sprite B. B is a child because it makes it easy to let the child actions worry about moving in a circle around cpv(0,0). The beauty of this is that while A moves around the screen, B follows it whilst also following it's orbit. It's like having the earth orbit the sun all the time having the moon orbiting the earth as the earth follows it's path.
A is subject to Chipmunks physics, and is an active body with a shape for collision detection.
B is a rogue body so that it is not subject to Chipmunk physics, but has a shape for the purposes of collision detection with other shapes (not A). B is also a subclass of CCPhysicsSprite.
What I'm finding is that B is not colliding with anything, and having used CCPhysicsDebugNode to see what is happening, I can see that although the Cocos2D sprite that is B is in the correct place, orbiting A, the Chipmunk shape for B is orbiting the bottom left corner of the screen.
I've tried all manner of convertToWorldSpace: calls, overriding setPosition, not using CCPhysicsSprite and using a cut down copy of cpSprite from an old copy of Kobold, but no matter what I try I just can't get the space to follow sprite B in the correct position on the screen.
One other bit of information is that I note that when A rotates to change direction of travel, this of course affects the orbit of A in that is can appear to speed up or slow down. I don't mind this effect, but what concerns me is that the space that is orbiting the bottom left seems to get out of sync with B. It continues to rotate around the screen corner, but it's position in the orbit is no longer in sync with B's position in it's orbit around A.
I have a nagging feeling that this is going to be harder than I thought. I had figured that the space would automatically overlay the body, and that if the body, which is visually represented by the sprite is in the right place, then the shape would be too. With one experiment I made B an active body by adding it to the space, and that showed the body AND shape in the same orbit around the screen corner whilst the sprite continued to orbit the correct position on screen.
I suspect I could fix this by adding B as a child of A's parent layer, but that would mean that I'd have to manually move A to follow B whilst maintaining it's orbit.
I'd love some advice.
Thanks
pkclsoft
Here is the code for the implementation of B:
Code: Select all
#import "Sweeper.h"
#import "GameConstants.h"
#import "GameLayer.h"
@implementation Sweeper {
GameLayer *device;
}
void sweeperBodyUpdatePosition(cpBody *body, cpFloat dt) {
// cpBodyUpdatePosition(body, dt);
}
- (void) initPhysicsInSpace:(cpSpace*)inSpace {
const float elasticity = 0.0f;
const float friction = 0.0f;
cpBody *body = cpBodyNew(10000.0, cpMomentForCircle(10000.0, self.contentSize.width/2.0, self.contentSize.width/2.0, cpvzero));
body->p = [CocosUtil screenCentre]; // starting place; this will be obsolete as soon as self is added to a parent
body->data = self;
body->w_limit = 0;
body->v_limit = 0;
cpShape* shape = cpCircleShapeNew(body, self.contentSize.width/2.0, cpvzero);
shape->e = elasticity;
shape->u = friction;
shape->group = BALL_GROUP;
shape->collision_type = kCollisionTypeSweeper;
shape->data = self;
shape->sensor = YES;
cpSpaceAddShape(inSpace, shape);
[self setBody:body];
}
- (id) initOnDevice:(GameLayer*)onDevice {
self = [super initWithSpriteFrameName:@"spriteB.png"];
if (self != nil) {
[self initPhysicsInSpace:[onDevice space]];
device = [onDevice retain];
}
return self;
}
- (void) dealloc {
if (device != nil) {
[device release];
}
[super dealloc];
}
+ (Sweeper*) sweeperOnDevice:(GameLayer*)onDevice {
return [[[Sweeper alloc] initOnDevice:onDevice] autorelease];
}
@end