从一个点到另一个点的路径有多少,其无疑是数不清的。两点之间直线是最短,但是在众多的游戏中,我们可能需要一些更具艺术感的轨迹,如:lol中的艾卡西亚OO,还有OO必须死中的普通小飞镖。这些攻击效果都可以在画面上动态绘制出一些好看的抛物线轨迹。
这些追踪目标的抛物线攻击轨迹大伙们都是怎么实现的呢。
问:
空间中有一枚起点和一枚终点,请依照空间中某些依据随机规划出一条路径,使得起点和终点能够平滑地连接起来。
贝塞尔曲线
想要在空间中的两点之间随机绘制一条平滑的曲线,需要先了解贝塞尔曲线绘制方案。 此曲线有三个节点,分别为起点,终点,控制点。起点为路径规划开始的节点 ,终点为路径结束的节点,而控制点就是使得轨迹能够平滑连接的节点。
由图可知,控制点分别与起点终点连接线段,而DE两点分别由AB两点向BC两点滑动,轨迹点F点则同时由D点向E点滑动。二阶的贝塞尔曲线即为由一枚控制点在两枚端点之间绘制抛物线。 在运动的过程中呢有三组线段比值是一直全等的,分别是:AD/DB = BE/EC = DF/FE。
此为二阶贝塞尔曲线,这种曲线自然也是有它的对应函数的,由于本题主要是为了解决轨迹规划的问题,所以不对更高阶的贝塞尔曲线做过多的讨论。
抛物线轨迹点
由图中的运动模式我们可以明白,ABC三点坐标是固定的,DEF的坐标是动态的。我们需要求得的就是轨迹点F的动态坐标。这种与线段长度有关的动态坐标位置我们一般都可以使用向量的的方法来对其坐标进行一个动态的追踪。此问有三段动态的向量对我们来说比较重要,分别是AD,DF,与BE。由曲线的全等要求:AD/DB = BE/EC = DF/FE,我们可以做出以下推导。
明确有起点A与终点C的坐标,DFE分别在线段AB,DE,BC上按比例滑动。按照向量的做法F点的坐标即为A点的坐标加向量AD与向量DF。经过推论可以得到F点的坐标公式如下:
Pf =Pa + 2(Pb - Pa) *(t/ rate) + (Pc - 2Pb + Pa) *(t/ rate) **2
其中t是当前的步数。
逻辑流
1. 设置起终点AC
2. 随机设置控制点B
3. 设置轨迹点步数rate
4. 计算所有轨迹点并绘制
完整代码
import random
import matplotlib.pyplot as plt
p_sta = [0, 0, 0]
p_end = [1, 1, 1]
p_con = [random.random(), random.random(), random.random()]
rate = int(10)
x = []
y = []
z = []
for t in range(rate):
pf = [p_sta[0] + 2*(p_con[0] - p_sta[0])*(t / rate) + (p_end[0] - 2*p_con[0] + p_sta[0])*(t / rate)**2,
p_sta[1] + 2*(p_con[1] - p_sta[1])*(t / rate) + (p_end[1] - 2*p_con[1] + p_sta[1])*(t / rate)**2,
p_sta[2] + 2*(p_con[2] - p_sta[2])*(t / rate) + (p_end[2] - 2*p_con[2] + p_sta[2])*(t / rate)**2]
x.append(pf[0])
y.append(pf[1])
z.append(pf[2])
fig1 = plt.figure()
ax1 = fig1.add_subplot(111, projection='3d')
ax1.set_xlabel("x")
ax1.set_ylabel("y")
ax1.set_zlabel("z")
ax1.scatter(x, y, z, color='r', marker='o')
plt.show()
由起点【0,0,0】到终点【0,0,1】我们可以看到随机的一枚控制点将直线拉伸成了曲线,曲线的路径会接近控制点但是并不会与其相交。注意,这种曲线轨迹的绘制方法也能够很容易的引申到更加高阶的贝塞尔曲线当中,曲线运动的本质并不会改变。
贝塞尔曲线是从数字量到模拟量的一种非常丝滑的过渡方式。不止于某些艺术作品,它已经进出到我们生活的很多方面,如机器人与运动控制,物理现象模拟等。其为各种数值的表现形式增添了一抹不属于他们的柔软温度。