Code for How to Create a Pong Game in Python Tutorial


View on Github

ball.py

import pygame, sys
import random
from settings import WIDTH, HEIGHT

pygame.init()

class Ball:
	def __init__(self, x, y, radius):
		self.x = x
		self.y = y
		self.radius = radius
		self.rect = pygame.Rect(self.x, self.y, radius, radius)
		self.color = pygame.Color("red")
		self.direction = None
		self.speed_x = 0
		self.speed_y = 0
		self._random_direction()

	def _random_direction(self):
		direction = ("right", "left")
		self.direction = random.choice(direction)

	def _ball_movement(self):
		# horizontal handling
		if self.direction == "right":
			self.speed_x = 18
		else:
			self.speed_x = -18

		# vertical handling
		if self.rect.y >= HEIGHT - self.radius:
			self.speed_y = -18
		elif self.rect.y <= 0 + self.radius:
			self.speed_y = 18

		# wall bounce handling
		self.rect.x += self.speed_x
		self.rect.y += self.speed_y

	def update(self, screen):
		self._ball_movement()
		pygame.draw.rect(screen, self.color, self.rect)

main.py

import pygame, sys
from settings import WIDTH, HEIGHT
from table import Table

pygame.init()

screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Ping Pong")

class Pong:
	def __init__(self, screen):
		self.screen = screen
		self.FPS = pygame.time.Clock()

	def draw(self):
		pygame.display.flip()

	def main(self):
		# start menu here
		table = Table(self.screen)  # pass to table the player_option saved to table.game_mode
		while True:
			self.screen.fill("black")

			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					pygame.quit()
					sys.exit()

			table.player_move()
			table.update()
			self.draw()
			self.FPS.tick(30)


if __name__ == "__main__":
	play = Pong(screen)
	play.main()

player.py

import pygame

class Player:
	def __init__(self, x, y, width, height):
		self.x = x
		self.y = y
		self.rect = pygame.Rect(self.x, self.y, width, height)
		self.color = pygame.Color("gray")
		self.player_speed = 16
	
		self.score = 0

	def move_up(self):
		self.rect.y -= self.player_speed

	def move_bottom(self):
		self.rect.y += self.player_speed

	def update(self, screen):
		pygame.draw.rect(screen, self.color, self.rect)

settings.py

WIDTH, HEIGHT = 990, 450

player_width, player_height  = 20, 90

table.py

import pygame, time
import sys
from player import Player
from ball import Ball
from settings import WIDTH, HEIGHT, player_width, player_height

class Table:
	def __init__(self, screen):
		self.screen = screen
		self.game_over = False
		self.score_limit = 10
		self.winner = None
		self._generate_world()

		# text info
		self.font = pygame.font.SysFont('Bauhaus 93', 60)
		self.inst_font = pygame.font.SysFont('Bauhaus 93', 30)
		self.color = pygame.Color("white")

	# create and add player to the screen
	def _generate_world(self):
		self.playerA = Player(0, HEIGHT // 2 - (player_height // 2), player_width, player_height)
		self.playerB = Player(WIDTH - player_width,  HEIGHT // 2 - (player_height // 2), player_width, player_height)
		self.ball = Ball(WIDTH // 2 - player_width, HEIGHT - player_width, player_width)

	def _ball_hit(self):
		# if ball is not hit by a player and pass through table sides
		if self.ball.rect.left >= WIDTH:
			self.playerA.score += 1
			self.ball.rect.x = WIDTH // 2
			time.sleep(1)
		elif self.ball.rect.right <= 0:
			self.playerB.score += 1
			self.ball.rect.x = WIDTH // 2
			time.sleep(1)

		# if ball land in the player
		if pygame.Rect.colliderect(self.ball.rect, self.playerA.rect):
			self.ball.direction = "right"
		if pygame.Rect.colliderect(self.ball.rect, self.playerB.rect):
			self.ball.direction = "left"

	def _bot_opponent(self):
		if self.ball.direction == "left" and self.ball.rect.centery != self.playerA.rect.centery:
			if self.ball.rect.top <= self.playerA.rect.top:
				if self.playerA.rect.top > 0:
					self.playerA.move_up()
			if self.ball.rect.bottom >= self.playerA.rect.bottom:
				if self.playerA.rect.bottom < HEIGHT:
					self.playerA.move_bottom()

	def player_move(self):
		keys = pygame.key.get_pressed()

		# for bot opponent controls
		self._bot_opponent()

		# for player controls
		if keys[pygame.K_UP]:
			if self.playerB.rect.top > 0:
				self.playerB.move_up()
		if keys[pygame.K_DOWN]:
			if self.playerB.rect.bottom < HEIGHT:
				self.playerB.move_bottom()

	def _show_score(self):
		A_score, B_score = str(self.playerA.score), str(self.playerB.score)
		A_score = self.font.render(A_score, True, self.color)
		B_score = self.font.render(B_score, True, self.color)
		self.screen.blit(A_score, (WIDTH // 4, 50))
		self.screen.blit(B_score, ((WIDTH // 4) * 3, 50))

	def _game_end(self):
		if self.winner != None:
			print(f"{self.winner} wins!!")
			pygame.quit()
			sys.exit()

	def update(self):
		self._show_score()

		self.playerA.update(self.screen)		
		self.playerB.update(self.screen)

		self._ball_hit()

		if self.playerA.score == self.score_limit:
			self.winner = "Opponent"

		elif self.playerB.score == self.score_limit:
			self.winner = "You"

		self._game_end()
		self.ball.update(self.screen)