我正在尝试实现一个球在 4 个垂直壁之间弹跳的动画,即球的速度恒定。问题是,我使用的框架要求我在每次与墙壁碰撞时告诉球的起点和终点。
在碰撞的那一刻,我可以访问球当前和之前与墙壁接触的位置。给定墙壁的坐标 x_min、x_max、y_min 和 y_max,以及球的这两个位置,计算下一个位置的最简单方法是什么?
我想到的所有算法都遵循一种蛮力方法,有许多 if-else 语句……我想知道是否有一些优雅的方法来处理这个问题。
[对不起,这是不完整的 - 我会发布它作为评论,但它太大并且涉及 ascii 艺术。我以后可能会删除它。]
如果您想要一种紧凑、优雅的方法,则可能更容易将球想象成一条直线,穿过重复的矩形图案。
+------+------+--*---+
| | | * |
| | |* |
+------+------*------+
| | *| |
| | * | |
+------+---*--+------+
| | * | |
| | * | |
+------+*-----+------+
| * | |
| *| | |
+----*-+------+------+
| * | | |
| * | | |
+-*----+------+------+
(您需要反映矩形,然后“免费”获得反弹)。
我很确定你可以使用类似于bresenham 算法的东西 来计算交点。
[感谢投票,但我不得不说,我认为这可能是一个痛苦的世界。跟踪反射,特别是如果恰好碰到角落,会很棘手......有时使用丑陋的代码更容易!]
我不确定这是否与您的想法相似,但我的想法是基本上像没有墙一样计算位置,然后以墙为中心点翻转适用的坐标。
所以,首先你计算:
new
\
\
\
---------
\
\
old
然后你把它翻译成:
---------
/ \
/ \
/ old
new
伪代码:
newX = oldX + xInc
newY = oldY + yInc
if newX < 0
newX = -newX
if newY < 0
newY = -newY
if newX > maxX
newX = maxX - (newX - maxX)
// or 2*maxX - newX
if newY > maxY
newY = maxY - (newY - maxY)
// or 2*maxY - newY
假设之前的反弹在位置 (x_min, y_prev) 处离开左壁,而当前反弹在 (x_curr, y_max) 处离开顶壁。下一次反弹应该在 (x_max, y_next) 处离开右侧墙壁,其中:
y_next = y_max - (y_max - y_prev) * (x_max - x_curr) / (x_curr - x_min)
这是简单的几何图形,由(上一次反弹、左上角、当前反弹)定义的三角形与三角形(当前反弹、右上角、下一次反弹)相似(形状相同但大小不同)。像这样:
+--*----+
| / \ |
|/ \ |
* \ |
| \|
| *
| |
+-------+
如果 y_next 小于 y_min,这意味着球会先于右墙撞到底墙。将在 (x_next, y_min) 发生,其中:
x_next = x_curr + (x_curr - x_min) * (y_max - y_min) / (y_max - y_prev)
像这样的东西:
+--*------+
| / \ |
|/ \ |
* \ |
| \ |
+-------*-+