停止精灵的移动- Box2D (cocos2d)



我正在制作一款游戏,我需要一个只在按下按钮时移动的对象。我有一个开始运动的方法,到目前为止,我通过破坏物体的主体来结束物体的运动。我遇到的问题是,我不能再次移动对象,因为程序现在会崩溃。我想知道是否有一种方法来重建身体一旦它被摧毁,因为我目前的检查身体是否仍然存在的方法是不工作。

这是我的代码。
NSMutableArray *spaceObjectsArray;
#pragma mark - HelloWorldLayer
@interface HelloWorldLayer()
-(void) initPhysics;
-(void) addNewSpriteAtPosition:(CGPoint)p;
-(void) createMenu;
@end
@implementation HelloWorldLayer
+(CCScene *) scene
{
    // 'scene' is an autorelease object.
    CCScene *scene = [CCScene node];
    // 'layer' is an autorelease object.
    HelloWorldLayer *layer = [HelloWorldLayer node];
    // add layer as a child to scene
    [scene addChild: layer];
    // return the scene
    return scene;
}
-(void)gameLogic:(ccTime)delta
{
    [self addSpaceObjects];
}
-(void) addSpaceObjects
{
    _spaceObject = [CCSprite spriteWithFile:@"blueDot.jpg"];

    //create spaceObject body
    b2BodyDef spaceObjectbBodyDef;
    spaceObjectbBodyDef.type=b2_dynamicBody;
    spaceObjectbBodyDef.userData = _spaceObject;
    //make the location of spaceObject
    CGSize winSize = [CCDirector sharedDirector].winSize;
    int minX= _spaceObject.contentSize.width/2;
    int maxX = winSize.width - _spaceObject.contentSize.width/2;
    int rangeX = maxX - minX;
    int actualX = (arc4random() % rangeX) + minX;
    _spaceObject.position = ccp(actualX, winSize.height + _ship.contentSize.height);
    spaceObjectbBodyDef.position.Set(actualX/PTM_RATIO, (winSize.height+_ship.contentSize.height)/PTM_RATIO);
    _spaceObjectBody= _world->CreateBody(&spaceObjectbBodyDef);
    //create spaceObject shape
    b2PolygonShape spaceObjectShape;
    spaceObjectShape.SetAsBox(_spaceObject.contentSize.width/PTM_RATIO/2, _spaceObject.contentSize.height/PTM_RATIO/2);
    //create spaceObject fixture
    b2FixtureDef spaceObjectShapeDef;
    spaceObjectShapeDef.shape= &spaceObjectShape;
    spaceObjectShapeDef.density = 2;
    spaceObjectShapeDef.restitution =0;
    spaceObjectShapeDef.friction=0;
    _spaceObjectFixture = _spaceObjectBody->CreateFixture(&spaceObjectShapeDef);
    [self addChild:_spaceObject];
    _spaceObject.tag=1;
    [spaceObjectsArray addObject:_spaceObject];
   //aply force on the object
    int randomValue = ((arc4random() % 5) *-1);
    b2Vec2 force = b2Vec2(0,randomValue);
    _spaceObjectBody ->ApplyLinearImpulse(force, _spaceObjectBody->GetPosition());

}

init方法,包含body的创建和定义

-(id) init
{
    if( (self=[super init])) {
        CGSize s = [CCDirector sharedDirector].winSize;

        //create spaceShip sprite and add it to the layer
        _ship = [CCSprite spriteWithFile:@"theShip.gif" ];
        _ship.position = ccp(s.width/2, 1.25*_ship.contentSize.height);
        [self addChild:_ship];
        //create the world
        b2Vec2 gravity = b2Vec2_zero;
        _world = new b2World(gravity);
        //create ship body
        b2BodyDef shipBodyDef;
        shipBodyDef.type = b2_dynamicBody;
        shipBodyDef.position.Set((s.width/2)/PTM_RATIO, (1.25*_ship.contentSize.height)/PTM_RATIO);
        shipBodyDef.userData = _ship;
        if(_shipBody == NULL){
        _shipBody =_world->CreateBody(&shipBodyDef);
        }
        //create ship shape
        b2PolygonShape shipShape;
        shipShape.SetAsBox(_ship.contentSize.width/PTM_RATIO/2, _ship.contentSize.height/PTM_RATIO/2);
        //create Ship definition and add to body
        b2FixtureDef ShipShapeDef;
        ShipShapeDef.shape = &shipShape;
        ShipShapeDef.density = 3;
        ShipShapeDef.friction =0;
        ShipShapeDef.restitution =0;
        _shipFixture = _shipBody->CreateFixture(&ShipShapeDef);
        //make the paddles
        //bottom left one
        _paddle1 = [CCSprite spriteWithFile:@"spritePaddle.jpeg"];
        int bottomOfScreenX = 0 + _paddle1.contentSize.width/2;
        int bottomOfScreenY = 0+_paddle1.contentSize.height/2;
        _paddle1.position = ccp(bottomOfScreenX,bottomOfScreenY);
        [self addChild:_paddle1];
        //bottom right one
        _paddle2 = [CCSprite spriteWithFile:@"spritePaddle.jpeg"];
        int bottomRightOfScreenX = s.width - _paddle2.contentSize.width/2;
        _paddle2.position = ccp(bottomRightOfScreenX, bottomOfScreenY);
        [self addChild:_paddle2];

        //continuously spawn spaceObjects
        [self schedule:@selector(gameLogic:) interval:1];

        // enable events
        self.touchEnabled = YES;

        // init physics
        [self schedule:@selector(tick:)];

    }
    return self;
}
-(void)tick:(ccTime) delta
{//this method is to simulate physics and to test for the position of where objects should be if force has been applied to them
    _world->Step(delta, 8, 8);
    for (b2Body *b=_world->GetBodyList(); b; b=b->GetNext()){
        if (b->GetUserData() != NULL){
            CCSprite *shipData = (CCSprite *)b->GetUserData();
            shipData.position = ccp(b->GetPosition().x *PTM_RATIO, b->GetPosition().y *PTM_RATIO);
        }
    }
}

移动船的桨被触碰逻辑

-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //Set up a way for touches to be turned into locations onscreen
    NSSet *allTouches = [event allTouches];
    UITouch *touch = [allTouches anyObject];
    CGPoint location = [touch locationInView:[touch view]];
    location = [[CCDirector sharedDirector] convertToGL:location ];
    //check to see if Left Paddle is being pressed
    if (CGRectContainsPoint([_paddle1 boundingBox], location)){
        b2Vec2 force = b2Vec2(-5,0);
        _shipBody->ApplyLinearImpulse(force, _shipBody ->GetPosition());
        }
    if (CGRectContainsPoint([_paddle2 boundingBox], location)){
        b2Vec2 force = b2Vec2(5,0);
        _shipBody->ApplyLinearImpulse(force, _shipBody->GetPosition());
    }
}

桨盒不再被触碰逻辑

-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    _world->DestroyBody(_shipBody);
}
-(void) dealloc
{
    delete _world;
    _world = NULL;

    [super dealloc];
}   
@end

破坏身体来结束它的运动并不是最好的解决方案。只有当你真的不希望它再成为模拟的一部分时,你才应该删除它。

有几个选项可以停止身体的运动:

1 -将其线速度设置为0。这将使它立即停止。如果有其他东西在推动它(例如与身体接触),你必须决定怎么做。

body->SetLinearVelocity(b2Vec2(0,0)));

2 -将其线性/角阻尼设置为0。这将消散它的动量,所以它会慢慢停下来。你使用的因子应该大于0。当的值较大时,物体会更快地停止,它将抵抗来自其他物体的移动(如果它们撞到它,它将减速并再次停止)。当你想让身体开始移动时,记得把线性/角阻尼调回0。

body->SetLinearDamping(0.2);
body->SetAngularDamping(0.2);

3 -将目标位置设置为seek to,并将位置设置为您想要的位置。这基本上是一个反馈控制回路,你在其中施加一个力,让它向你想要身体停留的地方移动。它可以用来让物体跟随路径等等。下面的代码是一个更大的代码库的一部分(您可以在这里看到它),但是您应该能够获得总体思路。该函数对对象施加推力,使其向目标方向推进。

void MovingEntity::ApplyThrust()
{
   // Get the distance to the target.
   b2Vec2 toTarget = GetTargetPos() - GetBody()->GetWorldCenter();
   toTarget.Normalize();
   b2Vec2 desiredVel = GetMaxSpeed()*toTarget;
   b2Vec2 currentVel = GetBody()->GetLinearVelocity();
   b2Vec2 thrust = GetMaxLinearAcceleration()*(desiredVel - currentVel);
   GetBody()->ApplyForceToCenter(thrust);
}

最新更新