Animating a CCSprite on cocos2d? - iphone

Hey guys, I'm new to cocos2d and iPhone development, im currently trying to create a game like "PapiJump",
What I'm currently having problems with, is animating the character CCSprite in my game,
I have created 3 images of my character, character pointing right, left and middle (http://i53.tinypic.com/ngzoyh.png)
so when the character changes its direction (left or right), it wont "jump" directly to the other direction but will animate..
In my code im using the TouchesEnded method, in this method im setting a variable named "touchState",
so if the user touched the right side of the screen it will set "touchState" to 1, otherwise it sets it to 2 (means left).
then in the "init" method i created a "schedule" that runs another method every 0.5 sec that is named: "updateGame",
the "updateGame" method updates the player's position, it works like that:
player.position = ccp(player.position.x , player.position.y - playerGravity.y);
I've read Ray's tutorial on animating CCSprites but i have no idea how to achieve the result that i need..
Thanks in advance and sorry for my bad english!

NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 4; ++i)
{
[walkAnimFrames addObject: [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: [NSString stringWithFormat:#"spr_fillin_0%d.png", i]]];
}
CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.0333f];
_sprite = [CCSprite spriteWithSpriteFrameName:#"spr_fillin_01.png"];
[_sprite runAction:[CCRepeatForever actionWithAction: [CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]]];
[<CCLAYER OR BATCH NODE> addChild:_sprite];
Edit: Looks like you're talking about just flipping the image around. You can just refetch a sprite with
_sprite = [CCSprite spriteWithSpriteFrameName:#"<New Sprite File>"];
(Or cache them and switch)

Can you clarify your question? If you want to set a different sprite frame, you can use setDisplayFrame:
CCSpriteFrame *spriteFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:frameName];
[sprite setDisplayFrame:frame];
or if you have an animation:
[sprite runAction:[CCAnimate actionWithAnimation:runAnimation restoreOriginalFrame:NO]];
But I feel like the question is a little vague.

if i got your question properly i can suggest two ways to solve your problem:
first you could rotate your object to till it is upside down, and the continue your previous animations using FlipX(or FlipY) flag marks as true or you can add an animation wich animates only characters rotation and when ever it's finnished change the FLipX(or FlipY) status.

Related

What is different between CCAnimate and CCAnimation?

I created a new project with cocos2d, and then create a layer and a sprite.
I am trying to apply an animation to my sprite, and I found some samples about that. But I don't understand the difference between CCAnimation and CCAnimate, so I haven't applied any animation for my sprite yet.
What is the difference between these two and what is the real meaning of them? How to use them?
Can any one explain me about that? Please help me.
Here is code from "Working with Sprites, and Sprite batch nodes" in cocos2d-iphone Programming Guide:
......
NSMutableArray *animFrames = [NSMutableArray array];
for(int i = 1; i < 15; i++) {
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"grossini_dance_%02d.png",i]];
[animFrames addObject:frame];
}
CCAnimation *animation = [CCAnimation animationWithName:#"dance" delay:0.2f frames:animFrames];
[sprite runAction:[CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:animation restoreOriginalFrame:NO]]];
As you can see, you need to use both CCAnimate and CCAnimation to run a CCSpriteFrame-based animation on the sprite. Per description of CCAnimation:
The CCAnimation object contains CCSpriteFrame objects, and a possible delay between the frames. You can animate a CCAnimation object by using the CCAnimate action. Example:
[sprite runAction:[CCAnimate actionWithAnimation:animation]];
Generally speaking, CCAnimation is a wrapper of frame container. CCAnimate is the action that the sprite need to do - in fact it is a subclass of CCAction, which represents an action that a sprite can "run", such as moving, jumping, rotating, etc. You can use its other subclasses to do some kinds of animation on your sprite without creating the frames yourself. Have a try with something like CCFadeIn, CCRotateBy, etc.

How would I make an explosion animation on iOS?

I have an iOS game, and when a ball hits a target it explodes.
What would be the best way to animate this explosion?
If you're looking for something simple.
Make a series of images that animate the explosion. Add those to a UIImageView and start the animation. Something like this:
UIImage *image0 = [UIImage imageNamed:#"explosion0.png"];
UIImage *image1 = [UIImage imageNamed:#"explosion1.png"];
UIImage *image2 = [UIImage imageNamed:#"explosion2.png"];
UIImage *image3 = [UIImage imageNamed:#"explosion3.png"];
myImageView.animationImages = [NSArray arrayWithObjects:image0, image1, image2, image3, nil];
[myImageView setAnimationDuration:0.75f];
[myImageView startAnimation];
For a bouncing ball game, the Cocos2D game- and Box2d physics- (included with Cocos2D) engines are a great way to go.
Ray Wenderlich has three great tutorials on exactly what you want to do:
Intro to Box2D with Cocos2D Tutorial: Bouncing Balls
How To Create A Breakout Game with Box2D and Cocos2D Tutorial: Part 1
How To Create A Breakout Game with Box2D and Cocos2D Tutorial: Part 2
Once you get past the basics of working with Box2d objects, the key step is to create a Contact Listener (as described in the tutorials) which will tell you when you have a collision. Check (by iterating over contacts in your tick method) if the colliding objects are the ones you want for the explosion, and if so add them to a vector of objects to be destroyed (we can't do this while iterating over contacts or we will invalidate the iterator). Remember the coordinates of the collision and set a flag for explosion.
After exiting the loop destroy the bodies and run the explosion effect at the saved position.
Cocos2D has some very nice built-in explosion effects, and the one I am using for my project is CCParticleSun. You can find some screenshots of someone using this effect here. (The curiously named CCParticleExplosion just gave a lot of confetti flying around the screen.)
Here is the relevant portion from some preliminary code I have working, which is mostly from the tutorial. You will still need to do everything else, eg. create and set up your world and bodies in your init method, update positions, apply forces, and draw in your tick method, implement your Contact Listener class, etc. For all this refer to the tutorials.
std::vector<b2Body *>toDestroy;
std::vector<MyContact>::iterator pos;
CGPoint p;
bool explode = FALSE;
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
if ((contact.fixtureA->GetBody() == _moonBody && contact.fixtureB->GetBody() == _moon2Body) ||
(contact.fixtureA->GetBody() == _moon2Body && contact.fixtureB->GetBody() == _moonBody)) {
NSLog(#"Moons collided!");
explode = TRUE;
p = CGPointMake(PTM_RATIO*(_moonBody->GetPosition().x + _moon2Body->GetPosition().x)/2.,PTM_RATIO*(_moonBody->GetPosition().y + _moon2Body->GetPosition().y)/2.);
if (std::find(toDestroy.begin(), toDestroy.end(), _moonBody) == toDestroy.end()) {
toDestroy.push_back(_moonBody);
}
if (std::find(toDestroy.begin(), toDestroy.end(), _moon2Body) == toDestroy.end()) {
toDestroy.push_back(_moon2Body);
}
}
}
std::vector<b2Body *>::iterator pos2;
for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) {
b2Body *body = *pos2;
if (body->GetUserData() != NULL) {
CCSprite *sprite = (CCSprite *) body->GetUserData();
[sprite.parent removeChild:sprite cleanup:YES]; }
world->DestroyBody(body);
}
if (explode)
{
explosion = [[CCParticleSun alloc]initWithTotalParticles:250];
explosion.texture = [[CCTextureCache sharedTextureCache] addImage:#"fire.png"];
explosion.autoRemoveOnFinish = YES;
explosion.startSize = 15.0f;
explosion.speed = 30.0f;
explosion.position = p;
explosion.duration = 1.0f;
[self addChild:explosion z:self.zOrder+1];
}
What you want, then, is a way to create a particle emission system. My suggestion is to use a CAEmitterLayer. Ray Wenderlich has a great tutorial: UIKit Particle Systems in iOS 5 Tutorial
iPhone Programming Tutorial: Animating a Game Sprite
If you need to make an explosion another alternative would to use Cocos2d and do:
CCParticleSun *anExplosion=[CCParticleGalaxy node];
[kk setPosition:ball.position];
[self addChild:anExplosion];
Not really an animation, also, from the question you don't seem to be using Cocos2d, but if you start using it you can do this...

how to implement two different animations on same sprite in cocos2d

I'm confused on using animations in cocos2d... I've a sprite which has 3 types of animations, like a smiley which laughs, cries and winks eyes... And I have separate sprite sheets for each of these animations... how will I be able to use these animations on the same sprite... Can anybody help me please???
Regards,
Suraj
It would be much easier to have all your animations on the same sprite sheet, as, if your sprite is using a CCBatchnode to do it's draw method, you'd have remove it as a child from 1 sheet, and readd it to another.
In your CCSprite subclass, set some CCAction's as instance variables.
In an initialization method, write those actions and store them to the instance variables.
Then when you want to use an animation, tell your sprite to run it.
E.g.
NSMutableArray *smileFrames = [NSMutableArray array];
[smileFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"character_smile.png"]];
[smileFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"character_smile2.png"]];
[smileFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:#"character_smile3.png"]];
CCAnimation *smileAnim = [CCAnimation
animationWithFrames:smileFrames delay:0.2f];
self.smileAction = [CCSequence actions:
[CCAnimate actionWithAnimation:smileAnim restoreOriginalFrame:NO],
[CCCallFunc actionWithTarget:self selector:#selector(smileFinished)],
nil];
Then you would simply use..
[sprite runAction:smileAction];
I have added a CCCallFunc to the end of the animation, as you may want to revert back to an idle animation after it is finished.
Don't forget to release any retained actions when the sprite is deallocated.

How do I animate a sprite using cocos2d?

I have a sprite which will move right,left and jump.
I need to add the action to a animated sprite ie an animated sprite should jump, turn right and left.
Can anyone please tell me how to do it with sample code.
This is quite simple with cocos2d code here:
Sprite *mySprite = [Sprite spriteWithFile#"mySprite.png"];
[mySprite setPosition:ccp(x,y)];
[self addChild:mySprite]; //This displays the Sprite in your layer
Now for the sequence you intend to do...
id moveRight = [MoveBy actionWithDuration:2 position ccp(x+k,y) //Where k is how much to the right you want it to go.
id moveLeft = [MoveBy actionWithDuration:2 position ccp(x-k,y)];
id jump = [JumpBy actionWithDuration:1 position:ccp (x,y) height:1 jumps:1];
id sequence = [Sequence actions:moveRight,moveLeft,jump,nil];
[mySprite runAction:sequence];
Hope that's clear.
-Oscar

Cocos2d - Shooting Game Problem

everyone, I made a shooting game just like 1942(classic shooting game),but here's the question, FPS drops to 5~6 when the fighter shoot out a straight line of bullet,about 7~8 bullets in the screen,Actually, only 8 bullets of player will appear in games, when bullets fly out of the screen they would reset to the fighter's center and become invisible,all bullets are individual sprites, just like:
Sprites * bullet1 = [Sprite spriteWithFile:#"bullet.png"];
........
Sprites * bullet8 = [Sprite spriteWithFile:#"bullet.png"];
Is there any method can store a lots of bullets instead of defining them one by one??
Because enemies may fire too, I can imagine the FPS may get closer to zero.....
Can anyone help me??
you could do something like have a "bullet pool" in there, as you are using cocos, what I would do is to allocate lot's of bullets when I start the game. Check how many bullets do you need approximately, pre allocate those.
When an Entity in your game needs to fire a bullet, it just asks for a bullet to this pool, you give the properties to the "pre allocated" bullet, the bullet appears on the screen, and when it impacts/disappear you then return that bullet to your bullet pool.
if you need some code:
/*You pre-allocate your bullets.*/
for(int i = 0; i < MAX_BULLETS; i++)
{
Bullet *aBullet = [[Bullet alloc] init];
[bulletsArray addObject:aBullet];
[aBullet release];
}
//Then in game when you fire:
Bullet *aBullet = [PoolManager bulletWithSprite:myBulletSprite]; // Where myBulletSprite is PRE allocated and you don't allocate sprites in Game.
You can store the sprites in an array:
NSMutableArray * bulletsBuilder = [[NSArray alloc] init];
for(int i = 0; i < MAX_NUMBER_OF_SPRITES; ++i) {
[bullets addObject:[Sprite spriteWithFile:#"bullet.png"]];
}
NSArray * bullets = [NSArray arrayWithArray:bulletsBuilder];
[bulletsBuilder release];
And access them later using their identifier:
Sprite * spr = [bullets objectAtIndex:spriteIndex];
What's a problem? Use sprite batching! It's kind of special layer that allow you to speed up the rendering of the multiple sprites.
CCSpriteBatchNode* batch = [CCSpriteBatchNode batchNodeWithFile:#"bullet.png"];
Unless you're not Texture Atlas you cannot use different sprites to render them.
Then load one sprite and add to the batch itself as many sprites as you need.
for(;i>10;){[batch addSprite:sprite];}
Add to self.
Core Animation layers are lightweight and should help your performance. You can load the image once and then load the bullets image into the contents of an array of CALayers. Something like this:
// bulletImage is an instance variable
bulletImage = [UIImage imageNamed:#"bullet.png"];
bulletLayers = [[NSMutableArray alloc] init];
for (i = 0; i < 9; ++i)
{
CALayer *bulletLayer = [CALayer layer];
[bulletLayer setBounds:[bulletImage bounds]];
[bulletLayer setPosition:gunBarrelOrigin];
[bulletLayer setContents:(id)[bulletImage CGImage]];
[bulletLayers addObject:bulletLayer];
}
// Use the array of layers.
// ...
You don't specify whether you are using views or layers in your Sprite class, but if you are loading the same image multiple times, you're definitely creating unnecessary overhead.