【Stage3D学习笔记续】山寨Starling(十一):Touch事件体系

我们的山寨Starling版本将会在这里停止更新了,主要还是由于时间比较有限,而且我们的山寨版本也很好的完成了他的任务“了解Starling的核心渲染”,接下来的Starling解析我们将会直接阅读Starling的源码来了解其它的内部运行方式。

Touch事件体系无疑是除了核心渲染外最重要的东西了,我们笔记中的Touch事件体系是基于Starling v1.1来解读的。

Touch事件体系简介:

在Starling的承继关系里是没有InteractiveObject类,因此所有的显示对象都默认具有交互功能。也就是说DisplayObject是定义了交互行为的。

我们看看主要的类的功能:

  • TouchEvent:Touch事件类,Starling中将原生的鼠标和触摸事件都统一封装成TouchEvent类,这样可以保证PC开发和移动端运行时的一致性,而不同于原生事件,TouchEvent的事件类型仅有一个“TouchEvent.TOUCH”。
  • Touch:一个Touch对象包含了在屏幕上的一个手指或鼠标的相关详细信息,如果是多点触控,则会存在多个Touch对象。
  • TouchPhase:因为TouchEvent只有一个事件类型“TOUCH”,那么我们要区分具体的情况(按下、移动和弹起等)就需要使用Touch对象的phase属性了,而TouchPhase则定义了phase属性存在的值。
  • TouchProcessor:Touch事件体系核心处理类,也是我们接下来要核心解读的类。
  • TouchMarker:内部使用,PC模拟多点触控时的显示对象。

Touch事件处理流程:

Starling中持有一个TouchProcessor类的实例“mTouchProcessor”,该类用来统一处理所有的Touch事件。

还需要注意的一点是,Touch事件会有"延迟",因为Starling捕获到原生Flash层的事件之后,不会马上派发给侦听Starling事件的对象,而是先发送内部的“队列”里面,然后根据帧频,进行集中处理。不过一般我们的帧频不会设置的太小,这个延迟对用户基本没有影响。

原生事件注册:

Starling类启动时会对Stage进行事件注册:

 1 public function Starling(xxx)
 2 {
 3     ...
 4     // register touch/mouse event handlers
 5     for each (var touchEventType:String in touchEventTypes)
 6         stage.addEventListener(touchEventType, onTouch, false, 0, true);
 7     ...
 8 }
 9
10 private function get touchEventTypes():Array
11 {
12     return Mouse.supportsCursor || !multitouchEnabled ?
13         [ MouseEvent.MOUSE_DOWN,  MouseEvent.MOUSE_MOVE, MouseEvent.MOUSE_UP ] :
14         [ TouchEvent.TOUCH_BEGIN, TouchEvent.TOUCH_MOVE, TouchEvent.TOUCH_END ];
15 }

我们可以看到会根据是否支持鼠标和是否开启多点触控来选择注册的事件类型,而所有事件的处理都交给onTouch方法。

onTouch方法处理:

 1 private function onTouch(event:Event):void
 2 {
 3     if (!mStarted) return;
 4
 5     var globalX:Number;
 6     var globalY:Number;
 7     var touchID:int;
 8     var phase:String;
 9
10     // figure out general touch properties
11     if (event is MouseEvent)
12     {
13         var mouseEvent:MouseEvent = event as MouseEvent;
14         globalX = mouseEvent.stageX;
15         globalY = mouseEvent.stageY;
16         touchID = 0;
17
18         // MouseEvent.buttonDown returns true for both left and right button (AIR supports
19         // the right mouse button). We only want to react on the left button for now,
20         // so we have to save the state for the left button manually.
21         if (event.type == MouseEvent.MOUSE_DOWN)    mLeftMouseDown = true;
22         else if (event.type == MouseEvent.MOUSE_UP) mLeftMouseDown = false;
23     }
24     else
25     {
26         var touchEvent:TouchEvent = event as TouchEvent;
27         globalX = touchEvent.stageX;
28         globalY = touchEvent.stageY;
29         touchID = touchEvent.touchPointID;
30     }
31
32     // figure out touch phase
33     switch (event.type)
34     {
35         case TouchEvent.TOUCH_BEGIN: phase = TouchPhase.BEGAN; break;
36         case TouchEvent.TOUCH_MOVE:  phase = TouchPhase.MOVED; break;
37         case TouchEvent.TOUCH_END:   phase = TouchPhase.ENDED; break;
38         case MouseEvent.MOUSE_DOWN:  phase = TouchPhase.BEGAN; break;
39         case MouseEvent.MOUSE_UP:    phase = TouchPhase.ENDED; break;
40         case MouseEvent.MOUSE_MOVE:
41             phase = (mLeftMouseDown ? TouchPhase.MOVED : TouchPhase.HOVER); break;
42     }
43
44     // move position into viewport bounds
45     globalX = mStage.stageWidth  * (globalX - mViewPort.x) / mViewPort.width;
46     globalY = mStage.stageHeight * (globalY - mViewPort.y) / mViewPort.height;
47
48     // enqueue touch in touch processor
49     mTouchProcessor.enqueue(touchID, phase, globalX, globalY);
50 }

onTouch方法中会区分原生鼠标事件和Touch事件,同时会获取到一些基础的信息(如全局坐标等)。

最终,会将收集到的核心信息调用mTouchProcessor.enqueue方法加入待处理队列。

Touch事件处理和抛出:

mTouchProcessor.enqueue方法收集每帧需要处理的事件,注意这个时候只是得到原生stage的一些鼠标或触摸的信息。

最终生成Starling的Touch事件是在Starling的onEnterFrame方法中调用的advanceTime方法中:

 1 private function advanceTime():void
 2 {
 3     var now:Number = getTimer() / 1000.0;
 4     var passedTime:Number = now - mLastFrameTimestamp;
 5     mLastFrameTimestamp = now;
 6
 7     mStage.advanceTime(passedTime);
 8     mJuggler.advanceTime(passedTime);
 9     mTouchProcessor.advanceTime(passedTime);
10 }

我们发现在处理完毕stage和动画的advanceTime方法后,紧接着就是处理mTouchProcessor的advanceTime方法。注意Starling的所有Touch事件抛出都是在该方法中执行的。而这里执行完毕后就会执行渲染,所以如果我们在Touch事件中改变对象的状态是在本帧就能看到效果的。

mTouchProcessor的advanceTime方法会处理收集的所有Touch事件消息,清理旧的Tap标记(因为Tap操作需要较长的生命周期,所以额外处理),更新已有的Touch对象;将mQueue排队的事件参数进行处理,产生新的Touch对象(通过hitTest方法寻找到该全局坐标下的target目标),并且如果需要的话,让这个Touch事件所对应的对象来派发这个事件。

Touch事件的使用:

1.对需要进行Touch监听的对象进行事件侦听:

1 sprite.addEventListener(TouchEvent.TOUCH, onTouch);

2.在onTouch方法中处理:

 1 private function onTouch(e:TouchEvent):void
 2 {
 3     //获取多个Touch对象,一个对象对应一个触碰,如果存在多个对象则表示是多点触碰
 4     var touches:Vector.<Touch> = e.touches;
 5     //只有一个触碰
 6     if(touches.length == 1)
 7     {
 8         //...
 9     }
10     //两个触碰
11     if(touches.length == 2)
12     {
13         //...
14     }
15 }

3.获取到的具体的Touch对象中包含需要的详细信息;

我这里只是简单的带过使用方法,更多详细的使用方法可以查看下面的电子书:

http://www.starlinglib.com/wiki/OutsideDocs.html

时间: 2024-10-14 21:28:20

【Stage3D学习笔记续】山寨Starling(十一):Touch事件体系的相关文章

【Stage3D学习笔记续】山寨Starling(三):Starling核心渲染流程

这篇文章我们剔除Starling的Touch事件体系和动画体系,专门来看看Starling中的渲染流程实现,以及其搭建的显示列表结构. 由于Starling是模仿Flash的原生显示列表,所以我们可以参照原有的知识体系来阅读Straling的代码. Starling类: Straling类是整个Starling框架的核心,该类会管理Straling的显示列表.Touch事件.动画处理等等多个模块的功能: 同时Starling类会实现框架内部的帧循环: 实例化Starling类后会Starling

【Stage3D学习笔记续】山寨Starling(十二):总结和一些没提到的东西

我们的山寨Starling到这里就告一段落了,不得不说这是一个非常优秀的2D框架,他的设计和架构为后来的许多框架都提供了很好的参考,比如现在正在崛起的Egret,我们的一番解读也只是窥见了Starling内部的一部分,有兴趣的朋友可以继续看Starling的源码,一定会有更多的收获! 后悔的是我到这个时间才悔悟过来(切确的说是面试被鄙视的结果),开始看3D这块的知识,但我始终坚信一个道理,付出永远不会太迟,Let`s keep moving! 查看Starling的更新日志来了解这个框架的动态也

【Stage3D学习笔记续】山寨Starling(二):VertexData探幽

还记得之前的学习笔记中我们的顶点缓冲数组中的顶点数据么,我们使用一个一维数组来记录所有的顶点数据,这是由于顶点缓冲上传数据时是使用的一维数组. 如果对顶点数据进行一层代码的封装,就能更加的方便我们来操作顶点数据了. 所以引入了VertexData(顶点数据)这个类来进行封装. 在Starling中一个顶点需要记录9个数据,分别如下: 坐标数据 x 和 y(2D游戏就不需要z轴了,但是Starling中留下了 z 轴的位置的),开始索引为 0: 颜色数据 r.g.b.a(顶点颜色),开始索引为 3

【Stage3D学习笔记续】真正的3D世界(一):透视矩阵

如果各位看官跟着我的学习笔记一路看过来的话,一定会吐槽我的,这都是什么3D啊?从头到尾整个都是在使用GPU绘制一堆2D图像而已,的确,之前我们一直使用正交矩阵利用GPU加速来实现2D世界的展示,算不上真3D,但是正是由于有了之前的学习我们实现真3D世界的学习才会更加轻松,下面的笔记就让我们真正的进入3D世界吧! 补充一下,我们的这部分学习笔记是基于<Adobe Flash 11 Stage3D(Molehill) 游戏编程初学者指南>一书的学习而来的. 赶快进入我们的主题,是否还记得之前的2D

【Stage3D学习笔记续】山寨Starling(十):高效游戏设计、纹理集和ATF

我发布了经过批处理优化的v0.3版,点击下载:https://github.com/hammerc/hammerc-study-Stage3D/archive/v0.3.zip 先看看我们批处理优化后程序的效果吧! 首先,为了能明显的看出差距,我把未优化v0.2版本的MovieClipTest.swf的动画数量调到250个,同时QuadBatchTest.swf的代码一致也是250个动画,只是使用的是经过批处理优化的v0.3版本. 为了查看实际的性能差异,我使用了scout,下面看看我们的成果吧

【Stage3D学习笔记续】山寨Starling(九):上下文丢失处理方法

Stage3D在运行中是存在随时会丢失上下文的尴尬情况. 渲染内容丢失的问题本身就说明是因为丢失了Context3D对象.出现此问题的原因很多,通常还不是因为Stage3D应用.比如在win7系统中,当按下Ctrl+Alt+Delete键时会出现类似“锁定计算机”和“启动任务管理器”的菜单选项,这就会引起渲染内容丢失.但这不是唯一的可能,还有些情况,在某些屏保程序激活时又或笔记本盖子合上时也会引起渲染内容丢失.甚至可以通过调用Context3D.dispose()方法来模拟渲染内容丢失事件.所以

【Stage3D学习笔记续】山寨Starling(五):纹理计算和尺寸计算

尺寸计算: Starling中的尺寸是以像素为单位的,这一切都得力于我们使用的正交矩阵,还记得我们顶点数据中的位置数据么,如果我们提交的矩形的四个顶点为(0, 0)(0, 100)(100, 0)(100, 100),那么最终通过正交矩阵的转换后绘制到舞台时将会是长宽都为100个像素的矩形. 那么Starling中的尺寸获取其实就是基于顶点数据来进行获取,详细代码可以参考DisplayObject中的getBounds方法,主要看继承类DisplayObjectContainer和Quad的具体

【Stage3D学习笔记续】真正的3D世界(六):空间大战

这就是书上的最终效果了,一个完整的空间大战游戏: 点击查看源码 这里并没有太多的新知识,所涉及的东西更多的是游戏开发方面的优化和技巧,下面我们大家一起来看看: 飞船: 类似粒子效果中的粒子创建方法,我们的游戏飞船也需要一样的创建机制进行创建,大家可以点击查看源码: GameActor GameActorPool 需要额外说明的是,添加了进行碰撞检测的机制,代码里写了基于球形的距离的碰撞检测(简单高效)和基于AABB盒的碰撞检测,但AABB盒的碰撞检测在实际的游戏中并没有使用. 另外添加了一点优化

【Stage3D学习笔记续】真正的3D世界(三):纹理效果

混合模式: 代码 示例是<Stage3D指南>中的直接弄出来的,可以通过点击键盘上的Q.W.E这3个按键,更换混合模式.模型和纹理,可以直观的查看不同混合模式的效果,住:下方的地形使用"context3D.setBlendFactors(Context3DBlendFactor.ONE, Context3DBlendFactor.ZERO);"正常混合模式渲染,上方中心的模型使用特定的混合模式渲染. 深度测试(Z-Buffer): 使用Z-Buffer的话,GPU会把每个像