文档章节

Libgdx中事件传递过程解析

asay
 asay
发布于 2017/03/29 17:17
字数 790
阅读 61
收藏 0

直接看代码.

先看stage中touchDown()

/** Applies a touch down event to the stage and returns true if an actor in the scene {@link Event#handle() handled} the
	 * event. */
	public boolean touchDown (int screenX, int screenY, int pointer, int button) {
		if (screenX < viewport.getScreenX() || screenX >= viewport.getScreenX() + viewport.getScreenWidth()) return false;
		if (Gdx.graphics.getHeight() - screenY < viewport.getScreenY()
			|| Gdx.graphics.getHeight() - screenY >= viewport.getScreenY() + viewport.getScreenHeight()) return false;

		pointerTouched[pointer] = true;
		pointerScreenX[pointer] = screenX;
		pointerScreenY[pointer] = screenY;

		screenToStageCoordinates(tempCoords.set(screenX, screenY));

		InputEvent event = Pools.obtain(InputEvent.class);
		event.setType(Type.touchDown);
		event.setStage(this);
		event.setStageX(tempCoords.x);
		event.setStageY(tempCoords.y);
		event.setPointer(pointer);
		event.setButton(button);

		Actor target = hit(tempCoords.x, tempCoords.y, true);
		if (target == null) {
			if (root.getTouchable() == Touchable.enabled) root.fire(event);
		} else {
			target.fire(event);
		}

		boolean handled = event.isHandled();
		Pools.free(event);
		return handled;
	}

 

在看Actor 中的fire()

/** Sets this actor as the event {@link Event#setTarget(Actor) target} and propagates the event to this actor and ancestor
	 * actors as necessary. If this actor is not in the stage, the stage must be set before calling this method.
	 * <p>
	 * Events are fired in 2 phases:
	 * <ol>
	 * <li>The first phase (the "capture" phase) notifies listeners on each actor starting at the root and propagating downward to
	 * (and including) this actor.</li>
	 * <li>The second phase notifies listeners on each actor starting at this actor and, if {@link Event#getBubbles()} is true,
	 * propagating upward to the root.</li>
	 * </ol>
	 * If the event is {@link Event#stop() stopped} at any time, it will not propagate to the next actor.
	 * @return true if the event was {@link Event#cancel() cancelled}. */
	public boolean fire (Event event) {
		if (event.getStage() == null) event.setStage(getStage());
		event.setTarget(this);

		// Collect ancestors so event propagation is unaffected by hierarchy changes.
		Array<Group> ancestors = Pools.obtain(Array.class);
		Group parent = this.parent;
		while (parent != null) {
			ancestors.add(parent);
			parent = parent.parent;
		}

		try {
			// Notify all parent capture listeners, starting at the root. Ancestors may stop an event before children receive it.
			Object[] ancestorsArray = ancestors.items;
			for (int i = ancestors.size - 1; i >= 0; i--) {
				Group currentTarget = (Group)ancestorsArray[i];
				currentTarget.notify(event, true);
				if (event.isStopped()) return event.isCancelled();
			}

			// Notify the target capture listeners.
			notify(event, true);
			if (event.isStopped()) return event.isCancelled();

			// Notify the target listeners.
			notify(event, false);
			if (!event.getBubbles()) return event.isCancelled();
			if (event.isStopped()) return event.isCancelled();

			// Notify all parent listeners, starting at the target. Children may stop an event before ancestors receive it.
			for (int i = 0, n = ancestors.size; i < n; i++) {
				((Group)ancestorsArray[i]).notify(event, false);
				if (event.isStopped()) return event.isCancelled();
			}

			return event.isCancelled();
		} finally {
			ancestors.clear();
			Pools.free(ancestors);
		}
	}

 

好吧,仔细看可以看清楚流程.但是我想用直白的语言总结一下.

在stage中hit() 只会选出一个actor作为此次点击的目标target.

然后这个actor调用fire(),在通知中有4个过程:

1.在捕获阶段,通知各个父节点的capture listeners,从最根部的节点开始.

2.再通知自己的capture listeners.

3.然后到了通知阶段,先通知自己的target listeners.

4.最后通知父节点的target listeners,从最近的节点开始.

此过程看明白以后,在游戏中控制事件Event就可以非常的灵活.

private boolean capture; // true means event occurred during the capture phase
private boolean bubbles = true; // true means propagate to target's parents
private boolean handled; // true means the event was handled (the stage will eat the input)
private boolean stopped; // true means event propagation was stopped
private boolean cancelled; // true means propagation was stopped and any action that this event would cause should not happen

补充:

1.capture 字段的意义:在自定义的Listeners中判断处于什么阶段是根据isCapture()判断的,所以在自定义的Listeners中禁止调用setCapture().

2.stoped 字段的意义:在上面4个过程中,随时想停止都可以调用stop() 或者 cancel() 来停止后面的过程.

3.bubbles 字段的意义:如果在前3个过程中,不想经历第4个过程,可以setBubbles(false).

4.handled 字段的意义:是针对多个InputProcessor及使用了InputMultiplexer的情况,如果handled为true,后面的InputProcessor就不再处理了.只有handled为false,后面的才会处理.

© 著作权归作者所有

asay
粉丝 0
博文 16
码字总数 5799
作品 0
郑州
私信 提问
LibGDX学习-LibGDX基本框架

Libgdx作者博客:http://www.badlogicgames.com/ Libgdx项目地址:https://github.com/libgdx/libgdx/ 关于LibGDX的学习,建议看看Beginning Android Games, 2nd Edition,该书也是由LibGDX作......

kangyunqiang
2013/12/01
0
0
Android游戏引擎--libgdx

Libgdx是一个跨平台的开发框架。它目前支持的平台有Windows,Mac OS X,Android,IOS和HTML5。 Libgdx允许你可以将代码不经任何修改的部署到多个平台。而不是修改你的代码适应不同的平台或者...

匿名
2010/08/04
31.1K
2
Libgdx 1.5.2 发布,跨平台游戏开发框架

Libgdx 1.5.2 发布,此版本更新内容如下: [1.5.2] - 修复问题 #2433 - 修复LWJGL在Mac OS X的本地载入问题 [1.5.1] - Gradle 升级到 2.2 - Android Gradle 工具升级到 1.0.0 - API更改:GWT...

宋志辉
2015/01/06
3.1K
23
Libgdx 1.6.1 发布,开源跨平台游戏开发框架

Libgdx 1.6.1 发布,更新内容如下: - Net.newServerSocket方法中添加可选的主机名,允许gdx开发的服务器程序进行特定的IP绑定。 - 更改iOS本地库的处理方式。从ios/build.gradle中移除updat...

宋志辉
2015/06/05
2.5K
12
Libgdx 1.5.4 发布,跨平台游戏开发框架

英文原文:http://www.badlogicgames.com/wordpress/?p=3635 [1.5.4] 添加对Titled maps 的图像层的支持。 添加从TMX maps(TextureMapObject)载入texture对象的支持。 添加FreeTypeFontGen...

宋志辉
2015/02/15
2.2K
7

没有更多内容

加载失败,请刷新页面

加载更多

如何有效地计算JavaScript中对象的键/属性数量?

计算对象的键/属性数的最快方法是什么? 是否可以在不迭代对象的情况下执行此操作? 即不做 var count = 0;for (k in myobj) if (myobj.hasOwnProperty(k)) count++; (Firefox确实提供了一...

技术盛宴
24分钟前
3
0
百度网址安全中心拦截解除的办法分享

临近2019年底,客户的公司网站被百度网址安全中心拦截了,公司网站彻底打不开了,影响范围很大,于是通过朋友介绍找到我们SINE安全公司寻求帮忙解封,关于如何解除百度的安全拦截提示,下面就...

网站安全
35分钟前
3
0
Tomcat8源码分析-启动流程-start方法

上一篇:Tomcat8源码分析-启动流程-load方法 前面讲了启动流程中的Catalina.load,进一步调用绝大部分组建的init操作,主要完成对server.xml解析,并根据解析的结果结合设置的Rule(规则)构造...

特拉仔
44分钟前
6
0
Xamarin.FormsShell基础教程(7)Shell项目关于页面的介绍

Xamarin.FormsShell基础教程(7)Shell项目关于页面的介绍 轻拍标签栏中的About标签,进入关于页面,如图1.8和图1.9所示。它是对应用程序介绍的页面。 该页面源自Views文件夹中的AboutPage.x...

大学霸
50分钟前
3
0
一步一步理解Impala query profile(一)

很多Impala用户不知道如何阅读Impala query profile来了解一个查询背后正在执行的操作,从而在此基础上对查询进行调优以充分发挥查询的性能。因此我想写一篇简单的文章来分享我的经验,并希望...

九州暮云
51分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部