Cocos2d 作为一个开源的2D游戏引擎,最初是用python语言实现,mac app开发流行后,提供了一个Objective-C的版本。采用Cocos2d框架开发iphone游戏,极大提高了开发的速度。简单介绍参见百度百科 ,cocos2d官网 。
Cocos2d 提供了两种touch处理方式,Standard Touch Delegate和 Targeted Touch Delegate方式(参见CCTouchDelegateProtocol.h中源代码),CCLayer默认是采用第一种方式(参见CCLayer的 registerWithTouchDispatcher方法)。
在CCLayer子类中要能接收touch事件,首先需要激活touch支持,在init方法中设置isTouchEnabled值为YES。
Standard方法中用户需要重载四个基本的touch处理方法,如下:
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
当touch事件发生时,会调用该方法响应touch事件。如果是单点touch,则只需要调用 UITouch *touch = [touches anyObject],就可以获取touch对象;如果需要响应多点 touch,则需要调用[[event allTouches] allObjects]返回一个UITouch的NSArray对象,然后使用NSArray的objectAtIndex依次访问各个UITouch对 象。为了获取UITouch对象的坐标(假设该UITouch名称为touch),调用[touch locationInView: [ touch view]]会返回一个UIView相关的坐标viewPoint。
使用Cocos2d的新建应用程序向导创建一个新的cocos2d application时,在xxxAppDelegate类的applicationDidFinishLaunching方法中CCDirector 会将UIView转换为支持OpenGL ES的EAGLView。此时,我们还需要将前面获取的UIView中的viewPoint转换为EAGLView坐标,调用[[CCDirector sharedDirector] convertToGL: viewPoint]即可实现。
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
-(void) ccTouchesCancelled:(NSSet*)touch withEvent:(UIEvent *)event;
这三个方法和ccTouchesBegan类似。
在standard方式中的响应处理事件处理的都是NSSet,而 targeted方式只处理单个的UITouch对象,在多点触摸条件下,应该采纳standard方式。在使用targeted方式之前需要重写 CCLayer中的registerWithTouchDispatcher方法:
//记得在头文件中导入“CCTouchDispatcher.h”
-(void) registerWithTouchDispatcher {
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
targeted方式中用户需要重载4个基本的处理方法,其中ccTouchBegan必须重写,其他三个是可选的。
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event; (必须实现)
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event;
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event;
- (void)ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event;
每次touch事件发生时,先调用ccTouchBegan方法,该方法对每个UITouch进行响应并返回一个BOOL值,若为YES,则后续的 ccTouchMoved、ccTouchEnabled和ccTouchCancelled才会接着响应。
在xxxAppDelegate类的applicationDidFinishLaunching 方法中加入下面代码 [glView setMultipleTouchEnabled:YES];
posted @ 2011-04-09 21:54 Penny●zheng 阅读(569) 评论(0)
编辑
一,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;