Ball Pool

How to Build 8 Ball Pool Game Using Python

How to Build 8 Ball Pool Game Using Python

Hello coder, welcome to the codewithrandom blog. It’s time to code a game in Python. In this article, we Build 8 Ball Pool Game Using Python. Creating an 8 Ball Pool Game using Python can be a challenging task, but it is possible using the Pygame library. We’ll cover the necessary steps involved in creating the game, including setting up the game window, creating the game board, adding game elements, and programming game logic.

8 Ball Pool Game Using Python

Before Starting 8 Ball Pool Game Using Python coding, check this video to know what we are going to make:

Before we can start 8 Ball Pool Game Using Python , we need to make sure that we have Python and the pygame library installed on our computer. Here are the steps to install them:

$ pip install pygame

To play the 8 Ball Pool Game Using Python, you can follow these steps:

  1. open any python code Editor.
  2. Import  the required  module .
  3. Copy the code for the 8 Ball Pool Game Using Python, which I provided Below in this article, and save it in a file named “game.py” (or any other name you prefer).
  4.  Run this  game.py to start the game.

That’s it! Have fun playing the 8 Ball pool Game Using Python.

8 Ball Pool Game using python

Here Complete Source code for the 8 Ball Pool Game Using Python project (Copy the code and Run )👇👇

import pygame
import sys
from math import *
import random

pygame.init()
width = 660
height = 360
outerHeight = 400
margin = 30
display = pygame.display.set_mode((width, outerHeight))
pygame.display.set_caption("8 Ball Pool")
clock = pygame.time.Clock()

background = (51, 51, 51)
white = (236, 240, 241)

gray = (123, 125, 125)

black = (23, 32, 42)
yellow = (244, 208, 63)
blue = (52, 152, 219)
red = (203, 67, 53)
purple = (136, 78, 160)
orange = (230, 126, 34)
green = (40, 180, 99)
brown = (100, 30, 22)
stickColor = (249, 231, 159)

colors = [yellow, blue, red, purple, orange, green, brown, black, yellow, blue, red, purple, orange, green, brown]

balls = []
noBalls = 15
radius = 10
friction = 0.005

# Ball Class
class Ball:
    def __init__(self, x, y, speed, color, angle, ballNum):
        self.x = x + radius
        self.y = y + radius
        self.color = color
        self.angle = angle
        self.speed = speed
        self.ballNum = ballNum
        self.font = pygame.font.SysFont("Agency FB", 10)

    # Draws Balls on Display Window
    def draw(self, x, y):
        pygame.draw.ellipse(display, self.color, (x - radius, y - radius, radius*2, radius*2))
        if self.color == black or self.ballNum == "cue":
            ballNo = self.font.render(str(self.ballNum), True, white)
            display.blit(ballNo, (x - 5, y - 5))
        else:
            ballNo = self.font.render(str(self.ballNum), True, black)
            if self.ballNum > 9:
                display.blit(ballNo, (x - 6, y - 5))
            else:
                display.blit(ballNo, (x - 5, y - 5))

    # Moves the Ball around the Screen
    def move(self):
        self.speed -= friction
        if self.speed <= 0:
            self.speed = 0
        self.x = self.x + self.speed*cos(radians(self.angle))
        self.y = self.y + self.speed*sin(radians(self.angle))

        if not (self.x < width - radius - margin):
            self.x = width - radius - margin
            self.angle = 180 - self.angle
        if not(radius + margin < self.x):
            self.x = radius + margin
            self.angle = 180 - self.angle
        if not (self.y < height - radius - margin):
            self.y = height - radius - margin
            self.angle = 360 - self.angle
        if not(radius + margin < self.y):
            self.y = radius + margin
            self.angle = 360 - self.angle

# Pocket Class
class Pockets:
    def __init__(self, x, y, color):
        self.r = margin/2
        self.x = x + self.r + 10
        self.y = y + self.r + 10
        self.color = color

    # Draws the Pockets on Pygame Window
    def draw(self):
        pygame.draw.ellipse(display, self.color, (self.x - self.r, self.y - self.r, self.r*2, self.r*2))

    # Checks if ball has entered the Hole
    def checkPut(self):
        global balls
        ballsCopy = balls[:]
        for i in range(len(balls)):
            dist = ((self.x - balls[i].x)**2 + (self.y - balls[i].y)**2)**0.5
            if dist < self.r + radius:
                if balls[i] in ballsCopy:
                    if balls[i].ballNum == 8:
                        gameOver()
                    else:
                        ballsCopy.remove(balls[i])

        balls = ballsCopy[:]

# Cue Stick Class
class CueStick:
    def __init__(self, x, y, length, color):
        self.x = x
        self.y = y
        self.length = length
        self.color = color
        self.tangent = 0

    # Applies force to Cue Ball
    def applyForce(self, cueBall, force):
        cueBall.angle = self.tangent
        cueBall.speed = force

    # Draws Cue Stick on Pygame Window
    def draw(self, cuex, cuey):
        self.x, self.y = pygame.mouse.get_pos()
        self.tangent = (degrees(atan2((cuey - self.y), (cuex - self.x))))
        pygame.draw.line(display, white, (cuex + self.length*cos(radians(self.tangent)), cuey + self.length*sin(radians(self.tangent))), (cuex, cuey), 1)
        pygame.draw.line(display, self.color, (self.x, self.y), (cuex, cuey), 3)


# Checks Collision
def collision(ball1, ball2):
    dist = ((ball1.x - ball2.x)**2 + (ball1.y - ball2.y)**2)**0.5
    if dist <= radius*2:
        return True
    else:
        return False

# Checks if Cue Ball hits any Ball
def checkCueCollision(cueBall):
    for i in range(len(balls)):
        if collision(cueBall, balls[i]):
            if balls[i].x == cueBall.x:
                angleIncline = 2*90
            else:
                u1 = balls[i].speed
                u2 = cueBall.speed

                balls[i].speed = ((u1*cos(radians(balls[i].angle)))**2 + (u2*sin(radians(cueBall.angle)))**2)**0.5
                cueBall.speed = ((u2*cos(radians(cueBall.angle)))**2 + (u1*sin(radians(balls[i].angle)))**2)**0.5

                tangent = degrees((atan((balls[i].y - cueBall.y)/(balls[i].x - cueBall.x)))) + 90
                angle = tangent + 90

                balls[i].angle = (2*tangent - balls[i].angle)
                cueBall.angle = (2*tangent - cueBall.angle)

                balls[i].x += (balls[i].speed)*sin(radians(angle))
                balls[i].y -= (balls[i].speed)*cos(radians(angle))
                cueBall.x -= (cueBall.speed)*sin(radians(angle))
                cueBall.y += (cueBall.speed)*cos(radians(angle))


# Checks Collision Between Balls
def checkCollision():
    for i in range(len(balls)):
        for j in range(len(balls) - 1, i, -1):
            if collision(balls[i], balls[j]):
                if balls[i].x == balls[j].x:
                    angleIncline = 2*90
                else:
                    u1 = balls[i].speed
                    u2 = balls[j].speed

                    balls[i].speed = ((u1*cos(radians(balls[i].angle)))**2 + (u2*sin(radians(balls[j].angle)))**2)**0.5
                    balls[j].speed = ((u2*cos(radians(balls[j].angle)))**2 + (u1*sin(radians(balls[i].angle)))**2)**0.5

                    tangent = degrees((atan((balls[i].y - balls[j].y)/(balls[i].x - balls[j].x)))) + 90
                    angle = tangent + 90

                    balls[i].angle = (2*tangent - balls[i].angle)
                    balls[j].angle = (2*tangent - balls[j].angle)

                    balls[i].x += (balls[i].speed)*sin(radians(angle))
                    balls[i].y -= (balls[i].speed)*cos(radians(angle))
                    balls[j].x -= (balls[j].speed)*sin(radians(angle))
                    balls[j].y += (balls[j].speed)*cos(radians(angle))

def border():
    pygame.draw.rect(display, gray, (0, 0, width, 30))
    pygame.draw.rect(display, gray, (0, 0, 30, height))
    pygame.draw.rect(display, gray, (width - 30, 0, width, height))
    pygame.draw.rect(display, gray, (0, height - 30, width, height))

def score():
    font = pygame.font.SysFont("Agency FB", 30)

    pygame.draw.rect(display, (51, 51, 51), (0, height, width, outerHeight))
    for i in range(len(balls)):
        balls[i].draw((i + 1)*2*(radius + 1), height + radius + 10)

    text = font.render("Remaining Balls: " + str(len(balls)), True, stickColor)
    display.blit(text, (width/2 + 50, height + radius/2))


def reset():
    global balls, noBalls
    noBalls = 15
    balls = []

    s = 70

    b1 = Ball(s, height/2 - 4*radius, 0, colors[0], 0, 1)
    b2 = Ball(s + 2*radius, height/2 - 3*radius, 0, colors[1], 0, 2)
    b3 = Ball(s, height/2 - 2*radius, 0, colors[2], 0, 3)
    b4 = Ball(s + 4*radius, height/2 - 2*radius, 0, colors[3], 0, 4)
    b5 = Ball(s + 2*radius, height/2 - 1*radius, 0, colors[4], 0, 5)
    b6 = Ball(s, height/2, 0, colors[5], 0, 6)
    b7 = Ball(s + 6*radius, height/2 - 1*radius, 0, colors[6], 0, 7)
    b8 = Ball(s + 4*radius, height/2, 0, colors[7], 0, 8)
    b9 = Ball(s + 8*radius, height/2, 0, colors[8], 0, 9)
    b10 = Ball(s + 6*radius, height/2 + 1*radius, 0, colors[9], 0, 10)
    b11 = Ball(s + 2*radius, height/2 + 1*radius, 0, colors[10], 0, 11)
    b12 = Ball(s, height/2 + 2*radius, 0, colors[11], 0, 12)
    b13 = Ball(s + 4*radius, height/2 + 2*radius, 0, colors[12], 0, 13)
    b14 = Ball(s + 2*radius, height/2 + 3*radius, 0, colors[13], 0, 14)
    b15 = Ball(s, height/2 + 4*radius, 0, colors[14], 0, 15)

    balls.append(b1)
    balls.append(b2)
    balls.append(b3)
    balls.append(b4)
    balls.append(b5)
    balls.append(b6)
    balls.append(b7)
    balls.append(b8)
    balls.append(b9)
    balls.append(b10)
    balls.append(b11)
    balls.append(b12)
    balls.append(b13)
    balls.append(b14)
    balls.append(b15)



def gameOver():
    font = pygame.font.SysFont("Agency FB", 75)
    if len(balls) == 0:
        text = font.render("You Won!", True, (133, 193, 233))
    else:
        text = font.render("You Lost! Black in Hole!", True, (241, 148, 138))

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                close()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    close()

                if event.key == pygame.K_r:
                    poolTable()
        display.blit(text, (50, height/2))

        pygame.display.update()
        clock.tick()

def close():
    pygame.quit()
    sys.exit()

# Main Function
def poolTable():
    loop = True

    reset()

    noPockets = 6
    pockets = []

    p1 = Pockets(0, 0, black)
    p2 = Pockets(width/2 - p1.r*2, 0, black)
    p3 = Pockets(width - p1.r - margin - 5, 0, black)
    p4 = Pockets(0, height - margin - 5 - p1.r, black)
    p5 = Pockets(width/2 - p1.r*2, height - margin - 5 - p1.r, black)
    p6 = Pockets(width - p1.r - margin - 5, height - margin - 5 - p1.r, black)

    pockets.append(p1)
    pockets.append(p2)
    pockets.append(p3)
    pockets.append(p4)
    pockets.append(p5)
    pockets.append(p6)

    cueBall = Ball(width/2, height/2, 0, white, 0, "cue")
    cueStick = CueStick(0, 0, 100, stickColor)


    start = 0
    end = 0

    while loop:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                close()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    close()

                if event.key == pygame.K_r:
                    poolTable()

            if event.type == pygame.MOUSEBUTTONDOWN:
                start = [cueBall.x, cueBall.y]
                x, y = pygame.mouse.get_pos()
                end = [x ,y]
                dist = ((start[0] - end[0])**2 + (start[1] - end[1])**2)**0.5
                force = dist/10.0
                if force > 10:
                    force = 10

                cueStick.applyForce(cueBall, force)


        display.fill(background)

        cueBall.draw(cueBall.x, cueBall.y)
        cueBall.move()

        if not (cueBall.speed > 0):

            cueStick.draw(cueBall.x, cueBall.y)

        for i in range(len(balls)):
            balls[i].draw(balls[i].x, balls[i].y)

        for i in range(len(balls)):
           balls[i].move()

        checkCollision()
        checkCueCollision(cueBall)
        border()

        for i in range(noPockets):
            pockets[i].draw()

        for i in range(noPockets):
            pockets[i].checkPut()

        if len(balls) == 1 and balls[0].ballNum == 8:
            gameOver()

        score()

        pygame.display.update()
        clock.tick(60)

poolTable()

Output for the 8 ball pool game using python👇👇

Conclusion

Hurray! You have successfully Create the 8 Ball Pool Game Using Python. developing an 8 Ball Pool game using Python can be a challenging yet rewarding experience. Through this project, you can gain valuable skills in Python programming, game development, and user interface design. By using the Pygame library, you can create a user-friendly interface for your game and implement the physics and game logic of 8 Ball Pool.

Overall, developing an 8 Ball Pool game using Python is a fun and challenging project that can help you improve your programming skills while creating an engaging game for others to enjoy. Hope you enjoyed building with us! Visit our homepage and you get lot’s of projects💝.



Leave a Reply