crash when add and remove sprite in cocos2d - cocos2d-iphone

i am doing something wrong, maybe someone could help me .
when app is start i add a sprite as a child,from DB like this :
b_pic=[CCSprite spriteWithFile:basic_pic];
b_pic.position=ccp(160,175);
[self addChild:b_pic];
then i do things,and run animation, so before animation starts, i remove the sprite with :
[b_pic.parent removeChild:b_pic cleanup:YES];
and then i am trying to add it back, BUT its crashes. i add it with :
b_pic=[CCSprite spriteWithFile:#"regular.png"];
b_pic.position=ccp(160,175);
[self addChild:b_pic];
what am i doing wrong here ?
i cant understand this child and parent thing.
i have also tried to remove the sprite with :
[self removeChild:b_pic cleanup:YES];
thanks a lot .

The sprite is an autorelease object in cocos2d. So when you remove the sprite the CleanUp should be NO like so...
[self removeChild:b_pic cleanup:NO];

Related

Dragging a sprite with TouchMoved

I'm using Xcode with Cocos2d version 3.0.
I want to drag sprites around the screen. I've done so successfully using the following code:
(void) touchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [touch locationInNode:self];
sprite1.position=touchLocation;
sprite2.position=touchLocation;
sprite3.position=touchLocation;
sprite4.position=touchLocation;
}
However, sometimes the sprites stop moving after a second. It's not a lag, because they never catch back up with my movement. They just stop! If I let go and start moving my touch again, the sprites start moving fine again / sometimes do the 'freeze thing' again.
Is it a memory issue?
Ok, I'm sure it must be memory. I copied this code onto a simple game with hardly any sprites and it worked perfectly.
Ok I've got it!
I had to unEnable the UISwipeGestureRecognizers while I moved the sprite.
The game was registering my touchesMoved movement as a swipe, and cancelling the touchesMoved commands.

It seems, that method is called twice, when collision happens . cocos2d-iphone

I use this code to show game over menu after _hero sprite and _enemy sprite collide :
if (CGRectIntersectsRect(_hero.boundingBox,_enemy.boundingBox)) {
CCActionCallFunc *_callShowMenu=[CCActionCallFunc actionWithTarget:self selector:#selector(showMenu)];
[self runAction:_callShowMenu];
// EDIT : I also remove both sprites when collision happens.
[_hero removeFromParent];
[_enemy removeFromParent];
}
In _callShowMenu I just stop all actions and show a sprite with half transparent black background image and buttons.
Sometimes when collision happens, it seems to me, that _callShowMenu is called twice, because
background is completely black, like there is the same image behind. Has anyone had a similar problem? (Mostly background image is half-transparent, as it should be).
EDIT:
-(void)showMenu{
[[CCDirector sharedDirector] pause];
CCSprite *_halfTransparentBackground=[CCSprite spriteWithImageNamed:#"halfTransparentBackground.png"];
_halfTransparentBackground.position=ccp(160, 280);
[self addChild:_blackBack z:5];
}
I found a solution using BOOL. Actually everyone uses BOOL in this case, so I don't need to reinvent the wheel.
BOOL doNotCallMeTwice;
Somewhere in the didLoad method:
doNotCallMeTwice=NO;
In the collision detection method:
if (doNotCallMeTwice==NO) {
[self showMenu];
}
And finally:
-(void)showMenu{
doNotCallMeTwice=YES;
}
Possibly, showMenu was called twice(or much more times),because collision detection is in the update method.

CCAction blocks does not works in cocos2d v3?

CCActionCallBlock *call=[CCActionCallBlock actionWithBlock:^
{
NSLog(#"***********done");
}];
[self runAction:call];
Is not working if i put it in another node, and add this node to my main scene .
It only works in my main scene, and not in any other layer added to that scene .
why ?
I just tried it and it works for me, have you called [super onEnter] on your scene?
If that does not work please a bit more code please.

cocos2d remove scene / scene transitions

I started my app using the base code found here in the menus tutorial. In this manner, all of my 'screens' (there are only 5 of them) are implemented as extensions of the CCLayer class, and I have a shared + Scene Manager which works by adding my layer classes as children to a new scene and then using the director to run or replace the currently playing scene:
+(void) goMenu{
// \/---------- Issue right here, next line:
CCLayer *layer = [MenuLayer node];
[SceneManager go: layer];
}
+(void) go: (CCLayer *) layer{
CCDirector *director = [CCDirector sharedDirector];
CCScene *newScene = [SceneManager wrap:layer];
if ([director runningScene]) {
[director replaceScene: newScene];
}else {
[director runWithScene:newScene];
}
}
+(CCScene *) wrap: (CCLayer *) layer{
CCScene *newScene = [CCScene node];
[newScene addChild: layer];
return newScene;
}
The problem I am having is as follows. Let's say I have 2 layers -- 'MenuLayer' and 'GameLayer'. I start off with MenuLayer and later on use [SceneManager go:[GameLayer node]] to transition over to GameLayer. From GameLayer, if I goMenu the app terminates with an 'NSInternalInconsistencyException', reason: 'child already added. It can't be added again' where indicated. I assumed that this is happening because I am trying to add some child sprites in the layer's init code and I am re-adding them again.
My first attempt at debugging was to call [self removeAllChildrenWithCleanup:YES]; within the onExit code of all my layers. That didn't solve the issue. I added in some debugging logs and found out the last line that executes before the script blows up is the indicated one [myLayerClass node];. The init code inside the layer class does not get executed at all -- so it can't be one of the sprites or other children being added that is causing the issue. Again -- remember that everything works the first time I try to open any scene. It's moving back to an opened scene that is currently problematic.
So I tried a different approach -- the approach used in Cocos2D Hello world. I modified all my Layer Classes by adding a singleton +(id) scene method defined as follows:
+(id) scene
{
CCScene *scene = [CCScene node];
myLayerClass *layer = [myLayerClass node];
[scene addChild: layer];
return scene;
}
Added in a [super dealloc] in the dealloc, and encapsulated all my init code within:
-(id) init
{
if( (self=[super init] )) {
// All init code here....
}
}
Of course, all of the goLayerName singleton methods in the scene manager had their contents replaced to match this -- for example:
+(void) goMenu {
//CCLayer *layer = [MenuLayer node];
//[SceneManager go: layerMenu];
CCDirector *director = [CCDirector sharedDirector];
if ([director runningScene])
[director replaceScene:[MenuLayer scene]];
else
[director runWithScene:[MenuLayer scene]];
}
I figured this was the way Cocos2D's hello world worked, it must be good. Also, since each of my scenes would be created once and once alone (and thus every layer would be created once and once alone). No effect whatsoever! The first time I visit any scene it runs as expected. Whenever I try to navigate back to any existing scene, I get the error I mentioned above.
I tried poking around SO and found this, but I am unsure how to properly implement it; also I'm not entirely sure that would even solve the issue -- since the symptoms are different (he just gets a pink screen, whereas my app terminates).
Any assistance would be appreciated.
For anyone who was interested in this question, I was able to resolve the issue.
In summary, any child of a child you add, will not be released with releaseAllChildrenWithClenup. That function will only release the immediate children, so you are responsible to release any nested children yourself.
In my game, I had some characters and their eyes were nested in the head sprites (so that I could just move / rotate the heads). The eyes had their own animation loop but I wanted them to transform with the head. All that worked, but since I had a line of code in init which basically [headSprite addChild:eyeSprite];, I had to also add [headSprite removeChild:eyeSprite]; in the onExit code to dissociate it, followed by releaseAllChildrenWithClenup to remove all of the n=1 level children as well.
Once that was handled, everything worked as advertised.

create a texture from a spritesheet cocos2d

Hey all
Basically all i want is to create CCTexture2D objects from a spritesheet. I can make individual sprites from
charSpriteCur = [CCSprite spriteWithTexture:charSheet.texture rect:CGRectMake(136, 0, 136, 223)];
but i want to get individual textures from a spritesheet so that i can use
[mySprite setTexture:tex];
to change the sprite as required. I dont need it to be an animated sprite i just want to be able to change its texture when i want using a spritesheet.
any ideas with this or what is the best approach?
thanks
g
I don't think this is possible. When I need to do this I instead remove the CCSprite node (which I have setup as a property in my class) and then make a new one. Here is an example:
[self removeChild:[self mySprite] cleanup:YES];
[self setMySprite:[CCSprite spriteWithSpriteFrameName:#"image.png"]];
[mySprite setAnchorPoint:ccp(0,1)];
[mySprite setPosition:ccp(623,872)];
[self addChild:mySprite z:5];