Streamlined, sound files etc.

pull/2/head
kaqu 3 years ago
parent b48fcd90ff
commit 444f10de52

@ -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):

@ -1,10 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
pandemic_pong_client.py
Pandemic Pong Client
"""
import pong_player, pong_object

@ -1,10 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
pandemic_pong_server.py
Pandemic Pong Server
"""
import pong_game

@ -36,3 +36,12 @@ STATE_GAMERESULTS = 3
STATE_FINALRESULTS = 4
STATE_RESTART = 5
STATE_EXIT = 6
"""File paths"""
wall_contact = './sounds/contact.ogg' # player & wall actually
player_contact = wall_contact
player_miss = './sounds/miss.wav'
game_splash = './sounds/splash.wav'
game_exit = './sounds/bye.wav'
game_win = './sounds/gamewin.wav'
match_win = './sounds/matchwin.wav'

@ -25,6 +25,12 @@ class PongGame:
def game_fsm(self, player1, player2):
"""Game engine state machine"""
if (player1.state & pgc.BTN_BASE3) > 0 or (player2.state & pgc.BTN_BASE3) > 0:
player1.state = 0 # Don't play me again
player2.state = 0
self.delay = 50 # Say good bye!
self.state = pgc.STATE_EXIT
if self.state == pgc.STATE_WELCOME:
self.delay = self.delay - 1
if self.delay < 1:
@ -61,9 +67,12 @@ class PongGame:
self.state = pgc.STATE_GAMERESULTS
elif self.state == pgc.STATE_GAMERESULTS:
if self.delay == 90:
playsound(pgc.game_win)
self.delay = self.delay - 1
if self.delay < 1:
if (self.p1_game > 2) or (self.p2_game > 2): # Set won?
if (self.p1_game > 2) or (self.p2_game > 2): # Set won?
self.delay = 100
self.state = pgc.STATE_FINALRESULTS # Yap!
else:
player1.score = 0
@ -73,15 +82,21 @@ class PongGame:
self.state = pgc.STATE_PLAY # Nope, move on to next game
elif self.state == pgc.STATE_FINALRESULTS:
if (player1.state & pgc.BTN_BASE3) > 0 or (player2.state & pgc.BTN_BASE3) > 0:
return False
elif ((player1.state & pgc.BTN_BASE4) > 0) or ((player2.state & pgc.BTN_BASE4) > 0):
if self.delay == 90:
playsound(pgc.match_win)
self.delay = self.delay - 1
if self.delay < 1:
player1.state = 0
player2.state = 0
self.state = pgc.STATE_START # Continue by start button press
#if self.state >= pgc.STATE_EXIT: not used ...
# return False
elif self.state == pgc.STATE_EXIT:
if self.delay == 40:
playsound(pgc.game_exit)
self.delay = self.delay - 1
if self.delay < 1:
return False
return True
def crashvectors(self, ball, player1, player2):
@ -109,7 +124,7 @@ class PongGame:
else:
ball.delta_y = ball.delta_y * 0.8 # Decrease angle
playsound('/usr/share/mint-artwork/sounds/logout.ogg') # Enforce caching ...
playsound(pgc.player_contact) # Enforce caching ...
else: # Ball moves left->right (---->)
if (ball.x + ball.w >= player2.x) and (ball.x < player2.x + player2.w): # Right player #2 in range?
@ -133,7 +148,7 @@ class PongGame:
else:
ball.delta_y = ball.delta_y * 0.8 # Decrease angle
playsound('/usr/share/mint-artwork/sounds/logout.ogg') # Enforce caching ...
playsound(pgc.player_contact) # Enforce caching ...
def pong_game(self, ball, player1, player2):
@ -157,12 +172,12 @@ class PongGame:
if rc != 0: # Miss left(-1) or right(1)
if rc == -1: # Player #2: +1
player2.score = player2.score + 1
ball.reinit(6 + (random() - 0.5) * 4, (random() - 0.5) * 10)
playsound('/usr/lib/libreoffice/share/gallery/sounds/laser.wav')
ball.reinit(8 + (random() - 0.5) * 4, (random() - 0.5) * 10)
playsound(pgc.player_miss)
else: # Player #1: +1
player1.score = player1.score + 1
ball.reinit(-(6 + (random() - 0.5) * 4), (random() - 0.5) * 10)
playsound('/usr/lib/libreoffice/share/gallery/sounds/laser.wav')
ball.reinit(-(8 + (random() - 0.5) * 4), (random() - 0.5) * 10)
playsound(pgc.player_miss)
return True

@ -54,11 +54,11 @@ class PongObject:
if sum_y < pgv.GAMEAREA_MIN_Y:
sum_y = pgv.GAMEAREA_MIN_Y
self.delta_y = -self.delta_y
playsound('/usr/share/mint-artwork/sounds/logout.ogg')
playsound(pgc.wall_contact)
elif sum_y + self.h > pgv.GAMEAREA_MAX_Y:
sum_y = pgv.GAMEAREA_MAX_Y - self.h
self.delta_y = -self.delta_y
playsound('/usr/share/mint-artwork/sounds/logout.ogg')
playsound(pgc.wall_contact)
self.x = sum_x
self.y = sum_y

@ -9,7 +9,6 @@ Pandemic Pong Player Logic
import os, fcntl
import libevdev
from playsound import playsound
import pong_constants as pgc # Pong global constants
import pong_globalvars as pgv # Pong global variables

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save