이번에는 cocos2d Touch Event  처리 방법이다.

터치 이벤트는 두가지 방법이 있는데, 하나는 싱글 터치 처리 방식이고, 나머지 하나는 멀티 터치 처리 방식이다.

게임을 할때, 좌우 방향 버튼도 있고, 발사 버튼, 점프 버튼 등이들어가는 아케이드 같은 게임들은 멀티 터치 처리를 해줘야 한다.
즉, 터치 이벤트들을 모두 받아서 차례로 다 처리 해줘야 하는 것이다.

하지만, 앵그리버드 같은 게임은 그냥 손가락 하나만 슥슥 움직이고, 눌러주고 하는 컨트롤이 대부분이기 때문에, 굳이 멀티 터치를 사용할 필요가 없다.
오직 한번에 터치 이벤트 하나만 처리하도록 만들면 되는 것이다.

그러면 다음 소스를 보면서, 첫번째는, 싱글터치 처리 방법에 대해서 알아보고, 두번째는 멀티 터치 처리 방법에 대해서 알아보자.
구현할 예제는 지난 예제에서 사용한 우리 거북군을 아무런 효과도 없이 그냥 터치가 들어오는 이벤트에 맞게 이리 저리 움직여 보는것으로 하자.

멀티 터치는 예제로 표현하기 좀 애매해서, 예제 동영상은 싱글 터치에 대해서만 촬영해서 올리도록 하겠다.

1. 싱글 터치만 사용할 경우.(지난 예제들과 똑같다,)

 

//

//  HelloWorldLayer.m

// 



// Import the interfaces

#import "HelloWorldLayer.h"



//static int transitionIndex=0;

static int effectIndex=0;


// HelloWorldLayer implementation

@implementation HelloWorldLayer

+(CCScene *) scene

{

// 'scene' is an autorelease object.

CCScene *scene = [CCScene node];

// 'layer' is an autorelease object.

HelloWorldLayer *layer = [HelloWorldLayer node];

// add layer as a child to scene

[scene addChild: layer];

// return the scene

return scene;

}


-(id) init

{

// always call "super" init

// Apple recommends to re-assign "self" with the "super" return value

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

        self.isTouchEnabled = YES;     // Layer를 초기화 할때, 나는 터치를 받겠습니다. 라고 해줘야 한다.     


}

return self;

}

 

- (void) registerWithTouchDispatcher {

    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];

}


- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {// 터치 시작했다.

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

    

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

NSLog(@"ccTouchBegan : %f , %f",convertedLocation.x ,convertedLocation.y);

    

    return YES;

   

}


- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event { // 엇? 움직이네?

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

    

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

NSLog(@"ccTouchMoved  %f , %f",convertedLocation.x ,convertedLocation.y);

    

    


}


- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { // 손뗐어.

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

    

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

NSLog(@"ccTouchEnded : %f , y : %f",convertedLocation.x ,convertedLocation.y);


    

}


- (void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event { // 터치한거 취소야.

    

} 
그런데 레이어마다 각가가 터치 이벤트를 처리할수 있게 되면 어떻게 되는거지? 하고 잠시 고민하고 생각했다면.!!! 굉장히 바람직하다.
처음에 나는매번 레이어가 바뀔때마다, "이 놈들은 터치를 받지 말아야 해" 하며 NO로 설정하는 작업을 넣어줬으나, cocos2d는 그렇게 호락 호락한 프레임워크가 아니었다. 

여러개의 레이어들이 중첩되어 있는 상태라면, 터치 이벤트를 처리할수 있돌고 한 레이어중 TOP에 올라오는 레이어가 해당 터치 이벤트를 받아먹게 된다. 위에서 언급한 각 레이어들을 직접 터치 enable/disable 해주는 작업이 필요한 경우도 있으나, 그렇게 많이 고민 할필요는 없다.
 
그리고 어떤 터치 방법을 사용할것이냐에 대해서 설정하는 것이, registerWithTouchDispatcher 메소드 인데, CCTouchDispatcher를 들여다보면 아래와 같이 되어 있습니다.

즉, 이 레이어에서 터치를 전달 받겠다고 하는 것이고, 그 이벤트들을 처리해주는 메소드들이 바로 위에 나오는 메소드들이다.
 

-(void) addStandardDelegate:(id<CCStandardTouchDelegate>) delegate priority:(int)priority

{

CCTouchHandler *handler = [CCStandardTouchHandler handlerWithDelegate:delegate priority:priority];

if( ! locked ) {

[self forceAddHandler:handler array:standardHandlers];

} else {

[handlersToAdd addObject:handler];

toAdd = YES;

}

}


각 터치 이벤트를 처리하는 메소드 아래 아래와 같은 내용이 있는데, 이건 좌표계를 변환해주는것이다. 우리가 사용하는 코코스2d좌표계와 openGL의 좌쵸가 다르기 때문에(y좌표) 아래 처럼 사용하는 것이다.

CGPoint location = [touch locationInView: [touch view]];  // 싱글 터치라서 touch를 바로 가져다가 쓴다.

    

GPoint convertedLocation = [[CCDirector sharedDirectorconvertToGL:location];



2. 멀티 터치를 사용할 경우.  (메소드의 인자가 다르다)

 

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

NSSet *allTouches = [event allTouches];

int count = [allTouches count];

if(count > 1){


NSArray *current_touches = [allTouches allObjects];

for(int i=0; i<count;i++){

UITouch *touch = [current_touches objectAtIndex:i];

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

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


}

}else {

UITouch *touch = [touches anyObject];

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

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


}

}


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

UITouch *touch = [touches anyObject];

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

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


}


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

UITouch *touch = [touches anyObject];

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

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


}


 
 
멀티 터치는 싱글 터치보다 역시 복잡하다. register하는 메소드는 사용하면 안되고, 위에서 보는 것처럼 함수를 구현해주면, 멀티 터치를 처리 해줄수 있다. 눈여겨 봐야 할부분은 began시에 터치 이벤트의 수를 세이라는 부분이다. 이놈이 지금 멀티 터치일경우,아닐경우를 잘 구분해서처리해줘야 한다.


오늘도 어김 없이. 예제를 하나 만들어보자.

거북군을 움직여 보자. 움직이는 방법은 손가락으로 화면의 임의의 곳을 터치 하면 거북군이 스멀 스멀 그쪽으로 이동하게 한다.

 

- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {

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

    

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

NSLog(@"ccTouchEnded : %f , y : %f",convertedLocation.x ,convertedLocation.y);


    [turtleSprite stopAllActions];

    [turtleSprite runAction: [CCMoveTo actionWithDuration:MOVE_DURATION position:convertedLocation]];

    

}

 

 이전까지 했던 소스에서, 터치가 업되는 순간에 위와 같이 해주면 터치된 좌표로 움직이게 된다. 너무 쉽다. 맞다!! 이렇게 시작하는거다 원래.

위 코드에서 CMoveTo 효과가 나오는데, 지난번에 이야기 한 것들과 마찬가지로 이것도 하나의 action이다, 이전것들은 effect 를 위한 action 들이고, 이넘은 아주 기초적인 action이다. 이 내용도 굉장히 많은데, 다음 포스트에서 basic action들을 비롯해서, 한번 또 다 확인해보도록 하자.

그리고 MOVE_DURATION 값을 3.0으로 줬는데, 의미하는 바는, 정해진 좌표까지 moveto하는데 걸리는 시간은 항상 일정하게 3초가 걸리도록 하라 이다.
즉, 멀리 찍으면 빨리 움직이고, 가까이 찍으면 천천히 움직이게 하는 것이다.


마지막으로 동영상 올라간다.
 

저작자 표시
신고

+ Recent posts

티스토리 툴바