OpenGL 游戏引擎能否创建它自己的 UIResponder 子类,类似于 Sprite Kit 为 SKNode 所做的?

Posted

技术标签:

【中文标题】OpenGL 游戏引擎能否创建它自己的 UIResponder 子类,类似于 Sprite Kit 为 SKNode 所做的?【英文标题】:Can a OpenGL game engine create it's own UIResponder subclass similar to Sprite Kit does for SKNode? 【发布时间】:2013-11-28 11:27:59 【问题描述】:

看起来UIResponder 与 UIView 交织在一起。然而,Sprite Kit 具有继承自 UIResponder 的 SKNode 类,因此它可以处理触摸事件。

如果您自己创建基于节点的游戏引擎:您能否创建自己的 UIResponder 子类,以便 OpenGL 渲染的对象可以响应类似于 UIView 层次结构的触摸事件?

触摸事件是如何进入 UIResponder 子类的?

【问题讨论】:

【参考方案1】:

UIResponder 没有什么特别之处——确实可以按照您的建议进行操作。 (虽然可能没有你想象的那么容易。)

实际上,UIResponder 是一个抽象超类。它不(AFAIK)自己实现事件调度;相反,它为处理事件的类定义了一个接口。如何处理事件取决于子类的实现。 UIApplicationUIWindowUIView 实现了响应者方法,将触摸事件传递给触摸下的视图——大概UIView 调用了自己的hitTest:withEvent: 方法来查找触摸下的子视图并转发事件。 Sprite Kit 将响应者模式扩展到其节点树模型中,因此SKView 可能通过调用其场景的convertPointFromView:nodeAtPoint: 方法来实现UIResponder 方法,以在将事件传递给该节点之前找到触摸下的节点。

如果您实现自己的UIView(或GLKView 或任何类型的视图)子类,您可以扩展响应者模式以包含您的自定义对象。如果您使用 OpenGL ES 绘制 3D 场景,并且有用于表示该场景元素的 Objective-C 类,请随意让这些类继承自 UIResponder

只是这样做不会神奇地将触摸事件转发给这些对象——就像UIView 确实命中测试以将事件转发给子视图和SKView 确实命中测试以将事件转发给节点一样,您的视图将需要进行命中测试以确定您的哪些自定义对象应该接收触摸事件(然后在该对象上调用适当的响应程序方法)。

如何在 OpenGL ES 视图中进行命中测试取决于您...您必须找到一种适合您应用需求的方法。命中测试(又名 selectionpicking)是 3D 编程中的大问题领域之一,所以有很多关于它的文章——做一些搜索,你会发现很多建议。以下是两种最常见方法的简要概述:

使用输出对象 ID 而不是像素颜色的特殊片段着色器(或重新配置的GLKBaseEffect)将场景重新渲染到屏幕外帧缓冲区,然后使用glReadPixels 查找触摸下的像素。 (OpenGL ES 3.0 中的多个渲染目标可能有助于提高性能。)使用glReadPixels 从 GPU 内存读取速度很慢,因此请仅读取触摸下的点(或如果您想允许一些误差范围,则读取它周围的小区域)以保持性能。

如果您知道场景元素在其 3D 坐标空间中的位置,则可以使用 GLKMathUnproject 函数将触摸位置(2D 屏幕空间中的一个点)转换为您的场景的 3D 世界空间,然后查看该线与场景几何体(或场景几何体的边界框)相交的位置,以确定哪个对象被触摸。 (这种方法称为射线投射。)

如果您将响应者模式扩展到您自己的自定义对象架构中,您需要确保您的类将事件正确地转发到响应者链中。阅读Event Handling Guide for ios了解详情。

【讨论】:

【参考方案2】:

我不相信这在 SKNode 的实现方式中是可能的。没有用于将自定义 UIResponder 子类插入响应者链的公共 API。

有关如何将 UIResponder 子类正确插入响应者链的详细信息,请参阅 ricksters 答案。请务必在子节点中覆盖 - (UIResponder *)nextResponder 以返回您的自定义视图类,以便响应者链仍然正确。

一种可能性是为每个 GL 对象创建一个 UIControl,并保持其位置同步。通过将这些控件添加为*** GL 视图的子视图,它们将被插入到响应者链中并接收触摸。另一种可能性是在顶层视图中处理触摸,并在那里执行命中测试以确定哪个 GL 节点与触摸相交。

【讨论】:

谢谢。命中测试似乎是要走的路。

以上是关于OpenGL 游戏引擎能否创建它自己的 UIResponder 子类,类似于 Sprite Kit 为 SKNode 所做的?的主要内容,如果未能解决你的问题,请参考以下文章

计算与加载 OpenGL 的法线

将 OpenGL 用于 2d 游戏的最有效方法是啥?

OpenGL游戏引擎渲染器[关闭]

简单的 C++,Linux 的 opengl 游戏引擎? [关闭]

GtKGLArea 无法创建 OpenGL 2.1 上下文

「游戏引擎 浅入浅出」4.1 Unity Shader和OpenGL Shader