我一直在尝试从几个小时开始设置重力,并将其与时间或我们称为独立于框架的弹跳球相关联。我做的所有事情我都猜对了,我尝试实现一种系统,使每次弹跳后球的高度都会降低。我什至没有开始,我的代码正在创建一些我不明白为什么的荒谬的东西。这是我的代码:

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:

java - 为什么这个球的能量在增加?-LMLPHP

更新:

这是我更新的代码,它干净,可理解且完美运行:

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/

10-10 03:14