Hello all cocos2d devs,
I'm trying to trigger different animations based on user input and can't get this to work.
First thing first - I'm new to Obj-C and Cocos2d.
I have PNG image and PLIST file created in Zwoptex. PNG contains images of knight: standing, walking and attacking. PLIST file contains former names of image files and coordinates of them.
The way I setup it inside init method:
// Set Sprite Cache - .plist will tell all about .png atlas
CCSpriteFrameCache *KnightCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[KnightCache addSpriteFramesWithFile:@"Knight.plist"];
// Make standing animation
CCAnimation *knightStandingAnimation = [[CCAnimation alloc] initWithName:@"KnightStandingAnimation" delay:1/10.0];
for ( int i=1; i < 7; ++i ) {
// frame name format: KnightStand1.png .. KnightStand6.png
NSString *frameName = [NSString stringWithFormat:@"KnightStand%i.png", i];
[knightStandingAnimation addFrame:[KnightCache spriteFrameByName: frameName]];
}
// Make walking animation
CCAnimation *knightWalkingAnimation = [[CCAnimation alloc] initWithName:@"KnightWalkingAnimation" delay:1/10.0];
for ( int i=1; i < 9; ++i ) {
// frame name format: KnightWalk1.png .. KnightWalk8.png
NSString *frameName = [NSString stringWithFormat:@"KnightWalk%i.png", i];
[knightWalkingAnimation addFrame:[KnightCache spriteFrameByName: frameName]];
}
// Make attacking animation
CCAnimation *knightAttackingAnimation = [[CCAnimation alloc] initWithName:@"KnightAttackingAnimation" delay:1/10.0];
for (int i=1; i < 10; ++i) {
// frame name format: KnightAttack1.png .. KnightAttack9.png
NSString *frameName = [NSString stringWithFormat:@"KnightAttack%i.png", i];
[knightAttackingAnimation addFrame:[KnightCache spriteFrameByName: frameName]];
}
// Set KnightSprite to animate standing
KnightSprite = [CCSprite spriteWithSpriteFrameName:@"KnightStand1.png"];
// Set standing action
id knightStanding = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:knightStandingAnimation]];
id knightWalking = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:knightWalkingAnimation]];
id knightAttacking = [CCAnimate actionWithAnimation:knightAttackingAnimation];
// Make Knight standing
[KnightSprite runAction:knightStanding];
// position our knight
KnightSprite.position = ccp(100, 150);
// add knight to scene ( self should be a visible CCLayer or CCScene )
[self addChild:KnightSprite];
That's the way I understand it from documentation and few (one) tutorial on animating sprites.
First I setup SpriteFrameCache with name and add to it PLIST file. PLIST file points to different frames inside big PNG file.
Then I create different animations based on frames in that frame cache.
Then I have to initialize main sprite of character with one of the frames inside frame cache.
Then I create actions that play animations
Finally I can setup initial sprite to run action, which runs animation and place it on screen (and add to layer).
Now to keep it simple, let's say I have Buttons: Walk and Attack. I want my knight to make standing animation when nothing is clicked and to perform it's animation when corresponding button is pressed. Whenever player stops pushing button knight should perform standing animation.
I'm trying to implement SneakyInput v0.2 which contains button and joy. Let's just focus on buttons.
//Implement Attack Button
SneakyButtonSkinnedBase *atkBut = [[[SneakyButtonSkinnedBase alloc] init] autorelease];
atkBut.position = ccp(448,32);
atkBut.defaultSprite = [ColoredCircleSprite circleWithColor:ccc4(255, 255, 255, 128) radius:32];
atkBut.pressSprite = [ColoredCircleSprite circleWithColor:ccc4(255, 0, 0, 255) radius:32];
atkBut.button = [[SneakyButton alloc] initWithRect:CGRectMake(0, 0, 64, 64)];
AttackButton = [atkBut.button retain];
AttackButton.isToggleable = YES;
[self addChild:atkBut];
[self schedule:@selector(tick:) interval:1.0f/120.0f];
//Implement Walk Button
SneakyButtonSkinnedBase *wlkBut = [[[SneakyButtonSkinnedBase alloc] init] autorelease];
wlkBut.position = ccp(348,32);
wlkBut.defaultSprite = [ColoredCircleSprite circleWithColor:ccc4(255, 255, 255, 128) radius:32];
wlkBut.pressSprite = [ColoredCircleSprite circleWithColor:ccc4(255, 0, 0, 255) radius:32];
wlkBut.button = [[SneakyButton alloc] initWithRect:CGRectMake(0, 0, 64, 64)];
WalkButton = [atkBut.button retain];
WalkButton.isToggleable = YES;
[self addChild:wlkBut];
[self schedule:@selector(tick:) interval:1.0f/120.0f];
And I have "tick" method:
-(void)tick:(float)delta {
// I also have joystick in my code and it's working but let's focus on buttons for now to keep it as simple as it can be
[self applyJoystick:Joystick toNode:KnightSprite forTimeDelta:delta];
}
To make this work I have to add to .h file this code:
@class SneakyJoystick;
@class SneakyButton;
// Practice Arena Layer
@interface PracticeArena : CCLayer {
SneakyJoystick *Joystick;
SneakyButton *AttackButton;
SneakyButton *WalkButton
CCSprite *KnightSprite;
}
This is just a variation of sample code Sneaky provided. It isn't self explanatory enough for me to understand it completely.
I do understand it adds two buttons to layer and setup how they look. How they work is written inside button.m file provided (I set it up to be toggle button). I also understand that tick callback is running and listening for user input.
Here is my problem. I can't get it to work.
I know about stopAllActions
If I modify tick method to check the value of buttons it ether doesn't compile, doesn't do anything or just crashes the app.
-(void)tick:(float)delta {
if (AttackButton.value == 1){
[KnightSprite stopAllActions];
[KnightSprite runAction: knightAttacking];
}
else {
[KnightSprite stopAllActions];
[KnightSprite runAction: knightStanding];
}
if (WalkButton.value == 1){
[KnightSprite stopAllActions];
[KnightSprite runAction: knightWalking];
}
else {
[KnightSprite stopAllActions];
[KnightSprite runAction: knightStanding];
}
[self applyJoystick:leftJoystick toNode:text forTimeDelta:delta];
}
I thnik I should add something to .h file, like this:
CCAction *knightAttacking;
But I don't know what exactly. I'm new to Obj-C and Cocos2d (and prgraming for that matter) I didn't found any tutorials or sample code about using different animations for same sprite based on user input so I work like I'm blind.
I tried to NSLog inside those ifs to see if code even gets there and console log is empty. That is strange since buttons do change color when I touch them and it is not too much changed from sample Sneaky provided.
I tried to use simple CCMenu with 2 CCMenuItems just to check if I can trigger those actions (first stopAllActions and then runAction) and this just stops running animation.
I'd really appreciate some help. I'm not asking for code (but it'd be much much much appreciated), but rather for direction, or what APIs to use, or in general how to do this. Keep in mind I'm new to all of this.