我有这个代码,它使用精灵运动的线性插值:
public void update(float dt) {
vx += (targetX - vx) * dt;
vy += (targetY - vy) * dt;
x += vx * dt;
y += vy * dt;
playerSprite.setPosition(x, y);
// other stuff, not related to the problem
}
public static void moveUp() {
targetY = -moveSpeed;
}
public static void moveDown() {
targetY = moveSpeed;
}
public static void moveLeft() {
targetX = -moveSpeed;
}
public static void moveRight() {
targetX = moveSpeed;
}
targetX
和targetY
是精灵应该前往的地方。
vx
和vy
是用于精灵当前速度的变量,两者都初始化为0。
dt
是自上次更新屏幕以来的帧时间差异。
moveSpeed
初始化为150。
运动是平滑的,这就是我想要的,然而,精灵永远没有它的速度(澄清:速度的绝对值)减慢。所以,我永远不会让精灵停止移动,如果我只是按一个移动键让它移动,它就会继续前进。 在目前的情况下,我如何实施摩擦?
答案 0 :(得分:0)
我不确定您使用的单位和坐标系,所以我将提供一个简单的例子。
在下面的Java源代码中,我从二维空间或平面中的10,10位置开始。精灵的当前速度为0.0,15.0,意味着每个时间段,速度在距离中除以时间,如每秒英尺,精灵将在X方向上移动0个单位,在Y方向上移动15个单位。
下面的循环是一个简单的重新计算,其中每次循环表示一定量的时间,并且在循环的底部,计算在给定速度的时间段内行进的距离的新值。我们还通过修改速度来减慢对象的速度。
我将其打印为逗号分隔的数据点值列表,以便我可以将序列拉入Excel并绘制值。当我用简单的折线图绘制Y位置值时,我看到的是Y位置在开始时有很大的变化,并且有一个很好的位置值曲线,表明每个时间段移动的距离越来越少,直到达到最终当速度为零时的值。
public static void main(String[] args) {
// TODO Auto-generated method stub
int i;
double dVelocityX = 0.0;
double dVelocityY = 15.0;
double dFriction = 0.90; // simple friction coefficient, 1.0 means no friction
int xStart = 10;
int yStart = 10;
System.out.print(" i,xStart,yStart,dVelocityX,dVelocityY\n");
for (i = 0; i < 60; i++) {
System.out.print(i+"," + xStart + "," + yStart+"," + dVelocityX + "," + dVelocityY + "\n");
xStart += dVelocityX;
yStart += dVelocityY;
dVelocityX *= dFriction;
dVelocityY *= dFriction;
}
}
实际数据输出的起始坐标为10,10,当结束时速度几乎为零时,坐标为10,138,时间为26秒。
你必须创建一种物理世界模拟,你可以在其中指定一些测量单位,以使它看起来有点逼真。所以你可能有一个大的桌面(一个二维平面),1000毫米宽和1000毫米长的单位,这个桌面以1毫米为单位标记。接下来你有一个直径为1毫米的圆形冰球。将圆盘放在坐标10,10处,圆盘的中心距离桌子的左边缘10毫米,距桌子底边10毫米,边缘靠近你。你推动冰球,使其以每秒15毫米的速度开始,然后从底部推动它,使其沿着工作台的纵向尺寸,正Y方向移动。如果没有摩擦,则在第一秒结束时,它将从位置10,10移动到位置10,25,然后在下一秒移动到位置10,40。
如果您将此插入此模拟器,您会看到输出类似于:
i,xStart,yStart,dVelocityX,dVelocityY
0,10,10,0.0,15.0
1,10,25,0.0,15.0
2,10,40,0.0,15.0
3,10,55,0.0,15.0
4,10,70,0.0,15.0
5,10,85,0.0,15.0
6,10,100,0.0,15.0
7,10,115,0.0,15.0
8,10,130,0.0,15.0
9,10,145,0.0,15.0
10,10,160,0.0,15.0
11,10,175,0.0,15.0
12,10,190,0.0,15.0
13,10,205,0.0,15.0
14,10,220,0.0,15.0
然后,如果你将摩擦力从dFriction的值从1.0改为,意味着没有摩擦,改为.90的值,你会看到冰球在行进时减速,所以在14秒的同一时间它没有移动到无摩擦的宇宙中。
i,xStart,yStart,dVelocityX,dVelocityY
0,10,10,0.0,15.0
1,10,25,0.0,13.5
2,10,38,0.0,12.15
3,10,50,0.0,10.935
4,10,60,0.0,9.8415
5,10,69,0.0,8.85735
6,10,77,0.0,7.971615000000001
7,10,84,0.0,7.174453500000001
8,10,91,0.0,6.457008150000001
9,10,97,0.0,5.811307335000001
10,10,102,0.0,5.230176601500001
11,10,107,0.0,4.707158941350001
12,10,111,0.0,4.236443047215001
13,10,115,0.0,3.8127987424935013
14,10,118,0.0,3.4315188682441513
现在,如果您更改测量单位,以便在计算位置时使用更精细的分辨率,比如使用千分尺而不是毫米,并且在时间上使用更精细的分辨率,比如使用百分之一秒而不是秒,那么差异更小在位置将变得更加引人注目和明显。因此,您可能必须使用Universe的比例来确定用于模拟的单位。
使用移动精灵等动画时,您必须选择一个时间段,在该时间段内,当您向用户呈现一系列帧或图像时,其中精灵的位置只会改变,帧到帧。精灵移动越快,帧显示速率必须越快,以提供平滑的运动。