152 lines
5.8 KiB
Python
152 lines
5.8 KiB
Python
|
import pygame
|
||
|
import sys
|
||
|
|
||
|
# Some constants that we use in the program
|
||
|
|
||
|
BACKGROUND_COLOR = (0, 0, 0) # Black background
|
||
|
SCREEN_SIZE = (800, 500) # Screen size is 500 x 500
|
||
|
PADDLE_COLOR = (255, 255, 255) # Paddle color is white
|
||
|
PADDLE_SIZE = (10, 100) # Paddle size is 10 x 100
|
||
|
BALL_COLOR = (255, 255, 255) # Ball color is white
|
||
|
BALL_RADIUS = 10 # Ball radius is 10 pixels
|
||
|
PLAYER_START_X_OFFSET = 50 # The amount of pixels the player is away from the wall on the X axis
|
||
|
PLAYER_START_Y_OFFSET = 200 # The amount of pixels the player is away from the wall on the Y axis
|
||
|
PLAYER_MOVE_SPEED = 400 # The amount the player moves when a key is pressed
|
||
|
FRAMERATE = 60 # The target framerate of the game
|
||
|
BALL_START_OFFSET = (250, 250) # The location of the ball when the game first starts
|
||
|
BALL_INITIAL_DIRECTION = [1, -1.5] # The initial direction of the ball, notice that this is not a tuple
|
||
|
BALL_SPEED = 100 # The speed of the ball
|
||
|
|
||
|
class Ball:
|
||
|
def __init__(self, x, y, direction, radius=BALL_RADIUS, speed=BALL_SPEED):
|
||
|
self.x = x
|
||
|
self.y = y
|
||
|
self.direction = direction
|
||
|
self.radius = radius
|
||
|
self.speed = speed
|
||
|
|
||
|
def render(self, window):
|
||
|
pygame.draw.circle(window, BALL_COLOR, (self.x, self.y), self.radius)
|
||
|
|
||
|
def bounce_x(self):
|
||
|
self.direction[0] = -self.direction[0]
|
||
|
|
||
|
def bounce_y(self):
|
||
|
self.direction[1] = -self.direction[1]
|
||
|
|
||
|
def update(self, dt):
|
||
|
new_x = self.x + (self.direction[0] * self.speed * dt)
|
||
|
new_y = self.y + (self.direction[1] * self.speed * dt)
|
||
|
|
||
|
# Check for a bounce with the top of the screen, we need to test the top of the ball
|
||
|
if new_y - self.radius < 0 :
|
||
|
new_y = self.radius
|
||
|
self.bounce_y()
|
||
|
|
||
|
# Check for a bounce with the bottom of the screen, we need to test the bottom of the ball
|
||
|
elif new_y + self.radius >= SCREEN_SIZE[1]:
|
||
|
new_y = SCREEN_SIZE[1] - self.radius
|
||
|
self.bounce_y()
|
||
|
|
||
|
self.x = new_x
|
||
|
self.y = new_y
|
||
|
|
||
|
class Player:
|
||
|
def __init__(self, x, y, width=PADDLE_SIZE[0], height=PADDLE_SIZE[1]):
|
||
|
self.x = x
|
||
|
self.y = y
|
||
|
self.width = width
|
||
|
self.height = height
|
||
|
|
||
|
def render(self, window):
|
||
|
pygame.draw.rect(window, PADDLE_COLOR, (self.x, self.y, self.width, self.height))
|
||
|
|
||
|
# Will move the player on the Y axis but only if it is certain
|
||
|
# that the player will not move out of the bounds of the screen
|
||
|
def move(self, amount):
|
||
|
if self.y + amount >= 0 and self.y + self.height + amount < SCREEN_SIZE[1]:
|
||
|
self.y += amount
|
||
|
|
||
|
# This class will represent our game
|
||
|
class Game:
|
||
|
# This function will be called when the class is first created
|
||
|
def __init__(self):
|
||
|
pygame.init()
|
||
|
self.window = pygame.display.set_mode(SCREEN_SIZE)
|
||
|
pygame.display.set_caption("Super awesome pong")
|
||
|
|
||
|
self.initialize_gameobjects()
|
||
|
|
||
|
def initialize_gameobjects(self):
|
||
|
self.player1 = Player(PLAYER_START_X_OFFSET, PLAYER_START_Y_OFFSET)
|
||
|
self.player2 = Player(SCREEN_SIZE[0] - PLAYER_START_X_OFFSET, PLAYER_START_Y_OFFSET)
|
||
|
self.ball = Ball(BALL_START_OFFSET[0], BALL_START_OFFSET[1], BALL_INITIAL_DIRECTION)
|
||
|
|
||
|
# Called when the game needs to be reset
|
||
|
def game_reset(self):
|
||
|
self.initialize_gameobjects()
|
||
|
|
||
|
# Calculates the collisions of the paddles with the ball
|
||
|
def check_collision(self):
|
||
|
if self.ball.x - self.ball.radius <= self.player1.x + self.player1.width:
|
||
|
# Ball is behind the left paddle
|
||
|
if self.player1.y <= self.ball.y + self.ball.radius and self.player1.y + self.player1.height >= self.ball.y - self.ball.radius:
|
||
|
# The paddle has catched the ball, bounce back
|
||
|
self.ball.bounce_x()
|
||
|
else:
|
||
|
self.game_reset()
|
||
|
|
||
|
if self.ball.x + self.ball.radius >= self.player2.x:
|
||
|
# Ball is behind the right paddle
|
||
|
if self.player2.y <= self.ball.y + self.ball.radius and self.player2.y + self.player2.height >= self.ball.y - self.ball.radius:
|
||
|
# The paddle has catched the ball, bounce back
|
||
|
self.ball.bounce_x()
|
||
|
else:
|
||
|
self.game_reset()
|
||
|
|
||
|
|
||
|
# This function will render the contents of the screen
|
||
|
def render(self):
|
||
|
self.window.fill(BACKGROUND_COLOR)
|
||
|
|
||
|
# Draw the two players
|
||
|
self.player1.render(self.window)
|
||
|
self.player2.render(self.window)
|
||
|
|
||
|
# Draw the ball
|
||
|
self.ball.render(self.window)
|
||
|
|
||
|
pygame.display.flip()
|
||
|
|
||
|
def start(self):
|
||
|
# The main loop will run until the QUIT event is triggered
|
||
|
# this event will be triggered by closing the window
|
||
|
clock = pygame.time.Clock()
|
||
|
while True:
|
||
|
# Check for user input
|
||
|
|
||
|
# Get a map of all currently pressed keys
|
||
|
keys = pygame.key.get_pressed()
|
||
|
|
||
|
# Change the movement of the player based on which key is pressed
|
||
|
dt = clock.get_time() / 1000
|
||
|
movement = PLAYER_MOVE_SPEED * dt
|
||
|
if keys[pygame.K_d]: self.player1.move(movement)
|
||
|
elif keys[pygame.K_f]: self.player1.move(-movement)
|
||
|
if keys[pygame.K_j]: self.player2.move(movement)
|
||
|
elif keys[pygame.K_k]: self.player2.move(-movement)
|
||
|
|
||
|
# Loop over all current events and check if the quit event was fired
|
||
|
for event in pygame.event.get():
|
||
|
if event.type == pygame.QUIT:
|
||
|
pygame.quit()
|
||
|
sys.exit()
|
||
|
|
||
|
self.ball.update(dt)
|
||
|
self.check_collision()
|
||
|
self.render()
|
||
|
clock.tick(FRAMERATE)
|
||
|
|
||
|
# Create the game object and start the game
|
||
|
game = Game()
|
||
|
game.start()
|