有一种更直接的方法可以代替重复的“光线投射”:
def predict(x, y, vx, vy, h, b):
"""
:param x: ball x position
:param y: ball y position
:param vx: ball x velocity
:param vy: ball y velocity
:param h: the field height
:param b: the y position the prediction is for
:return: ball x position at y = b
"""
m = vy / vx # slope
c = -x * m + y # y-intercept
val = (m * b + c) % (2 * h)
return min(val, 2 * h - val)
现在,一步一步来
m = vy / vx # slope
c = -x * m + y # y-intercept
val = (m * b + c)
显示球当前路径的简单线性函数。
这有效,但前提是球永远不会撞到侧壁。
一个模型
想象一下,原来的两边有相同高度的田地,一直延伸到无穷远。
现在“反弹次数”变成了“球经过的单元格数”。
此外,如果反弹次数是偶数,则从它击中的单元格的下边界到撞击点的距离与实际球在真实单元格中击中的高度相同。
因此
(m * b + c) % (2 * h)
要涵盖奇数反弹,您需要围绕h 镜像图表。
下面是图解说明:
由于不相关的图是具有高于h 的值的图,因此您取最小值。
可能的问题
在某些语言中,% 是余数运算符,但不是 python。
如果在某些情况下预测是否定的,请添加此内容。
val = ((m * b + c) % (2 * h) + 2 * h) % (2 * h)
此功能取决于“准确”碰撞。
因此,如果以与此类似的方式处理反弹,
if y not in range(0, y_max):
vy *= -1
预测会略有偏差。
如果你能改变核心游戏,使用
if y < 0:
y *= -1
vy *= -1
elif y > y_max:
y = 2 * y_max - y
vy *= -1
如果vx 为0,则会抛出divide by zero exception,但由于在这种情况下球永远不会撞到墙壁,这应该由球的移动逻辑处理。