CCTargetedTouchDelegate를 사용하면 ccTouchBegan 메서드에 발생한 터치 이벤트를 하나씩 넘겨주고 조건을 만족하는 터치 이벤트만 골라서 다른 메서드에 전달 합니다.
각 터치 이벤트를 사용할 지 말지는 ccTouchBegan에서 자신의 필요에 따라 구현하면 됩니다.
여기서는 방향 버튼에서 발생한 터치 이벤트만 사용하게 구현합니다.
/
// 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 = 0,
kTag_ArrowButtonPressed = 1,
kTag_ArrowButton = 2
};
@implementation GameLayer
@synthesize rightSprite, rightPressedSprite, leftSprite, leftPressedSprite;
- (id) init {
if( (self=[super init]) ) {
// CCLayer가 터치이벤트를 처리할 수 있도록 활성화시킵니다.
self.isTouchEnabled = YES;
// 화면의 픽셀 크기를 구합니다.
winSize = [[CCDirector sharedDirector] winSize];
[self createBackgroundParallax];
[self createArrowButtons];
}
return self;
}
// CCTargetedTouchDelegate를 이용하기 위해서는 registerWithTouchDispatcher 메소드를 override하여야 합니다.
// addTargeredDelegate를 self로 설정하였기 때문에 GameLayer안에서 터치이벤트를 핸들링하겠다는 말입니다.
- (void) registerWithTouchDispatcher {
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
- (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_ArrowButton];
[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_ArrowButtonPressed];
[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_ArrowButton];
[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_ArrowButtonPressed];
[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)];
}
- (void) stopMovingBackground {
NSLog(@"stop moving");
[self unschedule:@selector(moveBackground)];
}
- (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;
voidNode.position = newPos;
}
#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;
}
#pragma mark StandardTouchDelegate
/*
// 손가락이 닫는 순간 호출됩니다.
- (void) ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
UITouch *touch = [touches anyObject];
// 아래 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 TargetedTouchDelegate
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
BOOL ret = NO;
// 아래 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];
ret = YES;
}
return ret;
}
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
// 손가락이 버튼을 벗어나면 움직임을 중단합니다.
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)ccTouchEnded:(UITouch *)touch 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)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event {}
#pragma mark -
#pragma mark Memory Release
- (void) dealloc {
[rightSprite release];
[rightPressedSprite release];
[leftSprite release];
[leftPressedSprite release];
[super dealloc];
}
@end