Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 精灵椭圆运动_Java_Math - Fatal编程技术网

Java 精灵椭圆运动

Java 精灵椭圆运动,java,math,Java,Math,我试图让一个2d精灵以“弧形”(半椭圆)而不是直线移动。我有X和Y的起始和结束位置以及所需的半径 实现这一点的最佳方法是什么?如果你想让它在椭圆中移动,我所知道的最简单的方法是用sin给出y值作为时间的函数,用cos给出x值作为时间的函数。假设您正在使用System.currentTimeMillis();,您可以将初始时间存储在一个变量中(例如,double startTime=System.currentTimeMillis()),然后在每个帧中,通过从开始时间减去当前时间来获得经过的时间。

我试图让一个2d精灵以“弧形”(半椭圆)而不是直线移动。我有X和Y的起始和结束位置以及所需的半径


实现这一点的最佳方法是什么?

如果你想让它在椭圆中移动,我所知道的最简单的方法是用sin给出y值作为时间的函数,用cos给出x值作为时间的函数。假设您正在使用System.currentTimeMillis();,您可以将初始时间存储在一个变量中(例如,double startTime=System.currentTimeMillis()),然后在每个帧中,通过从开始时间减去当前时间来获得经过的时间。(例如,elapsedTme=System.currentTimeMillis()-startTime)。然后y值将是(y方向的半径)*sin(elapsedTime*速度)+椭圆中心的y值,x值将是(x方向的半径)*cos(elapsedTime*速度)+椭圆中心的x值


编辑:如果你有开始的X和Y坐标,但没有椭圆的中心,那么我认为获得中心的最简单方法就是计算出其余的变量,然后将它们插入到方程中。这里的数学应该不会太难。

您可能希望使用椭圆的参数形式,这里显示的公式

因为你有一个起始点,和一个结束点,你需要求解两端的t


然后,以相对较小的增量,从开始到结束逐步进行t。

我认为,通过一系列坐标变换可以最好地解决这个问题。为了简单起见,让我们假设你的两点是u和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
缩放corodinate系统的高度,使我们要跟踪的椭圆的高度为1。这可以通过以下缩放矩阵完成:

    | 1  0  0 |
S = | 0 1/h 0 |
    | 0  0  1 |
此设置之所以有用,是因为我们知道,如果我们在
u
v
之间的所需椭圆上取任意点,然后对其应用矩阵
SRT
,那么我们将最终将其转换为使用单位圆上的对应点,即从(1,0)到(-1,0)的路径。然而,更重要的是,这反过来起作用。如果我们将
SRT
的倒数应用于单位圆上的任何点,我们最终得到
u
v
之间原始椭圆路径上的对应点!为了达成交易,我们知道如何找到从(1,0)到(-1,0)的路径上的点,因此我们有一个算法来解决这个问题:

  • 对于给定的时间
    t
    ,如果您在时间
    t
    从(1,0)移动到(-1,0),请找到您在单位圆上的位置。称之为
    p
  • 计算p'=(SRT)-1p
  • p'
    是您要寻找的重点
  • 那么,问题是(SRT)-1是什么。幸运的是,我们有(SRT)-1=T-1R-1S-1,所有这些矩阵都可以轻松计算:

         | 1  0 -x2 |          | 1  0  x2 |
     T = | 0  1 -y2 |   T^-1 = | 0  1  y2 |
         | 0  0   1 |          | 0  0   1 |
    
         | x3  y3  0|          | x3 -y3 0 |
     R = |-y3  x3  0|   R^-1 = | y3  x3 0 |
         |  0   0  1|          |  0   0 1 |
    
         | 1  0   0 |          | 1  0   0 |
     S = | 0 1/h  0 |   S^-1 = | 0  h   0 |
         | 0  0   1 |          | 0  0   1 |
    
    简言之,最终算法如下:

    e0 = u' / ||u||
    e1 = perp(e0)
    
  • 给定u=(x0,y0)和v=(x1,y1),设w=(x2,y2)=((x0+x1)/2,(y0+y1)/2)
  • 让u'=u