I am developing game in cocos2d which contains CCSprite of apple,mango and banana shapes. Now i want user to draw line ( i guess through CCMoionStreak) within selected CCSprite (apple,mango or banana).
I have below question:
How can i achieve this draw line functionality? As User can only draw in selected shape.
Please help me out.
Thanks
I'm not sure whether I've understood you correctly but I think you could use something like this:
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector]convertToGL:location];
if (CGRectContainsPoint(sprite rect, location))
{
do your drawing
}
}
It's not clear what you want to happen if the user starts outside the sprite or ends outside the sprite. If this is like the ninja fruit game, detect where the swipe enters and exits the sprite (or approximate if the swipe is too fast). Otherwise, just check that the start and stop points are in the rect.
In either case, use ccDrawline between those points.
Related
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);
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.
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).
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!
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);
}