|
|
|
@ -8,7 +8,7 @@ Pandemic python/Qt5 pong clone
|
|
|
|
|
History:
|
|
|
|
|
--------
|
|
|
|
|
21.11.20/KQ Initial version
|
|
|
|
|
25.11.20/KQ Class based version ;)
|
|
|
|
|
25.11.20/KQ Class based version w/ scaling ;)
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import sys, os, fcntl, time, random
|
|
|
|
@ -28,39 +28,40 @@ from pong_player import PongPlayer
|
|
|
|
|
from pong_object import PongObject
|
|
|
|
|
from pong_game import PongGame
|
|
|
|
|
|
|
|
|
|
def draw_buttonstate(x, y, player, painter):
|
|
|
|
|
|
|
|
|
|
def draw_buttonstate(x, y, player, painter, scale_x, scale_y):
|
|
|
|
|
"""Indicate last button pressed (not strictly necessary ...)"""
|
|
|
|
|
if (player.state & pgc.BTN_TRIGGER) == pgc.BTN_TRIGGER:
|
|
|
|
|
painter.setPen(QPen(Qt.blue, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
|
|
|
|
|
painter.setBrush(QBrush(Qt.blue, Qt.SolidPattern)) # Fill
|
|
|
|
|
painter.drawEllipse(x, y, 20, 20) # Blue button
|
|
|
|
|
painter.drawEllipse(int(x * scale_x), int(y * scale_y), int(20 * scale_x), int(20 * scale_y)) # Blue button
|
|
|
|
|
if (player.state & pgc.BTN_TOP) == pgc.BTN_TOP:
|
|
|
|
|
painter.setPen(QPen(Qt.green, 1, Qt.SolidLine)) # Green
|
|
|
|
|
painter.setBrush(QBrush(Qt.green, Qt.SolidPattern))
|
|
|
|
|
painter.drawEllipse(x + 30, y, 20, 20)
|
|
|
|
|
painter.drawEllipse(int((x + 30) * scale_x), int(y * scale_y), int(20 * scale_x), int(20 * scale_y))
|
|
|
|
|
if (player.state & pgc.BTN_THUMB) == pgc.BTN_THUMB:
|
|
|
|
|
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine)) # Red
|
|
|
|
|
painter.setBrush(QBrush(Qt.red, Qt.SolidPattern))
|
|
|
|
|
painter.drawEllipse(x + 60, y, 20, 20)
|
|
|
|
|
painter.drawEllipse(int((x + 60) * scale_x), int(y * scale_y), int(20 * scale_x), int(20 * scale_y))
|
|
|
|
|
if (player.state & pgc.BTN_THUMB2) == pgc.BTN_THUMB2:
|
|
|
|
|
painter.setPen(QPen(Qt.yellow, 1, Qt.SolidLine)) # Yellow
|
|
|
|
|
painter.setBrush(QBrush(Qt.yellow, Qt.SolidPattern))
|
|
|
|
|
painter.drawEllipse(x + 90, y, 20, 20)
|
|
|
|
|
painter.drawEllipse(int((x + 90) * scale_x), int(y * scale_y), int(20 * scale_x), int(20 * scale_y))
|
|
|
|
|
|
|
|
|
|
class pongWindow(QMainWindow):
|
|
|
|
|
def __init__(self):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.title = "Pandemic Pong"
|
|
|
|
|
self.top= 0
|
|
|
|
|
self.left= 0
|
|
|
|
|
self.width = 1920
|
|
|
|
|
self.height = 960
|
|
|
|
|
self.top = 0
|
|
|
|
|
self.left = 0
|
|
|
|
|
self.win_width = 1920
|
|
|
|
|
self.win_height = 960
|
|
|
|
|
self.InitWindow()
|
|
|
|
|
|
|
|
|
|
def InitWindow(self):
|
|
|
|
|
self.setWindowTitle(self.title)
|
|
|
|
|
self.setGeometry(self.top, self.left, self.width, self.height)
|
|
|
|
|
#self.showFullScreen()
|
|
|
|
|
self.setGeometry(self.top, self.left, self.win_width, self.win_height)
|
|
|
|
|
self.showFullScreen()
|
|
|
|
|
self.pic = QPixmap("pictures/pong_background.png")
|
|
|
|
|
# Font metrics assume font is monospaced!
|
|
|
|
|
self.fntLarge = QFont("Monospace", 120)
|
|
|
|
@ -72,9 +73,16 @@ class pongWindow(QMainWindow):
|
|
|
|
|
self.fntMedium.setFixedPitch(True)
|
|
|
|
|
|
|
|
|
|
self.show()
|
|
|
|
|
playsound('/usr/share/mint-artwork/sounds/close.oga')
|
|
|
|
|
playsound('/usr/lib/libreoffice/share/gallery/sounds/laser.wav') # Enforce caching ...
|
|
|
|
|
playsound('/usr/share/mint-artwork/sounds/logout.ogg')
|
|
|
|
|
|
|
|
|
|
# Enforce caching ...
|
|
|
|
|
playsound(pgc.game_win)
|
|
|
|
|
playsound(pgc.match_win)
|
|
|
|
|
playsound(pgc.player_contact)
|
|
|
|
|
playsound(pgc.player_miss)
|
|
|
|
|
playsound(pgc.wall_contact)
|
|
|
|
|
playsound(pgc.game_exit)
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
playsound(pgc.game_splash)
|
|
|
|
|
|
|
|
|
|
self.timer = QTimer() # Start processing 'loop'
|
|
|
|
|
self.timer.setInterval(25) # 25ms
|
|
|
|
@ -85,31 +93,42 @@ class pongWindow(QMainWindow):
|
|
|
|
|
def paintEvent(self, event):
|
|
|
|
|
global game, ball, player1, player2
|
|
|
|
|
|
|
|
|
|
scale_x = self.width() / pgv.GAMEAREA_MAX_X
|
|
|
|
|
scale_y = self.height() / (pgv.GAMEAREA_MAX_Y + 20) # Compensate header
|
|
|
|
|
|
|
|
|
|
painter = QPainter(self) # Painter need's to be freshly picked ...
|
|
|
|
|
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
|
|
|
|
|
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern)) # Fill
|
|
|
|
|
|
|
|
|
|
painter.drawPixmap(self.rect(), self.pic) # Game background
|
|
|
|
|
|
|
|
|
|
#painter.drawText(10,30, "Game state: {} ({}) Scores: P1={} P2={}".format(game["state"], game["delay"], game["p1_game"], game["p2_game"]))
|
|
|
|
|
# Font metrics assume font is monospaced!
|
|
|
|
|
self.fntLarge = QFont("Monospace", int(120 * scale_y))
|
|
|
|
|
self.fntLarge.setKerning(False)
|
|
|
|
|
self.fntLarge.setFixedPitch(True)
|
|
|
|
|
self.fm = QFontMetrics(self.fntLarge)
|
|
|
|
|
self.fntMedium = QFont("Monospace", int(40 * scale_y))
|
|
|
|
|
self.fntMedium.setKerning(False)
|
|
|
|
|
self.fntMedium.setFixedPitch(True)
|
|
|
|
|
|
|
|
|
|
if game.state == pgc.STATE_WELCOME: # Welcome screen
|
|
|
|
|
painter.drawPixmap(self.rect(), QPixmap("pictures/pandemic_pong.png"))
|
|
|
|
|
painter.setFont(self.fntLarge)
|
|
|
|
|
painter.drawText(50, int(pgv.GAMEAREA_MAX_Y / 2)-100, "PANDEMIC")
|
|
|
|
|
painter.drawText(int(pgv.GAMEAREA_MAX_X / 2) + 300, int(pgv.GAMEAREA_MAX_Y / 2)+100, "PONG")
|
|
|
|
|
painter.drawText(int(50 * scale_x), int((pgv.GAMEAREA_MAX_Y / 2 - 100) * scale_y), "PANDEMIC")
|
|
|
|
|
painter.drawText(int((pgv.GAMEAREA_MAX_X / 2 + 300) * scale_x), int((pgv.GAMEAREA_MAX_Y / 2 + 100) * scale_y), "PONG")
|
|
|
|
|
|
|
|
|
|
elif game.state == pgc.STATE_START: # Wait for start button pressed
|
|
|
|
|
painter.setFont(self.fntMedium)
|
|
|
|
|
painter.drawText(300, int(pgv.GAMEAREA_MAX_Y / 2), "Press [Start] ...")
|
|
|
|
|
painter.drawText(int(pgv.GAMEAREA_MAX_X/2)+100, int(pgv.GAMEAREA_MAX_Y / 5), "Press [color] button")
|
|
|
|
|
painter.drawText(int(pgv.GAMEAREA_MAX_X/2)+100, int(pgv.GAMEAREA_MAX_Y / 5 * 2), "to infect player,")
|
|
|
|
|
painter.drawText(int(pgv.GAMEAREA_MAX_X/2)+100, int(pgv.GAMEAREA_MAX_Y / 5 * 3), "ball will pickup virus!")
|
|
|
|
|
painter.drawText(int(pgv.GAMEAREA_MAX_X/2)+100, int(pgv.GAMEAREA_MAX_Y / 5 * 4), "Match color to deflect!")
|
|
|
|
|
painter.drawText(int(150 * scale_x), int((pgv.GAMEAREA_MAX_Y / 2 - 100) * scale_y), "Press [Start] ...")
|
|
|
|
|
painter.drawText(int(50 * scale_x), int((pgv.GAMEAREA_MAX_Y / 2 + 100) * scale_y), "Press [Select] to abort")
|
|
|
|
|
painter.drawText(int((pgv.GAMEAREA_MAX_X / 2 + 100) * scale_x), int(pgv.GAMEAREA_MAX_Y / 5 * scale_y), "Press [color] button")
|
|
|
|
|
painter.drawText(int((pgv.GAMEAREA_MAX_X / 2 + 100) * scale_x), int(pgv.GAMEAREA_MAX_Y / 5 * 2 * scale_y), "to infect player,")
|
|
|
|
|
painter.drawText(int((pgv.GAMEAREA_MAX_X / 2 + 100) * scale_x), int(pgv.GAMEAREA_MAX_Y / 5 * 3 * scale_y), "ball will pickup virus!")
|
|
|
|
|
painter.drawText(int((pgv.GAMEAREA_MAX_X / 2 + 100) * scale_x), int(pgv.GAMEAREA_MAX_Y / 5 * 4 * scale_y), "Match color to deflect!")
|
|
|
|
|
|
|
|
|
|
elif game.state == pgc.STATE_PLAY: # Actual play 'til score reaches 10 points
|
|
|
|
|
# Ball gives NO indication ...
|
|
|
|
|
painter.drawRect(int(ball.x), int(ball.y), int(ball.w), int(ball.h)) # Ball
|
|
|
|
|
painter.drawRect(int(ball.x * scale_x), int(ball.y * scale_y), int(ball.w * scale_x), int(ball.h * scale_y)) # Ball
|
|
|
|
|
|
|
|
|
|
if player1.color == pgc.COL_WHITE:
|
|
|
|
|
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
|
|
|
|
@ -126,7 +145,7 @@ class pongWindow(QMainWindow):
|
|
|
|
|
elif player1.color == pgc.COL_YELLOW:
|
|
|
|
|
painter.setPen(QPen(Qt.yellow, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
|
|
|
|
|
painter.setBrush(QBrush(Qt.yellow, Qt.SolidPattern)) # Fill
|
|
|
|
|
painter.drawRect(int(player1.x), int(player1.y), int(player1.w), int(player1.h)) # Player left
|
|
|
|
|
painter.drawRect(int(player1.x * scale_x), int(player1.y * scale_y), int(player1.w * scale_x), int(player1.h * scale_y)) # Player left
|
|
|
|
|
|
|
|
|
|
if player2.color == pgc.COL_WHITE:
|
|
|
|
|
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
|
|
|
|
@ -143,7 +162,7 @@ class pongWindow(QMainWindow):
|
|
|
|
|
elif player2.color == pgc.COL_YELLOW:
|
|
|
|
|
painter.setPen(QPen(Qt.yellow, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
|
|
|
|
|
painter.setBrush(QBrush(Qt.yellow, Qt.SolidPattern)) # Fill
|
|
|
|
|
painter.drawRect(int(player2.x), int(player2.y), int(player2.w), int(player2.h)) # Player right
|
|
|
|
|
painter.drawRect(int(player2.x * scale_x), int(player2.y * scale_y), int(player2.w * scale_x), int(player2.h * scale_y)) # Player right
|
|
|
|
|
|
|
|
|
|
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Reset standard colour
|
|
|
|
|
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern))
|
|
|
|
@ -153,31 +172,30 @@ class pongWindow(QMainWindow):
|
|
|
|
|
# Score player #1
|
|
|
|
|
msg = str(player1.score)
|
|
|
|
|
msg_width = self.fm.width(msg)
|
|
|
|
|
painter.drawText(800 - msg_width, 154, "{}".format(msg))
|
|
|
|
|
painter.drawText(int((800 - msg_width) * scale_x), int(154 * scale_y), "{}".format(msg))
|
|
|
|
|
# Score player #2
|
|
|
|
|
painter.drawText(pgv.GAMEAREA_MAX_X - 840, 154, "{}".format(player2.score))
|
|
|
|
|
painter.drawText(int((pgv.GAMEAREA_MAX_X - 840) * scale_x), int(154 * scale_y), "{}".format(player2.score))
|
|
|
|
|
|
|
|
|
|
# Indicate Button states
|
|
|
|
|
draw_buttonstate(60, 50, player1, painter)
|
|
|
|
|
draw_buttonstate(pgv.GAMEAREA_MAX_X - 180, 50, player2, painter)
|
|
|
|
|
draw_buttonstate(60, 50, player1, painter, scale_x, scale_y)
|
|
|
|
|
draw_buttonstate(pgv.GAMEAREA_MAX_X - 180, 50, player2, painter, scale_x, scale_y)
|
|
|
|
|
elif game.state == pgc.STATE_GAMERESULTS: # Display winner of this game
|
|
|
|
|
painter.setFont(self.fntMedium)
|
|
|
|
|
if player1.score > 9:
|
|
|
|
|
msg = "Game player #1"
|
|
|
|
|
else:
|
|
|
|
|
msg = "Game player #2"
|
|
|
|
|
painter.drawText(50, int(pgv.GAMEAREA_MAX_Y / 2), msg)
|
|
|
|
|
painter.drawText(int(50 * scale_x), int(pgv.GAMEAREA_MAX_Y / 2 * scale_y), msg)
|
|
|
|
|
elif game.state == pgc.STATE_FINALRESULTS: # Display set winner
|
|
|
|
|
painter.setFont(self.fntMedium)
|
|
|
|
|
if game.p1_game > 2:
|
|
|
|
|
msg = "Match player #1"
|
|
|
|
|
else:
|
|
|
|
|
msg = "Match player #2"
|
|
|
|
|
painter.drawText(50, int(pgv.GAMEAREA_MAX_Y / 2), msg)
|
|
|
|
|
painter.drawText(int(50 * scale_x), int(pgv.GAMEAREA_MAX_Y / 2 * scale_y), msg)
|
|
|
|
|
elif game.state == pgc.STATE_EXIT: # Indicate good bye ...
|
|
|
|
|
painter.setFont(self.fntMedium)
|
|
|
|
|
painter.drawText(50, int(pgv.GAMEAREA_MAX_Y / 2), "Bye!")
|
|
|
|
|
|
|
|
|
|
painter.drawText(int(50 * scale_x), int(pgv.GAMEAREA_MAX_Y / 2 * scale_x), "Bye!")
|
|
|
|
|
|
|
|
|
|
@pyqtSlot()
|
|
|
|
|
def on_timer(self):
|
|
|
|
|