/* * File: Breakout.java * ------------------- * Name: * Section Leader: * * This file will eventually implement the game of Breakout. */ 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 = 400; public static final int APPLICATION_HEIGHT = 600; /** Dimensions of game board (usually the same) */ private static final int WIDTH = APPLICATION_WIDTH; private static final int HEIGHT = APPLICATION_HEIGHT; /** 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; /** Number of turns */ private static int NTURNS = 3; /* Method: run() */ /** Runs the Breakout program. */ public void run() { /* You fill this in, along with any subsidiary methods */ addMouseListeners(); initGame(); } private void initGame() { // this.setSize(APPLICATION_WIDTH, APPLICATION_HEIGHT); for (int i = 0; i < NBRICK_ROWS; i++) { for (int j = 0; j < NBRICKS_PER_ROW; j++) { GRect gr = new GRect(0 + j*(BRICK_WIDTH+BRICK_SEP), BRICK_Y_OFFSET + i*(BRICK_HEIGHT+BRICK_SEP), BRICK_WIDTH, BRICK_HEIGHT); gr.setFilled(true); switch(i) { case 0: case 1: gr.setFillColor(Color.red); break; case 2: case 3: gr.setFillColor(Color.ORANGE); break; case 4: case 5: gr.setFillColor(Color.YELLOW); break; case 6: case 7: gr.setFillColor(Color.GREEN); break; case 8: case 9: gr.setFillColor(Color.CYAN); break; default: gr.setFillColor(Color.black); } add(gr); brickCount++; } } paddle = new GRect((WIDTH - PADDLE_WIDTH)/2, HEIGHT - PADDLE_HEIGHT - PADDLE_Y_OFFSET, PADDLE_WIDTH, PADDLE_HEIGHT); paddle.setFilled(true); paddle.setFillColor(Color.black); add(paddle); oval = new GOval(paddle.getX() + (paddle.getWidth() - BALL_RADIUS)/2, paddle.getY() - BALL_RADIUS, BALL_RADIUS, BALL_RADIUS); oval.setFilled(true); oval.setColor(Color.black); add(oval); printGameInfo(); startGame(); } public void mouseMoved(MouseEvent e) { if (e.getX() <= getWidth() - paddle.getWidth()) { paddle.setLocation(e.getX(), paddle.getY()); } } private void startGame() { vx = rgen.nextDouble(3.0, 5.0); vy = -(rgen.nextDouble(3.0, 5.0)); if (rgen.nextBoolean(0.5)) vx = -vx; while (isAlived() == true && NTURNS > 0 && brickCount > 0) { oval.move(vx, vy); paddle.setLocation(oval.getX(), paddle.getY()); pause(PAUSE_TIME); if (isCollisionLeft() == true) { vx = -vx; } if (isCollisionRight() == true) { vx = -vx; } if (isCollisionTop() == true) { vy = -vy; } gobj = collisionObject(); if (gobj != null) { if (gobj == paddle) { vy = -vy; } else { vy = -vy; destoryBrick(gobj); } } } if (isAlived() == false) { destoryBall(); if (NTURNS > 0 && brickCount > 0) { pause(2000); restartGame(); } else { println("^^^ Gameover ^^^"); } } else if (brickCount == 0) { println("=== You Win! ==="); } else { println("^^^ &&&&&& ^^^"); } } private void restartGame() { oval = new GOval(paddle.getX() + (paddle.getWidth() - BALL_RADIUS)/2, paddle.getY() - BALL_RADIUS, BALL_RADIUS, BALL_RADIUS); oval.setFilled(true); oval.setColor(Color.black); add(oval); startGame(); } private boolean isAlived() { if (oval != null) { if (oval.getY() > paddle.getY() + paddle.getHeight() + BALL_RADIUS) { return false; } } return true; } private void destoryBall() { remove(oval); NTURNS--; printGameInfo(); } private void printGameInfo() { println("live: " + NTURNS); println("bricks: " + brickCount); println("----------------------"); } private boolean isCollisionLeft() { if (oval.getX() <= 0) { return true; } return false; } private boolean isCollisionRight() { if (oval.getX() + 2*BALL_RADIUS >= getWidth()) { return true; } return false; } private boolean isCollisionTop() { if (oval.getY() <= 0) { return true; } return false; } private GObject collisionObject() { GObject collider1 = getElementAt(oval.getX(), oval.getY()); GObject collider2 = getElementAt(oval.getX()+BALL_RADIUS, oval.getY()); GObject collider3 = getElementAt(oval.getX(), oval.getY()+BALL_RADIUS); GObject collider4 = getElementAt(oval.getX()+BALL_RADIUS, oval.getY()+BALL_RADIUS); if (vy > 0) { if (collider3 != null) return collider3; if (collider4 != null) return collider4; } else { if (collider1 != null) return collider1; if (collider2 != null) return collider2; } return null; } private void destoryBrick(GObject gobj) { if (gobj != null) { if (gobj != paddle) { remove(gobj); brickCount--; } } } /* private instance variable from myself */ private GOval oval; private GRect paddle; private RandomGenerator rgen = RandomGenerator.getInstance(); private int brickCount = 0; private double vx, vy; private GObject gobj; private static final int PAUSE_TIME = 10; }
运行结果: