Question

I've looked around quite a bit and haven't been able to find a concise answer to this question. For my Cocos2D game I have integrated the Chipmunk physics engine. On initialization, I setup the boundaries of the 'playing field' by establishing a series of bodies and static shapes as follows:

- (void)initPlayingField {
    // Physics parameters
    CGSize fieldSize = _model.fieldSize;
    CGFloat radius = 2.0;
    CGFloat elasticity = 0.3;
    CGFloat friction = 1.0;

    // Bottom
    CGPoint lowerLeft = ccp(0, 0);
    CGPoint lowerRight = ccp(fieldSize.width, 0);
    [self addStaticBodyToSpace:lowerLeft finish:lowerRight radius:radius elasticity:elasticity friction:friction];

    // Left
    CGPoint topLeft = ccp(0, fieldSize.height);
    [self addStaticBodyToSpace:lowerLeft finish:topLeft radius:radius elasticity:elasticity friction:friction];

    // Right
    CGPoint topRight = ccp(fieldSize.width, fieldSize.height);
    [self addStaticBodyToSpace:lowerRight finish:topRight radius:radius elasticity:elasticity friction:friction];

    // Top
    [self addStaticBodyToSpace:topLeft finish:topRight radius:radius elasticity:elasticity friction:friction];
}

This setup works, except for one thing-- the positions of the boundaries appear to be off by a significant amount of pixels to the right. After initializing a player, and sending him towards the boundary walls, it does not bounce off the edges of the screen (as I would expect by setting up the bounding box at 0,0), but rather some number of pixels (maybe 30-50) inwards from the edges of the screen. What gives?

I initially thought the issue came from where I was rendering the player sprite, but after running it through the debugger, everything looks good. Are there special protocols to follow when using chipmunk's positions to render sprites? Do I need to multiply everything by some sort of PIXELS_PER_METER? Would it matter if they are in a sprite sheet? A sprite batch node? Here is how I set the sprite position in my view:

Player *player = [[RootModel sharedModel] player];
self.playerSprite.position = player.position;
self.playerSprite.rotation = player.rotation;

And here is how I set the position in my Model:

- (void)update:(CGFloat)dt {
    self.position = self.body->p;
    self.rotation = self.body->a;
}

(Yes, I know it's redundant to store the position because chipmunk does that inherently.)

Also, bonus question for for those who finished reading the post. How might you move a body at a constant velocity in whatever direction it is facing, only allowing it to turn left or right at any given time, but never slow down?

Was it helpful?

Solution

What's the shape of the physics body? Perhaps you simply forgot to consider making the shape the same size of the sprite. If you only consider the position, then the sprite will be able to move halfway outside the screen at any border because its position is at the center of the sprite.

To move a body at constant velocity, set its velocity while disabling friction (set to 0?) and allowing it to rebound off of collisions with its impact speed (in Box2D that would be restitution = 1, don't know about Chipmunk).

OTHER TIPS

Have you tried debug drawing the collision shapes? Cocos2D 2.1 has my CCPhysicsDebugNode class in it that makes it pretty easy to add. That will let you know if your geometry is lined up with your graphics. How thick are your boundary shapes? Are you possibly adding the sprites to a parent node that might be offsetting them?

Chipmunk doesn't require you to tune it for any real units. You can just use pixels or whatever.

Lastly, @LearnCocos2D has the right idea about the constant velocity. Set friction to 0 and elasticity to 1.0. You will also probably want to check it's velocity every frame and accelerate it back towards it's normal velocity each frame. Colliding with non-static geometry will cause it to lose speed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top