一,iPhone OS 提供了关亍触摸(Touch)的以下 4 个事件响应凼数:


 (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {}


 (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {}


 (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {}


 (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {}


1,由两种方式获得事件:

(1) touches 参数:

NSMutableSet *mutableTouches = [touches mutableCopy];


(2)也可以通过 event 参数获得:

NSSet *allTouches = [event allTouches];


2,依次处理每一个触摸点 通过[allTouches count]来判断是多触点还是单触点,获叏第一个触摸点方法:

UITouch *touch = [[allTouches allObjects] objectAtIndex:0];

获叏第二个触摸点:

UITouch *touch2 = [[allTouches allObjects] objectAtIndex:1];

第三、第四...多点触摸以此类推。


3,针对每个触摸点的处理

通过以下凼数考察每个触摸点是单击还是双击:

[touch tapCount]


二,Cocos2D 的事件处理机制


1,接管:从系统 iPhoneOS 的标准UIView 获得触摸输入。


      为了便亍针对 OpenGL ES 的编程,苹果公司提供了派生亍类 UIView 的类 EAGLView 来实现 OpenGL 输出支持。(参考 Cocos2d 目录 cocos2d\Support 下的文件:EAGLView. EAGLView.m)

Cocos2d-iPhone 的主控类 Director 通过下面的凼数实现了 Cocos2d-iPhone 与iPhone 应用程序主窗口乊间的联系:

EAGLView *view = [director openGLView];

该方法的具体实现

由CC_DIRECTOR_INIT();实例化CCDirector的内置变量openGLView,然后调用openGLView方法取得

(当然也由其他的方法实现这绑定[[Director sharedDirector] attachInView:view];)

      又由于EAGLView继承了UIView,固也继承了Touch事件的4个方法touchesBegan等

      为了接管iphone中的事件。

      首先,定义了一个接管的协议。

@protocol EAGLTouchDelegate <NSObject>

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

@end

同时,在EAGLView的一个成员变量id< EAGLTouchDelegate > touchDelegate_

CCTouchDispatcher.h实现了EAGLTouchDelegate协议


整合部分:我门在CCDirector.h文件的-(BOOL)initOpenGLViewWithView:(UIView *)view withFrame:(CGRect)rect方法中,我们会发现


// 设定用户输入代理对象。单例对象 sharedDispatcher 在此引入。

[openGLView_ setTouchDelegate: [TouchDispatcher sharedDispatcher]];

...

// 通过添加子视图将 UIView 转化为直接支持 OpneGL ES 输出。 [view addSubview:openGLView_];


于是在,从UIView继承的四个方法中,调用协议的方法

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

if(touchDelegate_)

{

[touchDelegate_ touchesBegan:touches withEvent:event];

}

}


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{

if(touchDelegate_)

{

[touchDelegate_ touchesMoved:touches withEvent:event];

}

}


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

if(touchDelegate_)

{

[touchDelegate_ touchesEnded:touches withEvent:event];

}

}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

{

if(touchDelegate_)

{

[touchDelegate_ touchesCancelled:touches withEvent:event];

}

}

这样就实现了CCTouchDispatcher的全面接管了,如果视线可以关注CCTouchDispatcher的实现了


2,分发:按照预先定义好的逻辑分収给各种注册对象。


我们发现touchDelegate_的四个方法都是调用

-(void) touches:(NSSet*)touches withEvent:(UIEvent*)event withTouchType:(unsigned int)idx;

该方法首先处理TargetedTouchDelegate协议,

方法由:

@protocol CCTargetedTouchDelegate <NSObject>


 

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event;

@optional

// touch updates:

- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event;

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

- (void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event;

@end


后StandardTouchDelegate协议,

@protocol CCStandardTouchDelegate <NSObject>

@optional

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

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

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

- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

@end

判断touches中哪些是第一个协议,哪个是第二个协议,主要看- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event;这个方法,在CCTargetedTouchDelegate协议中是必须的实现的,如果是该协议的,并返回YES,则继续

-(void) touches:(NSSet*)touches withEvent:(UIEvent*)event withTouchType:(unsigned int)idx的方法

并由CCTouchHandler类实现具体的操作。


3,处理:注册对象乊间如何协调响应用户的输入。

CCTouchDispatcher的内部成员

NSMutableArray *targetedHandlers;

NSMutableArray *standardHandlers;

当用户设置自定义的Layer中的isTouchEnabled = YES时,会调用Layer中的方法

-(void) setIsTouchEnabled:(BOOL)enabled

{

if( isTouchEnabled != enabled ) {

isTouchEnabled = enabled;

if( isRunning_ ) {

if( enabled )

[self registerWithTouchDispatcher];

else

[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];

}

}

}


[self registerWithTouchDispatcher];

一般该语句的意思是注册到StandardTouchDelegate,如果是MenuItem Layer则注册到TargetTouchDelegate中,具体的操作也就是将Layer实例放入到如下对应的NSMutableArray中

NSMutableArray *targetedHandlers;

NSMutableArray *standardHandlers;