/* * File: Breakout.java * ------------------- * 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.*; import java.util.*; 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 final int NTURNS = 3; private static final Color COLORS[] = {Color.RED , Color.ORANGE, Color.YELLOW, Color.GREEN, Color.CYAN}; private static RandomGenerator generator = new RandomGenerator(); private static final int[] xPnts = {-10, -10, 10, 10}; private static final int[] yPnts = {-10, 10, -10, 10}; private GRect paddle; private GOval ball; private int numBricksRemaining, numTurnsRemaining; private double vx, vy; private boolean hitPaddle; private long lastTimestamp; /* Method: run() */ /** Runs the Breakout program. */ public void run() { this.setSize(WIDTH, HEIGHT); lastTimestamp = -1; addMouseListeners(); setUpGame(); while(true) { moveBall(); checkCollisions(); } } public void checkCollisions() { GObject collider = null; boolean hasCollision = false; boolean hitsPaddle = false; double x = ball.getX()+BALL_RADIUS; double y = ball.getY()+BALL_RADIUS; for(int i = 0; i < xPnts.length; i++) { collider = getElementAt(x+xPnts[i],y+yPnts[i]); if(collider != null && collider.equals(paddle)) { hitsPaddle = true; } else if(collider != null && !collider.equals(ball)) { remove(collider); hasCollision = true; break; } } if(hitsPaddle && vy > 0) changeDirectionY(); else if(hasCollision) changeDirectionY(); else hitPaddle = false; } public void moveBall() { if(lastTimestamp < 0) { lastTimestamp = System.currentTimeMillis(); } else { long elapsedTime = System.currentTimeMillis() - lastTimestamp; lastTimestamp = System.currentTimeMillis(); ball.move(vx*elapsedTime,vy*elapsedTime); if(ball.getX() < 0) { ball.setLocation(0, ball.getY()); changeDirectionX(); } else if(ball.getX()+2*BALL_RADIUS > WIDTH) { ball.setLocation(WIDTH - 2*BALL_RADIUS, ball.getY()); changeDirectionX(); } if(ball.getY() < 0) { ball.setLocation(ball.getX(), 0); changeDirectionY(); } } } public void changeDirectionX() { vx = -vx; } public void changeDirectionY() { vy = -vy; } public void mouseClicked(MouseEvent e) { setInitialVelocity(); } public void mouseMoved(MouseEvent e) { double mouseX = e.getX(); if(mouseX-PADDLE_WIDTH/2 > 0 && mouseX+PADDLE_WIDTH/2 < WIDTH) { paddle.setLocation(mouseX-PADDLE_WIDTH/2,paddle.getY()); } } private void setUpGame() { numBricksRemaining = NBRICKS_PER_ROW * NBRICK_ROWS; numTurnsRemaining = NTURNS; createBricks(); createPaddle(); createBall(); } private void createBricks() { for(int i = 0; i < NBRICKS_PER_ROW; i++) { for(int j = 0; j < NBRICK_ROWS; j++) { GRect brick = new GRect(BRICK_WIDTH, BRICK_HEIGHT); brick.setFilled(true); brick.setColor(COLORS[j/2]); add(brick); brick.setLocation(i*(BRICK_WIDTH+BRICK_SEP),BRICK_Y_OFFSET+j*(BRICK_HEIGHT+BRICK_SEP)); } } } private void createPaddle() { paddle = new GRect(PADDLE_WIDTH,PADDLE_HEIGHT); paddle.setFilled(true); paddle.setColor(Color.GRAY); add(paddle); paddle.setLocation((WIDTH-PADDLE_WIDTH)/2,HEIGHT-PADDLE_Y_OFFSET-PADDLE_HEIGHT); } private void createBall() { ball = new GOval(BALL_RADIUS*2,BALL_RADIUS*2); ball.setFilled(true); ball.setColor(Color.black); add(ball); ball.setLocation(WIDTH/2-BALL_RADIUS,HEIGHT/2-BALL_RADIUS); vx = 0; vy = 0; } private void setInitialVelocity() { if(vx == 0 && vy == 0) { vx = generator.nextDouble(1.0,3.0)/10; if(generator.nextBoolean(0.5)) vx = -vx; vy = generator.nextDouble(1.0,3.0)/10; if(generator.nextBoolean(0.5)) vy = -vy; } } }