2D 坐标系与 2D 变换

前言

本文对可用的 2D 坐标系和内置的 2D 变换进行了详细介绍。相关基础概念见 视口变换与画布变换

Transform2D 是用于在坐标系之间进行转换的矩阵,使用前最好先了解一下 Godot 提供了哪些坐标系。如果需要更深入地了解底层的相关信息,请参考 矩阵与变换 教程。

Godot 2D 坐标系

下图展示的是 Godot 2D 中的坐标系、节点变换、变换函数、坐标系相关函数的概览。最左侧是操作系统“窗口管理器”的屏幕,最右侧是 CanvasItem。简单起见,这张图中没有加入 SubViewportSubViewportContainerParallaxLayerParallaxBackground,尽管它们也能够影响变换。

这张图基于 Window(内嵌其他窗口)Window(没有内嵌窗口)CanvasLayerCanvasItemCanvasItemCanvasItem 的节点树绘制。节点树还可以有更加复杂的组合,例如可以让 Window 和 SubViewport 进行更深层的嵌套,不过本示例主要的目的还是展示通用的思考方法。

../../../_images/transforms_overview.webp

单击图片放大。

  • Item 坐标

    这是 CanvasItem 的局部坐标系。

  • 父 Item 坐标

    这是父级 CanvasItem 的局部坐标系。在画布中放置 CanvasItem 时,这些画布项会继承父级 CanvasItem 的变换。CanvasItems.top_level 则是例外。

  • 画布坐标

    之前的教程 画布层 中就提到过,画布有两种(Viewport 画布和 CanvasLayer 画布),两者用的都是画布坐标系。画布坐标也叫世界坐标。一个 Viewport 可以包含多个画布,不同画布所使用的坐标系可以不同。

  • 视口坐标

    这是 Viewport 的坐标系。

  • 相机坐标

    仅在内部使用,用于实现 3D 相机光线投射等功能。

  • 嵌入器坐标 / 屏幕坐标

    场景树中的各个 ViewportWindowSubViewport)不是嵌入在其他节点中,就是嵌入在操作系统的“窗口管理器”中。这种坐标系的原点位于 WindowSubViewport 的左上角,缩放与嵌入器或操作系统的“窗口管理器”一致。

    如果嵌入器是操作系统的“窗口管理器”,那么对应的坐标也可以称为屏幕坐标。

  • 绝对嵌入器坐标 / 绝对屏幕坐标

    这种坐标系的原点是所嵌节点或的操作系统的“窗口管理器”的左上角。缩放与嵌入器或操作系统的“窗口管理器”一致。

    如果嵌入器是操作系统的“窗口管理器”,那么对应的坐标也可以称为绝对屏幕坐标。

节点变换

此处涉及的节点都有一个或多个变换与之关联,将节点组合后就得到了在不同坐标系之间的变换。除了一些特殊情况之外,变换都是 Transform2D,下面列出了它们各自的详细信息和作用。

  • CanvasItem 变换

    CanvasItemControlNode2D 节点。

    Control 节点的变换包含相对于父节点原点的位置 position、缩放 scale 以及围绕轴心点的旋转 rotation

    Node2D 节点的变换为 transform,包含位置 position、旋转 rotation、缩放 scale 以及偏斜 skew

    变换会影响画布项本身,通常还会影响子级的 CanvasItem;如果是 SubViewportContainer 的话则会影响其包含的 SubViewport

  • CanvasLayer 变换

    CanvasLayer 的变换为 transform,会影响该 CanvasLayer 中的所有 CanvasItem,不会影响所属 Viewport 中的其他 CanvasLayerWindow

  • CanvasLayer 视口跟随变换

    The follow viewport transform is an automatically calculated transform, that is based on the Viewport's canvas transform and the CanvasLayer's follow viewport scale and can be used, if enabled, to achieve a pseudo-3D effect. It affects the same child nodes as the CanvasLayer transform.

  • 视口画布变换

    画布变换会影响该Viewport 默认画布中的所有 CanvasItem,还会影响启用了“跟随视口变换”的 CanvasLayerViewport 中活动 Camera2D 的工作原理就是修改这个变换。该变换不会影响 Viewport 中嵌套的 Window

  • 视口全局画布变换

    Viewport 还具有全局画布变换。这是主变换,会影响所有CanvasLayer和嵌套 Window 的变换,主要用于 Godot 的 CanvasItem 编辑器。

  • 视口拉伸变换

    最后,Viewport 拥有拉伸变换,用于调整视口的大小和拉伸。多分辨率 中介绍了 Window 中对该变换的用法,我们还可以通过 sizesize_2d_override 手动设置 SubViewport 的拉伸变换。平移 translation、旋转 rotation 和偏斜 skew 为默认值,只有缩放 scale 可以是非默认值。

  • 窗口变换

    多分辨率 中提到了 Window 内容的缩放和位移,为了实现这种效果,每个 Window 都包含了一个窗口变换。一个例子就是用来实现 Window 的黑边,这样 Viewport 就能够按照固定的纵横比来显示了。

  • 窗口位置

    每个 Window 都还有一个 position,描述的是它在嵌入器中的位置。嵌入器可以是另一个 Viewport,也可以是操作系统窗口管理器。

  • SubViewportContainer 收缩变换

    SubViewportContainerstretchstretch_shrink 声明的是它所包含的 SubViewport 是否使用相对于容器大小的整数级缩放以及对应的缩放系数。