0

我在让精灵做一个行走动画时遇到了一些麻烦。目前,它只显示动画的第一帧,并且在屏幕上“滑动”。我尝试了一些不同的方法,但没有成功,我需要一些帮助来找出问题所在。

下面是精灵类的头文件:

#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "mainGameLayer.h"

@class MainGameLayer, Waypoint, Tower;

@interface Unit : CCSprite {
    CGPoint myPosition;
    int maxHP;
    int currentHP;
    float walkingSpeed;
    Waypoint *destinationWaypoint;
    BOOL active;
}

@property (nonatomic, assign) MainGameLayer *theGame;

@property (nonatomic, strong) CCSprite *mySprite;
@property (nonatomic, strong) CCAction *walkAction;

@property (nonatomic, assign) float centerToSides;
@property (nonatomic, assign) float centerToBottom;

+(id) nodeWithTheGame: (MainGameLayer *)_game;
-(id) initWithTheGame: (MainGameLayer *)_game;
-(void) doActivate;
-(void) getRemoved;

@end

Sprite类实现文件:

#import "Unit.h"
#import "Tower.h"
#import "Waypoint.h"

#define HEALTH_BAR_WIDTH 20
#define HEALTH_BAR_ORIGIN -10

@implementation Unit

@synthesize theGame;
@synthesize mySprite;

+(id) nodeWithTheGame:(MainGameLayer *)_game
{
    return [[self alloc] initWithTheGame:_game];
}

// BELOW IS THE ORIGINAL INIT FUNCTION, UNMODIFIED, AND IN WORKING CONDITION
-(id) initWithTheGame:(MainGameLayer *)_game
{
    if ((self=[super init])) {

        CCArray *walkFrames = [CCArray arrayWithCapacity:6];
        for (int i = 0; i < 6; i++) {
            CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"hero_walk_%02d.png", i]];
            [walkFrames addObject:frame];
        }
        CCAnimation *walkAnimation = [CCAnimation animationWithSpriteFrames:[walkFrames getNSArray] delay:1.0/12.0];

        theGame = _game;
        maxHP = 40;
        currentHP = maxHP;

        active = FALSE;

        walkingSpeed = 0.5;

        Waypoint * waypoint = (Waypoint *)[theGame.waypoints objectAtIndex:([theGame.waypoints count]-1)];

        destinationWaypoint = waypoint.nextWaypoint;

        CGPoint pos = waypoint.myPosition;
        myPosition = pos;

        self.mySprite = [CCSprite spriteWithSpriteFrameName:@"hero_walk_00.png"];
        self.mySprite.position = pos;
        [self addChild:mySprite];

        mySprite.flipX = 180;

        self.walkAction = [CCRepeatForever actionWithAction: [CCAnimate actionWithAnimation:walkAnimation]];

        [theGame addChild:self];

        [self scheduleUpdate];

    }

    return self;
}

-(void) doActivate
{
    active = TRUE;
    [self stopAllActions];
    [self runAction: self.walkAction];
}

-(void)  update:(ccTime)dt
{
    if(!active)return;

    if([theGame circle:myPosition withRadius:1 collisionWithCircle:destinationWaypoint.myPosition
 collisionCircleRadius:1])
    {
        if(destinationWaypoint.nextWaypoint)
        {
            destinationWaypoint = destinationWaypoint.nextWaypoint;
        }else
        {
            //Reached the end of the road. Damage the player
            [theGame getHpDamage];
            [self getRemoved];
        }
    }

    CGPoint targetPoint = destinationWaypoint.myPosition;
    float movementSpeed = walkingSpeed;

    CGPoint normalized = ccpNormalize(ccp(targetPoint.x-myPosition.x,targetPoint.y-myPosition.y));
    mySprite.rotation = CC_RADIANS_TO_DEGREES(atan2(normalized.y,-normalized.x));

    myPosition = ccp(myPosition.x+normalized.x * movementSpeed,
                     myPosition.y+normalized.y * movementSpeed);

    [mySprite setPosition:myPosition];
}

-(void) getRemoved
{
    [self.parent removeChild:self cleanup:YES];
    [theGame.units removeObject: self];

    // Notify the game that we killed an enemy so we can check if we can send another wave
    [theGame enemyGotKilled];
}

-(void) draw
{
    ccDrawSolidRect(ccp(myPosition.x + HEALTH_BAR_ORIGIN, myPosition.y + 16), ccp(myPosition.x + HEALTH_BAR_ORIGIN + HEALTH_BAR_WIDTH, myPosition.y + 14), ccc4f(1.0, 0, 0, 1.0));

    ccDrawSolidRect(ccp(myPosition.x + HEALTH_BAR_ORIGIN, myPosition.y + 16), ccp(myPosition.x + HEALTH_BAR_ORIGIN + (float)(currentHP * HEALTH_BAR_WIDTH)/maxHP, myPosition.y + 14), ccc4f(0, 1.0, 0, 1.0));
}



@end

这是主要的游戏头文件:

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface MainGameLayer : CCLayer {
}

+ (CCScene *) scene;
- (BOOL) circle:(CGPoint)circlePoint withRadius:(float)radius collisionWithCircle:(CGPoint)circlePointTwo collisionCircleRadius:(float)radiusTwo;
void ccFillPoly (CGPoint *poli, int points, BOOL closePolygon);
- (void) enemyGotKilled;
- (void) getHpDamage;

@property (nonatomic, strong) NSMutableArray *towers;
@property (nonatomic, strong) NSMutableArray *waypoints;
@property (nonatomic, strong) NSMutableArray *units;

@end

最后是主要的游戏实现文件:

#import "MainGameLayer.h"
#import "Tower.h"
#import "Waypoint.h"
#import "Unit.h"


@implementation MainGameLayer

@synthesize towers;
@synthesize waypoints;
@synthesize units;

+ (CCScene *) scene
{
    CCScene *scene = [CCScene node];

    MainGameLayer *layer = [MainGameLayer node];

    [scene addChild: layer];

    return scene;
}

- (id) init
{
    if ((self = [super init])) {
        // Initialize
        self.isTouchEnabled = TRUE;
        CGSize winSize = [CCDirector sharedDirector].winSize;

        // Setting the background (Map)
        CCSprite *background = [CCSprite spriteWithFile:@"layout.png"];
        [self addChild: background];
        [background setPosition: ccp(winSize.width/2, winSize.height/2)];

        [self addWaypoints];

        // In Game Buttons / Menu
        CCMenuItem *sampleButton = [CCMenuItemImage itemWithNormalImage:@"sample.jpg" selectedImage:@"sample.jpg" target:self selector:@selector(samplePurchased:)];

        CCMenu *PurchaseUI = [CCMenu menuWithItems:sampleButton, nil];
        [PurchaseUI setScale:0.5];
        [PurchaseUI setPosition:ccp(63, 51)];
        [PurchaseUI alignItemsHorizontally];
        PurchaseUI.isTouchEnabled = TRUE;
        [self addChild: PurchaseUI];

        // Set up the sprite sheets (Currently in testing)
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"pd_sprites.plist"];
        CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"pd_sprites.pvr.ccz"];
        [self addChild: spriteSheet];
    }

    return self;

}

-(BOOL) canBuyTower
{
    return YES;
}

-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches) {
        CGPoint location = [touch locationInView: [touch view]];

        location = [[CCDirector sharedDirector] convertToGL: location];
        CCLOG(@"X: %f Y: %f", location.x, location.y);

        if ([self canBuyTower]) {
            // Spend the gold later
            Tower *tower = [Tower nodeWithTheGame:self location: location];
            [towers addObject: tower];
        }
    }
}

-(void) addWaypoints
{
    waypoints = [[NSMutableArray alloc] init];

    Waypoint * waypoint1 = [Waypoint nodeWithTheGame:self location:ccp(-25,360)];
    [waypoints addObject:waypoint1];

    Waypoint * waypoint2 = [Waypoint nodeWithTheGame:self location:ccp(73,360)];
    [waypoints addObject:waypoint2];
    waypoint2.nextWaypoint =waypoint1;

    Waypoint * waypoint3 = [Waypoint nodeWithTheGame:self location:ccp(467,360)];
    [waypoints addObject:waypoint3];
    waypoint3.nextWaypoint =waypoint2;

    Waypoint * waypoint4 = [Waypoint nodeWithTheGame:self location:ccp(905,360)];
    [waypoints addObject:waypoint4];
    waypoint4.nextWaypoint =waypoint3;

    Waypoint * waypoint5 = [Waypoint nodeWithTheGame:self location:ccp(1050,360)];
    [waypoints addObject:waypoint5];
    waypoint5.nextWaypoint =waypoint4;
}

-(BOOL) circle:(CGPoint)circlePoint withRadius:(float)radius collisionWithCircle:(CGPoint)circlePointTwo collisionCircleRadius:(float)radiusTwo
{
    float xdif = circlePoint.x - circlePointTwo.x;
    float ydif = circlePoint.y - circlePointTwo.y;

    float distance = sqrt(xdif*xdif + ydif*ydif);

    if (distance <= radius + radiusTwo) {
        return TRUE;
    }

    return FALSE;
}

-(void) samplePurchased: (id)sender
{
    Unit *unit = [Unit nodeWithTheGame: self];
    [units addObject: unit];
    [unit schedule:@selector(doActivate)];
}

@end
4

1 回答 1

0

Eventually this selector runs every frame:

-(void) doActivate
{
    active = TRUE;
    [self stopAllActions];
    [self runAction: self.walkAction];
}

So every frame it stops all actions, and runs a new walk action. Next frame walk action is stopped, then restarted. Rinse and repeat.

Since the walk anim is starting over every frame, it will never have any chance of advancing to the next frame.

于 2013-11-07T02:26:25.757 回答