## Pong reloaded // MagPi77 //pygamezero

Bernd54Albrecht
Posts: 30
Joined: Tue Jun 16, 2015 6:35 pm

### Pong reloaded // MagPi77 //pygamezero

Pong is an excellent example for using MCP3004/3008 as well as for pygamezero. We like that "old" game from 1972.
However, there is always room for improvement. My pupils wanted to change the BALLSPEED and have a winner, when a certain score is reached. Therefore, we amended the code as attached. BALLSPEED is initially 3 (versus 5) and gets faster every 60 seconds. No problem.
And we included an if-statement, whether p1Score or p2Score has reached END (for test purposes =3, later =10). We included a print-statement that gives the correct result in the shell. However, here comes our problem: the score on the game board is not updated to the final score, although the print-out in the shell is correct. Why do the statements in line 40 an 48 do not work?

attached the modified code and a photo of our home-made paddles with 10k-potentiometers. Pong_Paddles1024.jpg (115.03 KiB) Viewed 3266 times

Code: Select all

``````# pong game
# source MagPi 77, pages 32 - 35
# modified by Raspberry Pi course at JFS Bad Bramstedt, Germany

import pgzrun
import random
from gpiozero import MCP3004
import math
from time import time, sleep          # neu

pot1 = MCP3004(0)
pot2 = MCP3004(1)

# Set up the colours
BLACK = (0  ,0  ,0  )
WHITE = (255,255,255)
p1Score = p2Score = 0
END = 3                        # new: end of game, when first player has scored END
RESTART = 15                   # restart after xx seconds
BALLSPEED = 3                  # changed from 5 to initially 3
p1Y = 300
p2Y = 300
TIME = time()

def draw():
global screen
screen.fill(BLACK)
screen.draw.line((400,0),(400,600),"green")
drawBall()
screen.draw.text(str(p1Score) , center=(105, 40), color=WHITE, fontsize=60)
screen.draw.text(str(p2Score) , center=(705, 40), color=WHITE, fontsize=60)
winner()

def winner():           #new
global screen, p1Score, p2Score, BALLSPEED, TIME
if p2Score==END:
print("p1 = ",p1Score,"p2 = ",p2Score)
print("Winner is Player2")
screen.draw.tex[attachment=0]Pong_Paddles1024.jpg[/attachment]t(str(p2Score) , center=(705, 40), color=WHITE, fontsize=60)   # ???
BALLSPEED = 0
sleep(RESTART)
p1Score = p2Score = 0
BALLSPEED = 3
if p1Score==END:
print("p1 = ",p1Score,"p2 = ",p2Score)
print("inner is Player1")
screen.draw.text(str(p1Score), center=(105, 40), color=WHITE, fontsize=60)    # ???
BALLSPEED = 0
sleep(RESTART)
p1Score = p2Score = 0
BALLSPEED = 3

def update():
updateBall()

def init():
global ballX, ballY, ballDirX, ballDirY
ballX = 400
ballY = 300
a = random.randint(10, 350)
while (a > 80 and a < 100) or (a > 260 and a < 280):
a = random.randint(10, 350)

global p1Y, p2Y
p1rect = Rect((100, p1Y-30), (10, 60))
p2rect = Rect((700, p2Y-30), (10, 60))
screen.draw.filled_rect(p1rect, "red")
screen.draw.filled_rect(p2rect, "red")

global p1Y, p2Y

p1Y = (pot1.value * 540) +30
p2Y = (pot2.value * 540) +30

if keyboard.up:
if p2Y > 30:
p2Y -= 2
if keyboard.down:
if p2Y < 570:
p2Y += 2
if keyboard.w:
if p1Y > 30:
p1Y -= 2
if keyboard.s:
if p1Y < 570:
p1Y += 2

def updateBall():
global ballX, ballY, ballDirX, ballDirY, p1Score, p2Score, BALLSPEED, TIME
ballX += ballDirX*BALLSPEED
ballY += ballDirY*BALLSPEED
ballRect = Rect((ballX-4,ballY-4),(8,8))
p1rect = Rect((100, p1Y-30), (10, 60))
p2rect = Rect((700, p2Y-30), (10, 60))
if  time() - TIME > 60:             #new
BALLSPEED += 1                  #new
TIME = time()                   #new
print("BALLSPEED is now: ", BALLSPEED)

if checkCollide(ballRect, p1rect) or checkCollide(ballRect, p2rect):
ballDirX *= -1
if ballY < 4 or ballY > 596:
ballDirY *= -1
if ballX < 0:
p2Score += 1
init()
if ballX > 800:
p1Score += 1
init()

def checkCollide(r1,r2):
return (
r1.x < r2.x + r2.w and
r1.y < r2.y + r2.h and
r1.x + r1.w > r2.x and
r1.y + r1.h > r2.y
)

def drawBall():
screen.draw.filled_circle((ballX, ballY), 8, "white")
pass

init()
pgzrun.go()

``````

lucyhattersley
Posts: 29
Joined: Tue Aug 04, 2015 5:05 pm

### Re: Pong reloaded // MagPi77 //pygamezero

Typo on line 40.

Code: Select all

``screen.draw.tex[attachment=0]Pong_Paddles1024.jpg[/attachment]t(str(p2Score) , center=(705, 40), color=WHITE, fontsize=60)   # ???``
Should be:

Code: Select all

``screen.draw.text[attachment=0]Pong_Paddles1024.jpg[/attachment]t(str(p2Score) , center=(705, 40), color=WHITE, fontsize=60)   # ???``
(Edit: There's some other stuff as well. Try to read your code line-by-line. I find it helps to read from back to front one line at a time).

Bernd54Albrecht
Posts: 30
Joined: Tue Jun 16, 2015 6:35 pm

### Re: Pong reloaded // MagPi77 //pygamezero

However, my problem is not the missing t in text. This word was divided by the first attempt to attach a photo, which was placed in the middle of the code. So, this part must be deleted.

Bernd54Albrecht
Posts: 30
Joined: Tue Jun 16, 2015 6:35 pm

### Re: Pong reloaded // MagPi77 //pygamezero

Correction:

Code: Select all

``````# pong game
# source MagPi 77, pages 32 - 35
# modified by Raspberry Pi course at JFS Bad Bramstedt, Germany

import pgzrun
import random
from gpiozero import MCP3004
import math
from time import time, sleep          # neu

pot1 = MCP3004(0)
pot2 = MCP3004(1)

# Set up the colours
BLACK = (0  ,0  ,0  )
WHITE = (255,255,255)
p1Score = p2Score = 0
END = 3                        # new: end of game, when first player has scored END
RESTART = 15                   # restart after xx seconds
BALLSPEED = 3                  # changed from 5 to initially 3
p1Y = 300
p2Y = 300
TIME = time()

def draw():
global screen
screen.fill(BLACK)
screen.draw.line((400,0),(400,600),"green")
drawBall()
screen.draw.text(str(p1Score) , center=(105, 40), color=WHITE, fontsize=60)
screen.draw.text(str(p2Score) , center=(705, 40), color=WHITE, fontsize=60)
winner()

def winner():           #new
global screen, p1Score, p2Score, BALLSPEED, TIME
if p2Score==END:
print("p1 = ",p1Score,"p2 = ",p2Score)
print("Winner is Player2")
screen.draw.text(str(p2Score) , center=(705, 40), color=WHITE, fontsize=60)   # ???
BALLSPEED = 0
sleep(RESTART)
p1Score = p2Score = 0
BALLSPEED = 3
if p1Score==END:
print("p1 = ",p1Score,"p2 = ",p2Score)
print("inner is Player1")
screen.draw.text(str(p1Score), center=(105, 40), color=WHITE, fontsize=60)    # ???
BALLSPEED = 0
sleep(RESTART)
p1Score = p2Score = 0
BALLSPEED = 3

def update():
updateBall()

def init():
global ballX, ballY, ballDirX, ballDirY
ballX = 400
ballY = 300
a = random.randint(10, 350)
while (a > 80 and a < 100) or (a > 260 and a < 280):
a = random.randint(10, 350)

global p1Y, p2Y
p1rect = Rect((100, p1Y-30), (10, 60))
p2rect = Rect((700, p2Y-30), (10, 60))
screen.draw.filled_rect(p1rect, "red")
screen.draw.filled_rect(p2rect, "red")

global p1Y, p2Y

p1Y = (pot1.value * 540) +30
p2Y = (pot2.value * 540) +30

if keyboard.up:
if p2Y > 30:
p2Y -= 2
if keyboard.down:
if p2Y < 570:
p2Y += 2
if keyboard.w:
if p1Y > 30:
p1Y -= 2
if keyboard.s:
if p1Y < 570:
p1Y += 2

def updateBall():
global ballX, ballY, ballDirX, ballDirY, p1Score, p2Score, BALLSPEED, TIME
ballX += ballDirX*BALLSPEED
ballY += ballDirY*BALLSPEED
ballRect = Rect((ballX-4,ballY-4),(8,8))
p1rect = Rect((100, p1Y-30), (10, 60))
p2rect = Rect((700, p2Y-30), (10, 60))
if  time() - TIME > 60:             #new
BALLSPEED += 1                  #new
TIME = time()                   #new
print("BALLSPEED is now: ", BALLSPEED)

if checkCollide(ballRect, p1rect) or checkCollide(ballRect, p2rect):
ballDirX *= -1
if ballY < 4 or ballY > 596:
ballDirY *= -1
if ballX < 0:
p2Score += 1
init()
if ballX > 800:
p1Score += 1
init()

def checkCollide(r1,r2):
return (
r1.x < r2.x + r2.w and
r1.y < r2.y + r2.h and
r1.x + r1.w > r2.x and
r1.y + r1.h > r2.y
)

def drawBall():
screen.draw.filled_circle((ballX, ballY), 8, "white")
pass

init()
pgzrun.go()
``````

lucyhattersley
Posts: 29
Joined: Tue Aug 04, 2015 5:05 pm

### Re: Pong reloaded // MagPi77 //pygamezero

Ah, it's a logic error then.

I haven't fixed it but is related to the screen.draw.text nested inside winner(). This function is not being called. It seems to be repeating the score update in the draw() function so the winner() function should return to that function() (rather than trying to update the text itself).

You are also repeating the setup variables twice inside the winner() function definition. Maybe take the setup code and place it inside a separate function definition) and call this when the player has won (and call this after the draw() function has updated the score).

Maybe open it up in Thonny and use the Debug mode and step through and see where the variables and logic end up?

Bernd54Albrecht
Posts: 30
Joined: Tue Jun 16, 2015 6:35 pm

### Re: Pong reloaded // MagPi77 //pygamezero

I replaced the screen.draw.text statement with the full function draw. No joy!
I ran the debugger in Thonny -> error message, see attached screen shot. Thonny - -home-pi-PyGameZero-pong_gettingFaster.py @ 132 - 1_001.png (117.18 KiB) Viewed 3156 times
pgzrun obviously does not support the debugger.

The missing link to the above is the update function in pygamezero. In Pygame the display is deliberately updated at the end of all computations, in pygamezero the update is presumably at the beginning of the next round of the game. The draw.text statement is therefore prepared, but not executed, I guess.

Thanks for the support, Lucy, I will leave it as is.

MarkyV
Posts: 97
Joined: Wed Sep 21, 2016 1:52 pm
Location: Buckingham, UK
Contact: Website

### Re: Pong reloaded // MagPi77 //pygamezero

Hi - glad you are having fun with the pong game - I think I know why you are not seeing what you are expecting: When you call the winner() function whilst the scores are printed out to the console (which is updated outside the Pygame Zero draw cycle) The scores that you are drawing to the screen at that point are not seen because you are calling the sleep() function. Sleep halts all program activity so the draw cycle will not complete until it is released by sleep() - after the restart delay.

What you need to do is detect the endgame state in the draw() function and do your end game draw there - you could have a countdown to restart in the update() function or you could have the user press a key like the space bar - I have some example code below (just the sections you need to change to do a restart with the spacebar):

Code: Select all

``````def draw():
global screen, p1Score, p2Score
screen.fill(BLACK)
screen.draw.line((400,0),(400,600),"green")
drawBall()
screen.draw.text(str(p1Score) , center=(105, 40), color=WHITE, fontsize=60)
screen.draw.text(str(p2Score) , center=(705, 40), color=WHITE, fontsize=60)
if p2Score==END:
screen.draw.text("P2 Wins!" , center=(400, 30), color=WHITE, fontsize=60)
if p1Score==END:
screen.draw.text("P1 Wins!", center=(400, 30), color=WHITE, fontsize=60)

def on_key_down(key):
global p1Score, p2Score, BALLSPEED
if (p2Score == END or p1Score == END) and key.name == "SPACE":
p1Score = p2Score = 0
BALLSPEED = 3
print("Restart")

def update():
if p2Score < END and p1Score < END:
updateBall()

``````
Hope that helps Mark
My RaspberryPi Blog: http://thepimaker.online

Bernd54Albrecht
Posts: 30
Joined: Tue Jun 16, 2015 6:35 pm

### Re: Pong reloaded // MagPi77 //pygamezero

That was it! Many thanks to Mark.

Attached the revised code:

Code: Select all

``````# pong game
# source MagPi 77, pages 32 - 35
# modified by Raspberry Pi course at JFS Bad Bramstedt, Germany
# with the decisive contribution by MarkyV
# also thanks to Lucy Hattersley
# BALLSPEED starts rather slow, but increases every 60 seconds
# Game over, when one player scores 10
# Restart: Press Space Bar

import pgzrun
import random
from gpiozero import MCP3004
import math
from time import time, sleep          # neu

pot1 = MCP3004(0)            # change to MCP3008, if using 8-channel ADC
pot2 = MCP3004(1)            # change to MCP3008, if using 8-channel ADC

# Set up the colours
BLACK = (0  ,0  ,0  )
WHITE = (255,255,255)
p1Score = p2Score = 0
END = 10                        # new: end of game, when first player has scored END
RESTART = 15                   # restart after xx seconds
BALLSPEED = 3                  # changed from 5 to initially 3
p1Y = 300
p2Y = 300
TIME = time()

def draw():
global screen, p1Score, p2Score
screen.fill(BLACK)
screen.draw.line((400,0),(400,600),"green")
drawBall()
screen.draw.text(str(p1Score) , center=(105, 40), color=WHITE, fontsize=60)
screen.draw.text(str(p2Score) , center=(705, 40), color=WHITE, fontsize=60)
if p2Score==END:
screen.draw.text("Player2 wins!" , center=(400, 30), color=WHITE, fontsize=60)
if p1Score==END:
screen.draw.text("Player1 wins!", center=(400, 30), color=WHITE, fontsize=60)

def on_key_down(key):
global p1Score, p2Score, BALLSPEED
if (p2Score == END or p1Score == END) and key.name == "SPACE":
p1Score = p2Score = 0
BALLSPEED = 3
print("Restart")

def update():
if p2Score < END and p1Score < END:
updateBall()

def init():
global ballX, ballY, ballDirX, ballDirY
ballX = 400
ballY = 300
a = random.randint(10, 350)
while (a > 80 and a < 100) or (a > 260 and a < 280):
a = random.randint(10, 350)

global p1Y, p2Y
p1rect = Rect((100, p1Y-30), (10, 60))
p2rect = Rect((700, p2Y-30), (10, 60))
screen.draw.filled_rect(p1rect, "red")
screen.draw.filled_rect(p2rect, "red")

global p1Y, p2Y
p1Y = (pot1.value * 540) +30
p2Y = (pot2.value * 540) +30
if keyboard.up:
if p2Y > 30:
p2Y -= 2
if keyboard.down:
if p2Y < 570:
p2Y += 2
if keyboard.w:
if p1Y > 30:
p1Y -= 2
if keyboard.s:
if p1Y < 570:
p1Y += 2

def updateBall():
global ballX, ballY, ballDirX, ballDirY, p1Score, p2Score, BALLSPEED, TIME
ballX += ballDirX*BALLSPEED
ballY += ballDirY*BALLSPEED
ballRect = Rect((ballX-4,ballY-4),(8,8))
p1rect = Rect((100, p1Y-30), (10, 60))
p2rect = Rect((700, p2Y-30), (10, 60))
if  time() - TIME > 60:               #new
BALLSPEED += 1                  #new
TIME = time()                        #new
print("BALLSPEED is now: ", BALLSPEED)

if checkCollide(ballRect, p1rect) or checkCollide(ballRect, p2rect):
ballDirX *= -1
if ballY < 4 or ballY > 596:
ballDirY *= -1
if ballX < 0:
p2Score += 1
init()
if ballX > 800:
p1Score += 1
init()

def checkCollide(r1,r2):
return (
r1.x < r2.x + r2.w and
r1.y < r2.y + r2.h and
r1.x + r1.w > r2.x and
r1.y + r1.h > r2.y
)

def drawBall():
screen.draw.filled_circle((ballX, ballY), 8, "white")
pass

init()
pgzrun.go()

``````