【问题标题】:Box2D & Cocos2d level reset issueBox2D & Cocos2d 关卡重置问题
【发布时间】:2013-04-14 01:23:09
【问题描述】:

我有一个非常简单的关卡,其中有一个静态主体(和相关的精灵)。当用户触摸身体时,我移除精灵,销毁身体并用带有新精灵的动态身体替换它,然后我过渡到新场景。我的代码在第一次执行时运行良好,但是当重新加载这个场景时,当用户触摸身体时它会崩溃。

我将用于精灵的 .png 文件的文件名存储在精灵的 userData 字段中。然后当用户按下按钮(触摸身体)时,检索它是一件简单的事情。当我尝试访问精灵的 userData 字段时,在随后重新加载场景时会出现问题。而不是保存文件名,它是空的(null)。当我尝试使用文件名时,这反过来会使程序崩溃。

我不明白为什么它第一次有效,第二次无效。我设置了一个断点并观察分配给精灵的 userData 字段的文件名,但它只能在我第一次创建场景时检索。这是 ccTouchesBegan 方法。崩溃发生在我尝试分配 newSpriteFileName 的地方,因为在第二次运行时 oldSpriteFileName 是空的。

我刚刚对这个发疯了,但我相信这是显而易见的。一如既往地感谢您的帮助!

    (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        for( UITouch *touch in touches )
        {
            CGPoint touchLocation = [touch locationInView: [touch view]];
            touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];

    touchLocation = [self convertToNodeSpace:touchLocation];
    b2Vec2 locationWorld = b2Vec2(touchLocation.x/PTM_RATIO, touchLocation.y/PTM_RATIO);

    NSLog(@"Location x = %f, y = %f", touchLocation.x, touchLocation.y);
    b2AABB aabb;
    b2Vec2 delta = b2Vec2(1.0/PTM_RATIO, 1.0/PTM_RATIO);
    aabb.lowerBound = locationWorld - delta;
    aabb.upperBound = locationWorld +delta;
    SimpleQueryCallback callback(locationWorld);
    m_world->QueryAABB(&callback, aabb);

    //If they have not pressed a button yet, and this touch was actually inside 
    //one of the buttons then we will destroy the static button (and sprite) 
    //that they touched and replace it with a dynamic button
    //(and new darker sprite) that falls, spinning off of the screen.
    if(!replaceButtonPushedYet && callback.fixtureFound)
    {
        //Get a reference to the static body of the button they touched and wake it up
        b2Body *body = callback.fixtureFound->GetBody();
        body->SetAwake(true);

        //Get the position of the body (button) they touched and use it to 
        //position the new button.  This value is in Box2D coordinates, 
        //so when I position the new button I won't divide by PTM_RATIO.
        b2Vec2 touchedButtonPosition = body->GetPosition();

        //Get the sprite from the button the user pressed
        CCSprite *bodySprite = (CCSprite*)body->GetUserData();

        //Then extract the file name of the sprite.  I assigned this to 
        //sprite's userData when I loaded the sprite in the method          //"placeTheIndividualButton".  Now I am going to extract it and 
        //then replace "(up)" with "(down)" in that string
        //and that becomes the name of the sprite for the new (pressed) 
        //button I am getting ready to create.  It is all about the file
        //naming conventions!
        NSString *oldSpriteFileName = (NSString*)bodySprite.userData;
        NSString *newSpriteFileName = [oldSpriteFileName stringByReplacingOccurrencesOfString:@"up" withString:@"down"];


        //First remove the sprite tied to the button the user pressed, 
        //then destroy the body of the button.
        [self removeChild:bodySprite cleanup:YES];
        body->GetWorld()->DestroyBody(body);

        //Set the bool to true to keep this code from executing again.  
        //This ensures that once they press a button they can't 
        //press another one.
        replaceButtonPushedYet = true;

        //Build the new dynamic button that will fall and spin off the screen
        b2BodyDef buttonBodyDef2;
        b2PolygonShape buttonShape2;
        b2FixtureDef buttonShapeDef2;
        b2Vec2 vertices2[4];

        //load the sprite for the second button (pressed down) and add it to the layer
        level_down = [CCSprite spriteWithFile:newSpriteFileName];
        level_down.userData=newSpriteFileName;
        [self addChild:level_down];

        //Define the polygon that forms the second button (pressed down)
        buttonBodyDef2.type = b2_dynamicBody;
        //Not dividing touchedButtonPosition.x or .y by PTM_RATIO because 
        //they are already in Box2D coordinates
        buttonBodyDef2.position.Set(touchedButtonPosition.x, touchedButtonPosition.y);
        buttonBodyDef2.angularVelocity = 1.5;
        buttonBodyDef2.userData = level_down;
        buttonBody2 = m_world->CreateBody(&buttonBodyDef2);

        //Define the vertices for the replacement button
        vertices2[0].Set(-94/PTM_RATIO, -32/PTM_RATIO);
        vertices2[1].Set(94/PTM_RATIO, -32/PTM_RATIO);
        vertices2[2].Set(94/PTM_RATIO, 32/PTM_RATIO);
        vertices2[3].Set(-94/PTM_RATIO, 32/PTM_RATIO);
        buttonShape2.Set(vertices2, 4);

        //Define the shape for the replacement button
        buttonShapeDef2.shape = &buttonShape2;
        buttonShapeDef2.density = 50.01f;
        buttonShapeDef2.friction = 0.75f;
        buttonShapeDef2.restitution = 0.1f;

        //The static buttons and the dynamic buttons are both in this groupIndex.  
        //Since it is a negative number they will never collide.  If it was 
        //positive they would always collide.
        buttonShapeDef2.filter.groupIndex = -1;

        //Put the second button (pressed down) into the world.
        buttonBody2->CreateFixture(&buttonShapeDef2);

        //This starts a timer that fires every second to call the makeTransition 
        //method.  The code inside that method will check to see if the button 
        //has fallen off the screen yet.  If it has then it will transition to 
        //the new selected level.
        //The colon after makeTransition sends a ccTime (dt).  I don't need it, 
        //but may in the future so I left it in there.
        buttonFalling = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(makeTransition:) userInfo:nil repeats:YES];
    }
}

}

【问题讨论】:

    标签: cocos2d-iphone box2d user-data


    【解决方案1】:

    当您移除精灵时,NSString 可能会被释放。为什么不直接将纹理名称存储在实例变量中?

    【讨论】:

    • 每个身体都有不同的纹理,因此每个精灵都有不同的文件名。我为解决上述问题所做的是创建自己的 CCSprite 子类,并在我的类中添加几个 NSStrings 用于存储值。这就像一个冠军,但我仍然不确定为什么它不能使用 CCSprite 拥有的 userData。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 2011-08-01
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多