【问题标题】:Bouncing ball between 4 walls destination algorithm4 墙目标算法之间的弹跳球
【发布时间】:2013-10-19 22:56:24
【问题描述】:

我正在尝试实现一个球在 4 个垂直壁之间弹跳的动画,即球的速度恒定。问题是,我使用的框架要求我在每次球与墙壁碰撞时告诉球的起点和终点。

在碰撞的那一刻,我可以访问球当前和之前与墙壁接触的位置。给定墙壁的坐标 x_min、x_max、y_min 和 y_max,以及球的这两个位置,计算下一个位置的最简单方法是什么?

我想到的所有算法都遵循一种蛮力方法,有许多 if-else 语句......我想知道是否有一些优雅的方式来处理这个问题。

【问题讨论】:

  • 下一个位置是什么意思?你在做时间步骤吗?或者你的意思是它接下来会在哪里撞到另一面墙? “起点和终点”是什么意思?你能画一幅画,或者举一些实数的例子吗?通常,在从墙上弹起时,您只需更改其中一个速度(垂直速度)的符号。这就是我们所需要的......
  • 我的意思是下一个与墙壁碰撞的点。不涉及时间步长或速度 - 只告诉一旦球击中球,下一次应该击中的位置。 acfrancis 的评论完全符合我的意思。

标签: algorithm animation collision


【解决方案1】:

[对不起,这是不完整的——我会作为评论发布,但它太大并且涉及 ascii 艺术。我以后可能会删除它。]

如果您想要一种紧凑、优雅的方法,则可能更容易将球想象成一条直线,穿过重复的矩形图案。

+------+------+--*---+
|      |      | *    |
|      |      |*     |
+------+------*------+
|      |     *|      |
|      |    * |      |
+------+---*--+------+
|      |  *   |      |
|      | *    |      |
+------+*-----+------+
|      *      |      |
|     *|      |      |
+----*-+------+------+
|   *  |      |      |
|  *   |      |      |
+-*----+------+------+

(您需要反射矩形,然后“免费”获得反弹)。

我很确定你可以使用类似于 bresenham's algorithm 的东西 计算交点。

[感谢您的投票,但我不得不说,我认为这可能是一个痛苦的世界。跟踪反射,特别是如果恰好碰到角落,会很棘手......有时使用丑陋的代码更容易!]

【讨论】:

  • 乍一看,这种方法似乎确实更容易实现。我必须考虑一下使用它的最佳方式,但这听起来像是我正在寻找的优雅方式。
【解决方案2】:

假设上一次反弹在 (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)

类似这样的:

+--*------+
| / \     |
|/   \    |
*     \   |
|      \  |
+-------*-+

【讨论】:

  • 我想到了类似的东西,但听起来还是蛮力的方法——首先你必须找出球在哪一面墙,然后写一个与碰撞情况的直线方程地板/天花板,另一个用于与左/右墙的碰撞。然后仍然存在与其中一个角落发生碰撞的情况......好吧,我想没有更好的方法来处理这个问题。
【解决方案3】:

我不确定这是否和你的想法相似,但我的想法是基本上像没有墙一样计算位置,然后以墙为中心点翻转适用的坐标。

所以,首先你计算一下:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多