>> ROB BOWDEN: Hi.
I'm Rob.
Wondering how to implement this game?
Well, let's break out the staff solution.
>> So, let's first head down to the init functions that we told you to
implement first.
First one we'll take a look at it is init paddle.
All right, so remember that we want the paddle to be exactly centered in
the x-axis.
So we need to figure out where that should go.
>> Given the width of the board-- which is also hash defined up top--
we need to subtract out the paddle width and divide by 2, so that the
center of the paddle is in the center of the board.
Remember that the x-coordinate refers to the top left corner of the paddle,
and so this is exactly where we want it to be.
The y-coordinate doesn't matter as much because we can place
it wherever we want.
So we instantiating the paddle, we set the color black, we set fill to True
so it's a filled in rectangle, and we then add it to the window and return
the paddle.
And that's it for initializing the paddle.
>> It's going to be similar for init scoreboard.
So we're going to initialize the label, we're going to set the color to
light grey-- you can pick whatever you want-- we're going to set the font to
sans serif 48--
could also pick whatever you want--
we'll add it to the window.
Now this send to back isn't really necessary, it's just in case something
else happens to overlap the label.
Then when we use Detect Collision, Detect Collision will detect the other
thing before it detects the label.
But that really shouldn't affect us in this program.
>> Finally, we have this Update Scoreboard function that we wrote.
So let's take a look at that.
Now, here we see something that's almost identical to what
we saw in the label.c.
So we have a label--
a character buffer of 12 characters, which is just enough to handle any
integer, negative or positive.
Then we use sprintf to copy the points into that buffer.
So s this contains a string representing the number of points.
>> Finally, we set the label to that string.
And then we need to center the label in case we've gone from nine to 10
points and we've shifted it.
So we calculate the x and y-coordinates of the label which will
get width and the height of the window.
Although, we could also just use the constants Width and Height hash
defined up top.
We also get the width and height of the label and divide
that by 2 to center.
And then we use Set Location to actually put it in that location.
So that's it for init scoreboard.
>> OK.
So init ball is going to be very similar to init paddles as well.
We see here that we're using newgoval in order to instantiate a new ball.
And here we're using 2 times the radius as the width of the ball, and 2
times the radius as the height of the ball.
Now, also for newgoval, the x and y-coordinate that we pass in is going
to refer to the top left of the ball, which is actually
outside the ball itself.
So in order to get the ball exactly centered in the board, we need to pass
width divided by 2 for the center, and then subtract out the radius to push
the actual center of the ball into the center of the board.
And we do the exact same thing for the y-axis, except using
height instead of width.
>> So that places the ball in the center.
And this instantiates the ball, set the color to black, fill in the ball,
then finally add it to the window and return it.
And that's it for initializing the ball.
>> So now let's take a look at init bricks which is slightly more
complicated, but it's pretty similar to init paddle.
Now, first we need to figure out the width of each brick.
Remember that we have a constant called calls which specifies the
number of columns of bricks that we have.
So, we're going to determine the width of a single brick by taking the width
of the whole board, subtracting out the size of our gap--
which is hash defined up top and refers to the number of pixels that
should be between each brick--
and so we're going to have a total of gap times calls blank pixels in a
single row.
And that will also refer to some blank pixels to the left and right of the
left column and right column brick.
>> So subtract out those blank pixels leaves us with a number of pixels that
bricks are actually using.
And then we divide by calls to get the number of pixels per brick.
So here we define an array that just specifies the colors we want for each
row of bricks.
If we had more rows of bricks than colors that we specified, we'll see
that we'll just loop back around and use red again, and then orange and
yellow and so on.
>> So, as the p-set spec hints, we are going to loop over all the rows and
columns of the bricks.
But before we loop over the columns, we see here that we're specifying the
y position of each brick in that particular row.
We could also move this into the second for loop, but then we'd just be
doing the calculation over and over again when we don't need to.
>> So the y position of the brick is going to be margin, which is hash
defined up top and just refers to the space between the top of the board and
the start of all of the bricks.
And we're going to add to that the row that we're on times the height of an
individual brick plus the gap that is between each brick.
So this is also a vertical gap between each brick.
So that gives us the y-coordinate of the brick.
>> So here we're going to calculate the x-coordinate of the brick.
Now, we have gap divided by 2 since, remember before, I said that at the
left side of the board, we're going to leave a little space.
So gap divided by 2 is that space.
And then we're adding to that the column that we're on times width plus
gap, where width is the amount of space that a single brick takes up and
then gap is the space between each brick.
So that calculates the x-coordinate of the brick.
>> Now we just need to instantiate the brick given that x and y-coordinate
using width that we calculated for each brick, and break height which is
hash defined up top.
We set the color of the brick.
Notice we're using our colors array and we're passing in the row that were
on mod num colors which is going to make us wrap back around to red if we
have more rows than colors.
Finally, we'll fill in the brick color and add it to the window.
>> And that's it.
So, that's it for all of our initialization methods.
Now we need to look at that while loop that you had to fill in.
So here we see that this is our while loop that is going to continue until
game is over, which either means we run out of lives or
we run out of bricks.
>> So first thing we have is a Wait for Click.
So the game waits for us to actually click before the ball starts moving.
And then we're going to decrement lives.
So if we had three lives, now we're down to two lives, we're using our
third life.
We're going to center the ball.
So now, this isn't really going to help us on the very first life we play
since the ball is already going to have been centered from when we
instantiated it.
But we see when we end up losing the life and loop back around, then we're
going to want to recenter the ball from the bottom of the board back to
the center.
>> So, now here we need to generate the x velocity of the ball.
And, as per the spec, we're using d rand 48 to generate some random number
to specify the velocity.
We're adding one to that since we just want the velocity in the range of one
to two instead of zero to one.
Finally, we're using d rand 48 again in order to determine whether the ball
is going to move to the left or the right to start.
>> So d rand 48 returns a random number between zero and one, and so by asking
if that's less than 0.5, we have a 50 50 chance of switching the velocity of
the ball to be negative.
Finally, we set the vertical velocity of the ball to just be some constant.
We choose three.
And now we have another loop.
>> So this inner loop is going to continue.
Notice here, while bricks is greater than zero--
so if we run out of bricks, we've won the game and we can
break out of this loop--
and all Get y Ball less than height minus 2 times the radius.
So what this is recognizing is if the ball happens to go past the paddle, in
which case you've lost a life.
>> Looking inside this for loop we have the checking for a mouse event.
And so, if there is a mouse event, that means that we want to check to
see if the mouse was moved, and if the mouse was moved, we want to have the
paddle keep up with the mouse.
So, to do that, we calculate the new position of the paddle, which is going
to grab the position of the mouse-- which grabs the position using the
event that we were passed--
and then we're going to subtract out paddle width divided by 2, so the
paddle stays centered on the mouse instead of the left side of the paddle
staying centered.
>> So now we also want to be sure that we don't go over the left side or right
side of the board.
And so here we're just checking if the paddle would be off the left side of
the board, just stick it to the left side.
And here we're checking if the paddle would be over the right side of the
board, just stick it to the right side.
And finally, we actually set the location of the paddle.
>> Now, if there wasn't a mouse movement, that means we're going to
want to move the ball.
And so we already have the x and y velocity of the ball
and so we move it.
But now we want to detect a couple things.
So here we're detecting if we hit either the left or right side of the
board, we want the ball to bounce.
And so, in that case, we set x velocity to negative x velocity.
>> If the ball hit the top of the board, then we also want the ball bounce.
But now we want to change the y velocity.
Notice we don't have a condition for the ball hitting the bottom of the
board since that was already captured up here in this while loop.
>> Finally, we want to detect some collisions where if the ball hit
either the paddle or the brick, we want to do some special case things.
So if there was a collision, in which case objects will not be null, then,
if the object hit the paddle, we would just want to bounce the ball.
And here, also, we set the location of the ball to just above the paddle.
Notice we're taking the x position of the ball and just reusing that.
But here we're getting the y position of the paddle and moving the ball
above the paddle.
>> This is a special case so that the ball doesn't hit the paddle and then,
before it's able to move off the paddle, another loop goes around and
it thinks it's still on the panel and so the y velocity gets set back to
negative and then the ball just kind of sticks bouncing on the paddle.
So, if we did not hit the paddle, then we also want to check
if we hit the brick.
And so this is how we can check to see if we hit a brick.
>> We need to check for this because we may have actually hit the label and we
don't want to remove the label.
So if we hit a brick, we can remove that brick from the window, decrement
our count of the bricks, increment our number of points, and now we need to
update the scoreboard which is exactly the same as we saw before when we saw
init scoreboard.
But now we are just updating the scoreboard since we've changed the
number of points.
And it should now display that we hit one more break.
>> And finally, if we hit a brick we also want to bounce.
So finally, we pause just so that the ball isn't moving super fast and we
can actually hit it with our paddle.
And that's pretty much it.
So now we would loop back to the top of this while loop and continue until
either we lose a life or we run out of bricks.
>> What happens if we lose a life?
Then we're going to exit this while loop, and we'll see will loop back up
to the top of the outer while loop.
In which case, we're going to execute this set up again.
And this set up is going to have us wait for a click, decrement our number
of lives, recenter the ball, recalculate an x and y velocity, and
then resume the game.
>> And so, that will continue until either bricks ends up being less than
or equal to zero--
in which case we won the game--
or lives is less than zero, in which case we have lost the game.
So, once that's the case, we break out of that while loop, and we reach here
where we're going to wait for click before exiting the game so that the
game doesn't just immediately close on us.
And finally we'll close the window and that's it.
My name is Rob, and this was Breakout.