Pong

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

Link

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

Link

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