Cocos2d animation on sprite and detect contact on him - cocos2d-iphone

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.

Related

How to do Android COCOS-2d Menuitem Animation?

Cocos2d-android - I have an animation which has 5 Frames. which will rolling in position. how to make the button rolling like a globe.
I don't know if it can be done like menuitem, but you can make a sprite with forever action(animation of yours 5 frames)and in ccTouchesBegan/ccTouchesEnded you add code to go to another scene or for do an another function after touching on your sprite.
`private CCSprite animatedButton; // Make your sprite visible at begin of your class/layer.`
`animatedButton = CCSprite.sprite("yourImage.png");
CCAnimation buttonAnimation = CCAnimation.animation("", 1f);
buttonAnimation.addFrame("1.png");
buttonAnimation.addFrame("2.png");
addChild(animatedButton, 1);
CCIntervalAction buttonAction = CCAnimate.action(duration, buttonAnimation, false);
animatedButton.runAction(CCRepeatForever.action(buttonAction));
`
Now should be your button(CCSprite) animating. I didnt tried code. And now you just find out in ccTouchesBegan or ccTouchesEnded if your button was touched. If yes, you could do what you want. :)
`if(animatedButton.getBoundingBox.contains(x,y)){
CCScene scene = GameLayer.scene();
CCDirector.sharedDirector().replaceScene(scene);
}`
X and y are coordinates of touch;
You can add animations to menuitem. Like this
CCMenuItem button=CCMenuItemImage.item(image, image, this, "label");
button.setScaleX((winSize.width/8.0f)/image.getTexture().getWidth());
button.setScaleY((winSize.height/8.0f)/image.getTexture().getHeight());
button.setPosition(winSize.width/2,winSize.height+50);
CCAction actionMove42=CCSequence.actions(CCDelayTime.action(0.3f), CCEaseBackOut.action(CCMoveTo.action(1.0f, CGPoint.ccp(0,0))));
button.runAction(actionMove42);

How to after recreate of same sprite, continue touch events

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).

CCAction in box2d world

i'm newbie to both cocos2d and box2d and i've been struggling for two days with this problem : i have a scene with many sprites dropping down (with bodies attached to them). and i have a BackgroundLayer from which i add my background image into the scene (which is not involded into the physics simulation). In my backgroundLayer i'm trying to perform an action on a sprite :
(it blink in the first position and jump directly to the end position )
id flyBubble = [CCEaseInOut actionWithAction:[CCMoveTo actionWithDuration:0.7 position:randomEndPosition]];
but my sprite doesn't respond at all to this action!! my sprite doesn't have any b2body attached and seems like it respond to the tick: method of the physics world (which is in my Main Scene). How can i perform an action to a sprite that doesn't have a b2body attached.
any help would be appreciated!!! thanks
here is the entire code :
CCSprite *bubble = [CCSprite spriteWithFile:#"bubble.png"];
[self addChild:bubble];
CGPoint startPosition = ccp(100, 100);
bubble.position = startPosition;
CGPoint endPosition = ccp(400, 400);
id flyBubble = [CCEaseInOut actionWithAction:[CCMoveTo actionWithDuration:0.7 position:randomEndPosition]];
id remove = [CCCallBlockN actionWithBlock:^(CCNode *node) {
[self removeFruit:(CCSprite *)node];
}];
[bubble runAction:[CCSequence actions:flyBubble, remove, nil]];
I guess source and destination position of sprite is same. So no difference in action.
try like this..
sprite.position = ccp(0,0);
id flyBubble = [CCMoveTo actionWithDuration:0.7 position:randomEndPosition];
[sprite runAction:flyBubble];
i did a little mistake that costs me lot of times. it was in this line of code
id flyBubble = [CCEaseInOut actionWithAction:[CCMoveTo actionWithDuration:0.7 position:randomEndPosition]];
CCEaseInOut doesn't work i don't know why!! when i used CCEaseExponentialInOut it worked perfectly.
Thanks anyway!

Best way for z-ordering sprites on isometric map with cocos2d

after few headaches i figured out that using CCSpriteBatchNode with cocos2d olny allows to z-order sprites added to it as child (which is obvious, now i see..)
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"token_default.plist"];
CCSpriteBatchNode *tokenSpriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"token_default.png"];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"objects_default.plist"];
CCSpriteBatchNode *objectsSpriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"objects_default.png"];
CCSprite *token = [[[CCSprite alloc] initWithSpriteFrameName:#"token_SE.png"] autorelease];
[token setPosition:tokenSpawnPoint];
CCSprite *enemy = [[[CCSprite alloc] initWithSpriteFrameName:#"token_blak_SE.png"] autorelease];
[enemy setPosition:enemySpawnPoint];
CCSprite *houseA = [[[CCSprite alloc] initWithSpriteFrameName:#"house_small.png"] autorelease];
[houseA setPosition:[self randomHousePosition]];
CCSprite *houseB = [[[CCSprite alloc] initWithSpriteFrameName:#"house_big.png"] autorelease];
[houseB setPosition:[self randomHousePosition]];
[tokenSpriteSheet addChild:token];
[tokenSpriteSheet addChild:enemy];
[objectsSpriteSheet addChild:houseA];
[objectsSpriteSheet addChild:houseB];
and since i have to add them to the display list as follows..
[_isoMap addChild:objectsSpriteSheet];
[_isoMap addChild:tokenSpriteSheet];
there is no way i can change the z-order of single tokens between other houses...
they will be always rendered over the house until i change the order of these batch nodes
btw, i can "merge" all sprites' arts in one big single batch node... doing so it became possible to order sprites using sprite's coordinates
[fullSpriteSheet reorderChild:token z:token.position.y];
i'm a little stuck with it...... is there a way to achieve that, having different sprite bacth nodes? or is possible to programmatically merge two batchnodes? (or something like that)
i found KnightFight, a really interesting open project on github by LozArcher.. he used CCSpriteFrame and CCSprite's setDisplayFrame method, instead of batch nodes... but i can't run it since it seems to be an older version of cocos2d (apparently not working with xcode 4)
i found out that changing the vertexZ property of a CCNode (like a CCSprite) it actually changes its Z position (so it will be slightly bigger/smaller, and also translated)
so, in order to arrange on z-index CCSprites with different spriteSheet i had to use reorderChild method (to just change the rendering order) and mostly i need NOT TO USE CCSpriteBatchNode..
after a little refactoring of the above example, i should have:
CCSprite *token = [CCSprite spriteWithSpriteFrameName:#"token_SE.png"];
[token setPosition:tokenSpawnPoint];
CCSprite *enemy = [CCSprite spriteWithSpriteFrameName:#"token_blak_SE.png"];
[enemy setPosition:enemySpawnPoint];
CCSprite *houseA = [CCSprite spriteWithSpriteFrameName:#"house_small.png"];
[houseA setPosition:[self randomHousePosition]];
CCSprite *houseB = [CCSprite spriteWithSpriteFrameName:#"house_big.png"];
[houseB setPosition:[self randomHousePosition]];
[_isoMap addChild:token];
[_isoMap addChild:enemy];
[_isoMap addChild:houseA];
[_isoMap addChild:houseB];
i also added each sprite to a NSMutableArray
and then in a for loop (inside the update scheduled method):
CCSprite *sprite = [mySpritesArray objectAtIndex:i];
[_isoMap reorderChild:sprite z:(_isoMap.mapSize.height - sprite.y)];
hope this could help someone :)
I still think that is not better solution,
if your objects on map are moving dynamically, you can still stuck in z order issues.
I know its very old post, and people keep coming here by google search,
so I am posting solution here.
float lowestZ = tilemap.map.width +tilemap.map.height ;
float currentZ = self.gridLocation.x + self.gridLocation.y ;
int zOrderDecided = lowestZ + currentZ - 1 ;
[self.parent reorderChild:self z:zOrderDecided];
Set the Sprites Z order to it's Y position on the map. Reorder your dynamic sprites in an update loop. Calculate the Z order using the Sprites current Y position and the visible height of the map.
void LocalGameController::SetZOrderForObject(cocos2d::Sprite *object){
int objectZOrder = visibleSize.height - object->getPositionY();
context->reorderChild(object, objectZOrder);
}

How to transfer a CCSprite from one parent to another?

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];