Android RectF.intersects(RectF a,RectF b)在Canvas SurfaceView

时间:2018-04-27 21:54:31

标签: java android android-studio game-engine game-physics

我试图在两个RectF对象之间进行基本的碰撞检测,但似乎无法使其工作。到目前为止,我有一个EnemyCircle1对象从屏幕左侧移动到屏幕右侧并从墙壁反弹并反转方向,然后我有一个PlayerCircle对象,用户通过点击屏幕控制,我甚至无法得到如果两个对象彼此相交,则基本碰撞检测起作用。我已经尝试了近10种不同的碰撞公式而没有工作。这是我的MainActivity类:

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.graphics.Point;
//import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.Display;

// Change "extends AppCompatActivity" to just "extends Activity"
public class MainActivity extends Activity
{
// Declare GLOBAL (CLASS) instance objects || (Do not initialize)
public CustomView1 customView1;     // Declare an instance of customView

// Debugging
Handler handler1 = new Handler();
int delayForHandler1 = 5000; // Milliseconds

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    // Set desired screen orientation
    //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

    // Get a Display object to access screen details
        // Declare and initialize an object of type Display called (display) 
       //to a chain of two methods
        Display display = getWindowManager().getDefaultDisplay();
    // Load the resolution into a Point object
        // Declare and initialize an object of type Point called (size) to 
     //the default constructor
        Point size = new Point();
    // Get the horizontal and vertical sizes of current device
        // Use the "display" and "size" object together and the screen 
       //resolution is now stored in the "size" object
        display.getSize(size);
    // Initialize the customView1
        // Initialize the customView1 object and pass in the int values of 
     //screen resolution
        customView1 = new CustomView1(this, size.x, size.y);

    // Set the ContentView
    //setContentView(R.layout.activity_main);
    setContentView(customView1);

    // Debugging
    handler1.postDelayed(new Runnable() {
        @Override
        public void run() {
            System.out.println("FPS: " + Globals.AVERAGE_FPS);
            System.out.println("Enemy X: " + Globals.ENEMY_CIRCLE_1_X_COORD);
            System.out.println("Enemy Y: " + Globals.ENEMY_CIRCLE_1_Y_COORD);
            System.out.println("Enemy Width: " + Globals.ENEMY_CIRCLE_1_WIDTH);
            System.out.println("Enemy Height: " + Globals.ENEMY_CIRCLE_1_HEIGHT);
            System.out.println("PLAYER X: " + Globals.PLAYER_CIRCLE_X_COORD);
            System.out.println("PLAYER Y: " + Globals.PLAYER_CIRCLE_Y_COORD);
            System.out.println("PLAYER Width: " + Globals.PLAYER_CIRCLE_WIDTH);
            System.out.println("PLAYER Height: " + Globals.PLAYER_CIRCLE_HEIGHT);
            handler1.postDelayed(this, delayForHandler1);
        }
    }, delayForHandler1);
}

//**********************************************************************************************
// This method executes when the player starts the game (Or reopens the app)
@Override
protected void onResume()
{
    // Call the default version of this method
    super.onResume();

    // Tell the gameView resume method to execute
    customView1.resume();
}
// This method executes when the player quits the game (Or switches apps)
@Override
protected void onPause()
{
    // Call the default version of this method
    super.onPause();

    // Tell the gameView pause method to execute
    customView1.pause();
}


 } // END MainActivity Class

以下是我的Globals Class的代码:

import android.content.res.Resources;
import android.util.TypedValue;

public class Globals
{
// Average FPS
public static long AVERAGE_FPS;

// Screen/Canvas Dimensions
public static int GAME_WIDTH_X;
public static int GAME_HEIGHT_Y;

// LIVE X & Y Coordinates of EnemyCircle1
public static float ENEMY_CIRCLE_1_X_COORD;
public static float ENEMY_CIRCLE_1_Y_COORD;

// LIVE X & Y Coordinates of Player Circle
public static float PLAYER_CIRCLE_X_COORD;
public static float PLAYER_CIRCLE_Y_COORD;

// LIVE Width and Heights
public static float ENEMY_CIRCLE_1_WIDTH;
public static float ENEMY_CIRCLE_1_HEIGHT;
public static float PLAYER_CIRCLE_WIDTH;
public static float PLAYER_CIRCLE_HEIGHT;
}

以下是我的PlayerCircle类的代码:

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import javax.microedition.khronos.opengles.GL;

  public class PlayerCircle
  {
   // Declare and initialize GLOBAL (CLASS) constants
  final int STOPPED = 0;
  final int LEFT = 1;
  final int RIGHT = 2;
   final int UP = 3;
  final int DOWN = 4;


// Declare GLOBAL (CLASS) instance objects & variables || (Do not 
// initialize)
private RectF rect;
private float xVelocity;
private float yVelocity;
private int color;
private float playerSpeed;
private float length;
// X is the far left of the rectangle which forms our player
// private float x; // x Holds the horizontal position on the screen of the 
// player
private float y;

// Declare and initialize GLOBAL (CLASS) objects & variables
private float circleWidth = 100;   // Ball width 10px by 10px squared
private float circleHeight = 100;  // Ball height 10px by 10px squared
private int playerMoving = STOPPED;

// PlayerCircle NO-Arg Constructor
PlayerCircle(int screenX, int screenY)
{
    // player is 100 pixels wide and 100 pixels high
    length = 100; // width
    float height = 100;  // height

    xVelocity = 150;
    yVelocity = 150;

    // Set starting position of player on x coordinate
    // Start player in roughly the screen left
    //x = screenX / 4;
    x = (Globals.GAME_WIDTH_X / 2) + 400 ;

    // Set starting position of bat on y coordinate
    // Y is the top coordinate
    //y = screenY - 20;
    y = (Globals.GAME_HEIGHT_Y / 2) - 400;


    rect = new RectF(x, y, x + length, y + height);

    // Set player circle speed
    // How fast is the player circle in pixels per second
    playerSpeed = 350;
}

// Set Getters and Setters
// This is a getter method to make the rectangle that
// defines our ball available in BreakoutView class
RectF getRect()
{
    // Return a reference to the rect object (so we can draw it, collision 
 //detection, ect)
    return rect;
}
// This method will be used to change/set if the player is going left, 
 //right, up, down, or nowhere
void setMovementState(int state)
{
    // Set playerMoving to passed in "state"
    playerMoving = state;
}

// Reset method is passed in the screen resolutions
void reset()
{
    rect.left = Globals.GAME_HEIGHT_Y / 6;
    rect.top = Globals.GAME_WIDTH_X - 20;
    // Places the right and bottom of the ball appropriately to match the 
    //left/top based on the ball width/height
    rect.right = Globals.GAME_HEIGHT_Y / 2 + circleWidth;
    rect.bottom = Globals.GAME_WIDTH_X - 20 - circleHeight;
}

// This update method will be called once per frame from update in 
//CustomView1
// It determines if the player needs to move and changes the coordinates
// contained in rect if necessary
void update(long fps) // Pass in the most recent frame rate
{
    if (playerMoving == LEFT)
    {
        // Because we are doing this multiple times a second, we must divide 
     //by fps
        x = x - playerSpeed / fps;
    }

    if(playerMoving == RIGHT)
    {
        // Because we are doing this multiple times a second, we must divide 
    //by fps
        x = x + playerSpeed / fps;
    }

    if (playerMoving == UP)
    {
        // Because we are doing this multiple times a second, we must divide 
    //by fps
        y = y - playerSpeed / fps;
    }

    if (playerMoving == DOWN)
    {
        // Because we are doing this multiple times a second, we must divide 
    //by fps
        y = y + playerSpeed / fps;
    }

    // Update position of player to the rect object
    rect.left = x;
    rect.right = x + length;
    rect.bottom = y;
    rect.top = y + length;

}
}

以下是我的EnemyCircle1类的代码:

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;

 public class EnemyCircle1
{
// Declare and initialize GLOBAL (CLASS) constants
final int STOPPED = 0;
final int LEFT = 1;
final int RIGHT = 2;

// Declare GLOBAL (CLASS) instance objects & variables || (Do not 
 //initialize)
private RectF rect;             // Ball object for drawing, collision 
 //detection, and location
private float xVelocity;        // Horizontal velocity/speed of the ball ( - 
 //x = ball going left, +x = ball going right)
//private float yVelocity;        // Vertical velocity/speed of the ball ( - 
 //y = ball going up, +y - ball going down)
private float length;
// private float height;
private int color;
private float enemySpeed;

// X is the far left of the rectangle which forms our bar
private float xCoordinate;  

// Y is the top coordinate of the bar
private float yCoordinate;  

// Declare and initialize GLOBAL (CLASS) objects & variables
private float ballWidth = 100;   // Ball width 10px by 10px squared
private float ballHeight = 100;  // Ball height 10px by 10px squared
private int enemyMoving = STOPPED;

// Ball NO-Arg Constructor
EnemyCircle1()
{
    // player is 100 pixels wide and 100 pixels high
    length = 100;
    float height = 100;

    xVelocity = 300;
    //yVelocity = 0;

    // Set starting position of player on x coordinate
    xCoordinate = Globals.GAME_WIDTH_X / 2;

    // Set starting position of bat on y coordinate
    yCoordinate = (Globals.GAME_HEIGHT_Y / 2) - 50;

    rect = new RectF(xCoordinate, yCoordinate, xCoordinate + length, 
    yCoordinate + height);

    // Set enemy speed in pixels per second
    enemySpeed = 150;
}


// Set Getters and Setters
RectF getRect()
{
    // Return a reference to the rect object (so we can draw it, collision 
   //detection, ect)
    return rect;
}

// Reverse the direction of the ball in the X direction
void reverseXVelocity()
{
    // Reverse X Direction
    xVelocity = -xVelocity;
}

// ClearObstacleY method is passed y and is used to reset the top and bottom 
// positions of the ball
void clearObstacleY(float y)
{
    rect.bottom = y;
    rect.top = y - ballHeight;
}
// ClearObstacleY method is passed x and is used to reset the left and right 
// positions of the ball
void clearObstacleX(float x)
{
    rect.left = x;
    rect.right = x + ballWidth;
}
// Reset method is passed in the screen resolutions
void reset()
{
    rect.left = Globals.GAME_HEIGHT_Y / 2;
    rect.top = Globals.GAME_WIDTH_X - 20;
    // Places the right and bottom of the ball appropriately to match the 
   //left/top based on the ball width/height
    rect.right = Globals.GAME_HEIGHT_Y / 2 + ballWidth;
    rect.bottom = Globals.GAME_WIDTH_X - 20 - ballHeight;
}

void setMovementState(int state)
{
    // Set playerMoving to passed in "state"
    enemyMoving = state;
}

// Update method is passed the time the previous frame took
public void update(long fps)
{


    if (enemyMoving == LEFT)
    {
        xCoordinate = xCoordinate - xVelocity / fps;
    }
    if (enemyMoving == RIGHT)
    {
        xCoordinate = xCoordinate + xVelocity / fps;
    }

    // Update rect.left and rect.top by adding (velocity divided by fps)
    rect.left = rect.left + (xVelocity / fps);
    rect.right = rect.left + ballWidth;
  }
  }

最后这是我的CustomView1类的代码:

import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.RectF;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class CustomView1 extends SurfaceView implements Runnable
{
private Thread gameThread = null;

// Game is paused at the start, only used internally inside the thread
private boolean paused = true;

    // We will see it in action in the draw method soon.
    private SurfaceHolder ourHolder;

    private volatile boolean playing;

        private Canvas canvas;
        private Paint paint;

    // How wide and high is the screen?
    private int screenX;
    private int screenY;

    // This variable tracks the game frame rate
    private long fps;

    // This is used to help calculate the fps, stores the result of each 
    //frame
    private long timeThisFrame;

 // Main Game Objects
 // Player Circle Object
 private PlayerCircle player;
 // Enemy Circle 1 Object
 private EnemyCircle1 enemyCircle1;
 // Enemy Circle 2 Object
 //private EnemyCircle2 enemyCircle2;

 //***********************************************************************

 // MAIN CONSTRUCTOR
 public CustomView1(Context context, int x, int y)
 {
    super(context);

    // Initialize ourHolder and paint objects
    ourHolder = getHolder();
    paint = new Paint();

    // Initialize screenX and screenY because x and y are the passed 
    //variables from constructor
    screenX = x;
    screenY = y;

    // Set the Global Screen Size Variables
    Globals.GAME_WIDTH_X = screenX;
    Globals.GAME_HEIGHT_Y = screenY;

    // Player Circle Object
    player = new PlayerCircle(screenX, screenY);

    // Enemy Circle 1 Object
    enemyCircle1 = new EnemyCircle1();
    enemyCircle1.setMovementState(enemyCircle1.LEFT);

    // Enemy Circle 2 Object
    //enemyCircle2 = new EnemyCircle2();


    // Restart the game (to reset all positions)
    restart();
  }

 //************************************************************************

 // Runs when the OS calls "onPause" on BreakoutActivity method
 public void pause()
 {
    // Set playing to false
    playing = false;

    // Attempt to stop the gameThread
    try
    {
        // End the gameThread
        gameThread.join();
    }
    // If operation fails, throw error in Logs
    catch (InterruptedException e)
    {
        Log.e("Error:", "joining thread");
    }

  }

  // Runs when the OS calls "onResume" on BreakoutActivity method
  public void resume()
  {
    // Set playing to true
    playing = true;
    // Initialize the gameThread
    gameThread = new Thread(this);
    // Start the gameThread (Run Method begins to execute)
    gameThread.start();
  }

  //*************************************************************

 @Override
 public void run()
 {
    // Only continue if "playing" is true
    while (playing)
    {
        // Capture the current time in milliseconds and set it to 
       //startFrameTime
        long startFrameTime = System.currentTimeMillis();

        // Update the frame, only if "paused" is false
        if(!paused)
        {
            update();
        }

        // Draw the frame
        draw();

        // Calculate the fps for this frame, We can then use the result to
        // time animations and more.
        timeThisFrame = System.currentTimeMillis() - startFrameTime;
        // Check whether "timeThisFrame" is not equal to ZERO
        if (timeThisFrame >= 1)
        {
            // Get the frame per second that this frame took to execute
            fps = 1000 / timeThisFrame;
            Globals.AVERAGE_FPS = fps;
        }
      }
  }

  //*******************************************************************

  // Update game method (Private or Public?)
 private void update()
 {

    player.update(Globals.AVERAGE_FPS);
    Globals.PLAYER_CIRCLE_X_COORD = (player.getRect().left);
    Globals.PLAYER_CIRCLE_Y_COORD = (player.getRect().top);
    Globals.PLAYER_CIRCLE_WIDTH = Math.abs(player.getRect().width());
    Globals.PLAYER_CIRCLE_HEIGHT = Math.abs(player.getRect().height());

    enemyCircle1.update(Globals.AVERAGE_FPS);
    Globals.ENEMY_CIRCLE_1_X_COORD = (enemyCircle1.getRect().left);
    Globals.ENEMY_CIRCLE_1_Y_COORD = (enemyCircle1.getRect().top);
    Globals.ENEMY_CIRCLE_1_WIDTH = Math.abs(enemyCircle1.getRect().width());
    Globals.ENEMY_CIRCLE_1_HEIGHT = 
    Math.abs(enemyCircle1.getRect().height());

    //enemyCircle2.update(Globals.AVERAGE_FPS);

    // Check the Player for colliding with canvas boundaries walls
        // If the player hits the right hand side of screen
            // If the right coordinate of the player is colliding with the 
            //right of the screen - 20
            if (player.getRect().right > Globals.GAME_WIDTH_X - 20)
            {
                player.setMovementState(player.STOPPED);
                Log.i("CustomView1.update()","Player Collision with Right" + 
                "hand side of screen");
            }
          // If the player hits the left hand side of screen
            // If the left coordinate of the player is colliding with the 
            //left of the screen + 20
            if (player.getRect().left < (0) + 20)
            {
                player.setMovementState(player.STOPPED);
                Log.i("CustomView1.update()", "Player Collision with Left" +
            "hand side of screen");
            }
         // If the player hits the bottom hand side of screen
            // If the bottom coordinate of the player is colliding with the 
            //bottom of the screen + 20
            if (player.getRect().bottom > Globals.GAME_HEIGHT_Y - 200)
            {
                player.setMovementState(player.STOPPED);
                System.out.println("Player Collision with Bottom handside" + 
                "of screen");
            }
           // If the player hits the top hand side of screen
            // If the top coordinate of the player is colliding with the top 
            //of the screen + 20
            if (player.getRect().top < (0) + 410)
            {
                player.setMovementState(player.STOPPED);
                System.out.println("Player Collision with Top handside of" + 
                "screen");
            }
        // Check if the Player is colliding with Objects
        // Check if the player is colliding with enemyCircle1


                if (RectF.intersects(player.getRect(), 
                     enemyCircle1.getRect()))
                {
                    System.out.println("Detected collision!!!");
                    player.setMovementState(player.STOPPED);
                    enemyCircle1.setMovementState(enemyCircle1.STOPPED);
                }


       // Check the Enemy Circle One Object for colliding with walls
        // If the ball hits right wall bounce
            // If the right coordinate of the ball is colliding with the 
            //right of the screen - 10
            // (Because the ball is 10 pixels wide so it measures from left 
            //to right)
            if(enemyCircle1.getRect().right > Globals.GAME_WIDTH_X - 10)
            {
                // Reverse the ball's X velocity so it turns around and goes 
                //the other way
                enemyCircle1.reverseXVelocity();
                // Clears the Y Obstacle and bumps the ball XX pixels away 
                //so the ball doesn't get caught in a loop
                enemyCircle1.clearObstacleX(Globals.GAME_WIDTH_X - 120);
                System.out.println("EnemyCircle1 hit right hand side of" + 
               "screen, reversing direction to go left.");
                // Clears the Y Obstacle and bumps the ball 22 pixels away 
                //so the ball doesn't get caught in a loop
                //enemyCircle1.clearObstacleX(Globals.GAME_HEIGHT_X - 22);
            }
         // If the ball hits left wall bounce
            // If the left coordinate of the ball is colliding with the left 
            //of the screen
            if(enemyCircle1.getRect().left < 0)
            {
                // Reverse the ball's X velocity so it turns around and goes 
                 //the other way
                enemyCircle1.reverseXVelocity();
                // Clears the Y Obstacle and bumps the ball XX pixels away 
                //so the ball doesn't get caught in a loop
                enemyCircle1.clearObstacleX(25);
                System.out.println("EnemyCircle1 hit left hand side of"+ 
                "screen, reversing direction to go right.");
                // Clears the Y Obstacle and bumps the ball 2 pixels away so 
                //the ball doesn't get caught in a loop
                //enemyCircle1.clearObstacleX(2);
            }
        }

      //****************************************************************

  // Restart game method
  void restart()
  {
    enemyCircle1.reset();

    //enemyCircle2.reset(screenX, screenY);
  }

  //**************************************************

  private void draw()
  {
    // Make sure our drawing surface is valid or game will crash
    if (ourHolder.getSurface().isValid())
    {
        // Lock the canvas and prepares it to be ready to be drawn upon
        canvas = ourHolder.lockCanvas();

        // Draw the background color and clears/sets the screen to a full 
         //color (white)
        canvas.drawColor(Color.argb(255, 255, 255, 255));

        // Draw everything and all objects to the screen

        // Choose the brush color for drawing the first object(name of 
         //object) (white)
        paint.setColor(Color.RED);
        // Draw the User's Player Circle
        canvas.drawRect(player.getRect(), paint);

        // Choose the brush color for drawing the Enemy One (orange)
        paint.setColor(Color.argb(255, 249, 129, 0));
        // Draw the Enemy Circle One Object
        canvas.drawRect(enemyCircle1.getRect(), paint);
        // After everything is drawn to screen...
        // Show everything we have drawn
        ourHolder.unlockCanvasAndPost(canvas);
    }
   }

    // The SurfaceView class implements onTouchListener
    // So we can override this method and detect screen touches.
    @Override
    public boolean onTouchEvent(MotionEvent motionEvent)
    {

        switch (motionEvent.getAction() & MotionEvent.ACTION_MASK)
        {
            // User has touched the screen
            case MotionEvent.ACTION_DOWN:
                // FIRST Un-pause the update method
                paused = false;

                // Check to see if coordinates of touch are on the very 
               //right hand side of screen
                if((motionEvent.getX() > (Globals.GAME_WIDTH_X / 2) + 300))
                {
                    System.out.println("User touched the very right hand" +
                   "side of screen.(Wants the player to go right.)");
                    // Check if Player is colliding with right hand side of 
                    //walls before continuing
                    if (player.getRect().right > Globals.GAME_WIDTH_X - 20)
                    {
                        //player.setMovementState(player.STOPPED);
                    }
                    else
                    {
                        player.setMovementState(player.RIGHT);
                    }
                }
                // Check to see if coordinates of touch are on the very left 
               //hand side of screen
                else if ((motionEvent.getX() < (Globals.GAME_WIDTH_X / 2) - 
                 300))
                {
                    System.out.println("User touched the very left hand" + 
                     "side of screen.(Wants the player to go left.)");
                    // Check if Player is colliding with right hand side of 
                    //walls before continuing
                    if (player.getRect().left < (0) + 20)
                    {
                        //player.setMovementState(player.STOPPED);
                    }
                    else
                    {
                        player.setMovementState(player.LEFT);
                    }
                }
                // Check to see if coordinates of touch are on the very 
               //bottom side of screen
                else if ((motionEvent.getY() > (Globals.GAME_HEIGHT_Y / 2) + 
                     10))
                {
                    System.out.println("User touched the very bottom side"+ 
                     "of screen.(Wants the player to go down.)");
                    // Check if Player is colliding with bottom hand side of 
                     //walls before continuing
                    if (player.getRect().bottom > Globals.GAME_HEIGHT_Y - 
                     100)
                    {
                        //player.setMovementState(player.STOPPED);
                    }
                    else
                    {
                        player.setMovementState(player.DOWN);
                    }
                }
                // Check to see if coordinates of touch are on the very top 
                //side of screen
                else if ((motionEvent.getY() < (Globals.GAME_HEIGHT_Y / 2) + 
                   10))
                {
                    System.out.println("User touched the very top side" +  
                   "of screen.(Wants the player to go up.)");
                    // Check if Player is colliding with top hand side of 
                    //walls before continuing
                    if (player.getRect().top < (0) + 410)
                    {
                        //player.setMovementState(player.STOPPED);
                    }
                    else
                    {
                        player.setMovementState(player.UP);
                    }
                }
                break;
            // User has removed finger from screen
            case MotionEvent.ACTION_UP:
                System.out.println("User lifted their finger from the " +  
                 "screen.)");
                // Stop the player from moving
                player.setMovementState(player.STOPPED);
                break;
        }
        return true;

       } // END onTouchEvent Method

   } // END CustomView1 Class

对不起,如果有任何混淆,请告诉我,本网站的格式化程序令人困惑,我知道我的代码中有很多评论:D

1 个答案:

答案 0 :(得分:0)

尝试以下代码:)

PlayerCircle Class:

public class PlayerCircle
{
// Declare and initialize GLOBAL (CLASS) constants
final int STOPPED = 0;
final int LEFT = 1;
final int RIGHT = 2;
final int UP = 3;
final int DOWN = 4;


// Declare GLOBAL (CLASS) instance objects & variables || (Do not
// initialize)
private RectF rect;
private float xVelocity;
private float yVelocity;
private int color;
private float playerSpeed;
private float length;
// X is the far left of the rectangle which forms our player
private float x; // x Holds the horizontal position on the screen of the
// player
private float y;

// Declare and initialize GLOBAL (CLASS) objects & variables
private float circleWidth = 100;   // Ball width 10px by 10px squared
private float circleHeight = 100;  // Ball height 10px by 10px squared
private int playerMoving = STOPPED;

// PlayerCircle NO-Arg Constructor
PlayerCircle(int screenX, int screenY)
{
    // player is 100 pixels wide and 100 pixels high
    length = 100; // width
    float height = 100;  // height

    xVelocity = 150;
    yVelocity = 150;

    // Set starting position of player on x coordinate
    // Start player in roughly the screen left
    //x = screenX / 4;
    x = (Globals.GAME_WIDTH_X / 2) + 400 ;

    // Set starting position of bat on y coordinate
    // Y is the top coordinate
    //y = screenY - 20;
    y = (Globals.GAME_HEIGHT_Y / 2) - 400;


    rect = new RectF(x, y, x + length, y + height);

    // Set player circle speed
    // How fast is the player circle in pixels per second
    playerSpeed = 350;
}

// Set Getters and Setters
// This is a getter method to make the rectangle that
// defines our ball available in BreakoutView class
RectF getRect()
{
    // Return a reference to the rect object (so we can draw it, collision
    //detection, ect)
    return rect;
}
// This method will be used to change/set if the player is going left,
//right, up, down, or nowhere
void setMovementState(int state)
{
    // Set playerMoving to passed in "state"
    playerMoving = state;
}

// Reset method is passed in the screen resolutions
void reset()
{
    rect.left = Globals.GAME_HEIGHT_Y / 2;
    rect.top = Globals.GAME_WIDTH_X - 20;
    // Places the right and bottom of the ball appropriately to match the
    //left/top based on the ball width/height
    rect.right = Globals.GAME_HEIGHT_Y / 2 + circleWidth;
    rect.bottom = Globals.GAME_WIDTH_X - 20 + circleHeight;
}

// This update method will be called once per frame from update in
//CustomView1
// It determines if the player needs to move and changes the coordinates
// contained in rect if necessary
void update(long fps) // Pass in the most recent frame rate
{
    if (playerMoving == LEFT)
    {
        // Because we are doing this multiple times a second, we must divide
        //by fps
        x = x - playerSpeed / fps;
    }

    if(playerMoving == RIGHT)
    {
        // Because we are doing this multiple times a second, we must divide
        //by fps
        x = x + playerSpeed / fps;
    }

    if (playerMoving == UP)
    {
        // Because we are doing this multiple times a second, we must divide
        //by fps
        y = y - playerSpeed / fps;
    }

    if (playerMoving == DOWN)
    {
        // Because we are doing this multiple times a second, we must divide
        //by fps
        y = y + playerSpeed / fps;
    }

    // Update position of player to the rect object
    rect.left = x;
    rect.right = x + length;
    rect.top = y;
    rect.bottom = y + length;

}
}

EnemyCircle1类:

public class EnemyCircle1
{
// Declare and initialize GLOBAL (CLASS) constants
final int STOPPED = 0;
final int LEFT = 1;
final int RIGHT = 2;

// Declare GLOBAL (CLASS) instance objects & variables || (Do not
//initialize)
private RectF rect;             // Ball object for drawing, collision
//detection, and location
private float xVelocity;        // Horizontal velocity/speed of the ball ( -
//x = ball going left, +x = ball going right)
//private float yVelocity;        // Vertical velocity/speed of the ball ( -
//y = ball going up, +y - ball going down)
private float length;
// private float height;
private int color;
private float enemySpeed;

// X is the far left of the rectangle which forms our bar
private float xCoordinate;

// Y is the top coordinate of the bar
private float yCoordinate;

// Declare and initialize GLOBAL (CLASS) objects & variables
private float ballWidth = 100;   // Ball width 10px by 10px squared
private float ballHeight = 100;  // Ball height 10px by 10px squared
private int enemyMoving = STOPPED;

// Ball NO-Arg Constructor
EnemyCircle1()
{
    // player is 100 pixels wide and 100 pixels high
    length = 100;
    float height = 100;

    xVelocity = 300;
    //yVelocity = 0;

    // Set starting position of player on x coordinate
    xCoordinate = Globals.GAME_WIDTH_X / 2;

    // Set starting position of bat on y coordinate
    yCoordinate = (Globals.GAME_HEIGHT_Y / 2) - 50;

    rect = new RectF(xCoordinate, yCoordinate, xCoordinate + length,
            yCoordinate + height);

    // Set enemy speed in pixels per second
    enemySpeed = 150;
}


// Set Getters and Setters
RectF getRect()
{
    // Return a reference to the rect object (so we can draw it, collision
    //detection, ect)
    return rect;
}

// Reverse the direction of the ball in the X direction
void reverseXVelocity()
{
    // Reverse X Direction
    xVelocity = -xVelocity;
}

// ClearObstacleY method is passed y and is used to reset the top and bottom
// positions of the ball
void clearObstacleY(float y)
{
    rect.bottom = y;
    rect.top = y - ballHeight;
}
// ClearObstacleY method is passed x and is used to reset the left and right
// positions of the ball
void clearObstacleX(float x)
{
    rect.left = x;
    rect.right = x + ballWidth;
}
// Reset method is passed in the screen resolutions
void reset()
{
    rect.left = Globals.GAME_HEIGHT_Y / 2;
    rect.top = Globals.GAME_WIDTH_X - 20;
    // Places the right and bottom of the ball appropriately to match the
    //left/top based on the ball width/height
    rect.right = Globals.GAME_HEIGHT_Y / 2 + ballWidth;
    rect.bottom = Globals.GAME_WIDTH_X - 20 + ballHeight;
}

void setMovementState(int state)
{
    // Set playerMoving to passed in "state"
    enemyMoving = state;
}

// Update method is passed the time the previous frame took
public void update(long fps)
{


    if (enemyMoving == LEFT)
    {
        xCoordinate = xCoordinate - xVelocity / fps;
    }
    if (enemyMoving == RIGHT)
    {
        xCoordinate = xCoordinate + xVelocity / fps;
    }

    // Update rect.left and rect.top by adding (velocity divided by fps)
    rect.left = rect.left + (xVelocity / fps);
    rect.right = rect.left + ballWidth;
}
}