我试图让一个2d精灵以“弧形”(半椭圆形)而不是直线移动。我有X和Y的开始和结束位置以及所需的半径。
实施此方法的最佳方法是什么?
答案 0 :(得分:0)
如果你想让它在椭圆中移动,我所知道的最简单的方法是将y值作为时间与sin的函数,并将x值作为时间与cos的函数。假设您正在使用System.currentTimeMillis();,您将初始时间存储在变量中(例如,double startTime = System.currentTimeMillis()),然后在每个帧中,您将通过从中减去当前时间来获得经过时间开始时间。 (例如elapsedTme = System.currentTimeMillis() - startTime)。那么y值将是(y方向上的半径)* sin(elapsedTime * speed)+椭圆中心的y值,x值将是(x方向上的半径)* cos(elapsedTime * speed)椭圆中心的+ x值。
编辑:如果你有起始的X和Y坐标而不是椭圆的中心,那么我认为获得中心的最简单方法是弄清楚其余的变量,然后将它们插入等式中。那里的数学不应该太难。
答案 1 :(得分:0)
你可能想要使用椭圆的参数形式,这里显示的公式
http://en.wikipedia.org/wiki/Ellipse#General_parametric_form
因为你有一个起点pt,并且结束了pt,你需要在两端解决t,
然后从t开始到结束,以相对较小的增量步进。
答案 2 :(得分:0)
我认为这个问题最好通过一系列坐标变换来解决。为了简化符号,让我们假设你得到的两点是你和v。
假设您在一个非常简单的情况下工作 - 点u和v分别位于(1,0)和(-1,0),椭圆上的长轴长度为1。然后你只是追寻一个半圆。假设您希望以恒定速度在点之间进行插值,则可以使用以下公式:
x(t) = cos(pi * t)
y(t) = sin(pi * t)
当然,您不一定非常幸运能够进入此设置,因此我们可以进行一系列坐标转换以使您进入此配置。首先,让我们将点w定义为u =(x0,y0)和v =(x1,y1)之间的中间点。那就是:
w = (x2, y2) = ((x0 + x1) / 2, (y0 + y1) / 2)
现在,假设您翻译u和v以使w位于原点。这意味着u和v沿着相反的向量与原点等距。如果我们使用矩阵和齐次坐标,那么您可以将其表示为
| 1 0 -x2 |
T = | 0 1 -y2 |
| 0 0 1 |
此翻译后u和v的位置由Tu
和Tv
给出。我们将这些点称为u'和v'。
u' = (x0 - x2, x1 - y2) = (x0 / 2 - x1 / 2, y0 / 2 - y1 / 2)
v' = (x1 - x2, y1 - y2) = (x1 / 2 - x0 / 2, y1 / 2 - y0 / 2)
我们现在更接近于解决原始问题,但是我们遇到的问题是u'和v'与x轴没有很好地对齐,因为它们在原始问题中。为了解决这个问题,我们将应用一个旋转变换,使得u'最终为(1,0),v'最终为(0,1)。为此,我们需要设置一个坐标系,其中一个基矢量位于u'方向,另一个位于垂直于它的方向。为此,我们将按如下方式选择单位向量:
e0 = u' / ||u||
e1 = perp(e0)
perp
是一个垂直于e0
的单位向量。解决此问题的一种方法是,如果e0 = (x3, y3)
,则为e1 = perp(e0) = (-y3, x3)
。您可以验证此向量是否垂直于(x3, y3)
,因为它们的点积为零。
鉴于这些向量,我们可以定义一个转换,它将(1,0)映射到e0
和(0,1)到e1
|x3 -y3 0|
|y3 x3 0|
| 0 0 1|
(最后一列是针对齐次坐标系的)
当然,这与我们想要的相反 - 我们试图从e0
映射到(1,0),从e1
映射到(0,1)。为了得到这个矩阵,我们只是反转上面的矩阵。幸运的是,由于我们选择e0
和e1
为正交,上面的矩阵是正交的,所以它的逆是它的转置:
| x3 y3 0|
R = |-y3 x3 0|
| 0 0 1|
现在,如果我们将R
应用于u'
和v'
,我们最终会得到向量(1,0)和(-1,0),这就是我们想要的地方他们是。现在的问题是我们想要追踪的椭圆不一定具有单位高度。例如,如果我们将其高度称为h
,那么我们将描绘出具有半长轴h
和半轴1
的椭圆路径。但是这可以通过另一个坐标变换轻松校正,这次将坐标系统的高度缩放1 / h
因子,以便我们想要跟踪的椭圆的高度为1.这可以通过以下缩放来完成矩阵:
| 1 0 0 |
S = | 0 1/h 0 |
| 0 0 1 |
此设置有用的原因是我们知道如果我们在u
和v
之间的所需椭圆上取任何点,然后将矩阵SRT
应用于它,那么我们最终将它转换为使用单位圆上的对应点,这是从(1,0)到(-1,0)的路径。但更重要的是,这种方式相反。如果我们将SRT
的逆应用于单位圆上的任意点,我们最终会返回u
和{{1}之间原始椭圆路径上的相应点}!为了达成协议,我们知道如何找到从(1,0)到(-1,0)的路径上的点,因此我们有一个算法来解决这个问题:
v
,如果您在时间t
从(1,0)移动到(-1,0),则找到您在单位圆上的位置。称之为t
。p
是你要找的点。那么,问题是(SRT) -1 是什么。幸运的是,我们有(SRT) -1 = T -1 R -1 S -1 ,所有这些矩阵都可以很容易地计算出来:
p'
简而言之,最终算法如下:
很抱歉,如果这是一个很好的数学,但你的答案应该(希望!)由上述程序给出。
答案 3 :(得分:0)
我相信您正在寻找Bezier曲线,请检查http://www.math.ucla.edu/~baker/java/hoefer/Bezier.htm。源也可以在同一链接中获得。
如果您使用SWT,可以检查http://help.eclipse.org/helios/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html#drawArc(int,int,int,int,int,int)