(本文写作基于千锋3g学院提供的第三季讲授视频编写,详细请看笔记扉页:传送门)
这一期的视频主要介绍如何在上一期创建关卡图片之后加入点击事件的响应,让我们可以通过点击关卡或者是返回键获得事件的响应。
主要包括两个内容:座标转换&点击事件响应&物体(包括触摸点)之间的碰撞检测
座标转换:
关于座标,这里有两个不同的座标系:IOS View座标系 & OpenGL View座标系,下面列出两个座标系的特征
IOS View座标系:
1.座标原点(0,0)位于当前视图的左上角,以屏幕宽为x增量,屏高为y增量
2.CGPoint座标点也就是位置,格式为:(x, y)
3.CGSize表示某视图宽度和高度,格式为:(width, height)
4.CGRect同时表示视图的CGPoint和CGSize,格式为:(x, y, width, height)
5.frame是以父视图的左上角点作为原点的CGRect
6.bounds是指以自身视图的左上角点作为原点的CGRect
7.origin表示当前视图左上角的CGPoint
(frame与bounds的origin有时候是不同的。原因在于5、6点)
8.center表示视图中心位于父视图中的CGPoint
OpenGL View座标系:
1.座标原点(0,0)位于视图的左下角,以水平方向为x轴,垂直方向为y轴
2.AnchorPoint锚点位置(0.5,0.5)
3.frame和bounds的概念与UIView中一样
4.position就是CCNode的位置(CGPoint),等同与IOS VIew中的center
(PS:视频中,作者说到IOS View的座标原点是在左下角的,哦,旋回去就是原来的习惯的座标了对吧?事情并没那么简单,如果你在加入点击响应之后试图将触摸点用两种座标打印出来,你会发现IOS View 与 OpenGL View的座标原点无缘无故的从两个角落走到了一起,为什么会有这么基情的事情发生?且看iOS cocos2d学习笔记 之 《iOS View与OpenGL View的那些事》)
IOS View 与 OpenGL View之间的转换方法:
下面是两个座标通过导演类方法来转换的方法,先用[[CCDirector sharedDirector]--
// 从UI View座标转换到OpenGL View座标:
- (CGPoint) convertToGL: (CGPoint) uiPoint;
// 从OpenGL View座标转换到UI View座标:
- (CGPoint) convertToUI: (CGPoint) glPoint;
在这两个座标系中我们要搞清楚的是,我们究竟在哪个座标系上面进行操作。
点击事件响应
下面我们先了解和添加点击事件的响应:
首先要做的事情是:
在加载画面的时候加入一行代码打开触摸开关:
[self setIsTouchEnabled:YES]
以下就是我们要添加代理相应的方法,与UIKit的触摸事件相仿。
多个点击事件响应ccTouches触摸代理:
@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
单个点击事件响应ccTouch触摸代理:
@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
物体(包括触摸点)之间的碰撞检测
获取物件(精灵)边框的方法:
- (CGRect) boundingBox;
ps: 此方法适用于继承于CCNode的所有继承类的对象
eg: CCSprite *superman;
superman.boundingBox = (CGRect)Rect;
CGRect boundingBox = [superman boundingBox];
判断矩形
// 判断点point是否在矩形rect里
- (bool) CGRectContainsPoint (CGRect rect, CGPoint point)
// 判断两个矩形是否相交
- (bool) CGRectIntersectsRect (CGRect rect1, CGRect rect2)
// 判断矩形rect2是否在矩形rect1里
- (bool) CGRectContainsRect (CGRect rect1, CGRect rect2)
好了,介绍了上面一堆东西之后,下面要列出真正要做的事情步骤:
1、获取手指点击屏幕的座标
2、将手指座标从UIKit座标转换到OpenGL座标
3、获取游戏精灵的边框
4、检测手指座标与精灵边框是否有包涵关系(即手指有木有点到精灵内)
5、精灵做出响应动作
下面给出实现中ccTouchesEnded方法的代码:
- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1. 拿到ui触摸点
UITouch *oneTouch = [touches anyObject];
UIView *touchView = [oneTouch view];
NSLog(@"触摸点所触摸到的View:x = %f; y = %f",oneTouch.view.frame.origin.x, oneTouch.view.frame.origin.y);
// 取到当前触摸到的一个uiview
// 这里的touchview 就是 glview
CGPoint location = [oneTouch locationInView:touchView];
// oneTouch 相对 touchView 上的座标
NSLog(@"触摸点于所在View上的位置:x = %f, y = %f", location.x, location.y);
// 2.转成world opengl point
CGPoint worldGLPoint = [[CCDirector sharedDirector] convertToGL:location];
NSLog(@"触摸点转换成世界点:x = %f, y = %f", worldGLPoint.x, worldGLPoint.y);
CGPoint nodePoint = [self convertToNodeSpace:worldGLPoint];
NSLog(@"世界点转换成node点:x = %f, y = %f", nodePoint.x, nodePoint.y);
// 把世界座标转化为node座标 self
// self.children.count self 上所有的孩子
for (int i = 0; i < self.children.count; i++) {
CCSprite *oneSprite = [self.children objectAtIndex:i];
// 取得第i个精灵
if (CGRectContainsPoint(oneSprite.boundingBox, nodePoint) && oneSprite.tag == 100) {
// 判断触碰点与精灵的关系,如果nodePoint包含在oneSprite中
// 并且tag为100
CCScene *sc = [StartScene scene];
CCTransitionScene *trans = [[CCTransitionCrossFade alloc] initWithDuration:0.5f scene:sc];
[[CCDirector sharedDirector] replaceScene:trans];
[trans release];
}
else if (CGRectContainsPoint(oneSprite.boundingBox, nodePoint) && oneSprite.tag < succeedLevel + 1 && oneSprite.tag > 0)
{
NSLog(@"选中了第%d关", oneSprite.tag);
CCScene *gameScene = [GameScene sceneWithLevel:oneSprite.tag];
[[CCDirector sharedDirector] replaceScene:gameScene];
}
}
}
其实,这样的点击事件并不是我们常用的touchInsert方法,而是使用了检测触摸点与物件之间的位置检测来实现点击的,但从中我们却可以获取很多有用的相关知识。确实是值得一学的。
做到这一步,我们就可以进入我们游戏的核心,制作游戏内容了。
(学期开了就有很多东西要白忙,加上这篇文章写得还是挺呕心沥血的,因为里面涉及的内容很多,需要搞懂的事情还是蛮多蛮复杂的,出于责任心,我搞懂了再写好放上网啦)