2019-06-27 22:19:57 +00:00
|
|
|
# !/usr/bin/env python
|
|
|
|
# Based on work by - Siddharth Natamai
|
|
|
|
# At the moment, this source file runs on TWO of the 4 PySimpleGUI ports with a third one coming soon (Qt).
|
|
|
|
import PySimpleGUI as sg
|
|
|
|
import random
|
|
|
|
|
|
|
|
GAMEPLAY_SIZE = (700, 400)
|
|
|
|
BAT_SIZE = (20, 110)
|
|
|
|
STARTING_BALL_POSITION = (327, 200)
|
|
|
|
player_1_Starting_Score = 0
|
|
|
|
player_2_Starting_Score = 0
|
|
|
|
BALL_RADIUS = 12
|
|
|
|
# BACKGROUND_COLOR = 'lightblue' # if running on PySimpleGUIWeb
|
|
|
|
BACKGROUND_COLOR = 'black'
|
|
|
|
# BALL_COLOR = 'black' # if running on PySimpleGUIWeb
|
|
|
|
BALL_COLOR = 'green1'
|
|
|
|
num_rounds = 0
|
|
|
|
while num_rounds == 0:
|
|
|
|
try:
|
2019-10-23 20:10:03 +00:00
|
|
|
num_rounds = int(sg.popup_get_text(
|
|
|
|
'How many rounds would you like to play?'))
|
2019-06-27 22:19:57 +00:00
|
|
|
except Exception as e:
|
|
|
|
num_rounds = 0
|
|
|
|
|
|
|
|
|
|
|
|
class Ball:
|
|
|
|
def __init__(self, graph, bat_1, bat_2, colour):
|
|
|
|
self.graph = graph # type: sg.Graph
|
|
|
|
self.bat_1 = bat_1
|
|
|
|
self.bat_2 = bat_2
|
|
|
|
self.player_1_Score = player_1_Starting_Score
|
|
|
|
self.player_2_Score = player_2_Starting_Score
|
|
|
|
self.draw_P1 = None
|
|
|
|
self.draw_P2 = None
|
2019-10-23 20:10:03 +00:00
|
|
|
self.id = self.graph.draw_circle(
|
|
|
|
STARTING_BALL_POSITION, BALL_RADIUS, line_color=colour, fill_color=colour)
|
2019-06-27 22:19:57 +00:00
|
|
|
self.curx, self.cury = STARTING_BALL_POSITION
|
2019-10-23 20:10:03 +00:00
|
|
|
# self.graph.relocate_figure(self.id, STARTING_BALL_POSITION[0], STARTING_BALL_POSITION[1])
|
2019-06-27 22:19:57 +00:00
|
|
|
self.x = random.choice([-2.5, 2.5])
|
|
|
|
self.y = -2.5
|
|
|
|
|
|
|
|
def win_loss_check(self):
|
|
|
|
winner = None
|
|
|
|
if self.player_1_Score >= num_rounds:
|
|
|
|
winner = 'Player Right Wins'
|
|
|
|
if self.player_2_Score >= num_rounds:
|
|
|
|
winner = 'Player Left Wins'
|
|
|
|
return winner
|
|
|
|
|
|
|
|
def update_player1_score(self, val):
|
2019-10-23 20:10:03 +00:00
|
|
|
self.graph.delete_figure(self.draw_P1)
|
|
|
|
self.draw_P1 = self.graph.draw_text(
|
|
|
|
str(val), (170, 50), font=('Courier 60'), color='white')
|
2019-06-27 22:19:57 +00:00
|
|
|
|
|
|
|
def update_player2_score(self, val):
|
2019-10-23 20:10:03 +00:00
|
|
|
self.graph.delete_figure(self.draw_P2)
|
|
|
|
self.draw_P2 = self.graph.draw_text(
|
|
|
|
str(val), (550, 50), font=('courier 40'), color='white')
|
2019-06-27 22:19:57 +00:00
|
|
|
|
|
|
|
def hit_bat(self, pos):
|
|
|
|
bat_pos = (self.bat_1.curx, self.bat_1.cury)
|
|
|
|
if pos[0] >= bat_pos[0] and pos[0] <= bat_pos[0]+BAT_SIZE[0]:
|
|
|
|
if bat_pos[1] <= pos[1] <= bat_pos[1]+BAT_SIZE[1]:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
def hit_bat2(self, pos):
|
|
|
|
bat_pos = (self.bat_2.curx, self.bat_2.cury)
|
|
|
|
if pos[0] >= bat_pos[0] and pos[0] <= bat_pos[0]+BAT_SIZE[0]:
|
|
|
|
if bat_pos[1] <= pos[1] <= bat_pos[1]+BAT_SIZE[1]:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
def draw(self):
|
|
|
|
self.curx += self.x
|
|
|
|
self.cury += self.y
|
2019-10-23 20:10:03 +00:00
|
|
|
self.graph.relocate_figure(self.id, self.curx, self.cury)
|
2019-06-27 22:19:57 +00:00
|
|
|
if self.cury <= 0: # see if hit top or bottom of play area. If so, reverse y direction
|
|
|
|
self.y = 4
|
|
|
|
self.cury = 0
|
|
|
|
if self.cury >= GAMEPLAY_SIZE[1]-BALL_RADIUS/2:
|
|
|
|
self.y = -4
|
|
|
|
self.cury = GAMEPLAY_SIZE[1]-BALL_RADIUS/2
|
|
|
|
if self.curx <= 0: # see if beyond player
|
|
|
|
self.player_1_Score += 1
|
2019-10-23 20:10:03 +00:00
|
|
|
self.graph.relocate_figure(
|
|
|
|
self.id, STARTING_BALL_POSITION[0], STARTING_BALL_POSITION[1])
|
2019-06-27 22:19:57 +00:00
|
|
|
self.x = 4
|
|
|
|
self.update_player2_score(self.player_1_Score)
|
|
|
|
self.curx, self.cury = STARTING_BALL_POSITION
|
|
|
|
if self.curx >= GAMEPLAY_SIZE[0]:
|
|
|
|
self.player_2_Score += 1
|
2019-10-23 20:10:03 +00:00
|
|
|
self.graph.relocate_figure(
|
|
|
|
self.id, STARTING_BALL_POSITION[0], STARTING_BALL_POSITION[1])
|
2019-06-27 22:19:57 +00:00
|
|
|
self.x = -4
|
|
|
|
self.update_player1_score(self.player_2_Score)
|
|
|
|
self.curx, self.cury = STARTING_BALL_POSITION
|
|
|
|
if self.hit_bat((self.curx, self.cury)):
|
|
|
|
self.x = 4
|
|
|
|
if self.hit_bat2((self.curx, self.cury)):
|
|
|
|
self.x = -4
|
|
|
|
|
|
|
|
|
2019-10-23 20:10:03 +00:00
|
|
|
class PongBall():
|
|
|
|
def __init__(self, graph: sg.Graph, colour, x, width=BAT_SIZE[0], height=BAT_SIZE[1]):
|
2019-06-27 22:19:57 +00:00
|
|
|
self.graph = graph
|
2019-10-23 20:10:03 +00:00
|
|
|
self.id = graph.draw_rectangle(
|
|
|
|
(x - width / 2, 200), (x + width / 2, 200 + height), fill_color=colour)
|
2019-06-27 22:19:57 +00:00
|
|
|
self.y = 0
|
|
|
|
self.x = x
|
|
|
|
self.curx = x
|
|
|
|
self.cury = height/2
|
|
|
|
|
|
|
|
def up(self, amount):
|
|
|
|
self.y = -amount
|
|
|
|
|
|
|
|
def down(self, amount):
|
|
|
|
self.y = amount
|
|
|
|
|
|
|
|
@property
|
|
|
|
def curr_pos(self):
|
|
|
|
pos = self.cury
|
|
|
|
return pos
|
|
|
|
|
|
|
|
def draw(self):
|
2019-10-23 20:10:03 +00:00
|
|
|
self.graph.relocate_figure(self.id, self.curx, self.cury)
|
2019-06-27 22:19:57 +00:00
|
|
|
if self.cury + self.y + BAT_SIZE[1] <= GAMEPLAY_SIZE[1] and self.cury + self.y + BAT_SIZE[1] >= 0:
|
|
|
|
self.cury += self.y
|
|
|
|
if self.cury <= 0:
|
|
|
|
self.cury = 0
|
|
|
|
self.y = 0
|
|
|
|
if self.cury >= GAMEPLAY_SIZE[1]:
|
|
|
|
self.cury = GAMEPLAY_SIZE[1]
|
|
|
|
self.y = 0
|
|
|
|
|
|
|
|
|
|
|
|
def pong():
|
2019-10-23 20:10:03 +00:00
|
|
|
layout = [[sg.Graph(GAMEPLAY_SIZE,
|
|
|
|
(0, GAMEPLAY_SIZE[1]),
|
|
|
|
(GAMEPLAY_SIZE[0], 0),
|
|
|
|
background_color=BACKGROUND_COLOR,
|
|
|
|
key='-GRAPH-')],
|
|
|
|
[sg.Text(''),
|
|
|
|
sg.Button('Exit'),
|
|
|
|
sg.Text('Speed'),
|
|
|
|
sg.Slider((0, 20),
|
|
|
|
default_value=10,
|
|
|
|
orientation='h',
|
|
|
|
enable_events=True,
|
|
|
|
key='-SPEED-')]
|
|
|
|
]
|
|
|
|
|
|
|
|
window = sg.Window(
|
|
|
|
'Pong', layout, return_keyboard_events=True, finalize=True)
|
|
|
|
|
|
|
|
graph_elem = window['-GRAPH-'] # type: sg.Graph
|
|
|
|
|
|
|
|
bat_1 = PongBall(graph_elem, 'red', 30)
|
|
|
|
bat_2 = PongBall(graph_elem, 'blue', 670)
|
2019-06-27 22:19:57 +00:00
|
|
|
ball_1 = Ball(graph_elem, bat_1, bat_2, 'green1')
|
|
|
|
sleep_time = 10
|
|
|
|
|
|
|
|
while True:
|
|
|
|
ball_1.draw()
|
|
|
|
bat_1.draw()
|
|
|
|
bat_2.draw()
|
|
|
|
|
2019-10-23 20:10:03 +00:00
|
|
|
event, values = window.read(
|
|
|
|
timeout=sleep_time) # type: str, str
|
|
|
|
if event in (None, 'Exit'):
|
2019-06-27 22:19:57 +00:00
|
|
|
break
|
|
|
|
elif event.startswith('Up') or event.endswith('Up'):
|
|
|
|
bat_2.up(5)
|
|
|
|
elif event.startswith('Down') or event.endswith('Down'):
|
|
|
|
bat_2.down(5)
|
|
|
|
elif event == 'w':
|
|
|
|
bat_1.up(5)
|
|
|
|
elif event == 's':
|
|
|
|
bat_1.down(5)
|
2019-10-23 20:10:03 +00:00
|
|
|
elif event == '-SPEED-':
|
|
|
|
sleep_time = int(values['-SPEED-'])
|
2019-06-27 22:19:57 +00:00
|
|
|
|
|
|
|
if ball_1.win_loss_check():
|
2019-10-23 20:10:03 +00:00
|
|
|
sg.popup('Game Over', ball_1.win_loss_check() + ' won!!')
|
2019-06-27 22:19:57 +00:00
|
|
|
break
|
2019-10-23 20:10:03 +00:00
|
|
|
window.close()
|
|
|
|
|
2019-06-27 22:19:57 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
pong()
|