Basically, I'm trying to animate a sprite. When moving right I want one animation to play, and when moving left another to play. Here's my code-- nothing is happening at all, the sprite is merely shown on the screen.
-(void)moveLeft{
[sprite stopActionByTag:0];
NSMutableArray *spriteFrames2 = [NSMutableArray array];
CCSpriteFrame *frame4 = [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:#"KnightSpritesLeft10.png"];
CCSpriteFrame *frame5 = [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:#"KnightSpritesLeft11.png"];
CCSpriteFrame *frame6 = [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:#"KnightSpritesLeft12.png"];
[spriteFrames2 addObjectsFromArray:[NSArray arrayWithObjects:frame4,frame5,frame4,frame6, nil]];
CCAnimation *anim = [CCAnimation animationWithFrames:spriteFrames2 delay:0.15f];
CCAnimate *animate = [CCAnimate actionWithAnimation:anim];
CCRepeatForever *repeat = [CCRepeatForever actionWithAction:animate];
repeat.tag = 1;
[sprite runAction:repeat];
id moveToLeft = [CCMoveTo actionWithDuration:3.0 position:CGPointMake(0, sprite.position.y)];
[sprite runAction:moveToLeft];
}
-(void)moveRight{
[sprite stopActionByTag:1];
CGSize winSize = [[CCDirector sharedDirector]winSize];
NSMutableArray *spriteFrames = [NSMutableArray array];
CCSpriteFrame *frame1 = [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:#"KnightSpritesRight6.png"];
CCSpriteFrame *frame2 = [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:#"KnightSpritesRight4.png"];
CCSpriteFrame *frame3 = [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:#"KnightSpritesRight5.png"];
[spriteFrames addObjectsFromArray:[NSArray arrayWithObjects:frame1,frame2,frame1,frame3, nil]];
CCAnimation* anim = [CCAnimation animationWithFrames:spriteFrames delay:0.15f];
CCAnimate* animate = [CCAnimate actionWithAnimation:anim];
CCRepeatForever *repeat = [CCRepeatForever actionWithAction:animate];
repeat.tag = 0;
[sprite runAction:repeat];
id moveToRight = [CCMoveTo actionWithDuration:3.0 position:CGPointMake(winSize.width, sprite.position.y)];
[sprite runAction:moveToRight];
}
-(id) init
{
if( (self=[super init])) {
[[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:#"KnightImages2.plist"];
sprite = [CCSprite spriteWithSpriteFrameName:#"KnightSpritesRight6.png"];
sprite.position = ccp(240, 180);
[self addChild:sprite];
id actionSequence = [CCSequence actions:[CCCallFunc actionWithTarget:self selector:#selector(moveRight)],[CCCallFunc actionWithTarget:self selector:#selector(moveLeft)], nil];
CCRepeatForever *repeatForever = [CCRepeatForever actionWithAction:actionSequence];
[sprite runAction:repeatForever];
}
return self;
}
The way you've set this up is that the following happens, frame by frame:
Frame 1
execute moveRight
execute moveLeft
Frame 2
execute moveRight
execute moveLeft
Ad infinitum.
Since you're starting the animation all over every time you call moveRight or moveLeft, nothing really happens. You need to wait some time before running another animation for it to actually play. You can use the CCDelayTime action for this:
id actionSequence = [CCSequence actions:
[CCCallFunc actionWithTarget:self selector:#selector(moveRight)],
[CCDelayTime actionWithDuration:2],
[CCCallFunc actionWithTarget:self selector:#selector(moveLeft)],
[CCDelayTime actionWithDuration:2],
nil];
Related
I am using below code to add sprites which will be created after every 1.5 seconds as follows
[self schedule:#selector(addTraget:) interval:1.5];
-(void)addTraget:(ccTime)dt{
CCSprite *target = [CCSprite spriteWithFile:#"img1.png" rect:CGRectMake(0, 0, 80, 36)];
target.position = ccp(-target.contentSize.width/2, 100);
[self addChild:target];
target.tag = 1;
id actionMove = [CCMoveTo actionWithDuration:actualDuration*2.5 position:ccp(winSize.width + (target.contentSize.width/2), actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)];
id sequece = [CCSequence actions:delayTime1, calFun1, delayTime2, calFun2,actionMove, actionMoveDone, nil];
id repeate = [CCRepeatForever actionWithAction:sequece];
[target runAction:repeate];
}
as the addTarget method is scheduled then how to stop this scheduled action after some time of after satisfying a condition?
Only unschedule particular scheduler then use this:
[self unschedule:#selector(addTraget:)];
[self unscheduleAllSelectors]; //For all selectors
or,
[self unschedule:#selector(YOURSELECTOR)]; //For specific selector
I am having problem in stoping action. i have 2 sprite animation 1 is ant and second is grasshopper. WHen i am just calling ants animation it works fine but when i try to run both ant and grasshopper animation it gives me error.
* Assertion failure in -[CCSpriteBatchNode addChild:z:tag:], /Users/zohaib/Downloads/zohaibgame/zohaibgame/libs/cocos2d/CCSpriteBatchNode.m:183
it gives error when antMoveEnded is called.
ants animation code
-(void) walk_Ants
{
// 1) Cache the sprite frames and texture
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
#"ant-animation.plist"];
/// 2) Create a sprite batch node
CCSpriteBatchNode *spriteSheet_ant = [CCSpriteBatchNode
batchNodeWithFile:#"ant-animation.png"];
[self addChild:spriteSheet_ant];
// 3rd Step
// 3) Gather the list of frames
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 24; ++i) {
[walkAnimFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%d.png", i]]];
}
// 4th Step
// 4) Create the animation object
CCAnimation *walkAnim = [CCAnimation
animationWithSpriteFrames:walkAnimFrames delay:0.05f];
// 5th Step
// 5) Create the sprite and run the animation action
self.ants = [CCSprite spriteWithSpriteFrameName:#"1.png"];
_ants.position = ccp(winSize.width, winSize.height/6);
//_ants.position = ccp(459, 16);
self.walkActionAnt = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim]];
[_ants runAction:_walkActionAnt];
[spriteSheet_ant addChild:_ants];
CCLOG(#"Position %#",NSStringFromCGPoint(_ants.position));
[self walkingAnts];
}
-(void) walkingAnts
{
// 2) Set the desired velocity
float antVelocity = 480.0/10.0;
// 3) Figure out the amount moved in X and Y
CGPoint waking_Path = CGPointMake(X_AXIS_ENDINGPATH, _ants.position.y);
CGPoint moveDifference = ccpSub(waking_Path, _ants.position);
// 4) Figure out the actual length moved
float distanceToMove = ccpLength(moveDifference);
// 5) Figure out how long it will take to move
float moveDuration = distanceToMove / antVelocity;
// 7) Run the appropriate actions
//[_ants stopAction:_moveAction];
id restartAntWalk = [CCCallFuncN actionWithTarget:self selector:#selector(antMoveEnded:)];
self.moveActionAnt = [CCSequence actions:
[CCMoveTo actionWithDuration:moveDuration position:waking_Path],
restartAntWalk,
nil];
//self.moveActionAnt.tag = 121;
[_ants runAction:_moveActionAnt];
_movingAnt = TRUE;
}
- (void) antMoveEnded: (ccTime) dt
{
if(_ants.position.x == -50)
{
[_ants stopAction:_moveActionAnt];
//[self stopActionByTag:121];
_movingAnt = FALSE;
[self walk_Ants];
}
}
GrassHopper code ( mantis )
-(void) mantisCome
{
float w_index = arc4random() % 480;
//float h_index = arc4random() % 320;
self.moveActionMantis = [CCSequence actions:
[CCMoveTo actionWithDuration:2 position:ccp(w_index, 63)],
nil];
[_mantis runAction:_moveActionMantis];
[self schedule:#selector(timer:) interval:5];
}
-(void) mantisGo
{
self.moveActionMantis = [CCSequence actions:
[CCMoveTo actionWithDuration:2 position:ccp(-50, 280)],
nil];
[_mantis runAction:_moveActionMantis];
[self unschedule:#selector(timer:)];
[self mantisAnimation];
}
#pragma -mark Mantis Animation
-(void) mantisAnimation
{
// 1) Cache the sprite frames and texture
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
#"mantis-animation.plist"];
/// 2) Create a sprite batch node
CCSpriteBatchNode *spriteSheet_mantis = [CCSpriteBatchNode
batchNodeWithFile:#"mantis-animation.png"];
[self addChild:spriteSheet_mantis];
// 3rd Step
// 3) Gather the list of frames
NSMutableArray *walkAnimFrames_mantis = [NSMutableArray array];
for(int i = 1; i <= 14; ++i) {
[walkAnimFrames_mantis addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%d.png", i]]];
}
// 4th Step
// 4) Create the animation object
CCAnimation *walkAnim_mantis = [CCAnimation
animationWithSpriteFrames:walkAnimFrames_mantis delay:0.05f];
// 5th Step
// 5) Create the sprite and run the animation action
self.mantis = [CCSprite spriteWithSpriteFrameName:#"1.png"];
_mantis.position = ccp(winSize.width+100, winSize.height+100);
_mantis.flipX=YES;
//_mantis.position = ccp(459, 16);
self.walkActionMantis = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim_mantis]];
walkAnim_mantis.restoreOriginalFrame = NO;
[_mantis runAction:_walkActionMantis];
[spriteSheet_mantis addChild:_mantis];
//CCLOG(#"Position %#",NSStringFromCGPoint(_mantis.position));
[self mantisCome];
}
I figured out what was the problem.
when i was creating animation for ant i was using this code
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = 1; i <= 24; ++i) {
[walkAnimFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%d.png", i]]];
}
self.ants = [CCSprite spriteWithSpriteFrameName:#"1.png"];
and when creating animaiton for mantis
NSMutableArray *walkAnimFrames_mantis = [NSMutableArray array];
for(int i = 1; i <= 14; ++i) {
[walkAnimFrames_mantis addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%d.png", i]]];
}
self.mantis = [CCSprite spriteWithSpriteFrameName:#"1.png"];
i was using 1.png for both. self.ant and self.mantis. i created a new plist file and changed png name from 1.png to ant1.png . It works now.
According to this tutorial PVR images seem to be the best format for iOS sprites. However after creating a sprite sheet with Texturepacker and exporting out to this format I cannot get the animation to work in cocos2d.
According to the documentation here I should be using
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"LuckyCompiled.plist"];
But neither the tutorial nor the documentation explain how to do animation, except for this. Which is what the code below is based on.
But this only places the base image onto the layer and does not animate.
CCSprite *sprite = [[CCSprite alloc]init];
sprite.position = ccp(player.contentSize.width/2+40, winSize.height/2+40);
// Obtain the shared instance of the cache
CCSpriteFrameCache *cache = [CCSpriteFrameCache sharedSpriteFrameCache];
// load the frames
[cache addSpriteFramesWithFile:#"LuckyCompiled.plist"];
// It loads the frame named "frame1.png".
// IMPORTANT: It doesn't load the image "frame1.png". "frama1.png" is a just the name of the frame
CCSpriteFrame *frame = [cache spriteFrameByName:#"lucky1.png"];
[sprite setDisplayFrame:frame];
[self addChild:sprite];
NSMutableArray *animFrames = [NSMutableArray array];
for(int i = 1; i < 10; i++) {
CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"lucky%d.png",i]];
[animFrames addObject:frame];
}
NSLog(#"animaframes %#",animFrames);
CCAnimation *animation = [CCAnimation animationWithSpriteFrames:[NSArray arrayWithArray:animFrames]];
[sprite runAction:[CCAnimate actionWithAnimation:animation]];
Answer:
Needed to have a delay otherwise animation wasnt noticeable
[CCAnimation animationWithSpriteFrames:[NSArray arrayWithArray:animFrames]];
should have been (also no need to make is nsarray, mutable is fine)
[CCAnimation animationWithSpriteFrames:frames delay:0.1f];
Here is the code that I tried, it works fine.
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:#"walkFrames.plist"];
player = [CCSprite spriteWithSpriteFrameName:#"f1.png"];
NSMutableArray *frames = [NSMutableArray arrayWithCapacity:8];
for (int i = 1; i < 9; i++) {
NSString *file = [NSString stringWithFormat:#"f%d.png", i];
CCSpriteFrame *frame = [frameCache spriteFrameByName:file];
[frames addObject:frame];
}
CCAnimation *walkAnim =[CCAnimation animationWithSpriteFrames:frames delay:0.1f];
CCAnimate *animate = [CCAnimate actionWithAnimation:walkAnim];
CCRepeatForever *rep = [CCRepeatForever actionWithAction:animate];
player.position = ccp(23, 285);
[player runAction:rep];
[self addChild:player];
I am currently on the brink of throwing my computer at the wall because I cannot figure this out. I have done about 200 Google searches, and every link is clicked up to like page 6. I cannot find an answer. So here's the dirt:
I want my Enemies class to contain a shoot method. Simple enough right? Well, I have the action to move the enemies in the HelloWorldLayer method. I want to find a way to have (some type of) CCAction call that method from the Enemies.m class. Please help! And #Lukman your Object Oriented Programming answer didn't work. Thanks!
EDIT:
Here's what's in HelloWorldLayer.m that is necessary to the answer:
action = [CCSequence actions:
[CCMoveBy actionWithDuration:1 position:ccpMult(ccpNormalize(ccpSub(moveToPoint, buffDude.position)), 75)],
[CCMoveBy actionWithDuration:3 position:ccp(buffDude.position.x,buffDude.position.y)],
nil];
CCCallFuncO *a = [CCCallFuncO actionWithTarget:buffDude selector:(#selector(shoot:)) object:buffDude];
CCSequence *seq = [CCSequence actions:action,a, nil];
CCRepeatForever *repeat = [CCRepeatForever actionWithAction:seq];
[buffDude runAction:repeat];
And here's what is in Enemies.m:
#implementation BigAndStrongEnemy
+(id)enemy {
BigAndStrongEnemy *enemy = nil;
if((enemy = [[[super alloc] initWithFile:#"bigAndStrongEnemy.gif"] autorelease])) {
enemy.hp = 200;
enemy.pointsWorth = 1000;
}
return enemy;
}
-(void)spriteMoveFinished:(id)sender {
CCSprite *b = (CCSprite *)sender;
[self removeChild:b cleanup:YES];
}
-(void)shoot {
CCSprite *b = [CCSprite spriteWithFile:#"bullet.gif"];
b.position = ccp(self.position.x,self.position.y);
[self addChild:b];
[bullets addObject:b];
CGSize winSize = [[CCDirector sharedDirector] winSize];
CGPoint point = CGPointMake((winSize.width - (winSize.width - self.position.x)),0);
[b runAction:[CCSequence actions:
[CCMoveBy actionWithDuration:0.5 position:point],
[CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)],
nil]];
}
-(void)shoot:(id)sender {
BigAndStrongEnemy *e = (BigAndStrongEnemy *)sender;
[e shoot];
}
#end
as far as i understood CCCallFunc is what you need
hmm... hope this works:
id *func = [CCCallFunc actionWithTarget:buffDude selector:#selector(shoot)];
I am trying to make a sprite animate in cocos2D. I believe I have the animation set up, but how do I draw the animating sprite onto the screen? Here is what I have:
id anim = [[[CCAnimation alloc] initWithName:#"char_walking" delay:1/12.0] autorelease];
[anim addFrame:#"run2.png"];
[anim addFrame:#"run1.png"];
[anim addFrame:#"run3.png"];
[anim addFrame:#"run4.png"];
[anim addFrame:#"run3.png"];
[anim addFrame:#"run1.png"];
id myAction = [CCAnimate actionWithAnimation:anim];
id repeating = [CCRepeatForever actionWithAction:myAction];
[character do:repeating];
character = [CCSprite spriteWithSpriteFrame:anim];
character.position = ccp(160, 240);
[self addChild:character];
Thanks in advance,
John
Maybe it was just a cut-and-paste error, but it looks like you're telling the sprite to repeat the animation BEFORE you create it, so the character sprite you are adding to the node never gets the CCAnimate action sent to it.
You're not adding spriteFrames as the addFrame method requires.
with this line:
[character do:repeating];
maybe you're looking for [character runAction:repeating];
character = [CCSprite
spriteWithSpriteFrame:anim];
Here, anim is not a spriteFrame, it's a CCanimation.
basically, you have a few problems.
you could try something like this using zwoptex to create your .plist file:
CCSpriteFrameCache *cache = [CCSpriteFrameCache sharedSpriteFrameCache];
[cache addSpriteFramesWithFile:#"runImages.plist"];
CCSprite *startingImage = [CCSprite spriteWithSpriteFrameName:#"run1.png"];
[self addChild:startingImage];
//create your sprite frames
NSArray *animFrames = [[NSArray alloc] initWithCapacity:6];
[animFrames addFrame:[cache spriteFrameByName:#"run2.png"]];
[animFrames addFrame:[cache spriteFrameByName:#"run1.png"]];
[animFrames addFrame:[cache spriteFrameByName:#"run3.png"]];
[animFrames addFrame:[cache spriteFrameByName:#"run4.png"]];
[animFrames addFrame:[cache spriteFrameByName:#"run3.png"]];
[animFrames addFrame:[cache spriteFrameByName:#"run1.png"]];
//run the animation
CCAnimation *animation = [CCAnimation animationWithName:#"char_walking" delay:1/12.0 frames:animFrames];
id anim = [CCAnimate actionWithAnimation:animation restoreOriginalFrame:NO];
[startingImage runAction:anim];