CS106A Assignment 3 – Breakout

This assignment requires one to write the classic arcade game of Breakout.  Nine days for this would be given if I was attending Standford. Bonus points are given for adding features such as visual display of lives, sounds, scores, high score memory, making the ball bounce angle be dependent on where it hits the paddle, things like that.  I began this on 16/04/2017.  I closed programming on 24/04/2017 – 8 days.

The assignment might look daunting so it is suggested it be broken up into parts:

  • brick setup
  • paddle creation
  • create ball, get it moving and bouncing
  • check for collisions
  • consider adding extensions to the program

Brick Setup

The code used here came from the Pyramid code developed for Assignment 2, Problem 1.  I’d seemingly forgotten that java has cols and rows inbuilt and most importantly, the code to get blocks to be draw the next row across (or down) is * cols and * rows.

To make the program fancier, I whipped up a 5 minute badly tessellated background for my game and I used G3DRect to draw the bricks instead of GRect.

So far we have this:

Brick setup on the "game grid"

Brick setup with slightly longer screen thanks to the bg not fitting

Paddle Creation (and moving)

Easy to create a paddle modified with round edges: GRoundRect.  After I got it moving with some code I still do not fully understand, the paddle would dig into the RHS wall the depth of the curve and no amount of offsetting would fix it.  The offset seemed to do nothing and then, whammo, too much offset!

I’m thinking of going back to a standard GRect as at least that way, if it digs into the wall by 2px, it’ll not be obvious.

Paddle default and limits

Paddle default and limits

Ball Creation (and moving)

Originally I made the ball accoring to:

  • ball = new GOval (ballX, ballY, 2*BALL_RADIUS, 2*BALL_RADIUS);

Looking at the code later on how to draw a ball, the x1 and y1’s were stated to be diameter/2 , so I changed my code to:

  • ball = new GOval (ballX, ballY, BALL_RADIUS, BALL_RADIUS);

Drawing the ball was easy.  Getting the thing to move was troublesome. Lots of reading the Art and Science of Java and listening to YouTube videos while trying not to look at the code.

For reasons unknown, sometimes after losing a life, the ball would start moving up after clicking my mouse to continue.  Here, I’d left out some brackets around my random start x code.

Ball / paddle issues

Ball / paddle issues.  Ball’s also 2x as large as it should be.

Check For Collisions

The hardest bit of the program.  Lots of reading and re-reading the Assignment, the Java text and listening (and watching, curse it), YouTube vids.  When I finally got the collisions to work, I had two private voids, one for the walls, and one for the collider.

Here, the ball collided with the paddle, but visually went under it  It looks like the top of the ball was doing the colliding, not the bottom,

I needed to Boolean out the background and my GLabel’s so when the collider was not the paddle, then the blocks were the only thing left to collide with.

After running the program, I got the sticky paddle issue the Assignment said to check for.  Some of the bouncing off the bricks also seemed to be erratic and at one point, the ball went through a wall, and I assume kept going until I stopped the program.

Examining the output by monitoring some console outputs, here is what happens:

RHS wall collision vX: -5.551280649349126, vY: 3.0, ballX: 391.37188038970356, ballY: 191.0
RHS wall collision vX: 7.551280649349126, vY: 3.0, ballX: 398.9231610390527, ballY: 194.0
RHS wall collision vX: -5.551280649349126, vY: 3.0, ballX: 393.37188038970356, ballY: 197.0
RHS wall collision vX: 7.551280649349126, vY: 3.0, ballX: 400.9231610390527, ballY: 200.0

So, it looks like the ball’s doing a check, seeing it is on the other side (400.92…) and bouncing the wrong way.  I changed the ballX and Y to int as that way, a 400.92 should return as a 400, so should then bounce off the wall.  Nah, no good: RHS wall collision vX: 7.775510890046173, vY: 3.0, ballX: 400.6531325648025, ballY: 224.0

RHS wall collision after y return > 400

RHS wall collision after y return > 400

After viewing lecture 10 again, there’s some code that says, take the diff and reverse if ball through wall after check. I then implemented that and it made the ball look like it was doing donuts on the walls when it got fast.  It still did not take care of the ball heading out of the screen.

Perhaps this has something to do with the ball burrowing through the bricks if they are hit at their lower corner – ie. the makign assumptions on which getX() or getY() to do the collision check at.

Running the Game including beta testing

Here are the various game screens.  It would be easy to change the display for a splash page at the start or a high score table at the end (or even to cycle this sort of thing).

20170424 an example of testing using the console & println

20170424 an example of testing using the console & println

Game waiting for start

Game waiting for start

Life lost display

Life lost display

Game Over

Game Over

Level cleared

Level cleared – the red 0 is the brick counter included for testing.

After starting level 2 showing game setup with no change to score or lives.

After starting level 2 showing game setup with no change to score or lives.

“Improve” The Program With Extensions

Before beginning the coding for the program I decided to make this a fairly decent game and add the following features:

  • background.  Though making the bg 400 x 600, it would draw at 400 x 640 (unless I created it too long).  I fixed that with a scale factor.
  • score.
  • saved score and high score input. Not implemented.
  • congrats with celebratory sound at the end.
  • lives displayed on screen.
  • if score reached a certain point, add a life (set to 2000.  With current scoring, that’ll take forever as clearing level 1 gives 1000 points.  I need to see how to read a collider’s color and then assign points based on that.  Seemed to not work so not implemented.
  • if all bricks gone, add a level.  This in the v1 code is implemented by calling the runGame void and setting any tracked integers to their current value so they are not reset.
  • sound when ball hits paddle.
  • sound when ball hits wall.
  • sound when ball hits brick.
  • final (upper) two rows of brick need 2 hits to disappear (change color to track that or have a counter?). Not implemented.
  • lives and scores to be displayed in a RHS panel, rather than on screen. Not implemented.
  • ball sped up by 1 1.000000000001 per cycle.

Rather than whack these on after the main code was complete, I coded them into the program as I went along.

SummarySave

Save

Save

Summary

I got the program to work at the base level with some niggles:

  • the ball seemed to be hitting the bottom of the paddle and no matter what I did, it would sometimes seem to bounce off the bottom of the paddle and the screen before moving up again.
  • the ball seemed to be hitting about a ball width in from the walls and roof (and adding in offsets or chaining the BALL_RADIUS=-/* could not fix it.
  • Sometimes the ball would hit the side of a brick and then exit the screen.

Besides that, everything worked as I wanted.

So, what did I learn from Assignment 3?  Program the base program first and then do the fancy pants addons.  That way I can get the program shipped with no bugs and working according to the URS on time and in full!

Again, if I feel the need, I’ll come back to this at the end of the module and tweak the niggles which for now I’ll call “features”.

Somewhat buggy final product:  Packaged Jar file.  Extract zipped contents and run the breakout.jar file if you have java installed on your system.

Save