圆与2个矩形之间的碰撞检测?

时间:2015-02-27 03:03:40

标签: java android android-canvas

我设置代码的方式是我有3个白色矩形,与屏幕一样高,每个屏幕宽度的1/9。每个在屏幕上均匀分布。我还有另外3个黑色矩形,每个白色顶部有1个...与白色矩形左右相同,所以对于用户来说,看起来白色矩形中有一个间隙,而实际上它只是一个黑色的矩形在与屏幕一样高的白色矩形上的较小高度。无论如何,当矩形在屏幕上移动时,玩家必须通过白色矩形中的“间隙”传球。我想知道如何检测与“唯一白色区域”的碰撞。我的意思是如果球是安全的,如果它接触黑色和白色矩形但是如果玩家没有同时击中黑色和白色矩形则不安全的代码(如果我说不安全,如果它只打了白色矩形)玩家每次都会死,因为我说白色矩形和屏幕重叠的黑色矩形一样高。这是我的主要活动的代码:

public class GameScreen extends ActionBarActivity {
public static final String TAG = "BallActivity";
BallView mBallView = null;

Rectangle rectWhite1 = null
        , rectBlack1= null
        , rectWhite2 = null
        , rectBlack2= null
        , rectWhite3 = null
        , rectBlack3= null
        ,collisionRectangle = null;
int mPointMargin = 5; //specifies width of point adding zone when ball passes rectangle's right side

Handler RedrawHandler = new Handler(); //so redraw occurs in main thread
Handler RedrawHandler2 = new Handler();
Timer mTmr , mTmr2 = null;
TimerTask mTsk , mTsk2 = null;
int mScrWidth, mScrHeight;
int mRectSpeed = 7; //Game max speed should be 12!!!
int mBallSpeed = 15;
Scoreboard mScoreboard = new Scoreboard();
android.graphics.PointF mBallPos, mBallSpd;
//Going to be used to check if ball hits only white rectangle...use intersects method
Rect rectObject;



@Override
protected void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE); //hide title bar
    //set app to full screen and keep screen on
    getWindow().setFlags(0xFFFFFFFF, LayoutParams.FLAG_FULLSCREEN | LayoutParams.FLAG_KEEP_SCREEN_ON);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_game_screen);
    //create pointer to main screen
    final FrameLayout mainView = (FrameLayout) findViewById(R.id.main_view);

    //get screen dimensions
    Display display = getWindowManager().getDefaultDisplay();
    mScrWidth = display.getWidth();
    mScrHeight = display.getHeight();
    mBallPos = new PointF();
    mBallSpd = new PointF();




    //create variables for ball position and speed
    mBallPos.x = mScrWidth / 7;
    mBallPos.y = mScrHeight / 2;
    mBallSpd.x = 0;
    mBallSpd.y = 0;

    //create initial ball

    mBallView = new BallView(this, mBallPos.x, mBallPos.y, mScrWidth/30);


    //**************Create initial 6 rectangles****************
    rectWhite1 = new Rectangle(this, ((mScrWidth/9) * 8) + mScrWidth, 0 , ((mScrWidth/9) * 9) + mScrWidth, mScrHeight, 0xFFFFFFFF);
    rectBlack1 = new Rectangle(this,  ((mScrWidth/9) * 8) + mScrWidth, (mScrHeight/10) * 4 ,((mScrWidth/9) * 9) + mScrWidth ,(mScrHeight/10) * 6, 0xFFFFFF00);
    rectWhite2 = new Rectangle(this, ((mScrWidth/9) * 5) + mScrWidth, 0, ((mScrWidth/9) * 6) + mScrWidth, mScrHeight,0xFFFFFFFF);
    rectBlack2 = new Rectangle(this, ((mScrWidth/9) * 5) + mScrWidth, (mScrHeight/10) * 4, ((mScrWidth/9) * 6) + mScrWidth, (mScrHeight/10) * 6, 0xFFFFFF00);
    rectWhite3 = new Rectangle(this, ((mScrWidth/18) * 3) + mScrWidth, 0, ((mScrWidth/18) * 5) + mScrWidth, mScrHeight, 0xFFFFFFFF);
    rectBlack3 = new Rectangle(this, ((mScrWidth/18) * 3) + mScrWidth, (mScrHeight/10) * 4, ((mScrWidth/18) * 5) + mScrWidth, (mScrHeight/10) * 6 , 0xFFFFFF00);



    //Add to view

    mainView.addView(rectWhite1);
    rectWhite1.invalidate();

    mainView.addView(rectWhite2);
    rectWhite2.invalidate();

    mainView.addView(rectWhite3);
    rectWhite3.invalidate();

    mainView.addView(rectBlack1);
    rectBlack1.invalidate();

    mainView.addView(rectBlack2);
    rectBlack2.invalidate();

    mainView.addView(rectBlack3);
    rectBlack3.invalidate();


    mainView.addView(mBallView); //add ball to main screen
    mBallView.invalidate(); //call onDraw in BallView



    //listener for accelerometer, use anonymous class for simplicity
    ((SensorManager) getSystemService(Context.SENSOR_SERVICE)).registerListener(
            new SensorEventListener() {
                @Override
                public void onSensorChanged(SensorEvent event) {
                    //set ball speed based on phone tilt (ignore Z axis)
                    mBallSpd.x = -event.values[0] * mBallSpeed;
                    mBallSpd.y = event.values[1] * mBallSpeed;
                    //timer event will redraw ball
                }

                @Override
                public void onAccuracyChanged(Sensor sensor, int accuracy) {
                } //ignore
            },
            ((SensorManager) getSystemService(Context.SENSOR_SERVICE))
                    .getSensorList(Sensor.TYPE_ACCELEROMETER).get(0),
            SensorManager.SENSOR_DELAY_NORMAL);


} //OnCreate(mScrWidth/10) * 6

//For state flow see http://developer.android.com/reference/android/app/Activity.html
@Override
public void onPause() //app moved to background, stop background threads
{
    mTmr.cancel(); //kill\release timer (our only background thread)
    mTmr = null;
    mTsk = null;
    mTmr2.cancel();
    mTmr2 = null;
    mTsk2 = null;
    super.onPause();
}


@Override
public void onResume() //app moved to foreground (also occurs at app startup)
{
    final TextView scoreTextView = (TextView)findViewById(R.id.scoreTextView);

    final int[] blackRectangleTopHeights = {0, (mScrHeight/10) * 1, (mScrHeight/10) * 2,(mScrHeight/10) * 3,
                                               (mScrHeight/10) * 4,(mScrHeight/10) * 5,(mScrHeight/10) * 6,
                                               (mScrHeight/10) * 7};

    final int[] blackRectangleBottomHeights = {(mScrHeight/10) * 3,(mScrHeight/10) * 4,(mScrHeight/10) * 5,
                                              (mScrHeight/10) * 6, (mScrHeight/10) * 7,(mScrHeight/10) * 8,
                                              (mScrHeight/10) * 9,mScrHeight};
    final Random randomGenerator = new Random();


    runCircle();

    //************Set up rectangle moving mechanism and Logic*********************

    mTmr2 = new Timer();
    mTsk2 = new TimerTask() {
        @Override
        public void run() {

            int randomNumber = randomGenerator.nextInt(blackRectangleTopHeights.length);
            int topBlackRectHeight = blackRectangleTopHeights[randomNumber];
            int bottomBlackRectHeight = blackRectangleBottomHeights[randomNumber];

            //Moves rectangles left across the screen
            int rectWhite1Left = rectWhite1.getTheLeft() - mRectSpeed;
            int rectWhite1Right = rectWhite1.getTheRight() - mRectSpeed;
            rectWhite1.setX(rectWhite1Left, rectWhite1Right);

            int rectBlack1Left = rectBlack1.getTheLeft() - mRectSpeed;
            int rectBlack1Right = rectBlack1.getTheRight() - mRectSpeed;
            rectBlack1.setX(rectBlack1Left, rectBlack1Right);

            int rectWhite2Left = rectWhite2.getTheLeft() - mRectSpeed;
            int rectWhite2Right = rectWhite2.getTheRight() - mRectSpeed;
            rectWhite2.setX(rectWhite2Left, rectWhite2Right);

            int rectBlack2Left = rectBlack2.getTheLeft() - mRectSpeed;
            int rectBlack2Right = rectBlack2.getTheRight() - mRectSpeed;
            rectBlack2.setX(rectBlack2Left, rectBlack2Right);

            int rectWhite3Left = rectWhite3.getTheLeft() - mRectSpeed;
            int rectWhite3Right = rectWhite3.getTheRight() - mRectSpeed;
            rectWhite3.setX(rectWhite3Left, rectWhite3Right);

            int rectBlack3Left = rectBlack3.getTheLeft() - mRectSpeed;
            int rectBlack3Right = rectBlack3.getTheRight() - mRectSpeed;
            rectBlack3.setX(rectBlack3Left, rectBlack3Right);

            //Cycles rectangles when they hit left side of the screen
            // Randomizes where middle rectangle will be postitoned vertically
            if (rectWhite1.getTheRight() > 0 && rectWhite1.getTheRight() < 20) {
                rectWhite1.setX(mScrWidth, rectWhite1.getRectWidth() + mScrWidth);
            }

            if (rectBlack1.getTheRight() > 0 && rectBlack1.getTheRight() < 20) {
                rectBlack1.setX(mScrWidth, rectBlack1.getRectWidth() + mScrWidth);
                rectBlack1.setY(topBlackRectHeight, bottomBlackRectHeight);
            }

            if (rectWhite2.getTheRight() > 0 && rectWhite2.getTheRight() < 20) {
                rectWhite2.setX(mScrWidth, rectWhite2.getRectWidth() + mScrWidth);
            }

            if (rectBlack2.getTheRight() > 0 && rectBlack2.getTheRight() < 20) {
                rectBlack2.setX(mScrWidth, rectBlack2.getRectWidth() + mScrWidth);
                rectBlack2.setY(topBlackRectHeight, bottomBlackRectHeight);
            }

            if (rectWhite3.getTheRight() > 0 && rectWhite3.getTheRight() < 20) {
                rectWhite3.setX(mScrWidth, rectWhite3.getRectWidth() + mScrWidth);
            }

            if (rectBlack3.getTheRight() > 0 && rectBlack3.getTheRight() < 20) {
                rectBlack3.setX(mScrWidth, rectBlack3.getRectWidth() + mScrWidth);
                rectBlack3.setY(topBlackRectHeight, bottomBlackRectHeight);
            }

            //*********Keeps track of score and update TextView with score*************
            if (rectWhite1.getTheRight() > Math.round(mBallPos.x) - 5 && rectWhite1.getTheRight() < Math.round(mBallPos.x) + 5) {

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mScoreboard.addPoint();
                        scoreTextView.setText(mScoreboard.getScore() + "");
                    }
                });

            }

            if (rectWhite2.getTheRight() > Math.round(mBallPos.x) - mPointMargin && rectWhite2.getTheRight() < Math.round(mBallPos.x) + mPointMargin) {

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mScoreboard.addPoint();
                        scoreTextView.setText(mScoreboard.getScore() + "");
                    }
                });


            }

            if (rectWhite3.getTheRight() > Math.round(mBallPos.x) - mPointMargin && rectWhite3.getTheRight() < Math.round(mBallPos.x) + mPointMargin) {

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mScoreboard.addPoint();
                        scoreTextView.setText(mScoreboard.getScore() + "");
                    }
                });

            }

            //Speeds up game correspondingly to the score
            if (mScoreboard.getScore() == 10) {
                mRectSpeed = 8;
                mBallSpeed = 16;
            }
            if (mScoreboard.getScore() == 20) {
                mRectSpeed = 9;
                mBallSpeed = 17;
            }
            if (mScoreboard.getScore() == 30) {
                mRectSpeed = 10;
                mBallSpeed = 18;
            }
            if (mScoreboard.getScore() == 40) {
                mRectSpeed = 11;
                mBallSpeed = 19;
            }
            if (mScoreboard.getScore() == 50) {
                mRectSpeed = 12;
                mBallSpeed = 20;
            }
            if (mScoreboard.getScore() == 60) {
                mRectSpeed = 13;
                mBallSpeed = 21;
            }
            if (mScoreboard.getScore() == 70) {
                mRectSpeed = 14;
                mBallSpeed = 22;
            }
            if (mScoreboard.getScore() == 80) {
                mRectSpeed = 15;
                mBallSpeed = 23;
            }
            if (mScoreboard.getScore() == 90) {
                mBallSpeed = 24;
            }
            if (mScoreboard.getScore() == 100) {
                mBallSpeed = 25;
            }




            RedrawHandler2.post(new Runnable() {
                public void run() {
                    rectWhite1.invalidate();
                    rectWhite2.invalidate();
                    rectWhite3.invalidate();
                    rectBlack1.invalidate();
                    rectBlack2.invalidate();
                    rectBlack3.invalidate();

                }
            });



        }
    };
    mTmr2.schedule(mTsk2, 10, 10); //start timer (Timer 2)


    super.onResume();
} // onResume

private void runCircle() {

    //create timer to move ball to new position
    mTmr = new Timer();
    mTsk = new TimerTask() {
        public void run() {

    //move ball based on current speed
            mBallPos.x += mBallSpd.y;
            mBallPos.y += -mBallSpd.x;

            //if ball goes off screen, reposition to opposite side of screen
            if (mBallPos.x > mScrWidth) mBallPos.x = 0;
            if (mBallPos.y > mScrHeight) mBallPos.y = 0;
            if (mBallPos.x < 0) mBallPos.x = mScrWidth;
            if (mBallPos.y < 0) mBallPos.y = mScrHeight;

            //update ball class instance
            mBallView.x = mBallPos.x;
            mBallView.y = mBallPos.y;

        //redraw ball. Must run in background thread to prevent thread lock.
            RedrawHandler.post(new Runnable() {
                public void run() {
                    mBallView.invalidate();
                }
            });

      //If ball hits sides it goes to the redirect screen, YOU LOSE!
            if (mBallPos.y  == mScrHeight || mBallPos.y == 0 || mBallPos.x == mScrWidth|| mBallPos.x == 0 ) {

              goToRedirectScreen();
            }




        } //run
    }; // TimerTask

    mTmr.schedule(mTsk, 10, 10); //start timer (Timer)
}


@Override
public void onDestroy() //main thread stopped
{
    super.onDestroy();
    //wait for threads to exit before clearing app
    System.runFinalizersOnExit(true);
    //remove app from memory
    android.os.Process.killProcess(android.os.Process.myPid());
}

public void goToRedirectScreen()
{
    Intent intent = new Intent(this, Redirect.class);
    startActivity(intent);
}



}

我需要一个方法来检查mBallView是否只触及白色矩形而不是黑色和白色。或者如果您有任何其他解决方案,我会对所有方法持开放态度。提前谢谢。

我已经提到:

How to fix circle and rectangle overlap in collision response

Circle-Rectangle collision detection

但我没有看到如何将它们应用于我的特定情况。

0 个答案:

没有答案