Skip to content

Latest commit

 

History

History
236 lines (146 loc) · 11.8 KB

坐标系与角度.md

File metadata and controls

236 lines (146 loc) · 11.8 KB

坐标系与角度

坐标系

  • 坐标系定义

    游戏中实际使用的坐标系 X 正方向朝东➡️、Y 正方向朝南⬇️、Z 正方向朝上(高度),均为 float 浮点数。

    此坐标系的具体数据在游戏内不可见,但你可以通过日志、FFLogs、实体解析等各种方式获取到坐标数据。

    此坐标系与小地图的坐标轴方向一致,但坐标不同。比例尺一般为小地图 1 : 实际坐标 50,原点位置也并不一致。

    补充说明:

    如果你只是刚接触 FF14 的坐标系,你可以先忽略这段内容,记住图中的坐标系即可。

    这个定义和内存及网络包中的真实顺序不一样,真实的顺序是 X Z Y,即 Y 是高度轴、Z 是正南方向。

    FFXIV 解析插件将内存和网络包中的 YZ 定义颠倒并输出为日志,以匹配数学上的正常习惯,即 XOY 为水平面。

    后续 ACT 中的 OverlayPlugin、触发器等插件基本也都仿照此定义修改了顺序。

    这也带来了一些问题,无论平面还是三维坐标系都变成了左手系,且部分涉及到角度的数学函数可能与正常定义下有所出入。

    你可能在一些插件(如鲶鱼精邮差、卫月)中看见 Y Z 与之相反的定义,届时需留意。

  • 实际场地

    4.0 时期,大多数形状规则的八人本场地的中心坐标是 0, 0, 0

    5.0 以后,大多数新场地的中心坐标变为了 100, 100, 0,如下图所示。

    也有少数例外(如 P5s 被原型宝石兽踹到了 100, 100, -300)。

    场地的半径/半宽一般是 20,也有少数 15 (如高贝扎,M3s,一些矩形场地的短边)。

    你可以用触发器查询 ${_me.Pos} 获取自身的三维坐标,
    或使用 ${_entity[${_me.TargetID}].Pos} 获取自己选中的实体(Boss)的坐标,
    很容易判断出场地中心和半径/半宽。

下图以万魔殿 P6s 的场地为例,详细画出了坐标系(浅黄色)和面向(红色)的示意。

coord

面向

三个维度的坐标和一个水平旋转角(面向)构成了 FF14 中实体位姿的全部四个自由度,
即你只使用这四个参数即可精确描述一个实体的位姿信息。

无论在日志中还是在游戏底层,旋转角均为弧度表示的 float 浮点数,
范围从 -π (-3.14)π (3.14)

如上图,在俯视视角下,旋转角定义为从 z 正半轴方向(正南)开始旋转的角度,沿逆时针方向增加。

如正西为 -π/2,正南为 0,正东为 π/2,正北为 ±π

方向角的变化周期为 ,在原本的数值上增减 不会影响实际面向,
你一般也无需将角度标准化至 π

补充说明:

这不涉及三维旋转。

FF14 中的三维旋转通过四元数或矩阵定义和计算,仅和显示模型有关,实体并没有另外两个旋转自由度。

相关数学常数/函数

触发器中定义了很多数学常数/函数,以方便处理与坐标和方向角有关的数学计算。

注:目前触发器只识别小写函数名,但即将更新为大小写不敏感。

注意全部方向角均为弧度制。

相关数学常数

表达式 解释
pi / π 圆周率,3.1415...
pi2 等价于
pi05 等价于 π / 2
pi025 等价于 π / 4
pi0125 等价于 π / 8
pitorad 1 弧度等价的角度值,57.295...
piofrad 1° 等价的弧度,0.017453...

后两个常数为早期引入的,不建议用于角度 / 弧度转换。

弧度 → 角度可以使用后文的 rad2deg(rad) 函数;

角度 → 弧度可以直接用 °,如 30° 会计算为对应的弧度值 30° = 30 * 0.017453 = 0.5236

相关数学函数:三角函数

函数 解释
sin(θ) θ(弧度)的正弦
cos(θ) θ(弧度)的余弦
tan(θ) θ(弧度)的正切
cot(θ) θ(弧度)的余切
sec(θ) θ(弧度)的正割
csc(θ) θ(弧度)的余割
sec(θ) θ(弧度)的正割
arcsin(x) x 的反正弦(弧度)
arccos(x) x 的反余弦(弧度)
arctan(x) x 的反正切(弧度)
arctan2(x, y)
atan2(x, y)
优化的反正切函数,大致等价于 atan2(x / y)
但可以正确处理分母 y 接近 0 时的情况。

你可能会想问为什么这里是 x, y 而不是此函数一般定义下的 y, x
因为此坐标系的方向角 0 为 y 轴而非 x 轴,向量 (x, y) 的方向角就是 θ = atan2(x / y)

相关数学函数:距离 / 角度(基础)

函数 解释
d(x0, y0, x1, y1)
distance(x0, y0,
x1, y1)
(x0, y0)(x1, y1) 的平面欧式距离。
d(x0, y0, z0, ...,
x1, y1, z1, ...)
你也可以传入 2n 个参数,计算两个 n 维坐标的欧氏距离。
n = 1时等价于 abs(x0 - x1)
也可写为全称 distance(...)
L1d(x0, y0, z0, ...,
x1, y1, z1, ...)
类似 d(...),计算两个点的 L1 距离(曼哈顿距离)。
等于每个维度的坐标差的绝对值之和。
也可以写为全称:ManhattanDistance(...)
L∞d(x0, y0, z0, ...,
x1, y1, z1, ...)
类似 d(...),计算两个点的 L∞ 距离(切比雪夫距离)。
等于每个维度的坐标差的最大值。
也可以写为全称:ChebyshevDistance(...)
radtodeg(rad) 将弧度转化为角度。
degtorad(deg) 将角度转化为弧度。不推荐,建议直接使用 °
θ(x0, y0, x1, y1)
angle(x0, y0, x1, y1)
(x0, y0) 面向 (x1, y1) 时的方向角。
等价于atan2(x1 - x0, y1 - y0)
relθ(θ0, θ1)
relangle(θ0, θ1)
θ1 相对于 θ0 偏转的角度,可以用于判断 θ1θ0 的顺/逆时针方向。
相当于将 θ1 - θ0 的结果规范至 π
isθbetween(θ, minθ, maxθ)
isanglebetween(θ, minθ, maxθ)
θ 是否处于从 minθ 开始逆时针旋转到 maxθ 的区间范围内。
返回 0(false)或 1(true)。

角度无需规范化,minθ 可以数值上大于 maxθ
如判断方向角 -2.75 是否指向北半场,
即判断是否位于正东 π/2 到正西 -π/2 的范围:
isθbetween(-2.75, π/2, -π/2)

相关数学函数:射影函数

  • 射影距离:ProjectDistance(srcX, srcY, θ, tgtX, tgtY)

  • 射影高度:ProjectHeight(srcX, srcY, θ, tgtX, tgtY)

    定义如下图所示,注意 A 点处于反方向时,射影距离为负值。

    主要用于涉及直线/射线型 AoE 的计算,如 Boss 处于 O 点,面朝 θ 释放射线 AoE,玩家处于 A 点。

  • 衍生:IsPointInRay(srcX, srcY, θ, width, tgtX, tgtY)

    直接判断一个点是否处于一个射线 AoE 中。

    例:阿罗阿罗岛的风元精当前处于 (19, 28),面向正东(π/2),准备释放半宽 5、长度 40 的射线 AoE,

    你可以使用 IsPointInRay(19, 28, π/2, 5, ${_me.x}, ${_me.y}) 判断自己当前位置是否会被击中。

相关数学函数:角度取整

  • 概念

    副本中经常需要判断一个实体处于哪个方位。

    此时计算出方向角(如塔在 -2.45 方向)并不能输出结果,还需转换为枚举值,如塔在正西北 / 10 点钟方向。

    这通常需要复杂的 arctan2mod 计算,所以设计了这个角度取整用于简化计算。

    下面展示的角度取整函数可以直接将方向角近似到圆周的 n 等分方向,返回 0n - 1

  • roundir(θ, n) (n > 0)

    首先将圆周从正北开始 n 等分,从正北开始编号为 0, 1, ..., n - 1。如:

    n = 4,代表 正北 = 0,正西 = 1, 正南 = 2, 正东 = 3;
    n = 3,代表正三角形等分,正北 = 0,左下顶点方向 = 1,右下顶点方向 = 2;
    n = 12,与表盘类似,n 点钟方向 = 12 - n

    然后判断给定的方向 θ 更接近哪个方向,返回这个方向的编号。

    例 1:四等分场地,θ = 1.4(接近正东),则 roundir(1.4, 4) 会得到 3(取整至正东);
    例 2:八等分场地,θ = 0.8(接近东南),则 roundir(0.8, 8) 会得到 5(东南);

  • roundir(θ, -n) (-n < 0)

    除了上述情况以外,也会遇到另一种圆周等分方式,正北不是一个等分点,而位于两个等分点的正中心。

    如四个斜方向、绝巴哈 / P7s 倒三角、第二次大地摇动的倒五边形。

    在此函数中,用负值 -n 代表这种等分方式,如下图所示:

    上述八等分的八方例子如果改成这种四个斜方向的写法,则为:
    θ = 0.8(接近东南),roundir(0.8, -4) 会得到 2(东南)。

  • roundir(θ, ±n, digits)

    和小数取整的 round 函数一样,可以在最后指定 digits 参数,代表保留的小数位数。

    默认情况下取整,digits = 0 可省略。

    如果给定负数,代表不舍入。

  • roundvec(dx, dy, ±n, digits = 0)

    roundir 函数中的 θ 有时不是可以直接从日志或实体数据获取的面向,而是某个实体相对于某个坐标的方向。

    这时如果正常计算,就要先算出 θ,如 atan2(x - x0, y - y0),或 θ(x0, y0, x, y)

    而用这个函数可以直接接受 dx, dy (即 x - x0, y - y0)的方向向量,省去一步角度计算。

    实际上完全等价于:roundir(atan2(dx, dy), ±n, digits = 0)

  • 应用:输出文本

    • 结合字符串函数输出结果

      这些函数可以与字符串函数 f:pick(index): 文本1, 文本2, 文本3 结合使用,从弧度或坐标输出任何方向为字符串。

      如上述的八方表达式 roundir(${θ}, 8),结合字符串输出结果则为:

      ${f:pick(${n:roundir(${θ}, 8)}): 上北, 左上, 左西, 左下, 下南, 右下, 右东, 右上}

      这个表达式接收不同 ${θ} 输入时,即可直接返回对应的八方方向文本,而在传统的写法中需要写八个条件判断。

      如传入 ${θ} 为 0.8 时,即返回前文所述的结果 右下

    • 结合临时列表输出结果

      上述表达式亦可以写为:

      ${?l: 上北, 左上, 左西, 左下, 下南, 右下, 右东, 右上 [${n:roundir(${θ}, 8) + 1}]}

      这个表达式利用了临时变量新特性,意为:

      上北, 左上, 左西, 左下, 下南, 右下, 右东, 右上 字符串构建一个临时列表, 然后取 roundir(${θ}, 8) + 1 索引。

      由于触发器定义的列表从 1 开始,所以索引号 + 1。

  • 反函数: dir2rad(dir, ±n)

    有时也需要将取整过后的索引号重新转回方向角,即可使用这个函数。

    如:dir2rad(3, 4) 意为四等分圆周的第三个等分点对应的方向,得到正东对应的 1.57...

    注意这个函数不包含取整过程的反函数,如果传入的 dir 为小数,则会返回对应的非等分方向的方向角。