$ mkdir ~/cs170/labs/lab3 $ cd ~/cs170/labs/lab3
I seriously messed up on Wednesday, so I'm going to fix that today. Let's cover events in a little more detail, including what is going on behind the scenes! We will also talk about global variables, and why we can use them here instead of what we normally have to do.
If you did not get to the point that you had paddles moving for pong on Wednesday, now is the time to get that done. If you started, or already have pong from last class, you can copy it to today lab using the following commands:
$ cd ~/cs170/labs/lab3 $ cp ../lab2/pong.py .
Create a program in a file called pong.py, that allows two different players to control two different pong paddles. Each pong paddle will be represented by a single rectangle on either side of the window.
One of the player's paddles will be controlled with the mouse, while the other will be controlled by the keyboard. The keyboard player should use the up and down arrow keys to change the position of their paddle, while the mouse player should change the y location of the paddle by moving the mouse as the left button is
.Make sure you keep both paddles on the screen at all times!
Remember, the create_rectangle
method returns an ID that can be used to later change the
created object. So you'll need to keep track of one for each of
the paddles.
You will need to bind
both the
<B1-Motion>
and the <Key>
events, and you will need an event handler for each one of them.
The event object for the mouse will have x and y attributes, the coordinates of the mouse in the canvas. The event object for the keyboard will have a keysym attribute, which will describe which key was pressed.
move
method, but the mouse
controlled player will have to use the coords
method to update their paddle's
position.
You should have Pong paddles working by now, so now it's time to get to animating. For pong, you need a ball that can bounce off of the walls, and the players paddles.
In the pong.py file with your paddle code, create an oval that can travel around the screen. To start, simply get a ball that bounces off of all four walls. You can remove that later, once you have paddle collisions working.
Remember, you can use canvas.coords
to get
the current location of some entity that you have tagged. It gives
you 4 values back: the upper left coordinate, and the lower right
coordinate. You can use this method to get the current coordinates of
not only your ball, but the paddles as well. That should simplify
things greatly.
Collisions here can be perfect collisions: They only flip the sign on the a single dimension of the ball's velocity. You can make more complicated collisions later.
You are going to need two global variables for the ball: one for
the x component of velocity, and one for the y component of
velocity. This way, when you move
the
ball, you just need to pass the velocity components.
Collisions with the walls should be pretty simple. Compare the top y coordinate the the top coordinate of the window.If the top y coordinate is less than that top coordinate, flip the y velocity of the ball. You can do something similar for the other sides of the window.
Collisions with the paddles is slightly more complicated, but
easier if you abstract the logic. Create a function called
collision_detection_circle_rectangle
, which takes
8 parameters: the upper left coordinate of the
rectangle, the lower right coordinate of the rectangle, the
upper left coordinate of the circle, and the lower right
coordinate of the circle. This function should return True if
the circle overlaps with the rectangle.
As you have probably noticed, the ball gets stuck in the paddle if you happed to collide with the top (or bottom) of the paddle! There are two ways to deal with this: either make the paddle thin enough that it is not an issue, or handle collisions better. I personally prefer the latter, so why don't you fix the collisions.
The simple way to fix the top collisions is to also flip the y velocity if you hit the top or bottom of the paddle. That fixes the main issue, but is still less interesting. Real pong games change the angle at which the ball is moving, depending on where the ball hit on the paddle.
So, instead of simply flipping the velocity in the direction that intersects, you should determine a new angle for the ball that varies depending on the distance the center of the ball is from center of the paddle. Then, update the x an y components of the velocity based off this new angle.
Using rectangles is fine, but kind of a bit boring. A "real" pong game wouldn't use a simple rectangle for the paddle. Instead, they would use images for the paddles!
Search on google, or use GIMP to create your own paddle images. Then, look at the documentation for the Tk Canvas object, as well as the PhotoImage documentation. Load your images in, instead of using the rectangles. Can you make the paddle images you are using the same size as the rectangles, without manipulating the image manually?
Keep in mind, this will likely require you to alter your collision detection methods slightly!
When you have finished, create a tar file of your lab3
directory. To create a tar file, execute the following commands:
cd ~/cs170/labs tar czvf lab3.tgz lab3/
To submit your activity, go to cseval.roanoke.edu. You should
see an available assignment called Lab Assignment 3
.
Make sure you include a header listing the authors of the file.