概述
概括地说,在确定出发点与落点后,工坊的代码会为我们找到投掷的角度。非常感谢将这个工坊移植到外服的小伙伴albertewang。
-
国服代码:
T8RPA
-
Workshop code for servers outside of China:
DTV45
基础用法
- 按下
Q
键将当前位置设为落点,任意时刻按下CTRL+Q
回到落点。 - 在任意位置,按下
SHIFT
键获得投掷方向。 - 按下
E
键投掷生物手雷,若它未被阻挡,则一定会坠至落点。
辅助功能
- 按下鼠标
左键
传送至准星处。 - 按住
F
将镜头移至落点,镜头的角度于设置落点时确定。- 按下
F+CTRL
以前移镜头。 - 按下
F+SPACE
以后移镜头。
- 按下
- 按住鼠标
右键
可进入自动模式,此时会出现动态更新的红色指示器辅助瞄准。 - 按下
R
键保存当前位置,任意时刻按下CTRL+R
传送到上一次保存的位置。
演示视频
设计思路
验证猜想
出于生活的惯性思维,我猜想生物手雷的轨迹是一段抛物线,于是尝试验证。验证的过程需要两个参数:投掷速度(\(v_0\))、重力加速度(\(g\))。这些参数都是能够在工坊中测量得到的。
- 投掷速度:竖直上抛,时间、重力加速度、初速度三者满足:\(gt=2v_0\)。
- 重力加速度:在国王大道A点三楼记录高度与自由落体的滞空时间,满足:\(h=\frac{1}{2}gt^2\)。
至此,\(v_0\)、\(g\)成为已知量。之后我尝试设计了一个demo,在投掷手雷的同时绘制从玩家朝向出发,初速度为\(v_0\),加速度为\(g\)的抛物线。观察到抛物线与轨迹几乎完全重合,猜想成立。
导出投掷角度
已知投掷角度的情况下绘制轨迹是非常直观且简单的,但我们的任务是通过起点、落点、初速度求出投掷角度。尽管用到的都是初等数学知识,后者却繁杂了许多。
参考手雷在二维平面中的轨迹(上图),我们可以列出以下四个式子:
重力加速度\(g\)与抛出速度\(v_0\)是常量,已经通过测量得到了。因为抛出位置与落点是手动设置的,我们可以通过它们的向量得到\(h\)与\(w\)。
剩余共四个未知数,我们刚好有四个等式,于是能够得到:
接下来我们解一元二次方程,这里只需要向上抛的那一个解就好了。得到\(v_x\)、\(v_y\)后,将它们分解为三维空间中的单位方向向量即可。
导出滞空时间
在导出投掷角度的中间步骤中我们用到了所需的两段时间\(t_s\)、\(t_d\),遗憾的是在实现的过程中它们已被消除。不过在已经求出\(v_y\)的情况下,滞空时间的计算也很便捷。将抛物线的运动分为两部分:
- 从起点到最高点
- 从最高点到落点
这两部分在竖直方向上均可视作自由落体运动。对于前一段我们已知最大速度\(v_y\),则\(t_1=\frac{v_y}{g}\);对于后一段我们能够求出竖直方向上的位移,则\(t_2=\sqrt{\frac{2(h_p+h)}{g}}\),其中\(h_p=\frac{1}{2}gt_1^2\),而\(h\)为起点与落点在竖直方向上的高度差。最终用时为:\(t_1+t_2\)。
实现
实践出真知,许多问题只有行动起来以后才能够被发现。
克服精度限制
地图工坊的数字在\(x\)正半轴的表示范围为\([10^{-3}, 10^8]\)。测试时发现在对一般规模的输入参数进行运算的过程中,部分中间值远大于\(10^8\) 。为了能够得到正确答案,我们可以将所有的中间值乘以\(10^{-3}\),将小数位利用起来。在玩家尺度下,一定的的误差是能够接受的,代码中的这个值是\(10^{-4}\)。最终我们的代码满足了一般尺度下的求解需求。
改善穿模问题
通过射线命中位置
命令,我们可以得到玩家瞄准的目标坐标;但直接将玩家传送到该坐标是极其不负责任的,玩家有可能因穿模被传送到墙体后方、落入地下、卡入墙体中。有两个简单的候选方案:
方案一 | 方案二 | |
---|---|---|
改进 | 添加最近的可行走位置 约束 |
通过射线命中法线 修正传送点 |
优点 | 一定能够传送到安全的位置 | 误差较小 |
缺点 | 无法上高台且误差较大 | 可能会卡入墙体 |
无法上高台是致命的缺点,所以最终采用了方案二。但两个方案并不完全互斥,我们可以尝试在检测到玩家卡入墙体时将其传送至最近的可行走位置。目前的传送功能还是非常好用的,测试的过程中完全没有遇到问题。
代码
- 注意:因为兼容性或本地化存在的某些问题,导入中文代码时工坊可能会报错,可以尝试先在战网客户端中将语言(文字)切换为英文,粘贴英文版本的代码并保存,再将语言恢复至中文。