本帖最后由 六安🐟片 于 2024-11-27 13:06 编辑
如果有过UI开发经验的创作者可能会注意到,通过一些touch事件获取到的位置经常和屏幕中UI的位置对不上。
获取到的坐标是屏幕像素坐标,而屏幕中UI的坐标又是本地坐标,接着查文档又看到了绝对坐标。[猫猫惊恐!!]
一下出现了三个坐标,他们之间各自代表了什么含义?又是如何相互转换的?游戏开发中应该怎样使用?这篇文章会一次讲清楚。
电脑桌面空间和窗口空间
假设我们的电脑桌面大小是1920*1080的,上图中灰色的部分就代表我们的电脑桌面。
这时,打开口袋方舟客户端的窗口,这个窗口在桌面中,位置是(160,90),同样,在窗口最左上角的点,在桌面中位置也是(160,90)。但是,当我们看向窗口内部,以整个窗口为参考时,窗口最左上角的点坐标则是(0,0)。
同时,在电脑桌面上,窗口的大小是按桌面像素来算的,为1600x900,而在窗口中,窗口内部的大小又被定义为了1920x1080。
在这种情况下,我们可以将桌面的坐标系统看作绝对坐标系,将窗口的坐标系统看作本地坐标系。
绝对位置和本地位置的转换
在使用onRawTouchBegin()等手指触摸代理时,获取到的是桌面的绝对位置。因此,想要在游戏中使用的话,需要先转换成本地位置才可以使用。下面介绍了两种转换方法。
InputUtil.onRawTouchBegin().add((fingerIndex: number, position: Vector2) => {
// position目前是桌面绝对位置
console.log("onRawTouchBegin", fingerIndex, position);
// 方法1 通过absoluteToViewport转换为本地位置
let outViewportPosition = new Vector2();
let outPixelPosition = new Vector2();
absoluteToViewport(position, outPixelPosition, outViewportPosition);
// 方法2 获取到视口的Geometry, 通过absoluteToLocal获取到本地坐标
let viewportGeometry = getViewportWidgetGeometry();
let localPos2 = absoluteToLocal(viewportGeometry, position);
console.log("localPos1", outViewportPosition);
console.log("localPos2", localPos2);
console.log("localPixelPos", outPixelPosition);
})
通过absoluteToViewport进行坐标转换的时候可以获得两个坐标,一个是本地坐标,另一个是像素坐标。本地坐标就是以视口左上角为原点,以视口分辨率为标准的坐标。而像素坐标则是以视口左上角为原点,以桌面分辨率为标准的。通常,可以直接在游戏逻辑中使用的是本地坐标。
另一个获取玩家Touch事件的方法,onTouchBegin()获取到的则是像素坐标。如果在游戏中使用的话,也需要用screenToViewport()做一次转换。
InputUtil.onTouchBegin((index: number, location: Vector2, touchType: TouchInputType) => {
console.log("onTouchBegin", index, location, touchType);
const viewportPosition = screenToViewport(location);
console.log("viewportPosition", viewportPosition);
})
什么是Geometry
上文中的代码在使用absoluteToLocal()时,需要传入一个Geometry对象作为参数。那么什么是Geometry呢,我们又该怎样获得Geometry呢?
Geometry是一个界面几何坐标信息。包含了对UI widget有用的数据,尤其是位置/大小变换的数据。每当UI对象的变换时,都会在Geometry下记录用于计算位置/大小变换的最新信息。
可以通过tickSpaceGeometry获取到最后一次用于驱动Widget Tick的几何信息。之后就可以使用Geometry对象来进行本地坐标,绝对坐标和屏幕像素坐标的空间变换。
下面的代码描述了已知视口本地坐标下的一个点,如何转换成绝对坐标和屏幕的像素坐标:
const rootGeometry = this.rootCanvas.tickSpaceGeometry;
const rootAbsPosition = rootGeometry.getAbsolutePosition();
// 转换成绝对坐标
const absPosition = localToAbsolute(rootGeometry, localPosition);
// 屏幕坐标是绝对坐标减去窗口的的绝对位置
const localPixelPosition = absPosition.clone().subtract(rootAbsPosition);
上面这个示例项目的截图中定义了五个点,视口的左上角,右下角,中心,左下某点,右上某点。并分别打印了每个点的绝对坐标,本地坐标和屏幕像素坐标。可以拖动窗口的变化来进一步理解不同坐标的含义。
👇同时打开4个客户端窗口
👇在移动端开启游戏
示例项目
InputDemo.rar
(1.19 MB, 下载次数: 0)
|