Rect.offset() 不沿负 x 轴工作

Rect.offset() not working along negative x axis

我正在做一个 Pong 克隆,我已经将球实现为 Rect() 对象。现在我使用 Rect.offset(dx,dy) 移动球,它以指定的速度偏移球。为了使球从墙上弹起,我将相应轴的速度乘以 -1。现在沿着 Y 轴反弹,它完美地反弹,但沿着 X 轴它开始行为怪异。这是 android 工作室的一些小故障还是我做错了什么?

package com.nblsoft.pong;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.View;



public class PongLogic extends View {

    //set screen constrains in dip
    Configuration configuration = this.getResources().getConfiguration();
    int dpHeight = configuration.screenHeightDp; //The current height of the available screen space, in dp units, corresponding to screen height resource qualifier.
    int dpWidth = configuration.screenWidthDp; //The current width of the available screen space, in dp units, corresponding to screen width resource qualifier.

        //int smallestScreenWidthDp = configuration.smallestScreenWidthDp; //The smallest screen size an application will see in normal operation, corresponding to smallest screen width resource qualifier.

        //DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
        //float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
        //float dpWidth = displayMetrics.widthPixels / displayMetrics.density;

    private int dptopixel(int DESIRED_DP_VALUE){

        final float scale = getResources().getDisplayMetrics().density;

        return (int)((DESIRED_DP_VALUE) * scale + 0.5f);
    }

    private int pixeltodp(int DESIRED_PIXEL_VALUE){

        final float scale = getResources().getDisplayMetrics().density;

        return (int) ((DESIRED_PIXEL_VALUE) - 0.5f / scale);
    }

    //set paddle size, speed, position vector

    int AI_paddle_pos_x = 4 * (dptopixel(dpWidth)/100);           //3 for 320x480, 10 for 1080x1920 etc.
    int paddle_width  =     (dptopixel(dpWidth)/10);            //
    int AI_paddle_pos_y =     (dptopixel(dpHeight)/10);           //48 for 320x480, 190 for 1080x1920 etc.
    int paddle_height =     (dptopixel(dpHeight)/100) + 3;      //the paddle is 100% of the total height of phone.

    int user_paddle_pos_x = 4 * (dptopixel(dpWidth)/100) ;
    int user_paddle_pos_y = dptopixel(dpHeight) - ((dptopixel(dpHeight)/10) + (dptopixel(dpHeight)/100) + 3)  ;




    //User Paddle
    public Rect paddle_user = new Rect(user_paddle_pos_x,
                                       user_paddle_pos_y,
                                       user_paddle_pos_x + paddle_width,
                                       user_paddle_pos_y + paddle_height);

    //AI paddle
    Rect paddle_AI = new Rect(AI_paddle_pos_x,
                              AI_paddle_pos_y,
                              AI_paddle_pos_x + paddle_width,
                              AI_paddle_pos_y + paddle_height);


    //set ball position vector, Velocity vector, acceleration

    int ball_pos_x = 0 ;
    int ball_pos_y = (dptopixel(dpHeight)/2) ;
    int ball_size = dptopixel(dpWidth)/100 ;
    int ball_velocity = 3;


    // Ball
    Rect ball = new Rect(ball_pos_x,
                         ball_pos_y,
                         ball_pos_x+ball_size,
                         ball_pos_y+ball_size);


    //Override onDraw method
    @Override
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);

        Paint mytext  = new Paint();
        mytext.setColor(Color.WHITE);
        //mytext.setStyle(Paint.Style.STROKE);
        //mytext.setStrokeWidth(2);


        // Draw Middle point
        canvas.drawRect(0, ((dptopixel(dpHeight)) / 2), (dptopixel(dpWidth)), (((dptopixel(dpHeight)) / 2) + 2), mytext);

        //draw both paddles
        canvas.drawRect(paddle_user,mytext);
        canvas.drawRect(paddle_AI, mytext);

        //draw ball
        canvas.drawRect(ball,mytext);


    //Practise Methods
        //canvas.drawText(Integer.toString(dptopixel(dpHeight)),300,300,mytext);
        //canvas.drawText(Integer.toString(dptopixel(dpWidth)), 400, 400, mytext);

        //canvas.drawText(Integer.toString(dpHeight),500,500,mytext);
        //canvas.drawText(Integer.toString(dpWidth),600,600,mytext);

        //canvas.drawText("Fuck", 700, 700, mytext);
        //canvas.drawRect(0,0,dptopixel(dpWidth),dptopixel(dpHeight),mytext);


        //Game Loop Updater
        update();
        invalidate();
    }

    private void update() {

        if (ball.centerX() > (dptopixel(dpWidth))/2){
            ball.offset(-ball_velocity,ball_velocity);
        }
        else{
        ball.offset(ball_velocity,ball_velocity);
        }
    }

    //Override Touch method

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {

            paddle_user.offset(10,0);
        }
        return true;
    }


/*    @Override
    public boolean onTouch(View v, MotionEvent event) {
        this.paddle_user.offsetTo(10,10);
        return true; //Event Handled
    }
*/


    public PongLogic(Context context) {
        super(context);
        setBackgroundColor(Color.BLACK);            //to set background
        this.setFocusableInTouchMode(true);             //to enable touch mode

    }



}

好的,我已经弄清楚为什么偏移方法运行不正常了。首先,我在条件的 else 部分有原始偏移位置。其次,仅当 if 评估为真时,我才否定 dx 组件。这只发生了一帧,因为我正在评估 Rect 对象的 X 位置。一旦从球的位置减去 -dx,它就会变成假。

为了解决这个问题,我不得不将偏移量置于条件之外,并为 dx 和 dy 传递两个单独的值。然后我调整了条件,以便它只为变量分配正值和负值,这些变量后来传递给 offset() 函数,而不是调用偏移函数本身。

这是新的update()方法

private void update() {

        if (ball.centerX() > (dptopixel(dpWidth))/2){
            ball_velocity_x = -3;
        }
        else if (ball.centerY() > (dptopixel(dpHeight))) {
            ball_velocity_y = -3;
        }

        ball.offset(ball_velocity_x, ball_velocity_y);
    }