Activity Information
Learning Goals
- Think creatively to solve a computational problem
Prior Knowledge Required
- Functions in Python
- Vectors
Code Manipulation
- Interpret existing code
- Write new code that adds functionality to existing code
- Using while loops and if statements
Activity
Handout – Pong
Congrats! You’ve been hired as a programmer at Atari to work on their new game reboot: Pong, Glowscript edition.
Some of the other programmers at the company have made an early version of the game, but they have since started working on a new project, Rollercoaster Tycoon 2036, leaving you to finish Pong. Thankfully, they’ve left some comments in their code that explain what each part of it does.
Your goal is to make it so that every 10 successful bounces of the ball against the paddle, the ball will move 10% faster, 10 points will be added to the player’s score, and the ball’s color will be changed in this specific order:
- Red (starting color)
- White
- Blue
- Green
- Yellow
- Orange
You also need to make it so that if the player misses the ball, their score is reduced by 50 percent, and they drop down to their previous level, which means that the speed of the ball will be reduced by 10% and the ball will revert back to its previous color. If the ball is already at the initial color and speed when the player misses the ball, the speed and color of the ball should be unaffected.
Good luck!
Optional challenge: Make it so that the colors of the ball can cycle forever, so the player can reach an infinitely high level. For example, if the player manages to beat the orange level, the ball will turn red again and the speed and score will increase accordingly.
Code
GlowScript 3.1 VPython
scene.width=500
scene.height=500
#set positions, speeds, etc.
topline = 200
bottomline = topline*(-1)
leftline = topline*(-1)
rightline = leftline * -1
ballsize = 5
boxsize = 3
framerate = 300
ballshiftx = .5
ballshifty = .5
direction = 1 #this determines if the ball is moving in positive or negative direction
#make game frame
topbox = box(pos=vector(0,topline,0), size=vector(400,boxsize,.1) )
bottombox = box(pos=vector(0,bottomline,0), size=vector(400,boxsize,.1) )
leftbox = box(pos=vector(leftline,topline+bottomline,0), size=vector(boxsize,400,.1) )
rightbox = box(pos=vector(rightline,topline+bottomline,0), size=vector(boxsize,400,.1) )
ball = sphere(pos=vector(0,0+ballsize+boxsize,0), color=color.red, radius=ballsize)
#make paddle
paddle = box(pos=vec(0,bottomline+4 ,0), size=vec(20,2,2), color=color.white)
paddlemove = .5
#set starting values
count=0
level=0
score=0
#move the ball
i=0
while i==0:
rate(framerate)
#move paddle
k = keysdown()
if "left" in k and paddle.pos.x > leftline + 10:
paddle.pos.x = paddle.pos.x - paddlemove
if "right" in k and paddle.pos.x < rightline - 10:
paddle.pos.x = paddle.pos.x + paddlemove
#move ball
ball.pos.y = ball.pos.y + ballshifty
ball.pos.x = ball.pos.x + ballshiftx
#top bounce
if ball.pos.y >= topline-boxsize/2-ballsize:
ballshifty = ballshifty * -1
#left and right bounce
if ball.pos.x >= rightline-boxsize/2-ballsize:
ballshiftx = ballshiftx * -1
if ball.pos.x <= leftline+boxsize/2+ballsize:
ballshiftx = ballshiftx * -1
#paddle bounce
if (ball.pos.x-10 < paddle.pos.x <ball.pos.x+10) and (ball.pos.y-ballsize+1 <= paddle.pos.y):
ballshifty = ballshifty * -1
#bottom bounce & lose
if ball.pos.y <= bottomline+boxsize/2+ballsize:
ballshifty = ballshifty * -1
#ball under paddle - move the ball to above the paddle
if (ball.pos.x-10 < paddle.pos.x <ball.pos.x+10) and (ball.pos.y < paddle.pos.y):
ball.pos.y = ball.pos.y + 4
Answer Key
Handout
There are lots and lots of ways to solve this activity. A solution that uses functions is outlined below, but there are many ways to implement the appropriate changes in the code, such as:
- Create a list of the different colors and index the list according to what level the player is at, changing the color of the ball to the element of the list at that index.
- Create a singular large function that returns all the appropriate values.
- Add several nested if statements to the existing code, bypassing the need to use functions
Multiple functions solution:
First we need to figure out how to get something to trigger only every 10 bounces. To do this, we can count up a variable by one every time there is a bounce. The code that runs only when the ball hits the paddle is under the comment #paddle bounce. We can add: count = count + 1 as part of this code to count the number of bounces:
#paddle bounce
if (ball.pos.x-10 < paddle.pos.x <ball.pos.x+10) and (ball.pos.y-ballsize+1 <= paddle.pos.y):
ballshifty = ballshifty * -1
count = count + 1
Now, we want something to happen every 10 bounces so we can add a new if statement at the bottom of the wile loop that runs if count is 10:
if count == 10: # The code in the loop runs if the ball has bounced 10 times
count = 0 # Reset the number of bounces so that this if statement will run again after the next ten bounces
Now we need to figure out the rest of the code that goes in this if statement. The variables ballshiftx and ballshifty represent the distance the ball moves in the x and y directions each time the while loop runs. To increase the speed of the ball by 10%, we can increase both of these values by 10%:
if count == 10:
ballshiftx = ballshiftx + 0.1*ballshiftx # 10% = 0.1
ballshifty = ballshifty + 0.1*ballshifty
count = 0
We need to increase the score by 10 as well:
if count == 10:
score = score + 10
ballshiftx = ballshiftx + 0.1*ballshiftx
ballshifty = ballshifty + 0.1*ballshifty
count = 0
We still need to make it so the color of the ball changes. To do this, let’s make a function that we can use to check the color of the ball and return what the new color should be:
def newcolorup(currentcolor): # The input of the function will be the current color of the ball
if currentcolor == color.red: # If the ball is red
newcolor = color.white # the new color of the ball is white
if currentcolor == color.white: # If the ball is white
newcolor = color.blue # the new color of the ball is blue
if currentcolor == color.blue:
newcolor = color.green
if currentcolor == color.green:
newcolor = color.yellow
if currentcolor == color.yellow:
newcolor = color.orange
if currentcolor == color.orange:
newcolor = color.red
return newcolor # Return what the new color of the ball is
We’ll need a function that changes colors in the opposite direction as well for when the player misses the ball, so lets make that as well:
def newcolordown(currentcolor): # The input of the function will be the current color of the ball
if currentcolor == color.red: # If the ball is red
newcolor = color.orange # the new color of the ball is orange
if currentcolor == color.white:
newcolor = color.red
if currentcolor == color.blue:
newcolor = color.white
if currentcolor == color.green:
newcolor = color.blue
if currentcolor == color.yellow:
newcolor = color.green
if currentcolor == color.orange:
newcolor = color.yellow
return newcolor # Return what the new color of the ball is
Now we need to use the first function in the while loop. To do this we need to use a new variable to store the output of the function, then use that variable to change the color of the ball:
if count == 10:
score = score + 10
ballshiftx = ballshiftx + 0.1*ballshiftx
ballshifty = ballshifty + 0.1*ballshifty
newcolor = newcolorup(ball.color) # Input the current color of the ball into our function and store the output in the variable newcolor
ball.color = newcolor # change the color of the ball to the new color
count = 0
Now everything that happens every 10 bounces is taken care of. Now we need to add what happens when the player misses the ball. The code that runs only when the player misses the ball is under the comment #bottom bounce & lose. We want to reduce the player’s score by 50% whenever they miss, so we can say:
if ball.pos.y <= bottomline+boxsize/2+ballsize:
ballshifty = ballshifty * -1
score = score*0.5
We also want to reduce the speed of the ball and change its color, but this should only happen if the player is not at the base level. To check this we will need a nested if statement. This if statement can check to see if the magnitude of ballshiftx (or ballshifty) is greater than its original value. If it is, then we can reduce speed and change color, but if it isn’t we are at base level:
if ball.pos.y <= bottomline+boxsize/2+ballsize:
ballshifty = ballshifty * -1
score = score*0.5
count = 0
if abs(ballshiftx) > .5 # abs() is used because ballshiftx can be negative
ballshiftx = ballshiftx - ballshiftx*0.1
ballshifty = ballshifty - ballshifty*0.1
newcolor = newcolordown(ball.color)
ball.color = newcolor
Code
GlowScript 3.1 VPython
scene.width=500
scene.height=500
#set positions, speeds, etc.
topline = 200
bottomline = topline*(-1)
leftline = topline*(-1)
rightline = leftline * -1
ballsize = 5
boxsize = 3
framerate = 300
ballshiftx = .5
ballshifty = .5
direction = 1 #this determines if the ball is moving in positive or negative direction
#make game frame
topbox = box(pos=vector(0,topline,0), size=vector(400,boxsize,.1) )
bottombox = box(pos=vector(0,bottomline,0), size=vector(400,boxsize,.1) )
leftbox = box(pos=vector(leftline,topline+bottomline,0), size=vector(boxsize,400,.1) )
rightbox = box(pos=vector(rightline,topline+bottomline,0), size=vector(boxsize,400,.1) )
ball = sphere(pos=vector(0,0+ballsize+boxsize,0), color=color.red, radius=ballsize)
#make paddle
paddle = box(pos=vec(0,bottomline+4 ,0), size=vec(20,2,2), color=color.white)
paddlemove = .5
#set starting values
count=0
level=0
score=0
#color changing functions
def newcolorup(currentcolor):
newcolor = vec(0,0,0)
if currentcolor == color.red:
newcolor = color.white
if currentcolor == color.white:
newcolor = color.blue
if currentcolor == color.blue:
newcolor = color.green
if currentcolor == color.green:
newcolor = color.yellow
if currentcolor == color.yellow:
newcolor = color.orange
if currentcolor == color.orange:
newcolor = color.red
return newcolor
def newcolordown(currentcolor):
newcolor = vec(0,0,0)
if currentcolor == color.red:
newcolor = color.orange
if currentcolor == color.white:
newcolor = color.red
if currentcolor == color.blue:
newcolor = color.white
if currentcolor == color.green:
newcolor = color.blue
if currentcolor == color.yellow:
newcolor = color.green
if currentcolor == color.orange:
newcolor = color.yellow
return newcolor
#move the ball
i=0
while i==0:
rate(framerate)
#move paddle
k = keysdown()
if "left" in k and paddle.pos.x > leftline + 10:
paddle.pos.x = paddle.pos.x - paddlemove
if "right" in k and paddle.pos.x < rightline - 10:
paddle.pos.x = paddle.pos.x + paddlemove
#move ball
ball.pos.y = ball.pos.y + ballshifty
ball.pos.x = ball.pos.x + ballshiftx
#top bounce
if ball.pos.y >= topline-boxsize/2-ballsize:
ballshifty = ballshifty * -1
#left and right bounce
if ball.pos.x >= rightline-boxsize/2-ballsize:
ballshiftx = ballshiftx * -1
if ball.pos.x <= leftline+boxsize/2+ballsize:
ballshiftx = ballshiftx * -1
#paddle bounce
if (ball.pos.x-10 < paddle.pos.x <ball.pos.x+10) and (ball.pos.y-ballsize+1 <= paddle.pos.y):
ballshifty = ballshifty * -1
count = count + 1
#bottom bounce & lose
if ball.pos.y <= bottomline+boxsize/2+ballsize:
ballshifty = ballshifty * -1
score = score*0.5
count = 0
if abs(ballshiftx) >= .51:
ballshiftx = ballshiftx - ballshiftx*0.1
ballshifty = ballshifty - ballshifty*0.1
newcolor = newcolordown(ball.color)
ball.color = newcolor
#ball under paddle - move the ball to above the paddle
if (ball.pos.x-10 < paddle.pos.x <ball.pos.x+10) and (ball.pos.y < paddle.pos.y):
ball.pos.y = ball.pos.y + 4
# change color and speed up every 10 hits
if count == 10:
score = score + 10
ballshiftx = ballshiftx + 0.1*ballshiftx
ballshifty = ballshifty + 0.1*ballshifty
newcolor = newcolorup(ball.color)
ball.color = newcolor
count = 0