Advertisement

Please review my Pong code

Started by February 12, 2018 10:48 AM
0 comments, last by Arthev 6 years, 9 months ago

Hey folks, new here

I've decided to take the advice in this article.

So any comments and criticisms on my pong clone would be appreciated!

Written using Python 3 and Pygame.

Github repo: available here.

Thanks!


import pygame
import random
import colour_constants
import time
import json
import math
from pathlib import Path

SCREEN_SIZE = (640, 480)
BALL_DIAMETER = 32
MAX_FPS = 60
PADDLE_SIZE = (16, 64)
PADDLE_VEL = 10
HORIZONTAL_BAR = (SCREEN_SIZE[0], PADDLE_SIZE[0])
RECENT_HIT_RESET = 20
BLACK     = colour_constants.DISPLAYBLACK 
PUREBLACK = colour_constants.PUREBLACK #Easy access for colorkeying
SETTINGS_PATH = "config_pong.cfg"
GAME_INTENSIFYING_CONSTANT = 1.08

COLOUR    = colour_constants.APPLE2
player_one_up = pygame.K_q
player_one_down = pygame.K_a
player_two_up = pygame.K_o
player_two_down = pygame.K_l
points_per_game = 5

pygame.mixer.pre_init(44100, -16, 2, 2048)
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
font = pygame.font.SysFont("Mono", 32)
try:
    bounce_sound = pygame.mixer.Sound('bounce.wav')
    score_sound = pygame.mixer.Sound('score.wav')
    paddle_sound = pygame.mixer.Sound('paddle_bounce.wav')
    menu_sound = pygame.mixer.Sound('menu.wav')
except:
    raise UserWarning("Couldn't load sound files.")

class Play_Background:
    def __init__(self):
        self.surface = pygame.Surface(SCREEN_SIZE)
        self.surface.fill(BLACK)
        self.surface = self.surface.convert()
        pygame.draw.rect(self.surface, COLOUR, (0, 0, HORIZONTAL_BAR[0], HORIZONTAL_BAR[1]))
        pygame.draw.rect(self.surface, COLOUR, (0, SCREEN_SIZE[1] - HORIZONTAL_BAR[1], HORIZONTAL_BAR[0], HORIZONTAL_BAR[1]))
        pygame.draw.line(self.surface, COLOUR, (SCREEN_SIZE[0]//2, 0), (SCREEN_SIZE[0]//2, SCREEN_SIZE[1]))

    def draw(self) -> None:
        screen.blit( self.surface, (0, 0) )

class vector2:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def get_magnitude(self):
        return math.sqrt(self.x**2 + self.y**2)
    
    def normalize(self):
        magnitude = self.get_magnitude()
        self.x /= magnitude
        self.y /= magnitude

    def __add__(self, rhs):
        return vector2(self.x + rhs.x, self.y + rhs.y)
    
    def __mul__(self, scalar):
        return vector2(self.x * scalar, self.y * scalar)


class Paddle:
    def __init__(self, side, player, up_button=None, down_button=None):
        if side == "left":
            self.pos = vector2(SCREEN_SIZE[0]//40, SCREEN_SIZE[1]//2 - PADDLE_SIZE[1]//2)
        elif side == "right":
            self.pos = vector2(SCREEN_SIZE[0] - PADDLE_SIZE[0] - SCREEN_SIZE[0]//40, SCREEN_SIZE[1]//2 - PADDLE_SIZE[1]//2)
        else:
            raise ValueError("Illegal 'side' argument sent to Paddle.__init__:", side)
        if player and (up_button == None or up_button == None):
            raise ValueError("Illegal combination of player and buttons sent to Paddle.__init__. None buttons make no sense for player == True")
        self.side = side
        self.player = player
        self.up_button = up_button
        self.down_button = down_button
        self.vel = vector2(0, 0) #No initial movement.
        self.surface = pygame.Surface( (PADDLE_SIZE[0], PADDLE_SIZE[1]) )
        self.surface.fill(COLOUR)
        self.surface = self.surface.convert()
        self.score = 0
        if not player: self.wait_to_calculate = 0
        if not player: self.last_ball_dir = "left"
        if not player: self.expected_pos = 0

    def calculate_expected_pos(self, ball):
        posVec = vector2(ball.pos.x + BALL_DIAMETER//2, ball.pos.y + BALL_DIAMETER//2)
        velVec = vector2(ball.vel.x, ball.vel.y)
        while True:
            timer = 1/(MAX_FPS)
            posVec.x += velVec.x * timer
            posVec.y += velVec.y * timer
            #Pseudo_horizontal_bar_check_and_adjustment
            if posVec.y - BALL_DIAMETER//2 < HORIZONTAL_BAR[1]:
                velVec.y *= -1
                posVec.y = HORIZONTAL_BAR[1] + BALL_DIAMETER//2
            elif posVec.y + BALL_DIAMETER//2 > SCREEN_SIZE[1] - HORIZONTAL_BAR[1]:
                velVec.y *= -1
                posVec.y = SCREEN_SIZE[1] - BALL_DIAMETER//2 - HORIZONTAL_BAR[1]
            #Now for the bounce from the left side, if any
            if posVec.x - BALL_DIAMETER//2 < 0:
                posVec.x = BALL_DIAMETER//2
                velVec.x *= -1
            #And finally, handling for when found the expected pos
            if posVec.x + BALL_DIAMETER//2 > SCREEN_SIZE[0] - PADDLE_SIZE[0]:
                return posVec

    def calculate_expected_drift(self, case):
        yVel = self.vel.y
        yPos = self.pos.y
        while yVel > 5:
            yVel -= yVel / (MAX_FPS * 1.3)
            #movesim
            yPos += yVel * 1/MAX_FPS
            if yPos < HORIZONTAL_BAR[1]:
                yVel *= -0.75
                yPos = HORIZONTAL_BAR[1]
            elif yPos + PADDLE_SIZE[1] > SCREEN_SIZE[1] - HORIZONTAL_BAR[1]:
                yVel *= -0.75
                yPos = SCREEN_SIZE[1] - PADDLE_SIZE[1] - HORIZONTAL_BAR[1]
        if yPos + PADDLE_SIZE[1]//3 - self.expected_pos.y > PADDLE_SIZE[1]//4:
            return "under"
        elif (yPos + PADDLE_SIZE[1] - PADDLE_SIZE[1]//3) - self.expected_pos.y < -PADDLE_SIZE[1]//4:
            return "over"
        else:
            return "drift"

    def move(self, time_passed, ball) -> None:
        #Accelerate
        if self.player:
            pressed_keys = pygame.key.get_pressed()
            if pressed_keys[self.up_button]:
                self.vel.y -= PADDLE_VEL
            elif pressed_keys[self.down_button]:
                self.vel.y += PADDLE_VEL
            else:
                self.vel.y -= self.vel.y / (MAX_FPS * 1.3) #Found experimentally
        else:
            if self.expected_pos == 0:
                self.expected_pos = self.calculate_expected_pos(ball)
            if ball.vel.x > 0:
                self.last_ball_dir = "right"
                if self.wait_to_calculate > 0: self.wait_to_calculate -= 1
                else:
                    self.expected_pos = self.calculate_expected_pos(ball)
                    self.wait_to_calculate = RECENT_HIT_RESET//2
            elif ball.vel.x < 0:
                if self.last_ball_dir == "right":
                    self.last_ball_dir = "left"
                    self.expected_pos = self.calculate_expected_pos(ball)
                    self.wait_to_calculate = 0
            probable_drift = self.calculate_expected_drift("larger") #expected_pos y is larger than self y
            if probable_drift == "under":
                self.vel.y -= PADDLE_VEL
            elif probable_drift == "over":
                self.vel.y += PADDLE_VEL
            else:
                if abs(self.pos.y + PADDLE_SIZE[1]//2 - self.expected_pos.y) > PADDLE_SIZE[1]:
                    if self.pos.y + PADDLE_SIZE[1]//2 > self.expected_pos.y:
                        self.vel.y -= PADDLE_VEL
                    else:
                        self.vel.y += PADDLE_VEL
                self.vel.y -= self.vel.y / (MAX_FPS * 1.3)
        #Move
        self.pos.y += self.vel.y * time_passed
        if self.pos.y < HORIZONTAL_BAR[1] or self.pos.y + PADDLE_SIZE[1] > SCREEN_SIZE[1] - HORIZONTAL_BAR[1]:
            paddle_sound.play()
            self.vel.y *= -0.75
            if self.pos.y < HORIZONTAL_BAR[1]:
                self.pos.y = HORIZONTAL_BAR[1]
            else:
                self.pos.y = SCREEN_SIZE[1] - PADDLE_SIZE[1] - HORIZONTAL_BAR[1]

    def draw(self) -> None:
        screen.blit(self.surface, (self.pos.x, self.pos.y))

class Ball:
    def reset(self) -> None:
        self.last_hit = None
        self.pos = vector2(SCREEN_SIZE[0]//2, SCREEN_SIZE[1]//2)
        self.vel = vector2(SCREEN_SIZE[0] * random.random(), SCREEN_SIZE[1] * random.random())
        if random.random() < 0.5: self.vel.x *= -1
        if random.random() < 0.5: self.vel.y *= -1
        if abs(self.vel.x) < SCREEN_SIZE[0] * 0.1:
            self.reset()

    def __init__(self):
        self.pos = None
        self.vel = None
        self.surface = pygame.Surface( (BALL_DIAMETER, BALL_DIAMETER) )
        self.surface.set_colorkey(PUREBLACK)
        pygame.draw.circle( self.surface, COLOUR, (BALL_DIAMETER//2, BALL_DIAMETER//2), BALL_DIAMETER//2)
        self.surface = self.surface.convert_alpha()
        self.last_hit = None
        self.reset()

    def horizontal_bar_check_and_adjustment(self) -> None:
        if self.pos.y < HORIZONTAL_BAR[1] or self.pos.y + BALL_DIAMETER > SCREEN_SIZE[1] - HORIZONTAL_BAR[1]:
            self.vel.y *= -1
            bounce_sound.play()
            if self.pos.y < HORIZONTAL_BAR[1]:
                self.pos.y = HORIZONTAL_BAR[1]
            else:
                self.pos.y = SCREEN_SIZE[1] - BALL_DIAMETER - HORIZONTAL_BAR[1]

    def score_check(self) -> str: #Can also return None!
        if self.pos.x + BALL_DIAMETER < 0:
            return "right"
        elif self.pos.x > SCREEN_SIZE[0]:
            return "left"
        else:
            return None

    def simple_collision_check(self, paddles) -> Paddle: #Can also return None!
        left = paddles[0]
        right = paddles[1]
        if self.pos.x + BALL_DIAMETER < right.pos.x and self.pos.x > left.pos.x + PADDLE_SIZE[0]:
            return None
        #If we progress below here, a hit might happen... since the ball isn't *between* the paddles!
        if self.pos.x + BALL_DIAMETER > right.pos.x:
            #Ball might have hit the right paddle.
            if self.pos.y > right.pos.y + PADDLE_SIZE[1]:
                return None
            elif self.pos.y + BALL_DIAMETER < right.pos.y:
                return None
            else:
                return right
        else:
            #Ball might have hit the left paddle.
            if self.pos.y > left.pos.y + PADDLE_SIZE[1]:
                return None
            elif self.pos.y + BALL_DIAMETER < left.pos.y:
                return None
            else:
                return left

    def collision_handling(self, paddle) -> None:
        steps = PADDLE_SIZE[1]//2 + BALL_DIAMETER//2
        extreme = 1.12 #arcsin(0.9) = 1.12
        hit = self.pos.y + BALL_DIAMETER//2 - (paddle.pos.y + PADDLE_SIZE[1]//2)
        w = extreme/steps*hit
        newVec = 0 #This is a unit vector, hehe.
        if paddle.side == "left": newVec = vector2(-math.cos(w), -math.sin(w))
        else: newVec = vector2(math.cos(w), -math.sin(w))
        magnitude = self.vel.get_magnitude() * GAME_INTENSIFYING_CONSTANT * -1
        self.vel.normalize()
        newVec = newVec + self.vel #The two vectors can be scalar multiplied by some percentage for different admixtures.
        newVec.normalize()
        newVec = newVec * magnitude
        self.vel = newVec

    def move(self, time_passed, paddles) -> None:
        self.pos.x += self.vel.x * time_passed
        self.pos.y += self.vel.y * time_passed
        self.horizontal_bar_check_and_adjustment()
        quick_collision = self.simple_collision_check(paddles) #quick_collision will contain a paddle - or None.
        if quick_collision: 
            if quick_collision.side != self.last_hit:
                bounce_sound.play()
                self.last_hit = quick_collision.side
                self.collision_handling(quick_collision)

    def draw(self) -> None:
        screen.blit(self.surface, (self.pos.x, self.pos.y))

class Scoredrawer:
    def __init__(self):
        self.left = 0
        self.right = 0

    def draw(self, left, right): #Idea for improved performance: Check whether there's a change to a score and then only rendering if so.
        left_text  = font.render(str(left),  False, COLOUR).convert_alpha()
        right_text = font.render(str(right), False, COLOUR).convert_alpha()
        y_offset = HORIZONTAL_BAR[1] * 1.5
        screen.blit(left_text,  (SCREEN_SIZE[0]//2 - 32 - left_text.get_width(),  y_offset))
        screen.blit(right_text, (SCREEN_SIZE[0]//2 + 32, y_offset))

def display_winner(winner) -> None:
    winner_text = font.render( winner.capitalize() + " has won!", False, COLOUR).convert_alpha()
    screen.blit(winner_text, (SCREEN_SIZE[0]//2 - winner_text.get_width()//2,
                              SCREEN_SIZE[1]//2 - winner_text.get_height()//2))
    pygame.display.update()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.constants.QUIT:
                exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
                elif event.key == pygame.K_RETURN:
                    return

def play(win_score: int, two_player_mode: bool) -> str: #returns 'left' or 'right' depending on which player won
    clock = pygame.time.Clock()

    background = Play_Background()
    scoredrawer = Scoredrawer()
    ball = Ball()
    paddle1 = Paddle(side="left", player=True, up_button=player_one_up, down_button=player_one_down)
    paddle2 = Paddle(side="right", player=two_player_mode, up_button=player_two_up, down_button=player_two_down)
    paddles = [paddle1, paddle2] #Left side must go in paddles[0], right side in paddles[1].

    while True:
        for event in pygame.event.get():
            if event.type == pygame.constants.QUIT:
                exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()

        time_passed = clock.tick(MAX_FPS) / 1000.0 #time_passed is in seconds

        background.draw()

        ball.move(time_passed, paddles)
        for paddle in paddles: paddle.move(time_passed, ball)
        
        scorer = ball.score_check() #Either "left", "right" or None
        if scorer:
            score_sound.play()
            if scorer == "left":
                paddles[0].score += 1
                if paddles[0].score >= win_score:
                    display_winner(scorer)
                    return
            else:
                paddles[1].score += 1
                if paddles[1].score >= win_score:
                    display_winner(scorer)
                    return 
            ball.reset()

        scoredrawer.draw(paddles[0].score, paddles[1].score)
        ball.draw()
        for paddle in paddles: paddle.draw()
        pygame.display.update()

def display_intro() -> None:
    display_font = pygame.font.SysFont("mono", SCREEN_SIZE[0]//6)
    display_text = display_font.render("PongyPong", False, COLOUR, BLACK).convert()
    display_font2 = pygame.font.SysFont("mono", SCREEN_SIZE[0]//18)
    display_text2 = display_font2.render("by: Arthur", False, COLOUR, BLACK).convert()
    for i in range(256):
        screen.fill(BLACK)
        display_text.set_alpha(i)
        screen.blit(display_text, (SCREEN_SIZE[0]//2 - display_text.get_width()//2,
                                   SCREEN_SIZE[1]//2 - display_text.get_height()))

        pygame.display.update()
        time.sleep(1/100)
    for i in range(256):
        display_text2.set_alpha(i)
        screen.blit(display_text2, (SCREEN_SIZE[0]//2,
                                    SCREEN_SIZE[1]//2))
        pygame.display.update()
        time.sleep(1/200)
    time.sleep(0.25)

def settings_menu() -> None:
    def save_settings(dummy):
        current_settings = {'COLOUR':COLOUR,
                            'player_one_up':player_one_up,
                            'player_one_down':player_one_down,
                            'player_two_up':player_two_up,
                            'player_two_down':player_two_down,
                            'points_per_game':points_per_game}
        with open(SETTINGS_PATH, 'w') as settings_file:
            json.dump(current_settings, settings_file)
    
    def set_key(var):
        press_message = font.render( "Press the desired key...", False, COLOUR).convert_alpha()
        screen.blit(press_message, (SCREEN_SIZE[0]//2 - press_message.get_width()//2,
                                    SCREEN_SIZE[1] - font.get_linesize() * 1.5))
        pygame.display.update()
        pygame.event.clear()
        while True:
            for event in pygame.event.get():
                if event.type == pygame.constants.QUIT:
                    exit()
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        exit()
                    if event.key != pygame.K_RETURN:
                        menu_sound.play()
                        globals()[var] = event.key
                        return

    selection = 0
    options = [{'Text': 'Points Per Game: ', 'func': lambda x: None, 'var': 'points_per_game', 'extradraw': ['arrows', 'value']},
               {'Text': 'Colour', 'func': lambda x: None, 'var': 'COLOUR', 'extradraw':'arrows'},
               {'Text': 'Player One Up: ', 'func': set_key, 'var': 'player_one_up', 'extradraw':'button'},
               {'Text': 'Player One Down: ', 'func': set_key, 'var': 'player_one_down', 'extradraw':'button'},
               {'Text': 'Player Two Up: ', 'func': set_key, 'var': 'player_two_up', 'extradraw':'button'},
               {'Text': 'Player Two Down: ', 'func': set_key, 'var':'player_two_down', 'extradraw':'button'},
               {'Text': 'Save Settings', 'func': save_settings, 'var': 'return', 'extradraw': None}]

    colour_options = [colour_constants.AMBER,
                      colour_constants.LTAMBER,
                      colour_constants.GREEN1,
                      colour_constants.APPLE1,
                      colour_constants.GREEN2,
                      colour_constants.APPLE2,
                      colour_constants.GREEN3]

    colour_selection = 0
    for i, colour in enumerate(colour_options):
        if colour == COLOUR:
            colour_selection = i

    blinker = True
    while True:
        for event in pygame.event.get():
            if event.type == pygame.constants.QUIT:
                exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
                elif event.key == pygame.K_RETURN:
                    menu_sound.play()
                    options[selection]['func'](options[selection]['var'])
                    if options[selection]['var'] == 'return': return
                elif event.key in [pygame.K_DOWN, player_one_down, player_two_down]:
                    menu_sound.play()
                    if selection == len(options) - 1: selection = 0
                    else: selection += 1
                elif event.key in [pygame.K_UP, player_one_up, player_two_up]:
                    menu_sound.play()
                    if selection == 0: selection = len(options) - 1
                    else: selection -= 1
                elif event.key == pygame.K_RIGHT:
                    var = options[selection]['var']
                    if var == 'COLOUR':
                        menu_sound.play()
                        if colour_selection == len(colour_options) -1: 
                            colour_selection = 0
                        else: colour_selection += 1
                        globals()[var] = colour_options[colour_selection]
                    elif var == 'points_per_game':
                        menu_sound.play()
                        globals()[var] += 1
                elif event.key == pygame.K_LEFT:
                    var = options[selection]['var']
                    if var == 'COLOUR':
                        menu_sound.play()
                        if colour_selection == 0:
                            colour_selection = len(colour_options) - 1
                        else: colour_selection -= 1
                        globals()[var] = colour_options[colour_selection]
                    if var == 'points_per_game':
                        menu_sound.play()
                        globals()[var] = max(1, points_per_game - 1)

        screen.fill(BLACK)
        DIV = 32

        for i in range(len(options)):
            if i == selection:
                blinker = not blinker
                if blinker: continue
            text = font.render(options[i]['Text'], False, COLOUR).convert_alpha()
            screen.blit(text, (SCREEN_SIZE[0]//2 - text.get_width()//2,
                               SCREEN_SIZE[1]//DIV + font.get_linesize() * 1.5 * i))
            extradraw = options[i]['extradraw']
            if extradraw == 'arrows' or (type(extradraw) == list and 'arrows' in extradraw):
                h = text.get_height() * 0.75 // 1
                arrowsurface = pygame.Surface( (h, h) )
                arrowsurface.fill(BLACK)
                pygame.draw.polygon(arrowsurface, COLOUR,
                        ( (0, h//2), (h//2 - h//8, h//4), (h//2 - h//8, 3*h//4) ) )
                pygame.draw.polygon(arrowsurface, COLOUR,
                        ( (h, h//2), (h//2 + h//8, h//4), (h//2 + h//8, 3*h//4) ) )
                arrowsurface.convert()
                screen.blit(arrowsurface, (SCREEN_SIZE[0]//2 - text.get_width()//2 - arrowsurface.get_width() - 2,
                                           SCREEN_SIZE[1]//DIV + font.get_linesize() * 1.5 * i + h//8))
            if extradraw == 'value' or (type(extradraw) == list and 'value' in extradraw):
                valuesurface = font.render( str(globals()[options[i]['var']]), False, COLOUR).convert_alpha()
                screen.blit(valuesurface, (SCREEN_SIZE[0]//2 + text.get_width()//2 + 2,
                                           SCREEN_SIZE[1]//DIV + font.get_linesize() * 1.5 * i))
            if extradraw == 'button' or (type(extradraw) == list and 'button' in extradraw):
                buttonsurface = font.render( pygame.key.name(globals()[options[i]['var']]), False, COLOUR).convert_alpha()
                screen.blit(buttonsurface, (SCREEN_SIZE[0]//2 + text.get_width()//2 + 2,
                                           SCREEN_SIZE[1]//DIV + font.get_linesize() * 1.5 * i))
        pygame.display.update()

def main_menu() -> None:
    def one_player_mode():
        play(points_per_game, False)
    def two_player_mode():
        play(points_per_game, True)

    selection = 0
    options = [{'Text': '1-Player', 'func': one_player_mode},
               {'Text': '2-Player', 'func': two_player_mode},
               {'Text': 'Settings', 'func': settings_menu},
               {'Text': 'Exit', 'func': exit}]

    blinker = True
    while True:
        for event in pygame.event.get():
            if event.type == pygame.constants.QUIT:
                exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit()
                elif event.key == pygame.K_RETURN:
                    menu_sound.play()
                    options[selection]['func']()
                elif event.key in [pygame.K_DOWN, player_one_down, player_two_down]:
                    menu_sound.play()
                    if selection == len(options) - 1: selection = 0
                    else: selection += 1
                elif event.key in [pygame.K_UP, player_one_up, player_two_up]:
                    menu_sound.play()
                    if selection == 0: selection = len(options) - 1
                    else: selection -= 1

        screen.fill(BLACK)

        pseudopaddle = pygame.Surface( (PADDLE_SIZE[0]//2, PADDLE_SIZE[1]//2) )
        pseudopaddle.fill(COLOUR)
        pseudopaddle = pseudopaddle.convert()
        screen.blit(pseudopaddle, (SCREEN_SIZE[0]//2 - PADDLE_SIZE[1],
                                   SCREEN_SIZE[1]//10 - PADDLE_SIZE[0]//2))
        screen.blit(pseudopaddle, (SCREEN_SIZE[0]//2 + PADDLE_SIZE[1],
                                   SCREEN_SIZE[1]//10 + PADDLE_SIZE[0]//2))
        pseudoball = pygame.Surface( (BALL_DIAMETER//2, BALL_DIAMETER//2) )
        pseudoball.fill(BLACK)
        pygame.draw.circle( pseudoball, COLOUR, (BALL_DIAMETER//4, BALL_DIAMETER//4), BALL_DIAMETER//4)
        pseudoball = pseudoball.convert()
        screen.blit(pseudoball, (SCREEN_SIZE[0]//2 + BALL_DIAMETER//4,
                                 SCREEN_SIZE[1]//10 - BALL_DIAMETER//4))

        for i in range(len(options)):
            if i == selection:
                blinker = not blinker
                if blinker: continue
            text = font.render(options[i]['Text'], False, COLOUR).convert_alpha()
            screen.blit(text, (SCREEN_SIZE[0]//2 - text.get_width()//2,
                               SCREEN_SIZE[1]//4 + font.get_linesize() * 2 * i))

        pygame.display.update()

def load_settings() -> None:
    settings_path = Path(SETTINGS_PATH)
    if settings_path.is_file():
        with open(SETTINGS_PATH, 'r') as settings_file:
            settings = json.load(settings_file)
            for item in settings:
                globals()[item] = settings[item]
    else:
        default_settings = {'COLOUR':COLOUR,
                'player_one_up':player_one_up,
                'player_one_down':player_one_down,
                'player_two_up':player_two_up,
                'player_two_down':player_two_down,
                'points_per_game':points_per_game}
        with open(SETTINGS_PATH, 'w') as settings_file:
            json.dump(default_settings, settings_file)

if __name__ == '__main__':
    load_settings()
    display_intro()
    main_menu()

 

This topic is closed to new replies.

Advertisement