文档章节

Libgdx中事件传递过程解析

asay
 asay
发布于 2017/03/29 17:17
字数 790
阅读 23
收藏 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
博文 14
码字总数 5272
作品 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
Libgdx 1.6.4 发布,跨平台游戏开发框架

Libgdx 1.6.4 发布,更新内容: 翻译:宋志辉 [1.6.4] - TextField 光标和选择大小更改。https://github.com/libgdx/libgdx/commit/2a830dea348948d2a37bd8f6338af2023fec9b09 - FreeTypeFo......

oschina
2015/07/12
913
2
Android游戏引擎--libgdx

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

匿名
2010/08/04
29.3K
2
Libgdx 1.7.1 发布,跨平台开发框架

Libgdx 1.7.1 发布,此版本更新内容如下: - Fixes AtlasTmxMapLoader region name loading to tileset name instead of filename - Changes TiledMapPacker output, region names are tile......

oschina
2015/11/02
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

没有更多内容

加载失败,请刷新页面

加载更多

大数据教程(11.9)hive操作基础知识

上一篇博客分享了hive的简介和初体验,本节博主将继续分享一些hive的操作的基础知识。 DDL操作 (1)创建表 #建表语法CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_name ...

em_aaron
今天
2
0
OSChina 周四乱弹 —— 我家猫真会后空翻

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @我没有抓狂 :#今天听这个# 我艇牛逼,百听不厌,太好听辣 分享 Led Zeppelin 的歌曲《Stairway To Heaven》 《Stairway To Heaven》- Led Z...

小小编辑
今天
3
0
node调用dll

先安装python2.7 安装node-gyp cnpm install node-gyp -g 新建一个Electron-vue项目(案例用Electron-vue) vue init simulatedgreg/electron-vue my-project 安装electron-rebuild cnpm ins......

Chason-洪
今天
3
0
scala学习(一)

学习Spark之前需要学习Scala。 参考学习的书籍:快学Scala

柠檬果过
今天
3
0
通俗易懂解释网络工程中的技术,如STP,HSRP等

导读 在面试时,比如被问到HSRP的主备切换时间时多久,STP几个状态的停留时间,自己知道有这些东西,但在工作中不会经常用到,就老是记不住,觉得可能还是自己基础不够牢固,知识掌握不够全面...

问题终结者
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部