**Lab Assignment 1: Pong** This lab is longer than any of the previous short assignments. It is said that Athena, daughter of Zeus, leapt forth full-formed from Zeus' head. But unless you are Zeus, you will have to break this lab down into parts and solve some simpler problems first. I have, therefore, assigned a **checkpoint**, described in the checkpoint section below. You will solve this checkpoint problem and submit the solution as a short assignment several days before the main lab is due. The checkpoint will count for 5 out of the 40 points on this assignment. !!! WARNING **Don't stop once you reach the checkpoint. The assignment will take the entire week.** If you need help, get help early. # The game When I was 10, I went to visit my grandmother. She had a funky little box hooked to her black-and-white television, and we were able to play a simple video game involving a ball and two rectangles, which represented paddles. That game was called Pong, and it is not to be confused with the subterranean version played around here. Here's a video of what it looked like back then: [Atari Pong](http://www.youtube.com/watch?v=_tvTsbAXuRs&feature=player_embedded). The game has three important behaviors: 1. If the ball hits a vertical wall, the game is over. 2. If the ball hits a horizontal wall, it bounces off that wall. 3. If the ball hits the inner face of a paddle, it bounces off the paddle. Each paddle is independently controllable. Six keys on the keyboard control the game: - *a* moves the left paddle up. - *z* moves the left paddle down. - *k* moves the right paddle up. - *m* moves the right paddle down. - The space bar starts a new game. - *q* quits the program. The paddles should never leave the playing surface. While a paddle is touching the top wall, it cannot go up, and while a paddle is touching the bottom wall, it cannot go down. Even given these rules, you have much latitude in this assignment. You do not have to produce something that looks identical to my version; it is meant only to provide a demonstration of basic functionality. # Checkpoint: Moving the paddles You will start by putting up a graphics window with just the paddles. Each paddle is a rectangular block, 80 pixels high and 20 pixels wide, initially in the upper-left and lower-right corners of a 400 x 400 window. Like so:  You may choose whatever colors you like. The paddles may move up and down as follows: - If the user presses the *a* key, then the left paddle moves up. - If the user presses the *z* key, then the left paddle moves down. - If the user presses the *k* key, then the right paddle moves up. - If the user presses the *m* key, then the right paddle moves down. But no paddle may move outside the window. When the left paddle hits the top window boundary, pressing *a* has no effect, and when it hits the bottom window boundary, pressing *z* has no effect. Likewise, when the right paddle hits the top window boundary, pressing *k* has no effect, and when it hits the bottom window boundary, pressing *m* has no effect. Here's what my window looked like after I'd pressed *k* a few times:  And then after pressing *z* a few times:  *Make sure to define constants for things that never change*: - The height and width of the window. - The height and width of the paddles. - The four keys of interest. - The amount that a paddle moves when it moves. Remember that paddles move only vertically, and they may never move off the window. Your section leader will be able to run your code to verify that you got the behavior right. ## What to turn in for your checkpoint 1. Turn in three screenshots of your program: one of its initial state and two with the paddles having moved. 2. Turn in your .py source code listing. 3. Turn in a brief (one paragraph) description of how you plan to start the next part of the assignment. A good thing to mention would be a first step that simplifies things. (For example, "I plan to approach the next part of the assignment by first considering how to write a program that prints out "CONTACT" when a zero-radius ball hits a full-sized wall on the right side of the screen.) # How to proceed after the checkpoint As a next step, I recommend a simple animation of moving the ball. Start with the ball in the center of the window, and have it move to the right. Of course, in this first step, the ball will quickly leave the window, but that's OK: it's just a first step. Next, I recommend working on a function to detect whether the ball has moved beyond a vertical wall on the right hand side of the screen in the current time step. (Why *moved beyond*, and not *made contact with*? The ball might more than one pixel in each time step, so perfect equality may never be achieved. Greater-than and less-than operators are great!) This function will need to take some parameters describing the location of the ball and the x-coordinate of the wall. The function should return `True` or `False` depending on whether a collision has happened. After that, you could work on how the ball bounces when a collision happens. I find it useful to think in terms of velocities and state variables. An `x` variable might keep track of the ball location, and a `vx` variable might keep track of the horizontal component of the ball velocity (the amount the ball moves in the x direction each time step). After bouncing off of the left side of the screen, the x velocity should be positive. You could add three more walls, and new functions to check for collisions. Try out different directions of motion for the ball. Now you have a virtual pool table: four walls and a bouncing ball. Then you could add controllable paddles, and checks for collisions. And you could handle the fact that the ball should have a radius greater than zero, and that this will affect where bounces occur. How do you stop the ball's motion? One way is to keep a boolean state variable that says whether a game is in progress. If a game is not in progress, then don't update the ball's position. There might even be additional uses for this boolean state variable. How do you end the program when the user types *q*? Here's a really easy way: call the parameterless function `cs1_quit`, from cs1lib. # Design and style Your program should be understandable by wetware with the minimum possible effort. The logic should be as straightforward as possible. The beauty of a program lies in its design and in its style. ## Functions Don't be afraid to write functions that help your program out. I mentioned a couple earlier. But you should feel free to write more. Your functions should all be near the top of your code, not mixed in with code at the global level. This makes it easy to quickly see what functions you will be using. ## Constants Constant make code easier to read and modify. You could have constants for the keys that affect the game, height and width of the paddles, initial ball velocity, etc. Here's the rule of thumb. If you see a raw value, like 5, or "b", anywhere in the code except in an assignment to a constant, consider using a constant. Constants should be in all uppercase. ## Documentation You should include comments that tell the human reader what he or she needs to understand in order to make sense of your program. You should also choose descriptive variable and function names names. Meaningless names are bad, and misleading names are worse. # Extra Credit You can add all sorts of features to the basic Pong game for extra credit. Make sure, however, before you charge off and do extra credit that you have the basic game working correctly, that you've designed it as cleanly as possible, and that you've documented it well. Five points of extra credit is not worth as much to your final grade as five points on the lab. Also, **before you start any extra credit, save your basic pong source code, and submit that as your main submission. Also take a screenshot for submission before working on extra credit. Start a new Python file for any extra credit.** If you do pursue extra credit, include a text file in your submission that tells us what extra-credit features you've included. You can add plenty of extra-credit features. Here is a list of ideas to get you thinking, but by all means let your imagination go. - When the ball bounces off a moving paddle, accelerate the ball slightly in the direction of the paddle's motion: 10 points. - Random initial direction for the ball. (But make sure that it has enough horizontal and enough vertical component to be interesting. If the ball just goes up and down, or almost just up and down, the game is not going to be interesting.): 5 points. - Ball changing color each time it bounces off a paddle: 5 points. - Unpredictable bouncing: 5 points. - Fancy .png images for ball and paddles: 5 points. Here is how you can use .png images. Suppose you want to draw an image of a paddle, in paddle.png, at location (100, 150). Here's what you would do: ~~~ python from cs1lib import * img = load_image("paddle.png") ## somewhere in a drawing function called by start_graphics: draw_image(img, 100, 150) ~~~ Before you run your program, make sure to drag the image file into your PyCharm project. Crazier, less well-specified ideas (extra credit will be assigned relatively arbitrarily, according to how impressed we are): - More than two players. - Obstacles. - Obstacles that accelerate the ball. - [Breakout](https://en.wikipedia.org/wiki/Breakout_%28video_game%29), [Arkanoid](https://en.wikipedia.org/wiki/Arkanoid), or a pinball machine. # What to turn in Turn in a screenshot of your game in action, and the .py source code for your standard game. If you did extra credit, turn in additional extra-credit .py files, a text file explaining what you did for extra credit, and a screenshot of your extra-credit version. Submit everything via Canvas. # Honor Code The consequences of violating the Honor Code can be severe. Please always keep in mind the word and spirit of the Honor Code.