我一直在尝试从几个小时开始设置重力,并将其与时间或我们称为独立于框架的弹跳球相关联。我做的所有事情我都猜对了,我尝试实现一种系统,使每次弹跳后球的高度都会降低。我什至没有开始,我的代码正在创建一些我不明白为什么的荒谬的东西。这是我的代码:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
currentFrame = System.currentTimeMillis();
dt = currentFrame - lastFrame;
dt = dt/1000;
lastFrame = currentFrame;
myFreakinRect.set(0,0, canvas.getWidth(), canvas.getHeight());
freakinRed.setColor(Color.RED);
freakinRed.setStyle(Paint.Style.FILL);
canvas.drawRect(myFreakinRect, freakinRed);
//
// o yuea
if(goingDown) {
//velocityY = Math.sqrt(100 + 2*gravity*(posY));
velocityY = gravity*(currentFrame - runTime);
} else {
velocityY = downV - gravity*(currentFrame - runTime);
}
if(posX > w - ballRadius*2) {
goingRight = false;
}
if(posX < 0) {
goingRight = true;
}
if(posY > h - ballRadius*2) {
//initY = initY - 0.25F;
//if(initY < 0) initY = 0;
Log.i("xxx", String.valueOf(initY));
runTime = currentFrame;
downV = velocityY;
goingDown = false;
}
if(velocityY <= 0) {
goingDown = true;
runTime = currentFrame;
}
if(goingDown) posY += velocityY*dt;
else posY -= velocityY*dt;
if(goingRight) posX += velocityX*dt;
else posX -= velocityX*dt;
canvas.drawText(String.valueOf(posX)+" "+String.valueOf(posY), 10, 10, new Paint());
canvas.drawBitmap(rBall, (float)posX, (float)posY, myFreakingFaintPaint);
invalidate();
}
这是发生的GIF:
更新:
这是我更新的代码,它干净,可理解且完美运行:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
currentFrame = System.currentTimeMillis();
dt = currentFrame - lastFrame;
dt = dt/1000;
lastFrame = currentFrame;
velocityY = downV + gravity*(currentFrame - runTime);
posY += velocityY*dt;
posX += velocityX*dt;
if(posX > w - ballRadius*2 || posX < 0) {
velocityX = -velocityX;
}
if(posY >= h - ballRadius*2) {
posY = h - ballRadius*2 - 2;
runTime = currentFrame;
downV = -0.8*velocityY;
}
canvas.drawBitmap(rBall, (float)posX, (float)posY, null);
invalidate();
}
最佳答案
这里 ...
if(goingDown) {
//velocityY = Math.sqrt(100 + 2*gravity*(posY));
velocityY = gravity*(currentFrame - runTime);
} else {
velocityY = downV - gravity*(currentFrame - runTime);
}
...假设球在此帧内不反弹,则更新速度(实际上是速度)。
然后在这里...
if(posY > h - ballRadius*2) {
//initY = initY - 0.25F;
//if(initY < 0) initY = 0;
Log.i("xxx", String.valueOf(initY));
runTime = currentFrame;
downV = velocityY;
goingDown = false;
}
...您尚未更新
posY
,因此您正在确定由于先前的更新,球是否击中了地板。如果是这样,则可以反转运动方向,但要保持已经为该帧计算的速度。结果,每当球反弹时,其初始向上的速度便比其击中地面时的移动速度大一帧。您在球的运动顶部具有类似的效果,但是它较小,因为那里的速度很小。
有两种方法可以解决此问题。最简单的方法可能是在位置更新之后而不是之前执行跳动检查。
补充说明:
使用X和Y速度的符号代替单独的运动方向标记(从而使名称
velocityY
等准确)。您的代码将更简单,并且您将只需要处理一个垂直方向的变化,而不是两个,因为运动方程将自动处理另一个变化。您会遇到一些精度问题,因为您假设球在整个框架中都以相同的方向行进。如果您允许球达到高速,这可能会变得很明显:在回弹之前,它似乎会穿透地板。
该计算是可疑的:
dt = dt/1000
。由于dt
似乎是根据System.currentTimeMillis()
计算的,因此我倾向于猜测它也具有long
类型。在这种情况下,您将执行整数除法,从而失去精度。关于java - 为什么这个球的能量在增加?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37665134/