Beginner – First OOP in Python 3: Pygame Pong


I studied Python for a few months and recently decided to give up OOP and revise a pong game to a more object-oriented style. Please tell me how to improve my code.

Part of the code is an adaptation from this stack overflow question to the menu state.

There is a known problem with that MenuScene.handle_events () Function so I have to press the spacebar or enter key several times to intercept the event, but I do not consider it a significant mistake.

main.py

from __future__ import absolute_import
Import Pygame
Import colors, globals from the core.config
from core.scene import GameScene, SceneManager

def main ():
screen = pygame.display.set_mode ((Globals.win_width, Globals.win_height))
pygame.display.set_caption ("Pong")
clock = pygame.time.Clock ()
manager = SceneManager ()
Running = True
pygame.init ()
during the race:
clock.tick (120)
for an event in pygame.event.get ():
if event.type == pygame.QUIT:
Running = wrong
screen.fill (Colors.black)
manager.scene.render (screen)
manager.scene.handle_events (pygame.event.get ())
manager.scene.update ()
pygame.display.flip ()

pygame.quit ()

if __name__ == "__main__":
Main()

szene.py

of .actors import player, enemy, ball
from .config import Colors, Globals
Import Pygame

Class SceneManager (object):
def __init __ (self):
self.go_to (MenuScene ())

def go_to (self, scene):
self.scene = scene
self.scene.manager = self

Class Scene (Object):
def __init __ (self):
consist
def render (self, screen):
raise NotImplementedError
def update (self):
raise NotImplementedError
def handle_events (self, events):
raise NotImplementedError

Class MenuScene (scene):
def __init __ (self):
super (MenuScene, itself) .__ init__ ()
pygame.font.init ()
self.font = pygame.font.SysFont (& # 39; Arial & # 39 ;, 56)
self.sfont = pygame.font.SysFont (& # 39; Arial & # 39 ;, 32)
consist
def render (self, screen):
screen.fill (Colors.green)
text1 = self.font.render (& # 39; Pong Rework & # 39 ;, True, (255, 255, 255))
text2 = self.sfont.render (& # 39;> press the space bar to start <& # 39 ;, True, (255, 255, 255))
screen.blit (Text1, (200, 50))
screen.blit (Text2, (200, 350))
def update (self):
consist
def handle_events (self, events):
for e in events:
if e.type == pygame.KEYDOWN and (e.key == pygame.K_SPACE or e.key == pygame.K_RETURN):
self.manager.go_to (GameScene ())

Class GameScene (Scene):
def __init __ (self):
super (GameScene, itself) .__ init__ ()
pygame.font.init ()
self.font = pygame.font.SysFont ("Comic Sans MS", 30)
self.player = player ()
self.enemy = enemy ()
self.points = {"Player": 0, "Enemy": 0}
self.player_score = self.font.render ("{}". format (self.points)["player"]), 1, Colors.white)
self.enemy_score = self.font.render ("{}". format (self.points)["enemy"]), 1, Colors.white)
self.ball = ball ()

def render (self, screen):
screen.blit (self.player_score, (150,100))
screen.blit (self.enemy_score, (630,100))
pygame.draw.rect (Screen, Colors.white, Self.player)
pygame.draw.rect (Screen, Colors.white, self.enemy)
pygame.draw.rect (Screen, Colors.white, self.ball)

def update (self):
pressed = pygame.key.get_pressed ()
up, down = [pressed[key] for input (pygame.K_UP, pygame.K_DOWN)]self.handle_point ()
self.player.update (up, down)
self.enemy.update (self.ball.y)
self.ball.update (self.player, self.enemy)
return

def handle_events (self, events):
for event in events:
If event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
consist

def handle_point (self):

def update_points (key):
even points[key] + = 1
self.player_score = self.font.render ("{}". format (self.points)["player"]), 1, Colors.white)
self.enemy_score = self.font.render ("{}". format (self.points)["enemy"]), 1, Colors.white)

if selbst.ball.x <= self.ball.width:
            update_points("enemy")
            self.ball.reset()                     
        if self.ball.x >= (Globals.win_width + self.ball.width):
Update Points ("Player")
self.ball.reset ()
self.ball.dir_x * = -1  

Schauspieler.py

Import Pygame
from .config import globals, colors
by math import cos, sin, radiant, pi
Class Player (pygame.Rect):
def __init __ (self):
super (player, himself) .__ init__ (20,225,20,150)
self.velocity = 5
print ("player class initiated")
def update (yourself, up, down):
if above and yourself. y> = 10:
self.y - = self.velocity
if below and yourself <= Globals.win_height - (self.height +10):
            self.y += self.velocity
        pass

class Enemy(pygame.Rect):
    def __init__(self):
        super(Enemy,self).__init__(760,225,20,150)
        self.velocity = 3
        print("enemy class initated")
    def update(self,ballYpos):
        middle = self.y + self.height /2
        if ballYpos != middle:
            if ballYpos > middle and self.y <= Globals.win_height- (self.height + self.velocity):
self.y + = self.velocity
if ballYpos < middle and self.y >= self.velocity * 2:
self.y - = self.velocity


Class Ball (Pygame.Rect):
def __init __ (self):
great (ball, yourself) .__ init__ (400,300,20,20)
self.velocity = 5
self.angle = Radiant (0)
self.dir_x = cos (self.angle)
self.dir_y = -sin (self.angle)
print ("Ball class instantiated")
def reset (self):
self.x = 400
self.y = 300
self.angle = Radiant (0)
self.dir_x = cos (self.angle)
self.dir_y = -sin (self.angle)
Def Update (self, player, enemy):
self.x + = self.dir_x * self.velocity
self.y + = self.dir_y * self.velocity

self.handle_bound_collision ()
self.handle_paddle_collision (player, enemy)

def handle_bound_collision (self):
if yourself <=  0 or self.y>= Globals.win_height - 10:
self.dir_y * = -1.05

def handle_paddle_collision (self, player, enemy):
intersectY = self.y
if self.colliderect (player):
relativeIntersectY = (player.y + (player.height / 2)) - intersectY
normalizedRelativeIntersectY = relativeIntersectY / (player.height / 2)
self.angle = radian measure (normalizedRelativeIntersectY * 60)
self.dir_x = cos (self.angle)
self.dir_y = -sin (self.angle)

when self-colliding (enemy):
relativeIntersectY = (Enemy.y + (Enemy.Height / 2)) - IntersectY
normalizedRelativeIntersectY = relativeIntersectY / (enemy.height / 2)
self.angle = radian measure (normalizedRelativeIntersectY * 60)
self.dir_x = -cos (self.angle)
self.dir_y = sin (self.angle)

config.py

Class Globals:
win_width = 800
win_height = 600

Class colors:
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)