Natasha The Robot

Currently learning... Swift!                                                             You can follow me on Twitter here.                                            Subscribe via RSS here.

Subscribe to my Swift newsletter

Stanford CS106A Breakout Game Solution

Posted on

And now, the moment you’ve all been waiting for…. I FINISHED THE BREAKOUT GAME!!!!!! And it works :) As you’ve seen I’ve been posting how to do parts of the game, as outlined in Stanford CS106A Assignment 3, but this is the post where we all celebrate that the whole code put together works!

If you’re interested in seeing how to do only parts of the game, check out the following posts:

And if  you’re looking to see the full thing, here it is:


This is also available on github.

UPDATE: As a commenter below mentioned, I did not use the NTURNS variable in my game, mostly because I didn’t understand what NTURNS was supposed to be used for. Apparently it is the number of turns the user gets to lose Breakout before the game is over. So here is my updated 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;

/**Ball velocity*/	
	private double vx, vy;

/**Random number generator for vx*/	
	private RandomGenerator rgen = RandomGenerator.getInstance();

/** Animation delay or paust time between ball moves */	
	private static final int DELAY = 10;

/* Method: run() */
/** Runs the Breakout program. */
	public void run() {
		for(int i=0; i < NTURNS; i++) {
			setUpGame();
			playGame();
			if(brickCounter == 0) {
				ball.setVisible(false);
				printWinner();
				break;
			}
			if(brickCounter > 0) {
				removeAll();
			}
		}
		if(brickCounter > 0) {
			printGameOver();
		}
	}

	private void setUpGame() {
		drawBricks( getWidth()/2, BRICK_Y_OFFSET);
		drawPaddle();
		drawBall();
	}

	//adding an individual brick object
	private GRect brick;

	//drawing all the bricks necessary for the game
	private void drawBricks(double cx, double cy) {				

		/*need to have several columns in each row
		 * so there need to be two for loops, 
		 * one for loop for the rows and one for loop for the columns.
		 */ 

		for( int row = 0; row < NBRICK_ROWS; row++ ) {

			for (int column = 0; column < NBRICKS_PER_ROW; column++) {

				/* To get the x coordinate for the starting width:
				 * 	start at the center width, 
				 * 	subtract half of the bricks (width) in the row,  
				 * 	subtract half of the separations (width) between the bricks in the row,
				 * now you're at where the first brick should be, 
				 * so for the starting point of the next bricks in the column, you need to: 
				 * 	add a brick width 
				 * 	add a separation width
				 */

				double	x = cx - (NBRICKS_PER_ROW*BRICK_WIDTH)/2 - ((NBRICKS_PER_ROW-1)*BRICK_SEP)/2 + column*BRICK_WIDTH + column*BRICK_SEP;

				/* To get the y coordinate of the starting height:
				 * 	start at the given length from the top for the first row,
				 * 	then add a brick height and a brick separation for each of the following rows
				 */

				double	y = cy + row*BRICK_HEIGHT + row*BRICK_SEP;

				brick = new GRect( x , y , BRICK_WIDTH , BRICK_HEIGHT );
				add (brick);
				brick.setFilled(true);

				//Setting colors depending on which row the bricks are in

				if (row < 2) {
					brick.setColor(Color.RED);
				}
				if (row == 2 || row == 3) {
					brick.setColor(Color.ORANGE);
				}
				if (row == 4 || row == 5) {
					brick.setColor(Color.YELLOW);
				}
				if (row == 6 || row == 7) {
					brick.setColor(Color.GREEN);
				}
				if (row == 8 || row == 9) {
					brick.setColor(Color.CYAN);
				}
			}
		}
	}

	//adding individual paddle object
	private GRect paddle;

	//paddle set-up
	private void drawPaddle() {
		//starting the paddle in the middle of the screen
		double x = getWidth()/2 - PADDLE_WIDTH/2; 
		//the paddle height stays consistent throughout the game
		//need to make sure to subtract the PADDLE_HEIGHT, 
		//since the rectangle gets drawn from the top left corner
		double y = getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT;
		paddle = new GRect (x, y, PADDLE_WIDTH, PADDLE_HEIGHT);
		paddle.setFilled(true);
		add (paddle);
		addMouseListeners();
	}

	//making the mouse track the paddle
	public void mouseMoved(MouseEvent e) {
		/* The mouse tracks the middle point of the paddle. 
		 * If the middle point of the paddle is between half paddle width of the screen
		 * and half a paddle width before the end of the screen, 
		 * the x location of the paddle is set at where the mouse is minus half a paddle's width, 
		 * and the height remains the same
		 */
		if ((e.getX() < getWidth() - PADDLE_WIDTH/2) && (e.getX() > PADDLE_WIDTH/2)) {
			paddle.setLocation(e.getX() - PADDLE_WIDTH/2, getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT);
		}

	}

	//adding an individual ball object
	private GOval ball;

	//ball set-up
	private void drawBall() {
		double x = getWidth()/2 - BALL_RADIUS;
		double y = getHeight()/2 - BALL_RADIUS;
		ball = new GOval(x, y, BALL_RADIUS, BALL_RADIUS);
		ball.setFilled(true);
		add(ball);
	}

	private void playGame() {
		waitForClick();
		getBallVelocity();
		while (true) {
			moveBall();
			if (ball.getY() >= getHeight()) {
				break;
			}
			if(brickCounter == 0) {
				break;
			}
		}
	}

	private void getBallVelocity() {
		vy = 4.0;
		vx = rgen.nextDouble(1.0, 3.0);
		if (rgen.nextBoolean(0.5)) {
			vx = -vx; 
		}

	}

	private void moveBall() {
		ball.move(vx, vy);
		//check for walls
		//need to get vx and vy at the point closest to 0 or the other edge
		if ((ball.getX() - vx <= 0 && vx < 0 )|| (ball.getX() + vx >= (getWidth() - BALL_RADIUS*2) && vx>0)) {
			vx = -vx;
		}
		//We don't need to check for the bottom wall, since the ball can fall through the wall at that point
		if ((ball.getY() - vy <= 0 && vy < 0 )) {
			vy = -vy;
		}

		//check for other objects
		GObject collider = getCollidingObject();
		if (collider == paddle) {
			/* We need to make sure that the ball only bounces off the top part of the paddle  
			 * and also that it doesn't "stick" to it if different sides of the ball hit the paddle quickly and get the ball "stuck" on the paddle.
			 * I ran "println ("vx: " + vx + ", vy: " + vy + ", ballX: " + ball.getX() + ", ballY: " +ball.getY());"
			 * and found that the ball.getY() changes by 4 every time, instead of 1,
			 * so it never reaches exactly the the height at which the ball hits the paddle (paddle height + ball height), 
			 * therefore, I estimate the point to be greater or equal to the height at which the ball hits the paddle, 
			 * but less than the height where the ball hits the paddle minus 4. 
			 */

			if(ball.getY() >= getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT - BALL_RADIUS*2 && ball.getY() < getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT - BALL_RADIUS*2 + 4) {
				vy = -vy;	
			}
		}
		//since we lay down a row of bricks, the last brick in the brick wall is assigned the value brick.
		//so we narrow it down by saying that the collier does not equal to a paddle or null, 
		//so all that is left is the brick
		else if (collider != null) {
			remove(collider); 
			brickCounter--;
			vy = -vy;
		}
		pause (DELAY);
	}

	private GObject getCollidingObject() {

		if((getElementAt(ball.getX(), ball.getY())) != null) {
	         return getElementAt(ball.getX(), ball.getY());
	      }
		else if (getElementAt( (ball.getX() + BALL_RADIUS*2), ball.getY()) != null ){
	         return getElementAt(ball.getX() + BALL_RADIUS*2, ball.getY());
	      }
		else if(getElementAt(ball.getX(), (ball.getY() + BALL_RADIUS*2)) != null ){
	         return getElementAt(ball.getX(), ball.getY() + BALL_RADIUS*2);
	      }
		else if(getElementAt((ball.getX() + BALL_RADIUS*2), (ball.getY() + BALL_RADIUS*2)) != null ){
	         return getElementAt(ball.getX() + BALL_RADIUS*2, ball.getY() + BALL_RADIUS*2);
	      }
		//need to return null if there are no objects present
		else{
	         return null;
	      }

	}

	private void printGameOver() {
		GLabel gameOver = new GLabel ("Game Over", getWidth()/2, getHeight()/2);
		gameOver.move(-gameOver.getWidth()/2, -gameOver.getHeight());
		gameOver.setColor(Color.RED);
		add (gameOver);
	}

	private int brickCounter = 100;

	private void printWinner() {
		GLabel Winner = new GLabel ("Winner!!", getWidth()/2, getHeight()/2);
		Winner.move(-Winner.getWidth()/2, -Winner.getHeight());
		Winner.setColor(Color.RED);
		add (Winner);
	}
}

This is my original code, without the NTURNS:

/*
 * 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;

/**Ball velocity*/
	private double vx, vy;

/**Random number generator for vx*/
	private RandomGenerator rgen = RandomGenerator.getInstance();

/** Animation delay or paust time between ball moves */
	private static final int DELAY = 8;

/* Method: run() */
/** Runs the Breakout program. */
	public void run() {
		setUpGame();
		playGame();
	}

	private void setUpGame() {
		drawBricks( getWidth()/2, BRICK_Y_OFFSET);
		drawPaddle();
		drawBall();
	}

	//adding an individual brick object
	private GRect brick;

	//drawing all the bricks necessary for the game
	private void drawBricks(double cx, double cy) {

		/*need to have several columns in each row
		 * so there need to be two for loops,
		 * one for loop for the rows and one for loop for the columns.
		 */

		for( int row = 0; row < NBRICK_ROWS; row++ ) {

			for (int column = 0; column < NBRICKS_PER_ROW; column++) {

				/* To get the x coordinate for the starting width:
				 * 	start at the center width,
				 * 	subtract half of the bricks (width) in the row,
				 * 	subtract half of the separations (width) between the bricks in the row,
				 * now you're at where the first brick should be,
				 * so for the starting point of the next bricks in the column, you need to:
				 * 	add a brick width
				 * 	add a separation width
				 */

				double	x = cx - (NBRICKS_PER_ROW*BRICK_WIDTH)/2 - ((NBRICKS_PER_ROW-1)*BRICK_SEP)/2 + column*BRICK_WIDTH + column*BRICK_SEP;

				/* To get the y coordinate of the starting height:
				 * 	start at the given length from the top for the first row,
				 * 	then add a brick height and a brick separation for each of the following rows
				 */

				double	y = cy + row*BRICK_HEIGHT + row*BRICK_SEP;

				brick = new GRect( x , y , BRICK_WIDTH , BRICK_HEIGHT );
				add (brick);
				brick.setFilled(true);

				//Setting colors depending on which row the bricks are in

				if (row < 2) {
					brick.setColor(Color.RED);
				}
				if (row == 2 || row == 3) {
					brick.setColor(Color.ORANGE);
				}
				if (row == 4 || row == 5) {
					brick.setColor(Color.YELLOW);
				}
				if (row == 6 || row == 7) {
					brick.setColor(Color.GREEN);
				}
				if (row == 8 || row == 9) {
					brick.setColor(Color.CYAN);
				}
			}
		}
	}

	//adding individual paddle object
	private GRect paddle;

	//paddle set-up
	private void drawPaddle() {
		//starting the paddle in the middle of the screen
		double x = getWidth()/2 - PADDLE_WIDTH/2;
		//the paddle height stays consistent throughout the game
		//need to make sure to subtract the PADDLE_HEIGHT,
		//since the rectangle gets drawn from the top left corner
		double y = getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT;
		paddle = new GRect (x, y, PADDLE_WIDTH, PADDLE_HEIGHT);
		paddle.setFilled(true);
		add (paddle);
		addMouseListeners();
	}

	//making the mouse track the paddle
	public void mouseMoved(MouseEvent e) {
		/* The mouse tracks the middle point of the paddle.
		 * If the middle point of the paddle is between half paddle width of the screen
		 * and half a paddle width before the end of the screen,
		 * the x location of the paddle is set at where the mouse is minus half a paddle's width,
		 * and the height remains the same
		 */
		if ((e.getX() < getWidth() - PADDLE_WIDTH/2) && (e.getX() > PADDLE_WIDTH/2)) {
			paddle.setLocation(e.getX() - PADDLE_WIDTH/2, getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT);
		}

	}

	//adding an individual ball object
	private GOval ball;

	//ball set-up
	private void drawBall() {
		double x = getWidth()/2 - BALL_RADIUS;
		double y = getHeight()/2 - BALL_RADIUS;
		ball = new GOval(x, y, BALL_RADIUS, BALL_RADIUS);
		ball.setFilled(true);
		add(ball);
	}

	private void playGame() {
		waitForClick();
		getBallVelocity();
		while (true) {
			moveBall();
			if (ball.getY() >= getHeight()) {
				printGameOver();
				break;
			}
			if(brickCounter == 0) {
				ball.setVisible(false);
				printWinner();
				break;
			}
		}
	}

	private void getBallVelocity() {
		vy = 4.0;
		vx = rgen.nextDouble(1.0, 3.0);
		if (rgen.nextBoolean(0.5)) {
			vx = -vx;
		}

	}

	private void moveBall() {
		ball.move(vx, vy);
		//check for walls
		//need to get vx and vy at the point closest to 0 or the other edge
		if ((ball.getX() - vx = (getWidth() - BALL_RADIUS*2) && vx>0)) {
			vx = -vx;
		}
		//We don't need to check for the bottom wall, since the ball can fall through the wall at that point
		if ((ball.getY() - vy = getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT - BALL_RADIUS*2 && ball.getY() < getHeight() - PADDLE_Y_OFFSET - PADDLE_HEIGHT - BALL_RADIUS*2 + 4) {
				vy = -vy;
			}
		}
		//since we lay down a row of bricks, the last brick in the brick wall is assigned the value brick.
		//so we narrow it down by saying that the collier does not equal to a paddle or null,
		//so all that is left is the brick
		else if (collider != null) {
			remove(collider);
			brickCounter--;
			vy = -vy;
		}
		pause (DELAY);
	}

	private GObject getCollidingObject() {

		if((getElementAt(ball.getX(), ball.getY())) != null) {
	         return getElementAt(ball.getX(), ball.getY());
	      }
		else if (getElementAt( (ball.getX() + BALL_RADIUS*2), ball.getY()) != null ){
	         return getElementAt(ball.getX() + BALL_RADIUS*2, ball.getY());
	      }
		else if(getElementAt(ball.getX(), (ball.getY() + BALL_RADIUS*2)) != null ){
	         return getElementAt(ball.getX(), ball.getY() + BALL_RADIUS*2);
	      }
		else if(getElementAt((ball.getX() + BALL_RADIUS*2), (ball.getY() + BALL_RADIUS*2)) != null ){
	         return getElementAt(ball.getX() + BALL_RADIUS*2, ball.getY() + BALL_RADIUS*2);
	      }
		//need to return null if there are no objects present
		else{
	         return null;
	      }

	}

	private void printGameOver() {
		GLabel gameOver = new GLabel ("Game Over", getWidth()/2, getHeight()/2);
		gameOver.move(-gameOver.getWidth()/2, -gameOver.getHeight());
		gameOver.setColor(Color.RED);
		add (gameOver);
	}

	private int brickCounter = 100;

	private void printWinner() {
		GLabel Winner = new GLabel ("Winner!!", getWidth()/2, getHeight()/2);
		Winner.move(-Winner.getWidth()/2, -Winner.getHeight());
		Winner.setColor(Color.RED);
		add (Winner);
	}
}

Subscribe to my Swift newsletter

  • http://www.teachertechblog.com scott walker

    SOOOOO glad to find someone else going through this course! I was pulling my hair out on some of the steps for this breakout game and stumbled across your blog. Love it! I’m not too far behind you, so I’ll be looking forward to your updates. Also… noticed you didn’t implement the NTURNS into your code. Found that a nice little for loop wrapped around setupGame and playGame, plus a call to clearAll() did the trick.

    • http://learning2program.wordpress.com natasha the robot

      Oh, that’s what NTURNS was for!!! I was totally confused, lol. I’ll update it to include it. The breakout game is super difficult, and I think it’s partly meant to weed out the non-serious students from the class. The next one is waaaay easier. I did it all on my own without any hair pulling :)

  • http://none Faisal

    finally , I solved game too.
    your blog really , so wonderful.
    thank you very much :)

  • ms19

    how do you keep the bricks from resetting each iteration of NTURNS?

    • http://natashamurashev.com Natasha Murashev

      Hey,

      I did this a while ago, so I don’t remember all the details for this problem. Take a look at the code in the post and see if it can help you though!

      Best of luck,
      Natasha

  • Joey Berggeren

    Hi,
    When I try to execute this code on Eclipse, a window pops up saying that “This kind of launch is configured to open the Debug perspective when it suspends”, and then it tells me that I have a ClassNotFoundException. Do you know how to fix this?
    Thanks,
    Joey

    • http://natashamurashev.com Natasha Murashev

      Hey Joey,

      I’m not very familiar with Eclipse and don’t use it anymore as I’m learning other languages. I would recommend asking this on Stackoverflow.com…

      Best of luck!
      Natasha

  • marcus

    This is driving me nuts…..

    My mouse Listener won’t work and creates a java lang exception.

    “java.lang.NullPointerException”

    When I paste in your working paddle code Natasha, it just won’t cooperate.

    Then when I paste in your entire code, it does work.

    This is driving me crazy! I just can’t seem to work out what is causing my paddle not to work.

    • http://natashamurashev.com Natasha Murashev

      Have you watched the debugging lecture yet? If not, just watch it – it’s the end of lecture 18. It’s probably something really simple…

  • marcus

    Cool. Thanks Natasha, am checking it out now.

  • marcus

    Breakout has really tested my commitment to programming….lol

    I’ve struggled to get anything to work at times, so much so that I ended up setting up Eclipse on Linux, to see whether my Mac was playing games with me.

    The last hour epitomizes the problems.
    1) I couldn’t get my getCollidingObject() method to work. In the end I looked at someone else’s answer. His answer was the same as mine though…which left me scratching my head as to why mine wouldn’t return.
    2) Then I cribbed your answer Natasha, at which point my program started failing right back at the beginning, where previously it was working. (The debugging process now halts at addMouseListeners(), my first call of the program. Why should it do this all of a sudden when it’s been working fine before?

    Trying to learn programming on one’s own is not easy IMO.

    It’s not at all like being in a classroom where you can get roadblocks removed by the teacher…..

    anyone else had a similar experience?

  • marcus

    Phew! That was a small ordeal. Ordeal or no ordeal…could be a new Gameshow, featuring programming..haha

    Anyhow, I cracked this thing, I think /hope

    Your site helped me greatly Natasha.

    Quite a difficult problem I think.

    Oh – to anybody using Eclipse, once you start debugging, it completely messes up the interface if you don’t entirely know what you’re doing.

    The two biggest problems I had were

    1) Getting mouseListeners to work (which was a strange problem)

    2) Creating the collider GObject

    Good luck any Java initiates. Code coming

    • http://natashamurashev.com Natasha Murashev

      Wow Marcus, CONGRATULATIONS!!!!!!! Glad you powered though this problem and finished it. The rest of the problems in that class are a piece of cake compared to this one :)

  • marcus
    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;
      
    /** Runs the Breakout program. */
        public void run() 
        {
        	createGameEnvironment();   /*sets up game*/
        playGame();					/*sets game in action*/
        	}
      
        
        private void createGameEnvironment() 
        {	
        	addWall();
        	addPaddle();
        	addMouseListeners();	 /*necessary for dragging mouse and clicking to start*/
        	}
      
        
    	private void playGame() 
    	{	
    	plays++;       /*counts number of times game has been played*/
    	addBall();
        	addMessage();    /*start message*/
    	waitForClick();
    	setBallVelocity();
    	while (noOfBricks > -1)
    	{
    	ballMove();
    	pause(10);
    	}
    	hoorayMessage(); /*victory message*/
    	}
    
        private void addWall()  
        {
            // the first step:  draw  application window and bricks
        		for (int h = 0; h < NBRICK_ROWS; h++)
        			{
        		for (int j = 0; j < NBRICKS_PER_ROW; j++)
        				{ 
        				int x = BRICK_SEP/2 + j * (BRICK_SEP + BRICK_WIDTH);
        			GRect brick = new GRect (x, (h * (BRICK_HEIGHT + BRICK_SEP)) + BRICK_Y_OFFSET, BRICK_WIDTH,BRICK_HEIGHT);
        			if (h < 2) {brick.setFillColor(Color.red);}
        			else if (h < 4) {brick.setFillColor(Color.orange);}
        			else if (h < 6 ) {brick.setFillColor(Color.yellow);}
        			else if (h  APPLICATION_WIDTH)
                   {
                    paddle.setLocation(z - (PADDLE_WIDTH - (APPLICATION_WIDTH-z)), h);
                   }
                else
                   {
                    paddle.setLocation(z, h);
                   }
                }
            
        private void addBall()
        			{
        			ball = new GOval (x, y, BALL_RADIUS * 2, BALL_RADIUS * 2);
        			ball.setFilled(true);
        			ball.setFillColor(Color.red);
        			add(ball);
        			}
        
        
         private void setBallVelocity()
               {
            	   vx = rgen.nextDouble(1.0, 3.0);
            	   if (rgen.nextBoolean(0.5))
               {
               vx = -vx;
               }
               vy = 3.0;
               }
         
         private void ballMove()
         
         {
        	 ball.move(vx, vy);
        		 if (ball.getY() > 580 && plays  580 && plays == NTURNS)
        			 gameOver();
        		 if ( ball.getX()  380 )
        			 vx = -vx;
        		 if (ball.getY() < 0 )
        			 vy = -vy;
        	 GObject collider = getCollidingObject();
        	 	if (collider == null)
        	 		return;
        	 	else if (collider == paddle)
        		 vy = -vy;
        	 	else 
        	 	{ 
        	 		vy = -vy;
        	 		bounceClip.play();
        	 		remove (collider);
        	 		noOfBricks--; 
        	 }
         }
         
        	 
         private void addMessage()
         {
         	GLabel mess = new GLabel ("Click To Start",110,30);
         	mess.setFont(new Font("Serif", Font.BOLD, 33));
         	mess.setColor(Color.orange);
         	add(mess);
         	pause(1600);
         	mess.setVisible(false);
         }
         
         private void hoorayMessage()
         {
         	GLabel hooray = new GLabel ("CONGRATULATIONS - GAME OVER",45,220);
         	hooray.setFont(new Font("C", Font.BOLD, 17));
         	hooray.setColor(Color.MAGENTA);
         	add(hooray);
         }
         
      private GObject getCollidingObject()
      {
    	  double p = ball.getX();
    	  double q = ball.getY();
      if (getElementAt(p,q) != null) 
          return getElementAt(p,q);
      else if (getElementAt(p,q + 20) != null)
    	  return getElementAt(p,q + 20);
      else if (getElementAt(p + 20,q + 20) != null)
    	  return getElementAt(p +20,q + 20);
      else if (getElementAt(p + 20,q) != null)
    	  return getElementAt(p +20,q);
      else
    	  return null;  	
      }
      
    	private void gameOver()
    	{
    		GLabel over = new GLabel ("GAME OVER SADLY",15,220);
         	over.setFont(new Font("C", Font.BOLD, 33));
         	over.setColor(Color.BLUE);
         	add(over);
    		return;
    	}
        	 
      AudioClip bounceClip = MediaTools.loadAudioClip("bounce.au");
      private int plays = 0;
    	private int noOfBricks =100;
        private double y = APPLICATION_HEIGHT * 2/5;  
        private double x = APPLICATION_WIDTH/2 - BALL_RADIUS;  	        	
        private double vx, vy;  /**Ball velocity*/    
        private GOval ball;       
        private GRect paddle;
        private double h = HEIGHT - PADDLE_Y_OFFSET;
        private RandomGenerator rgen = RandomGenerator.getInstance();
    }
    
    
  • Marcus

    lol. A piece of cake? I’ve just done the commas assignment, and it wasn’t easy…mind you, my code architecture was all wrong, so I created a Heath Robinson style solution….hmmmm, I hope I learned something there.

  • Yu Kang

    Why should the ‘MouseMoved’ method be public? I don’t get it, can somebody tell me?

  • Pingback: Shout out to Natasha the Robot | Two Quarter Rican's Blog

  • Joey Anetsberger

    I know this is an old post, but I’m just now learning Java and following the CS 106A lectures and decided to try to do the breakout assignment. I have a question though. When you use a loop to construct the GRect bricks and give them a location, every time you construct a new GRect, doesn’t the old reference variable point to a new object? If so, doesn’t that leave the other brick GRect objects out for garbage collection?

    • Joey Anetsberger

      Ooops, by give them a location, I meant add them to the GraphicsProgram.

  • Michael

    I am stuck on the paddle part (I know that you probably don’t remember this old stuff). The paddle is trapped at the end of the screen if I slide it there. I peaked at your paddle code and noticed that if you don’t click on the center of the paddle it will move some of the paddle of the screen. Anyone else figuring this out?

  • aryan

    Hi I dldn’t understand &gt , &lt is it necessary plzzz tell me i stuck in my program

    • aryan

      &gt , &lt

      • aryan

        > <

    • http://reorg.co Natasha Murashev

      It’s just a formatting issue. Replace lt with less than and gt with greater than signs.

  • leo

    What is the < in the for loops?

    • leo

      &lt

      • leo

        sorry & l t

        • leo

          &gt

          • leo
          • leo

            I guess it is a formatting issue. I hope you dont mind if I try out the different stuff.
            >
            <

          • leo

            &&

          • leo

            &quotv

        • http://reorg.co Natasha Murashev

          Just a formatting issue. lt is less than, gt is greater than sign.

  • leo

    mouseMoved() is a method where the contents in the method is called when the mouse is moved. You did not quite define the method itself, but you are defining the contents within. I hope that helps.

  • Kevin

    The “getElementAt” causes the following error:

    “This element neither has attached source nor attached Javadoc and hence no
    Javadoc could be found.”

    How can I fix this?

  • Kevin

    The “getElementAt” causes the following error:

    “This element neither has attached source nor attached Javadoc and hence no
    Javadoc could be found.”

    How can I fix this??