How to make a sprite disappear with various animations on its click? - iphone

I am new to Cocos2D. I am making a simple game for iPhone in which I want my sprite to disappear with some animation. Till now I can make it disappear with the following code:-
-(void)selectSpriteForTouch:(CGPoint)touchLocation
{
for (CCSprite *sprite in targets)
{
if (CGRectContainsPoint(sprite.boundingBox, touchLocation))
{
NSLog(#"sprite was touched");
[sprite.parent removeChild:sprite cleanup:YES];
[[SimpleAudioEngine sharedEngine] playEffect:#"pop.wav"];
[[SimpleAudioEngine sharedEngine] setEffectsVolume:4.0f];
}
}
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for( UITouch *touch in touches )
{
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
[self selectSpriteForTouch:location];
NSLog(#"touch was detected");
}
}
Now I want the sprite to disappear with some animation or any effect. How can I do so?

As an example, this would make your sprite shrink until it disappears then remove it from it's parent:
-(void)selectSpriteForTouch:(CGPoint)touchLocation
...
if (CGRectContainsPoint(sprite.boundingBox, touchLocation))
{
[sprite runAction:[CCSequence actions:
[CCScaleTo actionWithDuration:0.4 scale:0],
[CCCallFuncO actionWithTarget:self selector:#selector(removeSprite:) object:sprite],
nil]];
...//play audio etc
}
....
}
-(void) removeSprite:(CCSprite*) s
{
[s.parent removeChild:s cleanup:YES];
}
For other actions, try CCMoveTo or CCJumpTo or CCRotateBy. You can run several actions at once, so above the runAction: line I provided, try another [sprite runAction:[CCRotateBy actionWithDuration:0.4 angle:360]]

Related

SpriteKit - TouchesMoved continues to report touch outside the sprite?

I have a sprite using a custom SKSpriteNode class added to a scene.
I want to do this effect: suppose I have 3 sprites side by side. I want the sprite to scale a little bit if it is touched or while the finger is touching it and as soon as the finger is not touching it, it should scale back to the original size.
What I mean is this: suppose the user gives a big finger slide from left to right, starting on the first sprite and ending past the last sprite. As the finger is sliding, I want the first sprite to scale up as soon as the finger enters its frame. As the finger continues to slide to right and reaches the second sprite, I want the first one to detect that the finger is not on its area and scale down to its original size. At the same time, the second sprite would scale up, because now the finger is inside its area. At any time the finger leaves the surface during the slide, just after passing the last sprite.
My problem is that I want to do this using logic inside the sprite class but when I implement touchesBegan, touchesMoved, etc., on that sprite's class it is not working because touchesMoved continues to report the finger even if it is not inside its area.
This is my touch logic inside the sprite's class:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
SKAction *scaleUp = [SKAction scaleTo:1.2 duration:0.2];
[self runAction:scaleUp];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self];
// CGPoint convertPT = [self convertPoint:touchLocation fromNode:self.parent];
NSLog(#"%#", NSStringFromCGPoint(touchLocation));
// if (CGRectContainsPoint(self.frame, touchLocation)) {
// NSLog(#"this is never fired?");
// }
}
The NSLog line will always print a location even if the finger is outside the layer...
I want TouchesMoved to stop firing after the finger is outside the sprite.
How do I do that?
I put this in a sub class and got good results.
You will still need some logic for when the begins outside the rect from within the game scene class.
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
SKAction *scaleUp = [SKAction scaleTo:1.2 duration:0.2];
[self runAction:scaleUp withKey:#"action"];
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
UITouch* touch = [touches anyObject];
CGPoint loc = [touch locationInNode:self.parent];
if (![self containsPoint:loc]) {
SKAction *scaleDown = [SKAction scaleTo:1.0 duration:0.1];
[self runAction:scaleDown];
}
else if ([self containsPoint:loc]) {
SKAction *scaleUp = [SKAction scaleTo:1.2 duration:0.1];
[self runAction:scaleUp];
}
}
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self removeActionForKey:#"action"];
SKAction *scaleDown = [SKAction scaleTo:1.0 duration:0.1];
[self runAction:scaleDown];
}
I havent got the subclass method working to my liking, but I did get it working well from the main scene -- a mess of if statements ... but does the job
// add a ivar to scene enforce one zoom spite at a time, SKSpriteNode *_currentZoomRect;
- (void) addSomeBlocks
{
for (int i = 1; i <= 3; i++) {
SKSpriteNode *rect = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(70, 70)];
rect.position = CGPointMake(100 * i , 160);
rect.name = #"inner";
[self addChild:rect];
}
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
UITouch* touch = [touches anyObject];
CGPoint loc = [touch locationInNode:self];
NSArray *nodes = [self nodesAtPoint:loc];
for (SKNode *n in nodes) {
if ([n.name isEqualToString:#"inner"]) {
_currentZoomRect = (SKSpriteNode *) n;
SKAction *scaleUp = [SKAction scaleTo:2.0 duration:0.05];
[n runAction:scaleUp withKey:#"action"];
}
}
}
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
UITouch* touch = [touches anyObject];
CGPoint loc = [touch locationInNode:self];
NSArray *nodes = [self nodesAtPoint:loc];
for (SKNode *n in nodes) {
if ([n.name isEqualToString:#"inner"]) {
if (_currentZoomRect) {
// can only allow one zoom at a time
if (n == _currentZoomRect && !n.hasActions) {
SKAction *scaleUp = [SKAction scaleTo:2.0 duration:0.05];
[n runAction:scaleUp];
}
else if (n != _currentZoomRect) {
SKAction *scaleDown = [SKAction scaleTo:1.0 duration:0.05];
[_currentZoomRect runAction:scaleDown];
SKAction *scaleUp = [SKAction scaleTo:2.0 duration:0.05];
[n runAction:scaleUp];
_currentZoomRect = (SKSpriteNode *) n;
}
}
else {
SKAction *scaleUp = [SKAction scaleTo:2.0 duration:0.05];
[n runAction:scaleUp];
_currentZoomRect = (SKSpriteNode *) n;
}
}
}
if (![nodes count] && _currentZoomRect) {
SKAction *scaleDown = [SKAction scaleTo:1.0 duration:0.05];
[_currentZoomRect runAction:scaleDown];
_currentZoomRect = nil;
}
}
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (_currentZoomRect) {
SKAction *scaleDown = [SKAction scaleTo:1.0 duration:0.05];
[_currentZoomRect runAction:scaleDown];
_currentZoomRect = nil;
}
}

I want to move sprite body when touch point detect

I want to move sprite body when i touch screen but it cant happen...
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
for(b2Body *b=world->GetBodyList();b;b=b->GetNext())
{
CGPoint location=[touch locationInView:[touch view]];
location=[[CCDirector sharedDirector]convertToGL:location];
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
if(b->GetUserData()!=NULL)
{
CCSprite *sprite =(CCSprite *)b->GetUserData();
b->SetTransform(b2Vec2(location.x, location.y), 0);
id action = [CCMoveTo actionWithDuration:0.4 position:CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO)];
[sprite runAction:action];
}
}
}
please help me...
thanks
Please try the below code it would work for you.
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for( UITouch *touch in touches ) {
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
for(b2Body *b=world->GetBodyList();b;b=b->GetNext())
{
if(b->GetUserData()!=NULL)
{
CCSprite *sprite =(CCSprite *)b->GetUserData();
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
b->SetTransform(b2Vec2(locationWorld.x, locationWorld.y), 0);
id action = [CCMoveTo actionWithDuration:0.4 position:CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO)];
[sprite runAction:action];
}
}
}
}
The sprite with the body moves to a location where the touch is Ended.
add self.isTouchEnabled = YES; in your init method

Render texture using Cocos 2d and Box 2d

I have a Cocos2d and Box2D application. I have a image bubble.png. I want to draw a chain of bubbles when the user swipes the screen.
Can anyone tell me how to do this ?
Thanks
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
{
//Add a new body/atlas sprite at the touched location
for( UITouch *touch in touches ) {
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
CCSprite *mist=[CCSprite spriteWithFile:#"bubble.png"];
mist.position=ccp(location.x,location.y);
[self addChild:mist];
}
}
You need to register with the touchdispatcher I think... ( [layer registerWithTouchDispatcher] )
[glView setMultipleTouchEnabled:YES]; (Maybe this is needed for swiping)

Particle engine problem

i am implementing particle engine and here is my code:
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init] ))
{
self.isTouchEnabled = YES;
emitter = [[CCParticleMeteor alloc] init];
emitter.texture = [[CCTextureCache sharedTextureCache] addImage:#"stars.png"];
emitter.position = ccp( 240, 160 );
[self addChild:emitter];
}
return self;
}
-(BOOL) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self ccTouchesMoved:touches withEvent:event];
return YES;
}
-(BOOL) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
CGPoint point = [[CCDirector sharedDirector] convertToGL:location];
emitter.position = ccp(point.x , point.y);
return YES;
}
And Here is the Screen shot:
Here is i want to need:
1-I want to change the direction of effect( Means flame move upward but i want downward).
2-I want to change the color of flame.
Please help if you can.....
1) A quick look at the particle system documentation gives you either angle or gravity to play with - try setting these to different values i.e.
emitter.angle = <the angle you want>
2) Edit stars.png to be the colour you want?

Weird issue with touchesMoved with multiple touches

I have code in place which lets you tap buttons and play a sound for each button, as well as sliding your fingers across the buttons and having each button play it's corresponding sound as you enter the button's area. It's working pretty good, except for a strange bug:
If you press your fingers on two buttons at the same time it will play both sounds initially. However, if you continue leaving your fingers on the button, and then release your fingers off the screen while moving one of them ever so slightly (still within the confines of each button), it will play one of the sounds of the two buttons. How can I prevent this from happening? I only want the sounds to play if you're sliding a finger across the buttons or hitting them initially, not if you're just moving them slightly while hitting two buttons at the same time and then releasing your finger.
Below is my code:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSSet *allTouches = [event allTouches];
touchesCount = [allTouches count];
for(UITouch *t in touches) {
CGPoint location = [t locationInView:t.view];
if(CGRectContainsPoint(soundButton1.frame, location))
{
if (!soundButton1.isHighlighted && touchesCount < 2){
soundID = #"0";
[self playSound];
[soundButton1 setHighlighted:YES];
}
}
else {
[soundButton1 setHighlighted:NO];
}
if(CGRectContainsPoint(soundButton2.frame, location))
{
if (!soundButton2.isHighlighted && touchesCount < 2){
soundID = #"1";
[self playSound];
[soundButton2 setHighlighted:YES];
}
}
else {
[soundButton2 setHighlighted:NO];
}
}
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *t in touches) {
CGPoint location = [t locationInView:t.view];
if(CGRectContainsPoint(soundButton1.frame, location))
{
[soundButton1 setHighlighted:YES];
soundID = #"0";
[self playSound];
}
if(CGRectContainsPoint(soundButton2.frame, location))
{
[soundButton2 setHighlighted:YES];
soundID = #"1";
[self playSound];
}
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *t in touches) {
CGPoint location = [t locationInView:t.view];
if(CGRectContainsPoint(soundButton1.frame, location))
{
[soundButton1 setHighlighted:NO];
}
if(CGRectContainsPoint(soundButton2.frame, location))
{
[soundButton2 setHighlighted:NO];
}
}
}
Try disabling the sounds for a short (very) period. In touchesEnded:withEvent:, check whether it has two touches, then do something like this,
soundDisabled = YES;
You can either request a selector to run after delay
[self performSelector:#selector(enableSound) withObject:nil afterDelay:0.2];
and then
- (void)enableSound {
soundDisabled = NO;
}
Or you could wait for the second finger to go up and then
soundDisabled = NO;