Note that there are some explanatory texts on larger screens.

plurals
  1. POBox2D & Cocos2d level reset issue
    primarykey
    data
    text
    <p>I have a very simple level that has a single static body (and associated sprite) in it. When the user touches the body, I remove the sprite, destroy the body and replace it with a dynamic body with a new sprite, and then I transition to a new scene. My code works perfectly the first time it is executed, but then when this scene is reloaded it crashes when the user touches the body. </p> <p>I store the filename of the .png file that I use for my sprite in the sprite's userData field. Then when the user presses the button (touches the body) it is a simple matter to retrieve it. The problem is occurring on subsequent reloads of the scene when I try to access the sprite's userData field. Instead of holding the filename it is empty (null). This in turn crashes the program when I try to use the filename.</p> <p>I cannot understand why it works the first time and not the second. I set a breakpoint and watch the filename getting assigned to the sprite's userData field, but it is only retrievable the first time I create the scene. Here is the ccTouchesBegan method. The crash occurs where I try to assign newSpriteFileName because on the second run through oldSpriteFileName is empty.</p> <p>I have just about gone crazy with this one, but I am sure it is something obvious. As always thanks for the help!!</p> <pre><code> (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-&gt;QueryAABB(&amp;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 &amp;&amp; callback.fixtureFound) { //Get a reference to the static body of the button they touched and wake it up b2Body *body = callback.fixtureFound-&gt;GetBody(); body-&gt;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-&gt;GetPosition(); //Get the sprite from the button the user pressed CCSprite *bodySprite = (CCSprite*)body-&gt;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-&gt;GetWorld()-&gt;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-&gt;CreateBody(&amp;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 = &amp;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-&gt;CreateFixture(&amp;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]; } } </code></pre> <p>}</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload