我如何引用特定对象?

时间:2014-01-08 14:45:41

标签: java reference

private void addBricks(){
    for (int i = 0; i < NBRICK_ROWS; i++){
        for (int j = 0; j < NBRICKS_PER_ROW; j++){

            int y = BRICK_Y_OFFSET + (i * (BRICK_HEIGHT + BRICK_SEP));
            int x = (BRICK_X_OFFSET) + (j * (BRICK_WIDTH + BRICK_SEP));
            brick = new GRect (x, y, BRICK_WIDTH, BRICK_HEIGHT );
            add (brick);
        }
    }
}

我正在尝试在这里制作突破性游戏,这是一段代码。

我在画布上添加了一组矩形。在我的计划中,我想在球击中它们时将其中的一部分移除。问题是我不知道具体如何引用它们。也就是说,我不知道在remove()中输入哪些参数,因为它们都是brick

创建的

谢谢!

以下整个计划

import acm.graphics.*;
import acm.program.*;
import acm.util.*;

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class Breakout extends GraphicsProgram {

/** Width and height of application window in pixels */
    public static final int APPLICATION_WIDTH = 440;
    public static final int APPLICATION_HEIGHT = 660;

/** Dimensions of game board (usually the same) */
    private static final int WIDTH = 400;
    private static final int HEIGHT = 600;

/** Dimensions of the paddle */
    private static final int PADDLE_WIDTH = 60;
    private static final int PADDLE_HEIGHT = 10;

/** Offset of the paddle up from the bottom */
    private static final int PADDLE_Y_OFFSET = 30;

/** Number of bricks per row */
    private static final int NBRICKS_PER_ROW = 10;

/** Number of rows of bricks */
    private static final int NBRICK_ROWS = 10;

/** Separation between bricks */
    private static final int BRICK_SEP = 4;

/** Width of a brick */
    private static final int BRICK_WIDTH =
      (WIDTH - (NBRICKS_PER_ROW - 1) * BRICK_SEP) / NBRICKS_PER_ROW;

/** Height of a brick */
    private static final int BRICK_HEIGHT = 8;

/** Radius of the ball in pixels */
    private static final int BALL_RADIUS = 10;

/** Offset of the top brick row from the top */
    private static final int BRICK_Y_OFFSET = 70;

/** Offset of the side bricks from the sides of game window so that the whole set of bricks are in the centre */
    private static final int BRICK_X_OFFSET = ((WIDTH - NBRICKS_PER_ROW * (BRICK_WIDTH + BRICK_SEP) + BRICK_SEP) / 2);

/** Number of turns */
    private static final int NTURNS = 3;

/** Game speed */
    private static final int DELAY = 1;

/* Method: run() */
/** Runs the Breakout program. */
    public void run() {
        addMouseListeners();
        addWorld();
        runGame();
    }

    private void addWorld(){
        setSize (APPLICATION_WIDTH, APPLICATION_HEIGHT);
        addPlayingBox();
        addBricks();
        addPaddle();
    }

    /* lives and number of bricks will be check before game runs
     * if there are either no lives of bricks left game is over
     * ball and ball physics are only added to the screen after there is a mouse click.
     */
    private void runGame(){
        while (true){
                // add a gameover label
        waitForClick();
        addBall();
        addBallMotion();
        }
    }

    //adds the playing area onto screen
    private void addPlayingBox(){

        topBounds = new GLine (0, 0, WIDTH, 0);
        bottomBounds = new GLine (0, HEIGHT, WIDTH, HEIGHT);
        leftBounds = new GLine (0, 0, 0, HEIGHT);
        rightBounds = new GLine (WIDTH, 0, WIDTH, HEIGHT);
        add (topBounds);
        add (bottomBounds);
        add (leftBounds);
        add (rightBounds);
    } 

    /*bricks are added to the top row and left column 1st and consequently to the its right column 
     * and to the next row when a row is all filled up
     */
    private void addBricks(){
        for (int i = 0; i < NBRICK_ROWS; i++){
            for (int j = 0; j < NBRICKS_PER_ROW; j++){

                int y = BRICK_Y_OFFSET + (i * (BRICK_HEIGHT + BRICK_SEP));
                int x = (BRICK_X_OFFSET) + (j * (BRICK_WIDTH + BRICK_SEP));
                brick = new GRect (x, y, BRICK_WIDTH, BRICK_HEIGHT );
                colorBrick(brick, i);
                add (brick);
            }
        }
    }

    // every consecutive 2 rows are colored the same
    private void colorBrick(GRect brick, int rowNumber){
        brick.setFilled (true);
        switch (rowNumber + 1) {
        case 1: case 2: brick.setColor(Color.red);
        break;
        case 3: case 4: brick.setColor(Color.orange);
        break;
        case 5: case 6: brick.setColor(Color.yellow);
        break;
        case 7: case 8: brick.setColor(Color.green);
        break;
        case 9: case 10:brick.setColor(Color.cyan);
        break;
        }
    }

    //adds paddle to screen
    private void addPaddle(){
        paddle = new GRect (WIDTH / 2 - PADDLE_WIDTH / 2, HEIGHT - PADDLE_Y_OFFSET, PADDLE_WIDTH, PADDLE_HEIGHT);
        paddle.setFilled(true);
        paddle.setColor (Color.BLACK);
        add (paddle);
    }

    //creates motion for the paddle according to mouse movement
    public void mouseMoved(MouseEvent e){
        paddle.setLocation ((e.getX() - PADDLE_WIDTH / 2), (double) (HEIGHT - PADDLE_Y_OFFSET));

    /* checks if the paddle within the playing area
     * if not, the paddles will stay at the extremities*/
        if ( paddle.getX() > (WIDTH - PADDLE_WIDTH)){
            paddle.setLocation((double) (WIDTH - PADDLE_WIDTH), (double) (HEIGHT - PADDLE_Y_OFFSET));
        }
        if ( paddle.getX() < 0){
            paddle.setLocation((double) 0, (double) (HEIGHT - PADDLE_Y_OFFSET));
        }
    }

    /* creates the ball 
     */
    private void addBall(){

        double ballInitXPosition = WIDTH / 2 - BALL_RADIUS;
        double ballInitYPosition = HEIGHT / 2 - BALL_RADIUS;
        ball = new GOval (ballInitXPosition, ballInitYPosition,
                            BALL_RADIUS * 2, BALL_RADIUS * 2);
        ball.setFilled(true);
        ball.setColor(Color.BLACK);
        add (ball);
    }

    /* kick start the ball motion with predetermined values
     */
    private void addBallMotion(){
    // y component of starting velocity; pixels per second
        vy = 0.3;

    /* x component of starting velocity; pixels per second
     * which ranges according to the random generator
     * can be negative or positive, ball can go left or right with equal chances
     * angle must not be 0 or 180 degrees otherwise the ball will not move anywhere else
     */
        vx = rgen.nextDouble(0.0, 0.5);
        if (rgen.nextBoolean(0.5)){
            vx = -vx;
        }
        while (true){
        ball.move(vx, vy);
        checkCollision();
        pause(DELAY);
        }
    }

    private void checkCollision(){
        checkWallCollision();
        checkBrickAndPaddleCollision();
    }

    //checks for wall collision
    private void checkWallCollision(){

        if ( (getCollidingObject() == leftBounds) || (getCollidingObject() == rightBounds )){
            vx = -vx;
        }
    //checks for floor and ceiling collision collision
        if ( (getCollidingObject() == topBounds) ){
            vy = -vy;
        }
        if ( (getCollidingObject() == bottomBounds)){
            remove (ball);
            runGame();

        }
    }

    /* check if there is any collision with brick or paddle
     */
    private void checkBrickAndPaddleCollision(){
        GObject collider = getCollidingObject();

        /* brick is removed and y direction of ball is reversed
         * bricks counter goes down by 1 and score goes up by 1 
         */
        if (collider != paddle && 
            collider != null && 
            collider != topBounds && 
            collider != rightBounds && 
            collider != bottomBounds && 
            collider != leftBounds){
            remove(collider);
            vy = -vy;
        }

        /* collide with paddle, y direction is reversed
         */
        else if (collider == paddle){
            vy = -vy;
        }
    } 

    //check for collision at the 4 sides of the ball
    //starting with the top and going clockwise
    //returns the object nearest to the screen that touches the sides of the ball
    private GObject getCollidingObject(){
        GObject ballTop = getElementAt ( (ball.getX() + BALL_RADIUS), (ball.getY() - .1) );
        GObject ballRight = getElementAt ( (ball.getX() + (BALL_RADIUS * 2) + .1), (ball.getY() + BALL_RADIUS) );
        GObject ballBottom = getElementAt ( (ball.getX() + BALL_RADIUS), ball.getY() + (BALL_RADIUS * 2) + .1);
        GObject ballLeft= getElementAt ( (ball.getX() - .1), (ball.getY() + BALL_RADIUS) );

        if (ballTop != null){
            return (ballTop);
        }
        else if (ballRight != null){
            return (ballRight);
        }
        else if (ballBottom != null){
            return (ballBottom);
        }
        else if (ballLeft != null){
            return (ballLeft);
        }
        return (null);
    }

    private GRect paddle;   // creates a paddle that only moves linearly according to mouses' x coordinate
    private GRect brick;

    private GOval ball;
    private double vx, vy;  // x and y components of the ball's velocity

    private RandomGenerator rgen = RandomGenerator.getInstance();

    // creates a bounding box that is the playing area
    private GLine topBounds;    
    private GLine bottomBounds;
    private GLine leftBounds;
    private GLine rightBounds;
}

3 个答案:

答案 0 :(得分:1)

你必须维护一个单独的砖块存在的映射。我想你也需要这样的东西来进行碰撞检测。我会做类似以下的事情。

public class Game
{
    Collection<Brick> bricks;
    Ball ball;

    public void initLocation()
    {
        for (int i = 0; i < NBRICK_ROWS; i++)
        {
            for (int j = 0; j < NBRICKS_PER_ROW; j++)
            {

                int y = BRICK_Y_OFFSET + (i * (BRICK_HEIGHT + BRICK_SEP));
                int x = (BRICK_X_OFFSET) + (j * (BRICK_WIDTH + BRICK_SEP));
                bricks.add(new Brick(x, y));
            }
        }
    }

    public void drawBricks()
    {
        for (Brick brick : bricks)
        {
            brickRect = new GRect(x, y, BRICK_WIDTH, BRICK_HEIGHT);
            add(brick);
        }
    }

}

public class Brick
{
    int x;
    int y;

    public Brick(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

public class Ball
{
    int x;
    int y;
}

此代码不完整,但应该让您了解如何保持对砖块的引用。当你检查碰撞时,你可以遍历砖块,找到与球发生碰撞的任何东西,然后在那块砖上调用remove()。

答案 1 :(得分:1)

因此,如果您使用外部库(add())中的acm.graphics,则需要保留自己添加的砖块副本。也许添加一个boolean值的二维数组或类似@thattolleyguy的结构建议你的类然后添加它们的方法

 private void addBrick(int x, int y)
 {
   brickArray[x][y] = true; //your own copy of brick locations

   int yloc = BRICK_Y_OFFSET + (i * (BRICK_HEIGHT + BRICK_SEP));
   int xloc = (BRICK_X_OFFSET) + (j * (BRICK_WIDTH + BRICK_SEP));
   brick = new GRect (xloc, yloc, BRICK_WIDTH, BRICK_HEIGHT );
   add (brick);
 }

然后,您可以使用removeBrick方法从阵列中轻松删除它们(将该位置设置为false)和外部库(或者您可能需要重绘)。


同时

对象引用brick仅在此函数中引用,因此它只需要是本地

private void addBricks()
{
 GRect brick;
 ...
   add(brick);
 ...
}

答案 2 :(得分:0)

如果我是你,我会将所有GRect存储在List<GRect>中。此列表应位于您的运营中心。

我认为绘图是由repaint()方法触发的。可能在sperate线程中,您需要检查球与每个GRect之间的距离,当您发现与球相交的GRect时,您可以将GRect传递给{{1} }}。

一个简单的解决方案是在每个remove()中保留isVisible标记,并在GRect中对其进行修改。顺便说一句,Java对象通过引用传递,您的修改将生效。