Hi I have written the following code in Python. Any improvements on my code will be appreciated as this is my first shot at pygame!
There are some problems in terms of functionality, to state briefly ball sometimes gets stuck within a paddle, which I am continuing to resolve
import pygame, sys
import random
from math import degrees, radians, sin, cos
pygame.init()
# Create a screen
win = pygame.display.set_mode((800,700))
win_info = pygame.display.Info()
win_w, win_h = win_info.current_w, win_info.current_h
pygame.display.set_caption("Pong")
pad_colour = (255,255,255) #White colour
pad_distance = 50
speed = 10
running = True
fps = 30
#############################################################################
class border(pygame.sprite.Sprite):
width = win_w
height = 10
def __init__(self,width, height, colour):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((width,height))
self.image.fill(colour)
self.rect = self.image.get_rect()
def draw(self):
win.blit(self.image, self.rect)
#############################################################################
class paddle(pygame.sprite.Sprite):
"""left arg refer to top left corner coordinate of paddle
"""
def __init__(self,width, height, speed, colour):
pygame.sprite.Sprite.__init__(self)
self.width = width
self.height = height
self.image = pygame.Surface([width, height])
self.image.fill(colour)
self.speed = speed
self.vel_x = 0
self.vel_y = 0
# Size of rectangle
self.rect = self.image.get_rect()
def move(self, x, y):
self.rect.move_ip(x,y)
def moveTo(self, x, y):
self.rect.topleft = (x,y)
def draw(self):
win.blit(self.image, (self.rect.x,self.rect.y))
#############################################################################
class ball(pygame.sprite.Sprite):
""" Facing takes 1 or -1 to determine direction of movement
"""
def __init__(self, radius, factor, colour):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([radius*2, radius*2])
pygame.draw.circle(self.image, colour, (radius,radius), radius)
self.rect = self.image.get_rect()
# Replace facing when finalising implementation of ball
self.facing = -1
self.factor = factor
self.vel_x, self.vel_y = self.randomMovement(factor)
def move(self, x,y):
self.rect.move_ip(x,y)
def moveTo(self, x, y):
self.rect.center = (x,y)
def collidePad(self):
self.vel_x = self.vel_x * -1
def draw(self):
win.blit(self.image, (self.rect))
def randomMovement(self,factor=None):
#unit vector
if factor == None:
# Used for all calls after ball instance is initialised
factor = self.factor
angle = radians(random.randint(30,80))
rand_y = random.randrange(-1,2,2)
y = sin(angle)
x = cos(angle)
""" How to get over the use of int and rounding errors. Using int the line before causes the vector to be 0,0 as the numbers after 0 are truncated"""
self.vel_x, self.vel_y = (int(x*factor),int(y*factor)*rand_y)
#print(x, y)
return self.vel_x, self.vel_y
#############################################################################
# Main Game Loop
def main():
white = (255,255,255)
border_height = 10
pad_width = int(win_w/50)
pad_height = int(win_h/6)
pad_left = paddle(pad_width, pad_height, speed, white)
pad_right = paddle(pad_width, pad_height, speed, white)
# Set X and Y of left pad
pad_left.rect.topleft = (pad_distance, int((win_h-pad_height)/2))
# Set X and Y of right pad
pad_right.rect.topleft = ((win_w-pad_distance-pad_width), int((win_h-pad_height)/2))
top_border = border(win_w, border_height, white)
top_border.rect.topleft = (0, 0)
bottom_border = border(win_w, border_height, white)
bottom_border.rect.topleft = (0, win_h-border_height)
gameBall = ball(10, 10, white)
gameBall.rect.center = (int(win_w/2), int(win_h/2))
to_draw = [pad_left, pad_right, top_border, bottom_border, gameBall]
redrawGameWin(to_draw)
backGround = pygame.Surface((win_w,win_h))
backGround.fill(white)
clock = pygame.time.Clock()
# Game Loop
while running:
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.display.quit()
pygame.quit()
sys.exit()
keys = pygame.key.get_pressed()
# Left pad moving up with top boundary collision
if keys[pygame.K_s] and pad_left.rect.y > 0:
if pad_left.rect.y - top_border.height - pad_left.speed <= 0 :
pad_left.vel_y = 0
pad_left.moveTo(pad_distance, top_border.height)
else:
pad_left.vel_y = -pad_left.speed
pad_left.move(0, pad_left.vel_y)
# Left pad moving down with bottom boundary collision
if keys[pygame.K_x]:
if pad_left.rect.y + pad_left.height + pad_left.speed + bottom_border.height >= win_h:
pad_left.vel_y = 0
pad_left.moveTo(pad_distance, win_h-pad_left.height-bottom_border.height)
else:
pad_left.vel_y = pad_left.speed
pad_left.move(0, pad_left.speed)
if not keys[pygame.K_s] and not keys[pygame.K_x]:
pad_left.vel_x, pad_left.vel_y = 0,0
# Right pad moving up with top boundary collision
if keys[pygame.K_k]:
if pad_right.rect.y - top_border.height - pad_right.speed <= 0:
pad_right.vel_y = 0
pad_right.moveTo(win_w-pad_distance-pad_right.width, top_border.height)
else:
pad_right.vel_y = -pad_right.speed
pad_right.move(0, pad_right.vel_y)
# Right pad moving down with bottom boundary collision
if keys[pygame.K_m]:
if pad_right.rect.y + pad_right.height + pad_right.speed + bottom_border.height >= win_h:
pad_right.vel_y = 0
pad_right.moveTo(win_w-pad_distance-pad_right.width, win_h-pad_right.height-bottom_border.height)
else:
pad_right.vel_y = pad_right.speed
pad_right.move(0, pad_right.vel_y)
if not keys[pygame.K_k] and not keys[pygame.K_m]:
pad_right.vel_x, pad_right.vel_y = 0,0
# Ball bouncing off top border
if gameBall.rect.colliderect(top_border.rect) or gameBall.rect.colliderect(bottom_border.rect):
gameBall.vel_y = gameBall.vel_y*-1
# Ball bouncing off right pad
if gameBall.rect.colliderect(pad_right.rect):
gameBall.vel_x = -(gameBall.vel_x + pad_right.vel_x)
gameBall.vel_y = gameBall.vel_y + pad_right.vel_y
# Ball bouncing off left pad
if gameBall.rect.colliderect(pad_left.rect):
gameBall.vel_x = -(gameBall.vel_x + pad_left.vel_x)
gameBall.vel_y = gameBall.vel_y + pad_left.vel_y
# Ball moving by velocity vector
gameBall.move(gameBall.vel_x, gameBall.vel_y)
# Ball moves off screem
if gameBall.rect.left >= win_w or gameBall.rect.right <=0:
gameBall.randomMovement()
gameBall.moveTo(int(win_w/2), int(win_h/2))
redrawGameWin(to_draw)
#############################################################################
def redrawGameWin(shapes):
#global dirty_rects
win.fill((0,0,0))
for shape in shapes:
shape.draw()
pygame.display.flip()
#############################################################################
if __name__ == "__main__":
main()