我有一個非常簡單的級別,其中包含一個靜態主體(以及相關的精靈)。當用戶觸摸身體時,我移除精靈,摧毀身體並用一個新的精靈替換爲動態身體,然後我轉換到新場景。我的代碼在第一次執行時完美運行,但是當這個場景重新加載時,它會在用戶觸及身體時崩潰。Box2D&Cocos2d級別重置問題
我在精靈的userData字段中存儲用於我的精靈的.png文件的文件名。然後,當用戶按下按鈕(觸摸身體)時,檢索它是一件簡單的事情。當我嘗試訪問精靈的userData字段時,隨後重新加載場景時會發生此問題。而不是保存文件名是空的(空)。當我嘗試使用文件名時,這又會使程序崩潰。
我不明白爲什麼它的作品第一次,而不是第二次。我設置了一個斷點並觀察文件名被分配到精靈的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];
}
}
}
每個物體都有不同的紋理,因此每個精靈都有不同的文件名。我所做的解決上述問題的方法是創建我自己的CCSprite子類,並將NSString添加到我用於存儲值的類中。這就像一個冠軍,但我仍然不確定爲什麼它不能使用CCSprite所具有的userData。 – Scooter