Jump to content

  • Log In with Google      Sign In   
  • Create Account

Pygame Pong Code Review


Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.


  • You cannot reply to this topic
1 reply to this topic

#1 jpkami   Members   -  Reputation: 106

Like
0Likes
Like

Posted 12 May 2014 - 02:30 AM

Hello everybody,

 

Following this article , A friend and I started with Pong. We found some previously working code from Nuorah and decided to upgrade some functionnalities : 

 - add a really basic AI

 - improved the collision detection to match higher ball "speed"

 - improved the bouncing on the paddle

 - add some leveling functionnality to help the losing player (padlle speed increases for the losing player)

 

So we decided to post here the code for advice on what could be improved, mainly for the colision detection (line 208), which is working but we have to draw an array of rects to detail the balll's "movement"

import pygame, sys, time, random
from pygame.locals import *

pygame.init()
mainClock = pygame.time.Clock()

#Constant of the board of the game
WINDOWWIDTH = 800
WINDOWHEIGHT = 600
SIZESIDES = 20
MIDDLESIZE = 10

#Speed of the game constants
FPS = 30
PADDLESPEED = 10

#Rects of the board of the game
TOPSIDE = pygame.Rect(0, 0, WINDOWWIDTH, SIZESIDES)
BOTTOMSIDE = pygame.Rect(0, WINDOWHEIGHT - SIZESIDES, WINDOWWIDTH, SIZESIDES)
MIDDLE = []
for i in range(0, 31):
    MIDDLE.append(pygame.Rect(WINDOWWIDTH/2 - MIDDLESIZE/2,15 + i*20, MIDDLESIZE, MIDDLESIZE))    

windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)

pygame.display.set_caption('Running_window')

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

gameIsPlaying = False

#These are used to print the scores
CHIFFRES =[
'''WWWWW
W   W
W   W
W   W
WWWWW''',
'''    W
    W
    W
    W
    W''',
'''WWWWW
    W
WWWWW
W    
WWWWW''',
'''WWWWW
    W
WWWWW
    W
WWWWW''',
'''W   W
W   W
WWWWW
    W
    W''',
'''WWWWW
W    
WWWWW
    W
WWWWW''',
'''WWWWW
W    
WWWWW
W   W
WWWWW''',
'''WWWWW
    W
  WWW
    W
    W''',
'''WWWWW
W   W
WWWWW
W   W
WWWWW''',
'''WWWWW
W   W
WWWWW
    W
WWWWW''',
'''''']

#Functions

    #Draw the score (in fact return a list with the rect to draw, drawn later with drawGame())
def drawChiffre(a, x, y):
    countx = 0
    county = 0
    rectList = []
    for piece in CHIFFRES[a]:
        if countx % 7 == 5 or countx % 7 == 6:
            countx +=1
            county +=0.5
        if piece == '''W''':
            rectList.append(pygame.Rect(x + (countx%7)*10, y + county*15, MIDDLESIZE, MIDDLESIZE*1.5))
            countx +=1
        elif piece == ''' ''':
            countx +=1
    return rectList

    #This function draws everything in the game. 
def drawGame(Paddle1, scoreP1, Paddle2, scoreP2, Ball):
    windowSurface.fill(BLACK)

    Paddle1.draw()
    Paddle2.draw()
    Ball.draw() 

    drawScoreP2 = drawChiffre(scoreP2, 450, 50)
    for piece in drawScoreP2:
        pygame.draw.rect(windowSurface, WHITE, piece)

    drawScoreP1 = drawChiffre(scoreP1, 300, 50)
    for piece in drawScoreP1:
        pygame.draw.rect(windowSurface, WHITE, piece)
        
    pygame.draw.rect(windowSurface, WHITE, TOPSIDE) 
    pygame.draw.rect(windowSurface, WHITE, BOTTOMSIDE)

    for piece in MIDDLE :
        pygame.draw.rect(windowSurface, WHITE, piece)

    #A function for writing a text with the most basic font
def write(text, fontSize, x, y):
    font = pygame.font.SysFont(None, fontSize)
    
    textR = font.render(text, True, WHITE)
    textRect = textR.get_rect()
    textRect.centerx = x
    textRect.centery = y
    windowSurface.blit(textR, textRect)

#Classes
        
    #The paddles
class Paddle:
    rect = pygame.Rect(0, 0, 0, 0)
    movement = 0
    padSpeed = 10
    def __init__(self, l, t, w, h):
        self.l = l
        self.t = t
        self.w = w
        self.h = h
    def setRect(self):
        self.rect = pygame.Rect(self.l, self.t, self.w, self.h)
        #print(self.rect)
    def setPadSpeed(self, scoreSelf, scoreAdv):
        if scoreSelf < scoreAdv:
            self.padSpeed = 10 + (scoreAdv-scoreSelf)*5
        else:
            self.padSpeed = 10
    def setPosition(self):
        self.position = self.t
    def setMovement(self, x):
        self.movement = x
    def move(self):
        self.t = self.t + self.movement*self.padSpeed
        self.setPosition()
        self.setRect()
    def draw(self):
        pygame.draw.rect(windowSurface, WHITE, self.rect)
    def collideWithSide(self, upSide, downSide):
        if (self.t + self.h) > downSide:
            self.setMovement(0)
        if (self.t) < upSide:
            self.setMovement(0)

	#AI
class AI(Paddle):
    def move(self, ball):
        if ball.t == self.t +self.h/2 :
            self.movement = 0
        elif ball.t < self.t +self.h/2 : 
            self.movement = -1
        elif ball.t > self.t +self.h/2:
            self.movement = 1
		
        self.t = self.t + self.movement*self.padSpeed
        self.setPosition()
        self.setRect() 
	
	
    #The ball
class Ball:
    rect = pygame.Rect(0, 0, 0, 0)
    rectList = []
    position = [0, 0]

    def __init__(self, l, t, w, h, x, y):
        self.speed = [x, y]
        self.l = l
        self.t = t
        self.w = w
        self.h = h
    def setRect(self):
        self.rect = pygame.Rect(self.l, self.t, self.w, self.h)
    def setPosition(self):
        self.position = [self.l, self.t]
    def setSpeed(self, x, y):
        self.speed = [x, y]
    def draw(self):
        pygame.draw.rect(windowSurface, WHITE, self.rect)
    def move(self):
        #vecteur ball
        self.rectList = []
        vectX = abs(round(self.speed[0]/2))
        signeX = (round(self.speed[0]/2))/vectX
        for i in range(0, vectX):
            self.rectList.append(pygame.Rect(self.l + (signeX*i*2), self.t + self.speed[1]*i/vectX, 2, 2))
            #print(self.rectList[i])
        self.l = self.l + self.speed[0]
        self.t = self.t + self.speed[1]
        self.setRect()
        self.setPosition()
    def bounce(self, paddle):
        #if self.rect.colliderect(paddle.rect):
        #print ("collide : " + str(paddle.rect.collidelist(self.rectList)))
        if paddle.rect.collidelist(self.rectList) != -1:
            self.setSpeed(-self.speed[0], self.speed[1] + (self.t - paddle.t - paddle.h/2)/5)
            rectinter = self.rectList[paddle.rect.collidelist(self.rectList)-1]
            if self.l < WINDOWWIDTH/2:
                self.l = 20
            else:
                self.l = WINDOWWIDTH-20
    def collideWithSide(self, upSide, downSide):
        if (self.t + self.h) > downSide or (self.t) < upSide:
            self.setSpeed(self.speed[0], -self.speed[1])

#Now the core of the game
while True:

    #Initialization of the score and of the paddles and ball
    scoreP1 = 0
    scoreP2 = 0

    paddle1 = Paddle(0, WINDOWHEIGHT/2 - 40, 15, 80)
    paddle2 = Paddle(WINDOWWIDTH - 15, WINDOWHEIGHT/2 - 40, 15, 80)
    ball = Ball(WINDOWWIDTH/2, WINDOWHEIGHT/2, 15, 15, random.randint(3, 5), random.randint(0, 0))

    #This is the "menu"
    while not gameIsPlaying:
        for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                if event.type == KEYDOWN:
                    if event.key == ord('s'):
                        gameIsPlaying = True
                    if event.key == ord('c'):
                        paddle1 = AI(0, WINDOWHEIGHT/2 - 40, 15, 80)
                        paddle2 = AI(WINDOWWIDTH - 15, WINDOWHEIGHT/2 - 40, 15, 80)
                        gameIsPlaying = True
                    if event.key == ord('x'):
                        paddle2 = AI(WINDOWWIDTH - 15, WINDOWHEIGHT/2 - 40, 15, 80)
                        gameIsPlaying = True
                if event.type == KEYUP:
                    if event.key == ord('q'):
                        pygame.quit()
                        sys.exit()
        

        drawGame(paddle1, scoreP1, paddle2, scoreP2, ball)

        write('Press s', 120, WINDOWWIDTH/4, WINDOWHEIGHT/2)
        write('to play!', 120, 3*WINDOWWIDTH/4, WINDOWHEIGHT/2)

        write('Press q', 60, 3*WINDOWWIDTH/8, 3*WINDOWHEIGHT/4)
        write('to quit.', 60, 5*WINDOWWIDTH/8, 3*WINDOWHEIGHT/4)
		
        write('UP', 30, 20, WINDOWHEIGHT/4)
        write('DOWN', 30, 36, 3*WINDOWHEIGHT/4)
        
        write('e', 60, WINDOWWIDTH - 15, WINDOWHEIGHT/4)
        write('c = AI', 60, WINDOWWIDTH - 15, 2*WINDOWHEIGHT/4)
        write('d', 60, WINDOWWIDTH - 15, 3*WINDOWHEIGHT/4)

        pygame.display.update()
        mainClock.tick(FPS)
        
    #This is the game playing
    while gameIsPlaying:

    
    
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE or event.key == ord('a'):
                    gameIsPlaying = False
                if event.key == K_UP:
                    paddle1.setMovement(-1)
                if event.key == K_DOWN:
                    paddle1.setMovement(1)
                if event.key == ord('e'):
                    paddle2.setMovement(-1)
                if event.key == ord('d'):
                    paddle2.setMovement(1)
            if event.type == KEYUP:
                if event.key == K_UP:
                    paddle1.setMovement(0)
                if event.key == K_DOWN:
                    paddle1.setMovement(0)
                if event.key == ord('e'):
                    paddle2.setMovement(0)
                if event.key == ord('d'):
                    paddle2.setMovement(0)
                

        #Move the ball and the paddles
        if paddle2.__class__.__name__ == "AI" :
            paddle2.move(ball)
        else: 
            paddle2.move()

        if paddle1.__class__.__name__ == "AI" :
            paddle1.move(ball)
        else: 
            paddle1.move()
        ball.move()

        #Collision between the ball and the paddles
        ball.bounce(paddle1)
        ball.bounce(paddle2)

        #Check if score and incrementation
        if ball.l <= 0:
            scoreP2 +=1
            paddle1.setPadSpeed(scoreP1, scoreP2)
            paddle2.setPadSpeed(scoreP2, scoreP1)
            ball = Ball(WINDOWWIDTH/2, WINDOWHEIGHT/2, 15, 15, random.randint(3, 5), random.randint(-10, 10))
        if ball.l >= WINDOWWIDTH:
            scoreP1 +=1
            paddle1.setPadSpeed(scoreP1, scoreP2)
            paddle2.setPadSpeed(scoreP2, scoreP1)
            ball = Ball(WINDOWWIDTH/2, WINDOWHEIGHT/2, 15, 15, -random.randint(3, 5), random.randint(-10, 10))

        #Check if winner and displaying and back to the menu
        if scoreP1 >= 10:
            write('WINNER', 60, WINDOWWIDTH/8, 2*WINDOWHEIGHT/8)
            pygame.display.update()
            time.sleep(1)
            gameIsPlaying = False

        if scoreP2 >= 10:
            write('WINNER', 60, 5*WINDOWWIDTH/8, 2*WINDOWHEIGHT/8)
            pygame.display.update()
            time.sleep(1)
            gameIsPlaying = False
            
        #Collision of the paddles and the ball with the sides
        paddle1.collideWithSide(20, 580)
        paddle2.collideWithSide(20, 580)
        ball.collideWithSide(20, 580)

        
        drawGame(paddle1, scoreP1, paddle2, scoreP2, ball)

        #Acceleration of the ball
        ball.setSpeed(ball.speed[0]*1.005, ball.speed[1])
        #print(ball.speed)
        write('Press escape to give up this game', 15, WINDOWWIDTH/8, WINDOWHEIGHT-SIZESIDES*2)

        pygame.display.update()
        mainClock.tick(FPS)

    pygame.display.update()
    mainClock.tick(FPS)

Thank you



#2 Vortez   Crossbones+   -  Reputation: 2709

Like
0Likes
Like

Posted 12 May 2014 - 03:31 AM

I only glanced at the code, but i think it's not that bad. The Chiffres array is a bit weird and take lots of space but beside that it seem pretty good.






Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.




PARTNERS