Need help with Breakout game
Hi,
I'm doing the Stanford Engineering Everywhere CS106a course. We've have been given an assignment to make the Breakout game. My problem is getting the ball to bounce off the bricks, I can get it to bounce off the paddle and walls alright but it will only detect a collision and bounce off the last brick created(the one in the bottom right corner). Any help(or even unrelated comments on my coding style) would be greatly appreciated. Here's my code:
Code:
/*
* 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 final int NTURNS = 3;
/* The horizontal and vertical centres of the window */
private static final int CENTRE_WINDOW_HOR = WIDTH/2;
private static final int CENTRE_WINDOW_VER = HEIGHT/2;
/** Runs the Breakout program. */
public void run() {
addMouseListeners();
setupGame();
runGame();
}
private void setupGame(){
drawBricks(BRICK_SEP, NBRICKS_PER_ROW, NBRICK_ROWS, BRICK_WIDTH, BRICK_HEIGHT, BRICK_Y_OFFSET);
addPaddle(PADDLE_WIDTH, PADDLE_Y_OFFSET);
}
private void runGame(){
while(lives > 0){
addBall();
vx = getRandomXVector();
pause(2000); //todo: make a method that does a 3-2-1 countdown before relaunching the ball.
boolean dead = false;
while(!dead){
moveBall();
vx = checkVerticalCollision(vx);
vy = checkTopCollision(vy);
dead = checkBottomCollision();
collider = checkObjectCollisions();
if(collider == paddle){
vy = -vy;
}
if(collider == brick){
vy = -vy;
//add code here to remove bricks and increment score
}
pause(20);
}
lives--;
}
}
/* Moves the paddle along the x-axis with the mouse */
public void mouseMoved(MouseEvent e){
paddle.move((e.getX()-paddle.getX()) - PADDLE_WIDTH / 2, 0);
if(paddle.getX() < 0){ // Sets the paddle to the leftmost side of the app window if the cursor leaves the window on the left.
paddle.setLocation(0, (HEIGHT - PADDLE_Y_OFFSET));
} else if((paddle.getX() + PADDLE_WIDTH) > WIDTH) { // Sets the paddle to the rightmost side of the app window if the cursor leaves the window on the right.
paddle.setLocation((WIDTH - PADDLE_WIDTH), (HEIGHT - PADDLE_Y_OFFSET));
}
}
/*Moves the ball using a random X vector and predefined Y vector*/
private void moveBall(){
ball.move(vx, vy);
}
/*Checks for collisions with the programs vertical bounds(i.e. the two sides) and reverses the x vector if there is.*/
private double checkVerticalCollision(double xVector){
if(((ball.getX() + (BALL_RADIUS * 2)) > WIDTH )|| (ball.getX() < 0)){
return -xVector;
}
return xVector;
}
/*Checks for collisions with the programs top bounding and reverses the value of the y vector if there is.*/
private double checkTopCollision(double yVector){
if(ball.getY() < 0){
return - yVector;
}
return yVector;
}
/*Checks for collisions with the bottom bounding and returns TRUE if there is.*/
private boolean checkBottomCollision(){
return ((ball.getY() + BALL_RADIUS * 2) > HEIGHT);
}
/*Checks for collisions with the paddle or bricks and returns which if there is a collision*/
private GObject checkObjectCollisions(){
return getElementAt(ball.getX(), ball.getY());
}
private void addPaddle(int paddleWidth, int distFromBottom){
paddle.setFilled(true); //Fills black
add(paddle, CENTRE_WINDOW_HOR -(PADDLE_WIDTH/2), (HEIGHT - distFromBottom));
}
private void addBall(){
ball.setFilled(true);
add(ball, CENTRE_WINDOW_HOR - BALL_RADIUS, CENTRE_WINDOW_VER - BALL_RADIUS);
}
/*Sets up the bricks for the game given the various parimeters */
private void drawBricks(int brickSeperation, int bricksPerRow, int brickRows, int brickWidth, int brickHeight, int brickDistFromTop){
for(int i = 0; i < brickRows; i++){
int brickXCoor = (brickSeperation / 2); //Must be left here as brickXCoor is "reset" after each iteration of the inner for loop.
for(int j = 0; j < bricksPerRow; j++){
brick = new GRect(brickWidth, brickHeight);
brick.setFilled(true);
brick.setColor(chooseBrickColor(i));
add(brick, brickXCoor, brickDistFromTop);
brickXCoor += (brickWidth + brickSeperation);
}
brickDistFromTop += (brickHeight + brickSeperation);
}
}
/*Creates a pseudo-random X vector for the ball between -3&-1 and 1&3*/
private double getRandomXVector(){
vx = rgen.nextDouble(1.0, 3.0);
if(rgen.nextBoolean()) vx = -vx;
return vx;
}
/* Chooses the color of the brick based on what row it is in. If the brick is on the 8th row(rowNumber == 7) or past its colour will be cyan.*/
private Color chooseBrickColor(int rowNumber){
if(rowNumber == 0 || rowNumber == 1){
return Color.RED;
} else if(rowNumber == 2 || rowNumber == 3){
return Color.ORANGE;
} else if(rowNumber == 4 || rowNumber == 5){
return Color.YELLOW;
} else if(rowNumber == 6 || rowNumber == 7){
return Color.GREEN;
} else {
return Color.CYAN;
}
}
/* Creates the paddle*/
private GRect paddle = new GRect(PADDLE_WIDTH, PADDLE_HEIGHT);
/* Creates the ball*/
private GOval ball = new GOval(BALL_RADIUS*2, BALL_RADIUS*2);
/* X & Y vectors used for the ball. */
private double vx;
private double vy = 3.0;
/*Numbers of lives the player has left*/
private int lives = NTURNS;
private GObject collider;
private GRect brick;
private RandomGenerator rgen = new RandomGenerator();
}
Thanks,
Tadhg.