Can't get sprite position - cocos2d-iphone

I have somewhere in my code something that I have done so many times, but now I can't!
for (b2Body* bo = world->GetBodyList(); bo; bo = bo->GetNext())
{
CCSprite *tempSprite = (CCSprite *) bo->GetUserData();
NSLog(#"%f",tempSprite.position.x); //crashes in this line.
I am counting the bodies on my world and I can see i have 22 of them, but every time i try to do somthing with: tempSprite.position.x it crashes!
I can also print this:
if(tempSprite != NULL)
NSLog(#"YES");
Why can't I get the position?
My world is working great; the contact listener is doing just fine; can't understand that.
any help ?

solved but not clearly why
i did
[badBondSheet1 removeChild:actora cleanup:YES];
[self removeChild:actorb cleanup:YES];
[self shiftEnemies:touchPointA]; // calls the code that i have posted
when shiftEnemies is the function that i have posted-that runs on all the bodies.
i have corrected to:
[self shiftEnemies:touchPointA];
[badBondSheet1 removeChild:actora cleanup:YES];
[self removeChild:actorb cleanup:YES];
and it works.
that was because i was running over my bodies, which some of them didnt have a userData, because i already cleaned up the sprite !
so you have to destroy body and clean the sprite and then run over your bodies.
conclusion: DO NOT CLEAN YOUR SPRITE, AND DO SOMETHING ELSE BEFOR YOU DESTROY YOUR BODY !
sounds reasonable ?

Related

How to push and pop scenes properly in Cocos2D v3.x

I push a preloaded scene B onto scene A like this. The root node in the scene B has an animation that runs for ~2 seconds, and I want scene B to be popped when the animation is done. I think it should work like below. However it crashes on popScene. Does push/pop really work in Cocos2D v3?
SceneRedroom* sceneredroom = (SceneRedroom*)[self.ccscenewithSceneredroom getChildByName:#"SceneRedroom" recursively:NO];
[sceneredroom.animationManager setCompletedAnimationCallbackBlock:^(id sender) {
[[CCDirector sharedDirector] popScene];
}];
[[CCDirector sharedDirector] pushScene:self.ccscenewithSceneredroom];
The crashes I get are fairly random. It seems like some things are incorrectly deallocated or similar when pushing and/or popping scenes.
After further research, I managed to find a solution to the problem I was having through this post. I removed the CCDirector pause and resume in my pauseGame and resumeGame methods then added this:
//pause
[sprite.actionManager pauseTarget:sprite];
//resume
[sprite.actionManager resumeTarget:sprite];
This stopped the animation and kept the "paused" state even if the game is closed then reopened and I didn't even need to play with the AppDelegate class :). I hope this helps others too.
UPDATE: Just in case anybody else is creating a sprite using a loop, here's how I managed to create the pause and resume function for it:
[sprite.actionManager pauseAllRunningActions];
[sprite.actionManager resumeTargets:[NSSet setWithArray:spriteArray]];
note the difference between the two (resumeTarget and resumeTargets) then since resumeTargets would ask for NSSet, I simply passed the array objects into a NSSet with the above code.
void PauseScene::goToMainMenuScene(cocos2d::Ref *sender)
{
Director::getInstance()->resume();
auto scene = MainMenuScene::createScene();
Director::getInstance()->replaceScene(TransitionFade::create(TRANSITION_TIME, scene));
}
void PauseScene::resumeScene(cocos2d::Ref *sender)
{
Director::getInstance()->popScene();
}
void PauseScene::restartScene(cocos2d::Ref *sender)
{
Director::getInstance()->resume();
auto scene = GameScene::createScene();
Director::getInstance()->replaceScene(TransitionFade::create(TRANSITION_TIME, scene));
}

cocos2d v3 chipmunk collision method not firing

ok so i've been messing around with chipmunk a bit, and i can get two sprites to bounce off of each other, but when i try to use the following method, it never fires,
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair tower:(CCNode *)nodeA BG:
(CCNode *)nodeB
{
NSLog(#"HELLO");
return YES;
}
Heres where I create the physics node:
_physics = [CCPhysicsNode node];
_physics.debugDraw = YES;
[self addChild:_physics z:1];
_physics.collisionDelegate = self;
I use this code to create the first sprite:
background = [CCSprite spriteWithImageNamed:gameLevelImage];
[background setPosition:ccp(winSize.width/2,winSize.height/2)];
background.physicsBody.collisionType = #"BG";
background.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:50 andCenter:self.position];
and this for the other :
tower = [[TowerType alloc] initWithTheGame:self location:ccp(winSize.width/2, winSize.height/2)];
[towers addObject:tower];
[self MenuItemsVisible];
tower.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:50 andCenter:tower.position];
tower.physicsBody.collisionType = #"tower";
I also have the protocol in the h file.
if anyone knows whats happening help would be greatly appreciated. (:
First of all, are both bodies under the same CCPhysicsNode?
Second, ccPhysicsCollisionBegin is just called when the collision BEGIN, so as both of your bodies are one over the other and they aparenttly will move together due to gravity the collision will never begin, because they started colliding. The cycle for collision evaluation is:
ccPhysicsCollisionBegin: called once both bodies start colliding
ccPhysicsCollisionPreSolve: called every frame update, before physics calculations
ccPhysicsCollisionPostSolve : called every frame, after physics calculations
ccPhysicsCollisionSeparates: called once they separate
Make sure your sprites are allocated properly before you try to set the collisionType. That was the issue for me in my similar case.

a SPECIFIC sprite- touch detection

since i havnt got an answer in my previos post, and no one solve that problem , i am asking this again. there is no 1 explanation regarding this.
i need to detect a sprite touch, a SPECIFIC one. in cocos2d+box2d.
lets say i have sprite CCSprite *ran that has a body, BUT , i have many of it .
if i detect a touch with the ccTouchesBegan , and use the if(CGRectContainsPoint(particularSpriteRect, currentPosition))
i will detect the touch in ran but i dont know who ran is this from all, and i need to destroy than specific ran , which i cant know who it was .
i find the best way to do that, as i do with contact listener that gives me the specific sprite user data :
CCSprite *actora = (CCSprite*)bodyA->GetUserData();
CCSprite *actorb = (CCSprite*)bodyB->GetUserData();
and then i know that actora is what needs to be destroy cause i have his user data.
[self removeChild:actora cleanup:YES];
so , again , i need to detect a sprite touch and KNOW who it was,cause i have many ran's.
i guess its something needs to involve the userData .
any direction please ?
thanks alot.
ok, i have got it :
this is what i do, to destroy the specific body, different from what was said here :
put the next code in the touch method :
CGPoint currentPosition = [touch locationInView: [touch view]];
currentPosition = [[CCDirector sharedDirector] convertToGL: currentPosition];
b2Vec2 locationWorld = b2Vec2(currentPosition.x/PTM_RATIO, currentPosition.y/PTM_RATIO);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
b2Fixture *bf1 = b->GetFixtureList();
if (bf1->TestPoint(locationWorld))
{
CCSprite *tempSprite = (CCSprite *) b->GetUserData();
if (tempSprite .tag==2 || tempSprite .tag==3)
{
[self removeChild:tempSprite cleanup:YES];
world->DestroyBody(b);
}
}
}
here if you touch the right sprite(tagged) , it get destroyed .

Repeatedly move a box2d body in a similar way to moving CCSprites with CCRepeatForever

I've got a problem with my current project.
What I'd like to do is make a b2Body move up and down repeatedly. I already know how to do this with a CCSprite:
[paddle runAction:[CCRepeatForever actionWithAction:
[CCSequence actions:
[CCMoveTo actionWithDuration:1.0 position:ccp([paddle position].x,[paddle position].y+40)],
[CCMoveTo actionWithDuration:1.0 position:ccp([paddle position].x,[paddle position].y)],
nil
]]];
Can anybody help me do the same thing with a b2Body?
Thanks in advance!
You will have to implement the sequence yourself, which involves:
keeping track of the current target position
from the current position of the body, detect whether it has reached the target
if it has, change the target position
apply force, impulse or set velocity as necessary to move the body
You might be able to extend CCMoveTo to make your own class to do this... I would look into that first.
i've got it dude,
in almost explanation, every CCsprite move depend on b2body movement -that movement is placed at 'tick' method-.
in my case, i reverse that way, i move b2body according to CCsprite movement on tick method, so i give these code on tick method:
for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {
if (b->GetUserData() != NULL) {
CCSprite *sprite = (CCSprite *)b->GetUserData();
if (sprite.tag == 4 || sprite.tag == 5) {
b2Vec2 b2Position = b2Vec2(sprite.position.x/PTM_RATIO,
sprite.position.y/PTM_RATIO);
float32 b2Angle = -1 * CC_DEGREES_TO_RADIANS(sprite.rotation);
b->SetTransform(b2Position, b2Angle);
}
}
}

not working - Box2D

I am using tilemap in my box2D game in which I have created powers. When the player hits the power, a score label is displayed on the screen. Along with this I want to remove that power from the tilemap when player hits it. I have displayed label but I am unable to remove the power. Here is some code :
In ContactListener I am calling the method which removes the power from tilemap :
void ContactListener::BeginContact(b2Contact *contact) {
else if(actorA.tag==obj.gamePower.tag) //obj is a DataClass object.
{
[GameScene addPointLabel]; // For displaying score label
[GameScene removePower:actorA];
}
+(void)removePower:(id)sender
{
GameScene *obj=[[GameScene alloc]init];
CCSprite *sprite = (CCSprite *)sender;
[obj removePowerFromScene:sprite];
[obj release];
}
-(void)removePowerFromScene:(id)sender
{
CCSprite *sprite = (CCSprite *)sender;
[self removeChild:sprite cleanup:YES];
}
I have created an object layer on tilemap to display power. But somehow, I am unable to remove it. Can someone help me?
If power is a CCNode why don't you remove it with [power removeFromParentAndCleanup:YES] ?
The (removePower:) does remove nothing because it creates a new scene and remove the sprite from that scene where the sprite does not belong to.
Another notice, be careful with contact listener. Removing o node in BeginContact is potential of crash. Let imagine the case that powerA contacts with both actor1 and actor2. The first call to BeginContact with powerA and actor1 removes powerA, so subsequent call to BeginContact with powerA envolved will crash !