i have 2 layers and on ccTouchMoves event i have to destroy and recreate sprite to move from 1st layer to 2nd
i did this something like that
-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
sprite = [CCSprite spriteWithFile:#"file.png"];
[[self parent] addChild: sprite]
if (sprite)
{
[sprite ccTouchBegan:touch withEvent:event];
// [character ccTouchMoved:touch withEvent:event];
}
[self removeFromParentAndCleanup:true];
}
sprite created and called method ccTouchBegan but after that method everything is terminate
how to call ccTouchMoved and ccTouchEnd just like simple touch event
If it's the same sprite, why destroy and recreate it? You can just keep on using the same sprite. In Kobold2D I added this method in a CCNode category to transfer ownership of a node from its current parent to a different parent:
-(void) transferToNode:(CCNode*)targetNode
{
CCNode* selfNode = [self retain];
[self removeFromParentAndCleanup:NO];
[targetNode addChild:selfNode z:selfNode.zOrder tag:selfNode.tag];
[selfNode release];
}
The important part is to remove the node (your sprite) from its current parent without cleaning up, so that schedulers and actions keep running. Then just add it as child to a different node (your 2nd layer).
Related
I am adding a new layer to a scene. The new layer is loaded from a ccb file which includes buttons:
[[CCDirector sharedDirector] pause]; //pauses current scene
CCScene *pauseMenue = [CCBReader loadAsScene:#"Pause"];
pauseMenue.positionType = CCPositionTypeNormalized;
pauseMenue.position= ccp(0.5,0.5);
[self addChild:pauseMenue]; //adds the pause Layer
How do I get the buttons to work? Using the CCControl Selector doesn't seem to work…
-Pause.ccb doesn't consists of further ccb files.
-Pause.ccb has its custom class in which I tried to implement the selectors.
I have my main scene, above it i set a new layer with CCLayer ,this layer has a button.
but when i hit that button (CCMenu), the layer behind it is also get the touches and do stuff.
I want to enable ONLY the upper layer touches, not the one under it .
How can i do that ? (setting touch priority ? how ? )
edit:
my layer is like that :
-(CCLayer*)showHelpLayer
{
self.isTouchEnabled=YES;
[[CCDirector sharedDirector].touchDispatcher addTargetedDelegate:self priority:-256 swallowsTouches:YES];
...
...
[self addChild:menu];
[menu setHandlerPriority:-257];
return self;
}
and i am adding it to the main scene like that :
helpLayer *hlp=[[helpLayer alloc]init];
[hlp showHelpLayer];
[self addChild:hlp z:100];
you could toy with priorities, but it gets nasty. I only do that in very very specific, well contained circumstances. The best approach is to disable input on your "underneath scene(s)" before you push the new layer and control objects.
If you chose to play with priorities, remember that all menus default to this priority (cocos2D 2.xx) :
kCCMenuHandlerPriority = -128,
so if you play with priority, i would put the layer at -256 (swallowing touches) and setHandlerPriority to -257 for your menu. So anything that falls through your menu is caught by the layer and swallowed (ie not passed 'below').
example for priority approach. The fly-through menu is a class that extends CCNode and does this onEnter, after creating all menu objects in the init method :
- (void)onEnter {
[super onEnter];
MPLOGDEBUG(#"");
[[CCDirector sharedDirector].touchDispatcher addTargetedDelegate:self priority:-256 swallowsTouches:YES];
[_backMenu setHandlerPriority:-257];
[_toggleOptionsMenu setHandlerPriority:-257];
[_dialogMenu setHandlerPriority:-257];
[_labelMenu setHandlerPriority:-257];
}
I know how to detect contact on all of my sprites that on screen .
I also know how to run animation forever on a sprite .
But when puting together the code for animation, with sprite sheet- you dont actually add the sprite as a child, but ONLY the sprite-sheet, than the sprite is a child of the sprite-sheet.
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"parrot.plist"];
CCSpriteBatchNode *spriteSheet = [ CCSpriteBatchNode batchNodeWithFile:#"parrot.png"];
fireBall=[CCSprite spriteWithSpriteFrameName:#"parrot1.png"];
fireBall.position=point;
[spriteSheet addChild:fireBall];
[self addChild:spriteSheet];
//here animation action perform on fireBall
In that case when looking for the fireBall for contact detection - you cant find him because he is not added as a child of the scene ,but of the sprite sheet.
How can i detect that sprite later on my code ? or there is another constellation to set the sprite sheet ?
thanks
You can get your fireBall sprite normally, like any other sprite...
There's some ways:
1) Create a property for your fireBall sprite:
#property (nonatomic, retain) CCSprite *fireBall;
And create and use it using self.fireball:
self.fireBall=[CCSprite spriteWithSpriteFrameName:#"parrot1.png"];
...
CGPoint fireBallPosition = self.fireBall.position;
2) Add fireBall as child on spriteSheet using tag, and get it back using the same tag.
[spriteSheet addChild:fireBall z:0 tag:1];
...
theFireBall = [spriteSheet getChildByTag:1];
But keep in mind that the fireBall position is relative of their parent, spriteSheet. So, if you move spriteSheet, you will also move spriteSheet.
-(void) redafter1
{
red = [CCMenuItemImage
itemFromNormalImage:#"red.png" selectedImage:#"redclick.png"];
red.position = ccp(175, 725);
redMenu = [CCMenu menuWithItems:red, nil];
redMenu.position = CGPointZero;
redMenu.scale = .75;
[self addChild:redMenu z:10];
}
How would I go about animating this object to move to another location on the screen? I am very new to this, please be basic in your explanation.
If you want to animate CCNode (this is base class of all cocos2d objects such as layers, sprites, labels, menuitems, etc.), you have to use actions mechanism. To move object, use CCMoveTo, CCMoveBy actions with runAction: method.
id moveAction = [CCMoveTo actionWithDuration: animationDuration position: targetPosition];
[nodeToAnimate runAction: moveAction];
In your case if you will run action on the object right after adding it to the some parent, that is visible (your scene or other visible parent), action will be started right after object appear.
You add [redMenu runAction:[CCMoveTo actionWithDuration:time position:place]]; (you choose time and position) at the end of your redafter1 function so when the parent method is eventually called by a method such as init your menu will move.Remember you cannot move a CCMenuItemImage because it's locked to the CCMenu's position. You have to move the CCMenu itself.Hope this was helpful.
I have a CCSprite called sprite that is a child of a CCLayer called movingLayer that is itself a child of the current CCLayer running my game logic, so it is self in this case. movingLayer is moving back and forth across the screen in a repeat forever action and sprite is riding along on it. I want to get sprite to "get off" of movingLayer and "get on" to self where it can do some actions of its own.
When I try to do this, I need to tell movingLayer to remove sprite and self to add sprite. This is what I did...
- (void)attack:(id)sender
{
[sprite stopAllActions];
[movingLayer removeChild:sprite cleanup:YES];
[self addChild:sprite z:1];
CGFloat distance = ccpDistance(sprite.position, ccp(sprite.position.x, -sprite.contentSize.height/2));
id goDown = [CCMoveTo actionWithDuration:distance/moveDuration position:ccp(sprite.position.x, -sprite.contentSize.height/2)];
id repeatDown = [CCRepeatForever actionWithAction:[CCSequence actions:[CCMoveTo actionWithDuration:0 position:ccp(sprite.position.x, sprite.contentSize.height/2+self.contentSize.height)], [CCMoveTo actionWithDuration:moveDuration position:ccp(sprite.position.x, -sprite.contentSize.height/2)], nil]];
id attackAction = [CCSequence actions:goDown, repeatDown, nil];
[sprite runAction:attackAction];
}
I think stopAllActions is redundant, but that's not the problem. If I remove sprite from movingLayer before adding it to self I crash for accessing a zombie, and if I try to add it to self first, I crash for trying to add something already added.
Have you tried setting cleanup to NO?
Alternatively, try to retain sprite before you remove it from movingLayer, then release it when you're done with it:
[sprite retain];
[movingLayer removeChild:sprite cleanup:YES];
[self addChild:sprite z:1];
[sprite release];