How to make a dynamic body static in Cocos2d v3.0

2019-04-17 06:42发布

问题:

I’m using Cocos2d v3 and want to change a body from dynamic to static after colliding with another body. At the moment I’ve got:

-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair static:(CCNode *)nodeA wildcard:(CCNode *)nodeB
{
   _player.physicsBody.type = CCPhysicsBodyTypeStatic;
}

or

-(BOOL)ccPhysicsCollisionPreSolve:(CCPhysicsCollisionPair *)pair static:(CCNode *)nodeA wildcard:(CCNode *)nodeB
{
   _player.physicsBody.type = CCPhysicsBodyTypeStatic;
   return YES;
}

but neither works. I get the error:

Aborting due to Chipmunk error: This operation cannot be done safely during a call to cpSpaceStep() or during a query. Put these calls into a post-step callback. Failed condition: !space->locked

I then tried to make a joint at the point of collision but it doesn’t work right.

Is there a way to change a body to dynamic as soon as it collides in v3? I can do it in later versions using Box2D. I want to stop gravity and other forces so it doesn’t move. I want to make it look like it stuck to a surface.

Read a little on post-step callbacks but i'm unfamiliar with how to use them.

Any help would be appreciated.

回答1:

As the error message states, you need to implement a post-step callback. To do this on Cocos2d 3.0 and with Objective Chipmunk you first need to import a new header file to access advanced chipmunk properties:

#import "CCPhysics+ObjectiveChipmunk.h"

Then add the callback in your collision handler:

-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair static:(CCNode *)nodeA wildcard:(CCNode *)nodeB
{
    [[_physicsNode space] addPostStepBlock:^{
        _player.physicsBody.type = CCPhysicsBodyTypeStatic;
    } key:_player];
}

Note that I assume you have access to your CCPhysicsNode in _physicsNode. The Chipmunk Space of CCPhysicsNodeis locked while the a physics step is calculated. During a calculation of a step collisions are resolved and objects are moved around - changing the body type during this calculation could result in unexpected behaviour.

Therefore you add the postStepBlockcallback. This is a place where a body type can be safely changed.

The key value you pass into the callback is used to ensure that the code is only called once (especially useful when removing objects, but it also makes sense in this case).

If also added an example implementation: https://www.makegameswith.us/gamernews/367/make-a-dynamic-body-static-in-cocos2d-30-with-chi