본문 바로가기

프로그래밍/cocos2d

animation이 적용된 sprite 여러개 생성하기




//

//  GameLayer.h

//  GameDemo

//

//  Created by cmpak on 5/10/10.

//  Copyright 2010 thefirstgood.com. All rights reserved.

//


#import "cocos2d.h"


@interface GameLayer : CCLayer {

    CGSize winSize;

    

    // 방향 전환에 쓰일 버튼

    // 눌리기 전과 눌렸을 때에 있도록 방향별로 두개씩 만든다.

    CCSprite  *rightSprite;

    CCSprite  *rightPressedSprite;

    CCSprite  *leftSprite;

    CCSprite  *leftPressedSprite;

// 발차기 버튼

    CCSprite  *kickSprite;

    CCSprite  *kickPressedSprite;

    

    BOOL isLeftPressed;

    BOOL isRightPressed;

    

    // 주인공 캐릭터 - 여자 이미지를 사용하지만 prince라고 부르겠습니다.

    CCSprite *princeSprite;

    

    // 주인공 캐릭터의 걷기 애니메이션

    CCAnimate *princeWalkAnimate;

// 주인공 발차기 애니메이션

    CCAnimate *princeKickAnimate;

// 발차기 애니메이션이 진행 중인지 검사하는데 사용합니다.

    BOOL isAnimating;

    

    // 캐릭터

    CCSpriteSheet *enemySpriteSheet;

    

    // 캐릭터 걷기 애니메이션

    CCAnimation   *enemyWalkAnimation;

}


@property (nonatomic, retain) CCSprite  *rightSprite;

@property (nonatomic, retain) CCSprite  *rightPressedSprite;

@property (nonatomic, retain) CCSprite  *leftSprite;

@property (nonatomic, retain) CCSprite  *leftPressedSprite;

@property (nonatomic, retain) CCSprite  *kickSprite;

@property (nonatomic, retain) CCSprite  *kickPressedSprite;

@property (nonatomic, retain) CCSprite  *princeSprite;

@property (nonatomic, retain) CCAnimate *princeWalkAnimate;

@property (nonatomic, retain) CCAnimate *princeKickAnimate;


@property (nonatomic, retain) CCSpriteSheet *enemySpriteSheet;

@property (nonatomic, retain) CCAnimation   *enemyWalkAnimation;


- (void) createBackgroundParallax;

- (void) createArrowButtons;

- (void) createPrinceAndAnimation;

- (void) createEnemyAndAnimation;


- (void) moveBackground;


- (void) startPrinceWalking;

- (void) stopPrinceWalking;


@end


(1) CCAnimate 대신 CCAnimation 변수를 정의했습니다. 각 스프라이트에 특정 애니메이션을 적용하려면 각각의 CCAnimate 객체가 필요합니다. 하나의 공통된 CCAnimate 객체를 여러개의 CCSprite에 적용할 수 없습니다. CCAnimation에 들어있는 애니메이션 정보로 스프라이트에 필요한 CCAnimate 객체를 따로 만듭니다.

(2) CCSprite를 관리하기 위해 CCSpriteSheet 클래스 객체를 만듭니다. CCSpriteSheet 클래스는 같은 스프라이트 시트를 사용해 만드는 스프라이트를 화면에 빠른 속도로 그려내는데 최적화된 노드입니다. 따라서 같은 스프라이트 시트로 만들어진 스프라이트만 자식으로 가질 수가 있습니다. 따라서 CCSprite외 다른 클래스 객체는 자식으로 갖지 못합니다.



//

//  GameLayer.m

//  GameDemo

//

//  Created by cmpak on 5/10/10.

//  Copyright 2010 thefirstgood.com. All rights reserved.

//


#import "GameLayer.h"


#define IMG_WIDTH 1600


enum {

    kTag_Parallax,

    kTag_Enemy,

    kTag_Prince,

    kTag_ControlButtonPressed,

    kTag_ControlButton

};



@implementation GameLayer


@synthesize rightSprite, rightPressedSprite, leftSprite, leftPressedSprite;

@synthesize kickSprite, kickPressedSprite;

@synthesize princeSprite, princeWalkAnimate, princeKickAnimate;

@synthesize enemySpriteSheet, enemyWalkAnimation;


- (id) init {

    if( (self=[super init]) ) {

        // CCLayer 터치이벤트를 처리할 있도록 활성화시킵니다.

        self.isTouchEnabled = YES;

        

        // 화면의 픽셀 크기를 구합니다.

        winSize = [[CCDirector sharedDirector] winSize];

        

        [self createBackgroundParallax];

        [self createPrinceAndAnimation];

        [self createEnemyAndAnimation];

        [self createArrowButtons];

    }

    

    return self;

}


- (void) onExit {

    [super onExit];

    

    // sprite sheet texture 캐시를 모두 지웁니다.   

    // 이상 사용하지않는 캐시를 반드시 지워주세요.

    [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];

}


- (void) createPrinceAndAnimation {

    // 위치정보 파일을 읽어들여 바로 CCSpriteFrame 만들어 캐시에 저장합니다.

    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"prince_walk_trim.plist"];

    

    // 프레임을 담을 Array 만듭니다.

    NSMutableArray *aniFrames = [NSMutableArray array];

    

    // 아주 간단히 프레임을 만들어 배열에 저장할 있습니다. 스프라이트 시트를 만들 사용된

    // 개별 이미지의 파일 이름을 사용하여 개별 프레임을 읽어들입니다.

    for(NSInteger idx = 1; idx <= 15; idx++) {

        CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache

                                spriteFrameByName:[NSString stringWithFormat:@"prince_walk_%02d.png", idx]];

        [aniFrames addObject:frame];

    }

    

    // 프레임으로 CCAnimation 만듭니다 프레임당 시간을 0.05초로 정해줍니다.

    CCAnimation *animation = [CCAnimation animationWithName:@"prince_walk" delay:0.05f frames:aniFrames];

    

    // CCAnimation action CCAnimate 만듭니다.

    CCAnimate *animate = [[CCAnimate alloc] initWithAnimation:animation restoreOriginalFrame:NO];

    self.princeWalkAnimate = animate;

    [animate release];

    

    // 첫번째 프레임을 만들 사용했던 이미지 파일 이름을 사용하여 주인공 sprite 만듭니다.

    CCSprite *sprite = [CCSprite spriteWithSpriteFrameName:@"prince_walk_01.png"];

    self.princeSprite = sprite;

    [self addChild:self.princeSprite z:kTag_Prince tag:kTag_Prince];

    

    // 위치계산이 편하도록 주인공의 anchorPoint 가운데 아래로 잡습니다.

    self.princeSprite.anchorPoint = ccp(0.5, 0);

    

    // 주인공을 화면 가운데 아래에서 13픽셀 위에 위치시킵니다.

    self.princeSprite.position = ccp(winSize.width / 2, 13);

    

    [sprite release];

// 발차기 애니메이션에 쓰일 스프라이트 시트의 위치정보 파일을 읽어들인다.

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"prince_kick_notrim.plist"];

[aniFrames removeAllObjects];

for(NSInteger idx = 1; idx <= 15; idx++) {

        CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache

                                spriteFrameByName:[NSString stringWithFormat:@"prince_kick_%02d.png", idx]];

        [aniFrames addObject:frame];

    }

    

    // 프레임으로 CCAnimation 만듭니다 프레임당 시간을 0.04초로 정해줍니다.

    animation = [CCAnimation animationWithName:@"prince_kick" delay:0.04f frames:aniFrames];

    

    // CCAnimation action CCAnimate 만듭니다.

    animate = [[CCAnimate alloc] initWithAnimation:animation restoreOriginalFrame:NO];

    self.princeKickAnimate = animate;

    [animate release];

}


- (void) createEnemyAndAnimation {

    // 위치정보 파일을 읽어들여 바로 CCSpriteFrame 만들어 캐시에 저장합니다.

    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"enemy_walk.plist"];

    

    // 위치정보 파일과 같은 이름을 가진 스프라이트 시트로 CCSpriteSheet 객체를 만듭니다.

    self.enemySpriteSheet = [CCSpriteSheet spriteSheetWithFile:@"enemy_walk.png"];

    [self addChild:self.enemySpriteSheet z:kTag_Enemy];

    

    // 프레임을 담을 Array 만듭니다.

    NSMutableArray *aniFrames = [NSMutableArray array];

    

    // 아주 간단히 프레임을 만들어 배열에 저장할 있습니다. 스프라이트 시트를 만들 사용된

    // 개별 이미지의 파일 이름을 사용하여 개별 프레임을 읽어들입니다.

    for(NSInteger idx = 1; idx <= 15; idx++) {

        CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache

                                spriteFrameByName:[NSString stringWithFormat:@"zombie_walk_%04d.png", idx]];

        [aniFrames addObject:frame];

    }

    

    // 프레임으로 CCAnimation 만듭니다 프레임당 시간을 0.15초로 정해줍니다.

    CCAnimation *walkAnimation = [[CCAnimation alloc] initWithName:@"enemy_walk" delay:0.15f frames:aniFrames];

    self.enemyWalkAnimation = walkAnimation;

    [walkAnimation release];

    

    // TEMP

    // 임시로 두명의 적을 만들어 주인공 캐릭터의 처음 위치의 왼쪽 오른쪽에 각각 위치시킵니다.

    for(NSInteger idx = 0; idx < 2; idx++) {

        // 첫번째 프레임으로 캐릭터 sprite 만듭니다.

        CCSprite *sprite = [CCSprite spriteWithSpriteFrameName:@"zombie_walk_0001.png"];

        sprite.anchorPoint = ccp(0.5, 0);

        

        if(idx == 0) {

            // 첫번째 적은 화면 중앙에서 왼쪽에

            sprite.position = ccp(winSize.width / 2 - 100, 13);

            sprite.flipX = YES;

        }else {

            // 두번째 적은 화면 중앙에서 오른쪽에 위치시킵니다.

            sprite.position = ccp(winSize.width / 2 + 100, 13);

            sprite.flipX = NO;

        }

        

        // 만들어진 스프라이트를 스프라이트 시트에 넣습니다.

        [self.enemySpriteSheet addChild:sprite];

        

        // 걷기 애니메이션을 시작합니다.

        CCAnimate *walkAnimate = [CCAnimate actionWithAnimation:self.enemyWalkAnimation restoreOriginalFrame:NO];

        [sprite runAction:[CCRepeatForever actionWithAction:walkAnimate]];

    }

}


- (void) createArrowButtons {

    // 왼쪽 화살표

    CCSprite *sprite = [[CCSprite alloc] initWithFile:@"arrow_left.png"];

    self.leftSprite = sprite;

    

    // 기본 anchorPoint 가운데, (0.5, 0.5)이므로 이미지의 가로 세로 크기의 반에 5픽셀의 

    // 여유를 두고 화면 아래에 표시합니다.

    self.leftSprite.position = ccp(10 + self.leftSprite.contentSize.width / 2

                                   self.leftSprite.contentSize.height / 2 + 5);

    

    [self addChild:self.leftSprite z:kTag_ControlButton];

    [sprite release];

    

    // 눌렸을 쓰일 왼쪽 화살표 

    sprite = [[CCSprite alloc] initWithFile:@"arrow_left_s.png"];

    self.leftPressedSprite = sprite;

    

    // self.leftSprite 똑같은 위치에 표시합니다.

    self.leftPressedSprite.position = self.leftSprite.position;

    

    // 눌렸을 때의 화살표를 하위 z-order 넣습니다. 그럼, 위에 같은 크기의 화살표가 

    // 똑같은 위치에 있으니까 가려서 화면상에 보이지 않게됩니다.

    [self addChild:self.leftPressedSprite z:kTag_ControlButtonPressed];

    [sprite release];

    

    // 오른쪽 화살표

    sprite = [[CCSprite alloc] initWithFile:@"arrow_right.png"];

    self.rightSprite = sprite;

    

    // 왼쪽 화살표에서 15픽셀 오르쪽에 위치시킵니다.

    self.rightSprite.position = ccp(self.leftSprite.position.x + self.rightSprite.contentSize.width + 15

                                    self.leftSprite.position.y);

    [self addChild:self.rightSprite z:kTag_ControlButton];

    [sprite release];

    

    // 눌렸을 쓰일 오른쪽 화살표 

    sprite = [[CCSprite alloc] initWithFile:@"arrow_right_s.png"];

    self.rightPressedSprite = sprite;

    

    // self.rightSprite 똑같은 위치에 표시합니다.

    self.rightPressedSprite.position = self.rightSprite.position;

    

    // 눌렸을 때의 화살표를 하위 z-order 넣습니다. 그럼, 위에 같은 크기의 화살표가 

    // 똑같은 위치에 있으니까 가려서 화면상에 보이지 않게됩니다.

    [self addChild:self.rightPressedSprite z:kTag_ControlButtonPressed];

    [sprite release];

// 발차기 버튼

    sprite = [[CCSprite alloc] initWithFile:@"kick.png"];

    self.kickSprite = sprite;

    self.kickSprite.position = ccp(winSize.width - self.kickSprite.contentSize.width / 2 - 5, self.leftSprite.position.y);

    [self addChild:self.kickSprite z:kTag_ControlButton];

    [sprite release];

    // 발차기 버튼 눌렸을

    sprite = [[CCSprite alloc] initWithFile:@"kick_s.png"];

    self.kickPressedSprite = sprite;

    self.kickPressedSprite.position = self.kickSprite.position;

    [self addChild:self.kickPressedSprite z:kTag_ControlButtonPressed];

    [sprite release];

}


- (void) createBackgroundParallax {

    // 이미지로 백그라운드에 쓰일 CCSprite 만듭니다.

    CCSprite *bgSprite1 = [CCSprite spriteWithFile:@"background1.png"];

    CCSprite *bgSprite2 = [CCSprite spriteWithFile:@"background2.png"];

    

    // Transform 사용되는 anchorPoint 왼쪽 아래 귀퉁이 (0, 0) 잡습니다

    bgSprite1.anchorPoint = ccp(0, 0);

    bgSprite2.anchorPoint = ccp(0, 0);

    

    // 위에서 만든 sprite 담을 parent CCParallaxNode 만듭니다.

    CCParallaxNode *voidNode = [CCParallaxNode node];

    

    // 배경 sprite Parallax 넣습니다.

    // parallaxRatio 가로/세로로 움직이는 속도라고 보시면 되겠습니다

    // 우리는 가로로만 움직이므로 y 값을 0으로 줍니다.

    

    // background1.png 파일의 세로 크기가 160 픽셀이기 때문에 positionOffset 이용하여 

    // 화면 위에 위치하도록 좌표를 조정합니다.

    // 뒤쪽에 깔릴 배경인 background1.png 천천히 움직이도록 parallaxRatio x 값을 1보다 작은

    // 0.4 설정합니다.

    [voidNode addChild:bgSprite1 z:0 parallaxRatio:ccp(0.4f, 0) positionOffset:ccp(0, winSize.height / 2)];    

    [voidNode addChild:bgSprite2 z:1 parallaxRatio:ccp(1.0f, 0) positionOffset:CGPointZero];


    [self addChild:voidNode z:kTag_Parallax tag:kTag_Parallax];

}



#pragma mark -

#pragma mark Game Play


- (void) startMovingBackground {

    // 만약 버튼 두개가 눌려졌으면 화면을 이동시키지 않습니다.

    if(isLeftPressed == YES && isRightPressed == YES)

        return;

    

    NSLog(@"start moving");

    [self schedule:@selector(moveBackground)];

    

    // 걷기 애니메이션을 시작합니다.

    [self startPrinceWalking];

}


- (void) stopMovingBackground {

    NSLog(@"stop moving");

    [self unschedule:@selector(moveBackground)];

    

    // 걷기 애니메이션을 멈춥니다.

    [self stopPrinceWalking];

}



- (void) moveBackground {

    // GameLayer 들어있는 parallax node 받습니다.

    CCNode *voidNode = [self getChildByTag:kTag_Parallax];

    

    // 프레임마다 움직일 거리

    CGPoint moveStep = ccp(3, 0);

    

    // 오른쪽 버튼이 눌려졌을 때는 반대로 움직임

    if(isRightPressed)

        moveStep.x = -moveStep.x;

    

    CGFloat bgParallaxRatio = 1.0f;

    

    CGPoint newPos = ccp(voidNode.position.x + moveStep.x, voidNode.position.y);

    

    // 배경이 양쪽 끝에 도달하면 이상 움직이지 않음

    if(isLeftPressed == YES && newPos.x > 0)

        newPos.x = 0;

    else if(isRightPressed == YES && newPos.x < -(IMG_WIDTH - winSize.width) / bgParallaxRatio)

        newPos.x = -(IMG_WIDTH - winSize.width) / bgParallaxRatio;

    

    // 주인공이 화면 가운데 있을 경우에만 배경을 움직입니다.

    CGFloat halfWinWidth = winSize.width / 2;

    if(self.princeSprite.position.x == halfWinWidth)

        voidNode.position = newPos;

    

    

    // 주인공의 방향을 정합니다.

    // flipX 이용하여 하나의 이미지로 방향을 표현할 있습니다.

    if(isRightPressed == YES)

        self.princeSprite.flipX = NO;

    else

        self.princeSprite.flipX = YES;

    

    // 만약 주인공이 화면 가운데 있지않을 경우에는 주인공을 화면가운데까지

    // 이동하게 합니다.

    

    if(isRightPressed == YES && self.princeSprite.position.x < halfWinWidth) {

        // moveStep.x 부호를 바꾼 이유는 배경과 주인공의 움직임 방향이 서로 반대이기 때문입니다.

        self.princeSprite.position = ccp(self.princeSprite.position.x + (moveStep.x * -1),

                                         self.princeSprite.position.y);

        // 가운데 이상 움직이지 않도록 체크합니다.

        if(self.princeSprite.position.x > halfWinWidth)

            self.princeSprite.position = ccp(halfWinWidth, self.princeSprite.position.y);

    }else if(isLeftPressed == YES && self.princeSprite.position.x > halfWinWidth) {

        // moveStep.x 부호를 바꾼 이유는 배경과 주인공의 움직임 방향이 서로 반대이기 때문입니다.

        self.princeSprite.position = ccp(self.princeSprite.position.x + (moveStep.x * -1),

                                         self.princeSprite.position.y);

        

        // 가운데 이상 움직이지 않도록 체크합니다.

        if(self.princeSprite.position.x < halfWinWidth)

            self.princeSprite.position = ccp(halfWinWidth, self.princeSprite.position.y);

    }

    

    // 배경의 끝에 도달하면 배경은 움직이지 않고 주인공을 화면 끝까지 이동시킵니다.

    if(newPos.x == 0 || newPos.x == -(IMG_WIDTH - winSize.width)) {

        CGPoint newPrincePos = ccp(self.princeSprite.position.x + (moveStep.x * -1), self.princeSprite.position.y);

        

        // 주인공이 화면의 왼쪽 또는 오른쪽 끝까지 도달했을 때는 이상 움직이지 않습니다.

        CGFloat halfWidth = self.princeSprite.contentSize.width / 2;

        if(newPrincePos.x <= halfWidth)

            newPrincePos.x = halfWidth;

        else if(newPrincePos.x >= winSize.width - halfWidth)

            newPrincePos.x = winSize.width - halfWidth;

        

        self.princeSprite.position = newPrincePos;

    }

}


- (void) startPrinceWalking {

    NSLog(@"주인공 걷기 시작");

    [self.princeSprite runAction:[CCRepeatForever actionWithAction:self.princeWalkAnimate]];

}


- (void) stopPrinceWalking {

    NSLog(@"주인공 걷기 ");

    [self.princeSprite stopAllActions];

}


- (void) kickAnimateCompleteHandler {

    // 버튼을 다시 보이도록 합니다.

    self.kickSprite.visible = YES;

    [self.princeSprite stopAllActions];

isAnimating = NO;

}


#pragma mark -

#pragma mark Touch Event Handling


// 터치가 버튼 Sprite안에서 이루어졌는지 확인합니다.

- (BOOL) isTouchInside:(CCSprite*)sprite withTouch:(UITouch*)touch {

    // Cocoa 좌표 

CGPoint location = [touch locationInView: [touch view]];

    

    // Cocoa 좌표를 cocos2d 좌표로 변환합니다

CGPoint convertedLocation = [[CCDirector sharedDirector] convertToGL:location];

    

    CGFloat halfWidth = sprite.contentSize.height / 2.0;

    CGFloat halfHeight = sprite.contentSize.height / 2.0;

    

    if(convertedLocation.x > (sprite.position.x + halfWidth) ||

       convertedLocation.x < (sprite.position.x - halfWidth) ||

       convertedLocation.y < (sprite.position.y - halfHeight) ||

       convertedLocation.y > (sprite.position.y + halfHeight) ) {

        return NO;

    }

    

    return YES;

}


// 손가락이 닫는 순간 호출됩니다.

- (void) ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {

// 발차기를 하고 있는 동안에는 움직일 없도록 합니다

// 또한 발차기 애니메이션이 진행되는 동안에는 다시 발차기를 없습니다.

if(isAnimating == YES) {

        NSLog(@"Touch Began ignored");

        return;

    }

    UITouch *touch = [touches anyObject];

    

// 발차기 버튼이 터치되었는지 검사

    if([self isTouchInside:self.kickSprite withTouch:touch] == YES) {

        self.kickSprite.visible = NO;

        // 발차기 공격의 유효 타격거리 안에 들어와 있는 적이 있는지 확인합니다.

        // 주인공 sprite 중심에서 40 픽셀, sprite 중심에서 30픽셀 되는 거리를 발차기 유효거리로 정합니다.

        // 위에서 사용된 수치는 현재 사용중인 이미지의 모양과 크기에 따라서 정한 숫자이므로

        // 자신이 사용할 이미지에 맞게 조정하시면 됩니다

        NSArray *enemies = [self.enemySpriteSheet children];

        for(CCSprite *enemy in enemies) {

            if( (self.princeSprite.flipX == NO  &&

                 self.princeSprite.position.x + 40 >= enemy.position.x - 30 &&

                 self.princeSprite.position.x + 40 <= enemy.position.x + 30) ||

               (self.princeSprite.flipX == YES &&

                self.princeSprite.position.x - 40 <= enemy.position.x + 30 &&

                self.princeSprite.position.x - 40 >= enemy.position.x - 30) )

            {

                NSLog(@"HIT!");

            }

        }

        

isAnimating = YES// 발차기 애니메이션이 진행

        [self.princeSprite runAction:[CCSequence actions:

  self.princeKickAnimate,

  [CCCallFunc actionWithTarget:self selector:@selector(kickAnimateCompleteHandler)],

  nil]];

    }

    // 아래 Boolean 변수 대신에 leftSprite rightSprite visible 값을 직접 사용해도 무방합니다.

    isLeftPressed = NO;

    isRightPressed = NO;

    

    // 터치가 왼쪽 또는 오른쪽 화살표 안에 들어왔는지 확인합니다.

    if([self isTouchInside:self.leftSprite withTouch:touch] == YES) {

        // 왼쪽 화살표를 안보이게 합니다. 그럼 아래에 있던 눌릴 보여지는 이미지가 나타날 것입니다.

        self.leftSprite.visible = NO;

        

        isLeftPressed = YES;

    }else if([self isTouchInside:self.rightSprite withTouch:touch] == YES) {

        // 오른쪽 화살표를 안보이게 합니다.

        self.rightSprite.visible = NO;

        

        isRightPressed = YES;

    }

    

    // 버튼이 눌려졌으면 화면을 움직입니다.

    if(isLeftPressed == YES || isRightPressed == YES)

        [self startMovingBackground];

}


// 손가락을 떼는 순간 호출됩니다.

- (void)ccTouchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {

    // 배경화면을 멈춥니다.

    if(isLeftPressed == YES || isRightPressed == YES)

        [self stopMovingBackground];

    

    // 감춰졌던 버튼이미지를 다시 보이게 합니다.

    if(isLeftPressed == YES)

        self.leftSprite.visible = YES;

    

    if(isRightPressed == YES

        self.rightSprite.visible = YES;

}


// 손가락을 움직일 계속해서 호출됩니다.

- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];

    

    // 손가락이 버튼을 벗어나면 움직임을 중단합니다.

    if(isLeftPressed == YES && [self isTouchInside:self.leftSprite withTouch:touch] == NO) {

        self.leftSprite.visible = YES;

        [self stopMovingBackground];

    }else if(isRightPressed == YES && [self isTouchInside:self.rightSprite withTouch:touch] == NO) {

        self.rightSprite.visible = YES;

        [self stopMovingBackground];

    }

}



//- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {}


#pragma mark -

#pragma mark Memory Release


- (void) dealloc {

    [rightSprite release];

    [rightPressedSprite release];

    [leftSprite release];

    [leftPressedSprite release];

[kickSprite release];

    [kickPressedSprite release];

    

    [princeSprite release];

    [princeWalkAnimate release];

[princeKickAnimate release];

    

    [enemySpriteSheet release];

    [enemyWalkAnimation release];

    

    [super dealloc];

}


@end


(1) CCSpriteSheet 클래스의 Children 함수로 각각의 Sprite를 가져올 수 있습니다.