【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进行事件注册:
public function Starling(xxx)
{
...
// register touch/mouse event handlers
for each (var touchEventType:String in touchEventTypes)
stage.addEventListener(touchEventType, onTouch, false, 0, true);
...
} private function get touchEventTypes():Array
{
return Mouse.supportsCursor || !multitouchEnabled ?
[ MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_MOVE, MouseEvent.MOUSE_UP ] :
[ TouchEvent.TOUCH_BEGIN, TouchEvent.TOUCH_MOVE, TouchEvent.TOUCH_END ];
}
我们可以看到会根据是否支持鼠标和是否开启多点触控来选择注册的事件类型,而所有事件的处理都交给onTouch方法。
onTouch方法处理:
private function onTouch(event:Event):void
{
if (!mStarted) return; var globalX:Number;
var globalY:Number;
var touchID:int;
var phase:String; // figure out general touch properties
if (event is MouseEvent)
{
var mouseEvent:MouseEvent = event as MouseEvent;
globalX = mouseEvent.stageX;
globalY = mouseEvent.stageY;
touchID = 0; // MouseEvent.buttonDown returns true for both left and right button (AIR supports
// the right mouse button). We only want to react on the left button for now,
// so we have to save the state for the left button manually.
if (event.type == MouseEvent.MOUSE_DOWN) mLeftMouseDown = true;
else if (event.type == MouseEvent.MOUSE_UP) mLeftMouseDown = false;
}
else
{
var touchEvent:TouchEvent = event as TouchEvent;
globalX = touchEvent.stageX;
globalY = touchEvent.stageY;
touchID = touchEvent.touchPointID;
} // figure out touch phase
switch (event.type)
{
case TouchEvent.TOUCH_BEGIN: phase = TouchPhase.BEGAN; break;
case TouchEvent.TOUCH_MOVE: phase = TouchPhase.MOVED; break;
case TouchEvent.TOUCH_END: phase = TouchPhase.ENDED; break;
case MouseEvent.MOUSE_DOWN: phase = TouchPhase.BEGAN; break;
case MouseEvent.MOUSE_UP: phase = TouchPhase.ENDED; break;
case MouseEvent.MOUSE_MOVE:
phase = (mLeftMouseDown ? TouchPhase.MOVED : TouchPhase.HOVER); break;
} // move position into viewport bounds
globalX = mStage.stageWidth * (globalX - mViewPort.x) / mViewPort.width;
globalY = mStage.stageHeight * (globalY - mViewPort.y) / mViewPort.height; // enqueue touch in touch processor
mTouchProcessor.enqueue(touchID, phase, globalX, globalY);
}
onTouch方法中会区分原生鼠标事件和Touch事件,同时会获取到一些基础的信息(如全局坐标等)。
最终,会将收集到的核心信息调用mTouchProcessor.enqueue方法加入待处理队列。
Touch事件处理和抛出:
mTouchProcessor.enqueue方法收集每帧需要处理的事件,注意这个时候只是得到原生stage的一些鼠标或触摸的信息。
最终生成Starling的Touch事件是在Starling的onEnterFrame方法中调用的advanceTime方法中:
private function advanceTime():void
{
var now:Number = getTimer() / 1000.0;
var passedTime:Number = now - mLastFrameTimestamp;
mLastFrameTimestamp = now; mStage.advanceTime(passedTime);
mJuggler.advanceTime(passedTime);
mTouchProcessor.advanceTime(passedTime);
}
我们发现在处理完毕stage和动画的advanceTime方法后,紧接着就是处理mTouchProcessor的advanceTime方法。注意Starling的所有Touch事件抛出都是在该方法中执行的。而这里执行完毕后就会执行渲染,所以如果我们在Touch事件中改变对象的状态是在本帧就能看到效果的。
mTouchProcessor的advanceTime方法会处理收集的所有Touch事件消息,清理旧的Tap标记(因为Tap操作需要较长的生命周期,所以额外处理),更新已有的Touch对象;将mQueue排队的事件参数进行处理,产生新的Touch对象(通过hitTest方法寻找到该全局坐标下的target目标),并且如果需要的话,让这个Touch事件所对应的对象来派发这个事件。
Touch事件的使用:
1.对需要进行Touch监听的对象进行事件侦听:
sprite.addEventListener(TouchEvent.TOUCH, onTouch);
2.在onTouch方法中处理:
private function onTouch(e:TouchEvent):void
{
//获取多个Touch对象,一个对象对应一个触碰,如果存在多个对象则表示是多点触碰
var touches:Vector.<Touch> = e.touches;
//只有一个触碰
if(touches.length == 1)
{
//...
}
//两个触碰
if(touches.length == 2)
{
//...
}
}
3.获取到的具体的Touch对象中包含需要的详细信息;
我这里只是简单的带过使用方法,更多详细的使用方法可以查看下面的电子书:
http://www.starlinglib.com/wiki/OutsideDocs.html
【Stage3D学习笔记续】山寨Starling(十一):Touch事件体系的更多相关文章
- 【Stage3D学习笔记续】山寨Starling(三):Starling核心渲染流程
这篇文章我们剔除Starling的Touch事件体系和动画体系,专门来看看Starling中的渲染流程实现,以及其搭建的显示列表结构. 由于Starling是模仿Flash的原生显示列表,所以我们可以 ...
- 【Stage3D学习笔记续】山寨Starling(八):核心优化(批处理)的实现
批处理是使GPU进行高效绘制的一种技术手段,也是整个渲染流程中最核心的技术,到目前为止我们并没有使用到这种技术手段,下面我们看看我们现在的渲染机制. 先想一想我们最开始是怎么向GPU绘制一幅图像的,可 ...
- 【Stage3D学习笔记续】山寨Starling(六):动画实现和测试
我发布了一个版本v0.2,该版本是未优化版本,且没有添加Touch事件体系,但是由于是最基础且未优化的,所以可以通过参考代码快速的了解实现原理. 接下来的一段笔记开始进行渲染优化,我会把所有的目光都集 ...
- 【Stage3D学习笔记续】山寨Starling(十二):总结和一些没提到的东西
我们的山寨Starling到这里就告一段落了,不得不说这是一个非常优秀的2D框架,他的设计和架构为后来的许多框架都提供了很好的参考,比如现在正在崛起的Egret,我们的一番解读也只是窥见了Starli ...
- 【Stage3D学习笔记续】山寨Starling(二):VertexData探幽
还记得之前的学习笔记中我们的顶点缓冲数组中的顶点数据么,我们使用一个一维数组来记录所有的顶点数据,这是由于顶点缓冲上传数据时是使用的一维数组. 如果对顶点数据进行一层代码的封装,就能更加的方便我们来操 ...
- 【Stage3D学习笔记续】山寨Starling(一):从事件说起
我在GitHub上新开了一个项目:https://github.com/hammerc/hammerc-study-Stage3D 山寨的Starling版本我取名叫做Scorpio2D,以后的笔记中 ...
- 【Stage3D学习笔记续】真正的3D世界(一):透视矩阵
如果各位看官跟着我的学习笔记一路看过来的话,一定会吐槽我的,这都是什么3D啊?从头到尾整个都是在使用GPU绘制一堆2D图像而已,的确,之前我们一直使用正交矩阵利用GPU加速来实现2D世界的展示,算不上 ...
- 【Stage3D学习笔记续】山寨Starling(四):渲染代码实现及测试程序
本章会实现最核心的代码,所以涉及点会比较多,这里会发布一个版本,方便日后的回退查看. 点击下载:https://codeload.github.com/hammerc/hammerc-study-St ...
- 【Stage3D学习笔记续】山寨Starling(十):高效游戏设计、纹理集和ATF
我发布了经过批处理优化的v0.3版,点击下载:https://github.com/hammerc/hammerc-study-Stage3D/archive/v0.3.zip 先看看我们批处理优化后 ...
随机推荐
- 泛型编程、STL的概念、STL模板思想及其六大组件的关系,以及泛型编程(GP)、STL、面向对象编程(OOP)、C++之间的关系
2013-08-11 10:46:39 介绍STL模板的书,有两本比较经典: 一本是<Generic Programming and the STL>,中文翻译为<泛型编程与STL& ...
- PHP 简单的加密解密算法
<?php /** * * @创建时间:2015-3-12 下午2:07:33 * @作者:YuMing * @描述:异或加密解密类 */ class Yihuo extends CI_Cont ...
- Exynos 4412的启动过程分析[2]
做实验时我们是把 bin 文件烧入SD卡,比如前面做的汇编流水灯实验. 问:是谁把这些指令从 SD 卡读出来执行? 答:是固化在芯片内部ROM上的代码---它被称为iROM ,iROM是厂家事先烧写在 ...
- String.IndexOf String.IndexOf String.Substring
String.IndexOf String.IndexOf 方法 (Char, Int32, Int32)报告指定字符在此实例中的第一个匹配项的索引.搜索从指定字符位置开始,并检查指定数量的字符位置. ...
- javascript 小日历
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx. ...
- 【HDOJ】4317 Unfair Nim
基本的状态压缩,想明白怎么dp还是挺简单的.显然对n个数字进行状态压缩,dp[i][j]表示第i位状态j表示的位向高位产生了进位. /* 4317 */ #include <iostream&g ...
- 【HDOJ】4601 Letter Tree
挺有意思的一道题,思路肯定是将图转化为Trie树,这样可以求得字典序.然后,按照trie的层次求解.一直wa的原因在于将树转化为线性数据结构时要从原树遍历,从trie遍历就会wa.不同结点可能映射为t ...
- Function 1 - hello world
Function 1 - hello world Make a simple function called greet that returns the most-famous "hell ...
- MySql命令的基本操作
MySQL的基本命令: 登录:mysql -h -u root -p password:*****; 例如:mysql -h127.0.0.1 -uroot -p 增加一个用户: grant all ...
- bzoj1433:[ZJOI2009]假期的宿舍
明显的二分图最大匹配. #include<cstdio> #include<cstring> #include<cctype> #include<algori ...