''' Module containing Ball class. ''' import consts import pyxel from time import time from math import isclose from random import randint, getrandbits class Ball: ''' Class containing methods and variables related to the ball. ''' def __init__(self, x_direction_right): self.x = consts.BIG_MARGIN + ( consts.BALL_RADIUS * 2 ) if x_direction_right else consts.SCREEN_WIDTH - consts.BIG_MARGIN - ( consts.BALL_RADIUS * 2) + 1 self.y = randint(int(consts.SCREEN_HEIGHT_ONE_QUARTER), int(consts.SCREEN_HEIGHT_THREE_QUARTERS)) self.speed = consts.BALL_SPEED self.x_direction_right = x_direction_right self.y_direction_up = bool(getrandbits(1)) self.curved = False def draw(self): ''' Draws a ball. ''' pyxel.circ(self.x, self.y, consts.BALL_RADIUS, consts.ORANGE) def update_position(self): ''' Updates ball's position according to current direction. ''' extra_speed = 0 if self.curved else 1 if self.x_direction_right and self.y_direction_up: self.x += self.speed + extra_speed self.y -= self.speed - extra_speed elif not self.x_direction_right and self.y_direction_up: self.x -= self.speed + extra_speed self.y -= self.speed - extra_speed elif self.x_direction_right and not self.y_direction_up: self.x += self.speed + extra_speed self.y += self.speed - extra_speed else: self.x -= self.speed + extra_speed self.y += self.speed - extra_speed def paddle_bounce(self, paddle): ''' Changes ball's direction and curve when bouncing off the paddle. ''' paddle_edge = paddle.x + 1 if paddle.player == 1 else paddle.x if isclose(self.x, paddle_edge, abs_tol=consts.BALL_RADIUS): if (self.y + consts.BALL_RADIUS >= paddle.y) and (self.y - consts.BALL_RADIUS <= paddle.y + consts.PADDLE_LENGTH): self.x_direction_right = not self.x_direction_right if (self.y + consts.BALL_RADIUS > paddle.y + consts.PADDLE_LENGTH - consts.PADDLE_TIP) or (self.y - consts.BALL_RADIUS < paddle.y + consts.PADDLE_TIP): self.curved = True else: self.curved = False def edge_bounce(self): ''' Changes ball's direction when bouncing off the table's edge. ''' if self.y - consts.BALL_RADIUS <= consts.MEDIUM_MARGIN: self.y_direction_up = not self.y_direction_up elif self.y + consts.BALL_RADIUS >= (consts.SCREEN_HEIGHT - consts.MEDIUM_MARGIN): self.y_direction_up = not self.y_direction_up def score_event(self, game): ''' Increments paddle's score when ball is out of the table on the opponent's side and repositions the ball. Returns time of the score. ''' score_time = 0 if self.x >= consts.SCREEN_WIDTH or self.x <= 0: if self.x >= consts.SCREEN_WIDTH: game.first_paddle.score += 1 game.ball = Ball(x_direction_right=False) else: game.second_paddle.score += 1 game.ball = Ball(x_direction_right=True) game.state = 'score' score_time = time() return score_time