Class based full functioning version

pull/2/head
kaqu 2020-11-25 13:48:52 +01:00
parent 9698defbb2
commit b48fcd90ff
11 changed files with 545 additions and 548 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
__pycache__/*
backup/*

View File

@ -1,388 +0,0 @@
#!/usr/bin/env python3
#
# evalgamepad.py
# Reading two USB gamepads & making sense of it (try pong)...
#
#-----------------------------------------------------------------------
# 'lsusb' ouput: Bus 002 Device 003: ID 0079:0011 DragonRise Inc. Gamepad
# Bus 002 Device 002: ID 0079:0011 DragonRise Inc. Gamepad
#
# input devices: /dev/input/event6
# /dev/input/event7
#
import sys, os, fcntl, time, random
import libevdev
from playsound import playsound
# Buttons in 'state<n>'
BTN_TRIGGER = 1 # [Blue/X]
BTN_THUMB = 2 # [Red/A]
BTN_THUMB2 = 4 # [Yellow/B]
BTN_TOP = 8 # [Green/Y]
BTN_TOP2 = 16 # [Frontal left]
BTN_PINKIE = 32 # [Frontal right]
BTN_BASE3 = 64 # [Centre left]
BTN_BASE4 = 128 # [Centre right]
GAMEAREA_MIN_X = 0 # Game area definition
GAMEAREA_MAX_X = 1920 # Assume FHD resolution
GAMEAREA_MIN_Y = 15
GAMEAREA_MAX_Y = 940 #-GAMEAREA_MIN_Y
COL_WHITE = 0
COL_BLUE = 1
COL_GREEN = 2
COL_RED = 3
COL_YELLOW = 4
COLORDELAY = 100
def init_player(path, x, y, w, h):
# Gamepad init.
fd = open(path, "rb")
fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK)
dev = libevdev.Device(fd)
return {
"fd" : fd, # File descriptor to close (later ...)
"dev" : dev, # Actual gamepad of this player
"state" : 0, # Button mask (as above)
"delta_x" : 0, # Current delta setting
"delta_y" : 0,
"color" : COL_WHITE, # 'Infection' colour
"delay" : 0, # 'Infectious' time
"x" : x, # Current actual position
"y" : y, # Start at center
"w" : w,
"h" : h,
"score" : 0
}
def reinit_player(player, x, y, delta_x, delta_y):
player["x"] = x
player["y"] = y
player["delta_x"] = delta_x
player["delta_y"] = delta_y
player["state"] = 0
player["color"] = COL_WHITE
player["delay"] = 0
def exit_player(player):
player["fd"].close()
def init_object(x, y, w, h, delta_x, delta_y):
return {
"delta_x" : delta_x, # Current movement
"delta_y" : (random.random() - 0.5) * 10,
"color" : COL_WHITE,
"delay" : 0,
"x" : x, # Current position
"y" : y,
"w" : w, # Size of object
"h" : h,
}
def reinit_object(obj, delta_x, delta_y):
obj["x"] = GAMEAREA_MAX_X/2 - obj["w"]/2
obj["y"] = GAMEAREA_MAX_Y/2 - obj["h"]/2
obj["delta_x"] = delta_x
obj["delta_y"] = delta_y
obj["color"] = COL_WHITE
obj["delay"] = 0
def print_event(e):
print("Event: time {}.{:06d}, ".format(e.sec, e.usec), end='')
if e.matches(libevdev.EV_SYN):
if e.matches(libevdev.EV_SYN.SYN_MT_REPORT):
print("++++++++++++++ {} ++++++++++++".format(e.code.name))
elif e.matches(libevdev.EV_SYN.SYN_DROPPED):
print(">>>>>>>>>>>>>> {} >>>>>>>>>>>>".format(e.code.name))
else:
print("-------------- {} ------------".format(e.code.name))
else:
print("type {:02x} {} code {:03x} {:20s} value {:4d}".format(e.type.value, e.type.name, e.code.value, e.code.name, e.value))
def eval_gamepad(player):
bChanged = False
try:
for e in player["dev"].events():
#print_event(e)
# Event type 1 (EV_KEY)
# Event code 288 (BTN_TRIGGER) <- 1=[Blue/X]
# Event code 289 (BTN_THUMB) <- 1=[Red/A]
# Event code 290 (BTN_THUMB2) <- 1=[Yellow/B]
# Event code 291 (BTN_TOP) <- 1=[Green/Y]
# Event code 292 (BTN_TOP2) <- 1=[Frontal left]
# Event code 293 (BTN_PINKIE) <- 1=[Frontal right]
# Event code 294 (BTN_BASE)
# Event code 295 (BTN_BASE2)
# Event code 296 (BTN_BASE3) <- 1=[Centre left]
# Event code 297 (BTN_BASE4) <- 1=[Centre right]
if e.type.value == 1: # Non-Cross events
if e.value == 1: # Simple buttons may act as toggles
if e.code.value == 288: # BTN_TRIGGER
if player["delay"] <= 0: # As long as we're not infectious ...
player["state"] = BTN_TRIGGER # player["state"] ^ BTN_TRIGGER
player["color"] = COL_BLUE # Infect 'blue'
player["delay"] = COLORDELAY # Start infectious time immediately ...
elif e.code.value == 289: # BTN_THUMB
if player["delay"] <= 0: # As long as we're not infectious ...
player["state"] = BTN_THUMB # player["state"] ^ BTN_THUMB
player["color"] = COL_RED
player["delay"] = COLORDELAY
elif e.code.value == 290: # BTN_THUMB2
if player["delay"] <= 0: # As long as we're not infectious ...
player["state"] = BTN_THUMB2 # player["state"] ^ BTN_THUMB2
player["color"] = COL_YELLOW
player["delay"] = COLORDELAY
elif e.code.value == 291: # BTN_TOP
if player["delay"] <= 0: # As long as we're not infectious ...
player["state"] = BTN_TOP # player["state"] ^ BTN_TOP
player["color"] = COL_GREEN
player["delay"] = COLORDELAY
elif e.code.value == 292: # BTN_TOP2
player["state"] = player["state"] ^ BTN_TOP2
elif e.code.value == 293: # BTN_PINKIE
player["state"] = player["state"] ^ BTN_PINKIE
elif e.code.value == 296: # BTN_BASE3
player["state"] = player["state"] ^ BTN_BASE3
elif e.code.value == 297: # BTN_BASE4
player["state"] = player["state"] ^ BTN_BASE4
bChanged = True
# Event type 3 (EV_ABS)
# Event code 0 (ABS_X) <- Cross: 127=Neutral, 0=[Left], 255=[Right]
# Event code 1 (ABS_Y) <- Cross: 127=Neutral, 0=[Top], 255=[Down]
elif e.type.value == 3: # EV_ABS
if e.code.value == 0: # ABS_X
if e.value == 0:
player["delta_x"] = player["delta_x"] - 1
elif e.value == 255:
player["delta_x"] = player["delta_x"] + 1
else: # 127/Neutral
player["delta_x"] = 0
else: # ABS_Y
if e.value == 0:
player["delta_y"] = player["delta_y"] - 1
elif e.value == 255:
player["delta_y"] = player["delta_y"] + 1
else: # 127/Neutral
player["delta_y"] = 0
bChanged = True
#if bChanged:
# print("State=",player["state"], "X=", player["delta_x"], "Y=", player["delta_y"])
except libevdev.EventsDroppedException:
print("Dropped!")
for e in player["dev"].sync():
print_event(e)
return bChanged
def eval_position(player, min_x, max_x):
bChanged = False
sum_x = player["x"] + player["delta_x"] * 10 #255
if sum_x < min_x:
sum_x = min_x
elif sum_x + player["w"] > max_x:
sum_x = max_x - player["w"]
sum_y = player["y"] + player["delta_y"] * 10 #255
if sum_y < GAMEAREA_MIN_Y:
sum_y = GAMEAREA_MIN_Y
elif sum_y + player["h"] > GAMEAREA_MAX_Y:
sum_y = GAMEAREA_MAX_Y - player["h"]
if (sum_x != player["x"]) or (sum_y != player["y"]):
bChanged = True
player["x"] = sum_x
player["y"] = sum_y
return bChanged
def eval_object(obj):
bChanged = 0
sum_x = obj["x"] + obj["delta_x"]
sum_y = obj["y"] + obj["delta_y"]
if sum_x < GAMEAREA_MIN_X:
#sum_x = GAMEAREA_MIN_X
#obj["delta_x"] = -obj["delta_x"]
bChanged = -1 # Miss left
elif sum_x + obj["w"] > GAMEAREA_MAX_X:
#sum_x = GAMEAREA_MAX_X - obj["w"]
#obj["delta_x"] = -obj["delta_x"]
bChanged = 1 # Miss right
if sum_y < GAMEAREA_MIN_Y:
sum_y = GAMEAREA_MIN_Y
obj["delta_y"] = -obj["delta_y"]
playsound('/usr/share/mint-artwork/sounds/logout.ogg')
elif sum_y + obj["h"] > GAMEAREA_MAX_Y:
sum_y = GAMEAREA_MAX_Y - obj["h"]
obj["delta_y"] = -obj["delta_y"]
playsound('/usr/share/mint-artwork/sounds/logout.ogg')
obj["x"] = sum_x
obj["y"] = sum_y
return bChanged
def draw_objects(ball, player1, player2): # Update objects on playground
print("\rB: ", ball["x"], "/", ball["y"], end="")
print(" P1: ", player1["x"], "/", player1["y"], " S:", hex(player1["state"]), " ", end="")
print(" P2: ", player2["x"], "/", player2["y"], " S:", hex(player2["state"]), " ", end="")
def gameloop(ball, player1, player2):
while True:
# 1. Retrieve user entries
bChanged = eval_gamepad(player1)
if bChanged:
if (player1["state"] & BTN_BASE4) > 0: # Exit?
print("Player #1 aborted game")
break
bChanged = eval_gamepad(player2) # Exit?
if bChanged:
if (player2["state"] & BTN_BASE4) > 0:
print("Player #2 aborted game")
break
# 2. Adjust player positions
bChanged = eval_position(player1)
if bChanged:
print("Player #1: ", player1["x"], " / ", player1["y"])
bChanged = eval_position(player2)
if bChanged:
print("Player #2: ", player2["x"], " / ", player2["y"])
# 3. Adjust object positions
eval_object(ball)
# 4. Refresh game area drawing
draw_objects(ball, player1, player2)
# 5. Little delay for testing
time.sleep(0.1)
STATE_WELCOME = 0
STATE_START = 1
STATE_PLAY = 2
STATE_GAMERESULTS = 3
STATE_FINALRESULTS = 4
STATE_RESTART = 5
STATE_EXIT = 6
def init_game(): # Create base playground
return {
"state" : STATE_WELCOME, # State of game
"delay" : 100,
"p1_game" : 0, # Results
"p2_game" : 0
}
def next_gamestate(ga, player1, player2):
if ga["state"] == STATE_WELCOME:
ga["delay"] = ga["delay"] - 1
if ga["delay"] < 1:
ga["state"] = STATE_START
elif ga["state"] == STATE_START: # Start new game
if (player1["state"] & BTN_BASE4) > 0 or (player2["state"] & BTN_BASE4) > 0: # [Start] pressed?
reinit_player(player1, 10, GAMEAREA_MAX_Y/2-50, 0, 0)
reinit_player(player2, GAMEAREA_MAX_X-40, GAMEAREA_MAX_Y/2-50, 0, 0)
ga["p1_game"] = 0
ga["p2_game"] = 0
player1["score"] = 0
player2["score"] = 0
ga["state"] = STATE_PLAY
elif ga["state"] == STATE_PLAY: # Remain playing 'til 10 points
if player1["delay"] > 0: # Infectious time running?
player1["delay"] = player1["delay"] - 1 # Yap!
if player1["delay"] <= 0:
player1["color"] = COL_WHITE
player1["state"] = 0
if player2["delay"] > 0: # for both players ...
player2["delay"] = player2["delay"] - 1
if player2["delay"] <= 0:
player2["color"] = COL_WHITE
player2["state"] = 0
if player1["score"] > 9 or (player2["score"] > 9):
if player1["score"] > 9: # Figure out winner
ga["p1_game"] = ga["p1_game"] + 1 # & count game accordingly
else:
ga["p2_game"] = ga["p2_game"] + 1
ga["delay"] = 100
ga["state"] = STATE_GAMERESULTS
elif ga["state"] == STATE_GAMERESULTS:
ga["delay"] = ga["delay"] - 1
if ga["delay"] < 1:
if (ga["p1_game"] > 2) or (ga["p2_game"] > 2): # Set won?
ga["state"] = STATE_FINALRESULTS # Yap!
else:
player1["score"] = 0
player2["score"] = 0
reinit_player(player1, GAMEAREA_MAX_X-40, GAMEAREA_MAX_Y/2-50, 0, 0)
reinit_player(player2, 10, GAMEAREA_MAX_Y/2-50, 0, 0)
ga["state"] = STATE_PLAY # Nope, move on to next game
elif ga["state"] == STATE_FINALRESULTS:
if (player1["state"] & BTN_BASE3) > 0 or (player2["state"] & BTN_BASE3) > 0:
return False
elif ((player1["state"] & BTN_BASE4) > 0) or ((player2["state"] & BTN_BASE4) > 0):
player1["state"] = 0
player2["state"] = 0
ga["state"] = STATE_START # Continue by start button press
#if ga["state"] >= STATE_EXIT: not used ...
# return False
return True
def main(args):
try:
# Initialize
init_gamearea()
ball = init_object(10, 10, 15, 15, 2.0, 1.5)
player1 = init_player(args[1],10, GAMEAREA_MAX_Y/2, 10, 160)
player2 = init_player(args[2],GAMEAREA_MAX_X-30, GAMEAREA_MAX_Y/2, 10, 160)
# Work ...
gameloop(ball, player1, player2)
# Quit gracefully
exit_player(player2)
exit_player(player1)
except KeyboardInterrupt: # Never comes ... (?!)
pass
except IOError as e:
import errno
if e.errno == errno.EACCES:
print("Insufficient permissions to access {} or {}".format(path1, path2))
elif e.errno == errno.ENOENT:
print("Device {} or {} does not exist".format(path1, path2))
else:
raise e
if __name__ == "__main__":
if len(sys.argv) < 3:
print("usage: ./evalgamepad.py /dev/input/event<n> /dev/input/event<m>")
sys.exit(1)
main(sys.argv)

217
pandemic_pong.py Normal file → Executable file
View File

@ -7,7 +7,8 @@ Pandemic python/Qt5 pong clone
History:
--------
21.10.20/KQ Initial version
21.11.20/KQ Initial version
25.11.20/KQ Class based version ;)
"""
import sys, os, fcntl, time, random
@ -21,110 +22,27 @@ from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt, QTimer, pyqtSlot, QEvent
from PyQt5.QtGui import QPainter, QBrush, QPen, QFont, QFontMetrics
import evalgamepad
def crashvectors(ball, player1, player2):
if ball["delta_x"] < 0: # Ball moves right->left (<----)
if (ball["x"] <= player1["x"] + player1["w"]) and (ball["x"] > player1["x"]): # Left player #1 in range?
if ball["y"] + ball["h"] >= player1["y"]: # Ball lower than player upper bound?
if ball["y"] <= player1["y"] + player1["h"]: # Ball higher than player lower bound?
if ball["color"] == evalgamepad.COL_WHITE:
ball["color"] = player1["color"] # Pick up 'infection' (if any)
elif ball["color"] != player1["color"]: # Infectious ball!
return # w/o vaccine -> no save!
ball["delta_x"] = -ball["delta_x"] * 1.2 # Invert direction & speed up
if player1["delta_y"] > 0.0: # Going downwards
if ball["delta_y"] > 0.0: # As well?
ball["delta_y"] = ball["delta_y"] * 1.2 # Increase angle
else:
ball["delta_y"] = ball["delta_y"] * 0.8 # Decrease angle
elif player1["delta_y"] < 0.0:
if ball["delta_y"] < 0.0: # As well?
ball["delta_y"] = ball["delta_y"] * 1.2 # Increase angle
else:
ball["delta_y"] = ball["delta_y"] * 0.8 # Decrease angle
playsound('/usr/share/mint-artwork/sounds/logout.ogg') # 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?
if ball["y"] + ball["h"] >= player2["y"]: # Ball lower than player upper bound?
if ball["y"] <= player2["y"] + player2["h"]: # Ball higher than player lower bound?
if ball["color"] == evalgamepad.COL_WHITE:
ball["color"] = player2["color"] # Pick up 'infection' (if any)
elif ball["color"] != player2["color"]: # Infectious ball!
return # w/o vaccine -> no save!
ball["delta_x"] = -ball["delta_x"] * 1.2 # Invert direction & speed up
if player2["delta_y"] > 0.0: # Going downwards
if ball["delta_y"] > 0.0: # As well?
ball["delta_y"] = ball["delta_y"] * 1.2 # Increase angle
else:
ball["delta_y"] = ball["delta_y"] * 0.8 # Decrease angle
elif player2["delta_y"] < 0.0:
if ball["delta_y"] < 0.0: # As well?
ball["delta_y"] = ball["delta_y"] * 1.2 # Increase angle
else:
ball["delta_y"] = ball["delta_y"] * 0.8 # Decrease angle
playsound('/usr/share/mint-artwork/sounds/logout.ogg') # Enforce caching ...
def pong_game(game, ball, player1, player2):
if evalgamepad.next_gamestate(game, player1, player2) == False: # Exit
return False
#print("Game state: {}".format(game["state"]))
# 1. Retrieve user entries
bChanged = evalgamepad.eval_gamepad(player1)
bChanged = evalgamepad.eval_gamepad(player2) # Exit?
if game["state"] == evalgamepad.STATE_PLAY: # Actually playing?
# 2. Adjust player positions
bChanged = evalgamepad.eval_position(player1, evalgamepad.GAMEAREA_MIN_X, evalgamepad.GAMEAREA_MAX_X/2-50)
#if bChanged:
# print("Player #1: ", player1["x"], " / ", player1["y"])
bChanged = evalgamepad.eval_position(player2, evalgamepad.GAMEAREA_MAX_X/2+50, evalgamepad.GAMEAREA_MAX_X)
#if bChanged:
# print("Player #2: ", player2["x"], " / ", player2["y"])
# 3. Crash analyses
crashvectors(ball, player1, player2)
# 4. Adjust object positions (ball & potentially others ...)
rc = evalgamepad.eval_object(ball)
if rc != 0: # Miss left(-1) or right(1)
if rc == -1: # Player #2: +1
player2["score"] = player2["score"] + 1
evalgamepad.reinit_object(ball, 6 + (random.random() - 0.5) * 4, (random.random() - 0.5) * 10)
playsound('/usr/lib/libreoffice/share/gallery/sounds/laser.wav')
else: # Player #1: +1
player1["score"] = player1["score"] + 1
evalgamepad.reinit_object(ball, -(6 + (random.random() - 0.5) * 4), (random.random() - 0.5) * 10)
playsound('/usr/lib/libreoffice/share/gallery/sounds/laser.wav')
return True
import pong_constants as pgc # Pong global constants
import pong_globalvars as pgv # Pong global variables
from pong_player import PongPlayer
from pong_object import PongObject
from pong_game import PongGame
def draw_buttonstate(x, y, player, painter):
if (player["state"] & evalgamepad.BTN_TRIGGER) == evalgamepad.BTN_TRIGGER:
"""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
if (player["state"] & evalgamepad.BTN_TOP) == evalgamepad.BTN_TOP:
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)
if (player["state"] & evalgamepad.BTN_THUMB) == evalgamepad.BTN_THUMB:
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)
if (player["state"] & evalgamepad.BTN_THUMB2) == evalgamepad.BTN_THUMB2:
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)
@ -175,111 +93,90 @@ class pongWindow(QMainWindow):
#painter.drawText(10,30, "Game state: {} ({}) Scores: P1={} P2={}".format(game["state"], game["delay"], game["p1_game"], game["p2_game"]))
if game["state"] == evalgamepad.STATE_WELCOME: # Welcome screen
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(evalgamepad.GAMEAREA_MAX_Y / 2)-100, "PANDEMIC")
painter.drawText(int(evalgamepad.GAMEAREA_MAX_X / 2) + 300, int(evalgamepad.GAMEAREA_MAX_Y / 2)+100, "PONG")
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")
elif game["state"] == evalgamepad.STATE_START: # Wait for start button pressed
elif game.state == pgc.STATE_START: # Wait for start button pressed
painter.setFont(self.fntMedium)
painter.drawText(300, int(evalgamepad.GAMEAREA_MAX_Y / 2), "Press [Start] ...")
painter.drawText(int(evalgamepad.GAMEAREA_MAX_X/2)+100, int(evalgamepad.GAMEAREA_MAX_Y / 5), "Press [color] button")
painter.drawText(int(evalgamepad.GAMEAREA_MAX_X/2)+100, int(evalgamepad.GAMEAREA_MAX_Y / 5 * 2), "to infect player,")
painter.drawText(int(evalgamepad.GAMEAREA_MAX_X/2)+100, int(evalgamepad.GAMEAREA_MAX_Y / 5 * 3), "ball will pickup virus!")
painter.drawText(int(evalgamepad.GAMEAREA_MAX_X/2)+100, int(evalgamepad.GAMEAREA_MAX_Y / 5 * 4), "Match color to deflect!")
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!")
elif game["state"] == evalgamepad.STATE_PLAY: # Actual play 'til score reaches 10 points
""" Ball gives NO indication ...
if ball["color"] == evalgamepad.COL_WHITE:
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
if player1.color == pgc.COL_WHITE:
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern)) # Fill
elif ball["color"] == evalgamepad.COL_BLUE:
elif player1.color == pgc.COL_BLUE:
painter.setPen(QPen(Qt.blue, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.blue, Qt.SolidPattern)) # Fill
elif ball["color"] == evalgamepad.COL_GREEN:
elif player1.color == pgc.COL_GREEN:
painter.setPen(QPen(Qt.green, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.green, Qt.SolidPattern)) # Fill
elif ball["color"] == evalgamepad.COL_RED:
elif player1.color == pgc.COL_RED:
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.red, Qt.SolidPattern)) # Fill
elif ball["color"] == evalgamepad.COL_YELLOW:
painter.setPen(QPen(Qt.yellow, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.yellow, Qt.SolidPattern)) # Fill
"""
painter.drawRect(int(ball["x"]), int(ball["y"]), int(ball["w"]), int(ball["h"])) # Ball
if player1["color"] == evalgamepad.COL_WHITE:
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern)) # Fill
elif player1["color"] == evalgamepad.COL_BLUE:
painter.setPen(QPen(Qt.blue, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.blue, Qt.SolidPattern)) # Fill
elif player1["color"] == evalgamepad.COL_GREEN:
painter.setPen(QPen(Qt.green, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.green, Qt.SolidPattern)) # Fill
elif player1["color"] == evalgamepad.COL_RED:
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.red, Qt.SolidPattern)) # Fill
elif player1["color"] == evalgamepad.COL_YELLOW:
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), int(player1.y), int(player1.w), int(player1.h)) # Player left
if player2["color"] == evalgamepad.COL_WHITE:
if player2.color == pgc.COL_WHITE:
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern)) # Fill
elif player2["color"] == evalgamepad.COL_BLUE:
elif player2.color == pgc.COL_BLUE:
painter.setPen(QPen(Qt.blue, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.blue, Qt.SolidPattern)) # Fill
elif player2["color"] == evalgamepad.COL_GREEN:
elif player2.color == pgc.COL_GREEN:
painter.setPen(QPen(Qt.green, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.green, Qt.SolidPattern)) # Fill
elif player2["color"] == evalgamepad.COL_RED:
elif player2.color == pgc.COL_RED:
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine)) # Color/Linewidth/Pattern
painter.setBrush(QBrush(Qt.red, Qt.SolidPattern)) # Fill
elif player2["color"] == evalgamepad.COL_YELLOW:
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), int(player2.y), int(player2.w), int(player2.h)) # Player right
painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) # Reset standard colour
painter.setBrush(QBrush(Qt.white, Qt.SolidPattern))
#painter.drawText(10, 30, "x: {}".format(ball["x"]))
#painter.drawText(10, 40, "y: {}".format(ball["y"]))
#painter.drawText(10,50, "Player #1 delta_y: {}".format(player1["delta_y"]))
#painter.drawText(10,60, "Player #2 delta_y: {}".format(player2["delta_y"]))
# Game scores
painter.setFont(self.fntLarge)
# Score player #1
msg = str(player1["score"])
msg = str(player1.score)
msg_width = self.fm.width(msg)
painter.drawText(800 - msg_width, 154, "{}".format(player1["score"]))
painter.drawText(800 - msg_width, 154, "{}".format(msg))
# Score player #2
painter.drawText(evalgamepad.GAMEAREA_MAX_X-840, 154, "{}".format(player2["score"]))
painter.drawText(pgv.GAMEAREA_MAX_X - 840, 154, "{}".format(player2.score))
# Indicate Button states
draw_buttonstate(60, 50, player1, painter)
draw_buttonstate(evalgamepad.GAMEAREA_MAX_X - 180, 50, player2, painter)
elif game["state"] == evalgamepad.STATE_GAMERESULTS: # Display winner of this game
draw_buttonstate(pgv.GAMEAREA_MAX_X - 180, 50, player2, painter)
elif game.state == pgc.STATE_GAMERESULTS: # Display winner of this game
painter.setFont(self.fntMedium)
if player1["score"] > 9:
if player1.score > 9:
msg = "Game player #1"
else:
msg = "Game player #2"
painter.drawText(50, int(evalgamepad.GAMEAREA_MAX_Y / 2), msg)
elif game["state"] == evalgamepad.STATE_FINALRESULTS: # Display set winner
painter.drawText(50, int(pgv.GAMEAREA_MAX_Y / 2), msg)
elif game.state == pgc.STATE_FINALRESULTS: # Display set winner
painter.setFont(self.fntMedium)
if game["p1_game"] > 2:
if game.p1_game > 2:
msg = "Match player #1"
else:
msg = "Match player #2"
painter.drawText(50, int(evalgamepad.GAMEAREA_MAX_Y / 2), msg)
elif game["state"] == evalgamepad.STATE_EXIT: # Indicate good bye ...
painter.drawText(50, int(pgv.GAMEAREA_MAX_Y / 2), msg)
elif game.state == pgc.STATE_EXIT: # Indicate good bye ...
painter.setFont(self.fntMedium)
painter.drawText(50, int(evalgamepad.GAMEAREA_MAX_Y / 2), "Bye!")
painter.drawText(50, int(pgv.GAMEAREA_MAX_Y / 2), "Bye!")
@pyqtSlot()
@ -289,7 +186,7 @@ class pongWindow(QMainWindow):
self.timer.stop() # Block overrun
if pong_game(game, ball, player1, player2) == False:
if game.pong_game(ball, player1, player2) == False:
sys.exit(0)
self.update() # Redraw
@ -300,10 +197,10 @@ if __name__ == '__main__':
try:
# Initialize
random.seed()
game = evalgamepad.init_game()
ball = evalgamepad.init_object(evalgamepad.GAMEAREA_MAX_X/2, evalgamepad.GAMEAREA_MAX_Y/2, 20, 20, 8.0, 2.5)
player1 = evalgamepad.init_player(sys.argv[1], 10, evalgamepad.GAMEAREA_MAX_Y/2-50, 20, 160)
player2 = evalgamepad.init_player(sys.argv[2], evalgamepad.GAMEAREA_MAX_X-40, evalgamepad.GAMEAREA_MAX_Y/2-50, 20, 160)
game = PongGame()
ball = PongObject(pgv.GAMEAREA_MAX_X/2, pgv.GAMEAREA_MAX_Y/2, 20, 20, 8.0, 2.5)
player1 = PongPlayer(sys.argv[1], 10, pgv.GAMEAREA_MAX_Y/2-50, 20, 160)
player2 = PongPlayer(sys.argv[2], pgv.GAMEAREA_MAX_X-40, pgv.GAMEAREA_MAX_Y/2-50, 20, 160)
except IOError as e:
import errno
@ -320,7 +217,7 @@ if __name__ == '__main__':
rc = app.exec_() # & run logic
# Quit gracefully
evalgamepad.exit_player(player2)
evalgamepad.exit_player(player1)
player2.exit()
player1.exit()
sys.exit(rc)

10
pandemic_pong_client.py Normal file
View File

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

10
pandemic_pong_server.py Normal file
View File

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

38
pong_constants.py Normal file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
pong_constants.py
Pandemic Pong global constants
"""
"""Buttons in 'state<n>'"""
BTN_STATE_NONE = 0 # No Button pressed ...
BTN_TRIGGER = 1 # [Blue/X]
BTN_THUMB = 2 # [Red/A]
BTN_THUMB2 = 4 # [Yellow/B]
BTN_TOP = 8 # [Green/Y]
BTN_TOP2 = 16 # [Frontal left]
BTN_PINKIE = 32 # [Frontal right]
BTN_BASE3 = 64 # [Centre left]
BTN_BASE4 = 128 # [Centre right]
# Colors to be used
COL_WHITE = 0 # White = not infectious
COL_BLUE = 1 # Virus color
COL_GREEN = 2 # Virus color
COL_RED = 3 # Virus color
COL_YELLOW = 4 # virus color
"""Infectiousness time"""
COLORDELAY = 100
"""Game states"""
STATE_WELCOME = 0
STATE_START = 1
STATE_PLAY = 2
STATE_GAMERESULTS = 3
STATE_FINALRESULTS = 4
STATE_RESTART = 5
STATE_EXIT = 6

171
pong_game.py Normal file
View File

@ -0,0 +1,171 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
pong_game.py
Pandemic Pong Game Engine
"""
from random import random
from playsound import playsound
import pong_constants as pgc # Pong global constants
import pong_globalvars as pgv # Pong global variables
from pong_player import PongPlayer
from pong_object import PongObject
class PongGame:
def __init__(self):
self.state = pgc.STATE_WELCOME # State of game
self.delay = 100 # Automatically leave splash screen ...
self.p1_game = 0 # Results (reset)
self.p2_game = 0
def game_fsm(self, player1, player2):
"""Game engine state machine"""
if self.state == pgc.STATE_WELCOME:
self.delay = self.delay - 1
if self.delay < 1:
self.state = pgc.STATE_START
elif self.state == pgc.STATE_START: # Start new game
if (player1.state & pgc.BTN_BASE4) > 0 or (player2.state & pgc.BTN_BASE4) > 0: # [Start] pressed?
player1.reinit(10, pgv.GAMEAREA_MAX_Y/2-50, 0, 0)
player2.reinit(pgv.GAMEAREA_MAX_X-40, pgv.GAMEAREA_MAX_Y/2-50, 0, 0)
self.p1_game = 0
self.p2_game = 0
player1.score = 0
player2.score = 0
self.state = pgc.STATE_PLAY
elif self.state == pgc.STATE_PLAY: # Remain playing 'til 10 points
if player1.delay > 0: # Infectious time running?
player1.delay = player1.delay - 1 # Yap!
if player1.delay <= 0:
player1.color = pgc.COL_WHITE
player1.state = 0
if player2.delay > 0: # for both players ...
player2.delay = player2.delay - 1
if player2.delay <= 0:
player2.color = pgc.COL_WHITE
player2.state = 0
if player1.score > 9 or (player2.score > 9):
if player1.score > 9: # Figure out winner
self.p1_game = self.p1_game + 1 # & count game accordingly
else:
self.p2_game = self.p2_game + 1
self.delay = 100
self.state = pgc.STATE_GAMERESULTS
elif self.state == pgc.STATE_GAMERESULTS:
self.delay = self.delay - 1
if self.delay < 1:
if (self.p1_game > 2) or (self.p2_game > 2): # Set won?
self.state = pgc.STATE_FINALRESULTS # Yap!
else:
player1.score = 0
player2.score = 0
player1.reinit(10, pgv.GAMEAREA_MAX_Y/2-50, 0, 0)
player2.reinit(pgv.GAMEAREA_MAX_X-40, pgv.GAMEAREA_MAX_Y/2-50, 0, 0)
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):
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
return True
def crashvectors(self, ball, player1, player2):
"""Collission detection"""
if ball.delta_x < 0: # Ball moves right->left (<----)
if (ball.x <= player1.x + player1.w) and (ball.x > player1.x): # Left player #1 in range?
if ball.y + ball.h >= player1.y: # Ball lower than player upper bound?
if ball.y <= player1.y + player1.h: # Ball higher than player lower bound?
if ball.color == pgc.COL_WHITE:
ball.color = player1.color # Pick up 'infection' (if any)
elif ball.color != player1.color: # Infectious ball!
return # w/o vaccine -> no save!
ball.delta_x = -ball.delta_x * 1.2 # Invert direction & speed up
if player1.delta_y > 0.0: # Going downwards
if ball.delta_y > 0.0: # As well?
ball.delta_y = ball.delta_y * 1.2 # Increase angle
else:
ball.delta_y = ball.delta_y * 0.8 # Decrease angle
elif player1.delta_y < 0.0:
if ball.delta_y < 0.0: # As well?
ball.delta_y = ball.delta_y * 1.2 # Increase angle
else:
ball.delta_y = ball.delta_y * 0.8 # Decrease angle
playsound('/usr/share/mint-artwork/sounds/logout.ogg') # 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?
if ball.y + ball.h >= player2.y: # Ball lower than player upper bound?
if ball.y <= player2.y + player2.h: # Ball higher than player lower bound?
if ball.color == pgc.COL_WHITE:
ball.color = player2.color # Pick up 'infection' (if any)
elif ball.color != player2.color: # Infectious ball!
return # w/o vaccine -> no save!
ball.delta_x = -ball.delta_x * 1.2 # Invert direction & speed up
if player2.delta_y > 0.0: # Going downwards
if ball.delta_y > 0.0: # As well?
ball.delta_y = ball.delta_y * 1.2 # Increase angle
else:
ball.delta_y = ball.delta_y * 0.8 # Decrease angle
elif player2.delta_y < 0.0:
if ball.delta_y < 0.0: # As well?
ball.delta_y = ball.delta_y * 1.2 # Increase angle
else:
ball.delta_y = ball.delta_y * 0.8 # Decrease angle
playsound('/usr/share/mint-artwork/sounds/logout.ogg') # Enforce caching ...
def pong_game(self, ball, player1, player2):
if self.game_fsm(player1, player2) == False: # Exit
return False
# 1. Retrieve user entries
bChanged = player1.eval_gamepad()
bChanged = player2.eval_gamepad()
if self.state == pgc.STATE_PLAY: # Actually playing?
# 2. Adjust player positions
bChanged = player1.eval_position(pgv.GAMEAREA_MIN_X, pgv.GAMEAREA_MAX_X/2-50)
bChanged = player2.eval_position(pgv.GAMEAREA_MAX_X/2+50, pgv.GAMEAREA_MAX_X)
# 3. Crash analyses
self.crashvectors(ball, player1, player2)
# 4. Adjust object positions (ball & potentially others ...)
rc = ball.eval_object()
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')
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')
return True
if __name__ == "__main__":
print("pong_game has no function, call 'pandemic_pong.py'")

14
pong_globalvars.py Normal file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
pong_globalvars.py
Pandemic Pong global variables
"""
""" Game area dimensions, shall be mutable to adjust for window resize (later)"""
GAMEAREA_MIN_X = 0 # Game area left border
GAMEAREA_MAX_X = 1920 # Assume FHD resolution by default
GAMEAREA_MIN_Y = 15 # Game area top border
GAMEAREA_MAX_Y = 940 # Game area bottom range

69
pong_object.py Normal file
View File

@ -0,0 +1,69 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
pong_object.py
Pandemic Pong Objects logic (i.e. ball ;)
"""
from random import random # For random start data ...
from playsound import playsound # Play some sounds
import pong_constants as pgc # Pong global constants
import pong_globalvars as pgv # Pong global variables
class PongObject:
def __init__(self, x, y, w, h, delta_x, delta_y):
"""Initialize non-player object (i.e. 'ball' - but maybe more objects later!)"""
self.x = x # Current position
self.y = y
self.w = w # Size of object
self.h = h
self.delta_x = delta_x # Current movement
self.delta_y = (random() - 0.5) * 10 # TODO: Move logic to caller ...
self.color = pgc.COL_WHITE
self.delay = 0
def reinit(self, delta_x, delta_y):
"""Re-Initialize object for next game"""
self.x = pgv.GAMEAREA_MAX_X/2 - self.w/2
self.y = pgv.GAMEAREA_MAX_Y/2 - self.h/2
self.delta_x = delta_x
self.delta_y = delta_y
self.color = pgc.COL_WHITE
self.delay = 0
def eval_object(self):
"""Object movement w/ sound support"""
bChanged = 0
sum_x = self.x + self.delta_x
sum_y = self.y + self.delta_y
if sum_x < pgv.GAMEAREA_MIN_X:
#sum_x = GAMEAREA_MIN_X
#self.delta_x = -self.delta_x
bChanged = -1 # Miss left
elif sum_x + self.w > pgv.GAMEAREA_MAX_X:
#sum_x = GAMEAREA_MAX_X - self.w
#self.delta_x = -self.delta_x
bChanged = 1 # Miss right
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')
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')
self.x = sum_x
self.y = sum_y
return bChanged
if __name__ == "__main__":
print("***** pong_object has no function, call 'pandemic_pong.py'!")

175
pong_player.py Normal file
View File

@ -0,0 +1,175 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
pong_player.py
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
def print_event(e):
"""Sample from libevdev docs, useful for testing ..."""
print("Event: time {}.{:06d}, ".format(e.sec, e.usec), end='')
if e.matches(libevdev.EV_SYN):
if e.matches(libevdev.EV_SYN.SYN_MT_REPORT):
print("++++++++++++++ {} ++++++++++++".format(e.code.name))
elif e.matches(libevdev.EV_SYN.SYN_DROPPED):
print(">>>>>>>>>>>>>> {} >>>>>>>>>>>>".format(e.code.name))
else:
print("-------------- {} ------------".format(e.code.name))
else:
print("type {:02x} {} code {:03x} {:20s} value {:4d}".format(e.type.value, e.type.name, e.code.value, e.code.name, e.value))
class PongPlayer:
"""The player consists of gamepad input & variables"""
def __init__(self, path, x, y, w, h):
# Gamepad init.
self.fd = open(path, "rb") # File descriptor to close (later ...)
fcntl.fcntl(self.fd, fcntl.F_SETFL, os.O_NONBLOCK)
self.dev = libevdev.Device(self.fd) # Actual gamepad of this player
self.state = pgc.BTN_STATE_NONE # Button mask (as listed above)
self.x = x # Current position
self.y = y
self.w = w # Dimensions
self.h = h
self.delta_x = 0 # Current delta (speed) settings
self.delta_y = 0
self.color = pgc.COL_WHITE # 'Infection' colour (white = cleared)
self.delay = 0 # 'Infectious' time
self.score = 0 # Current score points of this player
def reinit(self, x, y, delta_x, delta_y):
"""Re-initialize player for next game"""
self.state = 0
self.x = x
self.y = y
self.delta_x = delta_x
self.delta_y = delta_y
self.color = pgc.COL_WHITE
self.delay = 0
def exit(self):
"""To quit gracefully, we should close the event queues ..."""
self.fd.close()
def eval_gamepad(self):
"""Decode gamepad events (if any ...)"""
bChanged = False
try:
for e in self.dev.events():
#print_event(e)
# Event type 1 (EV_KEY)
# Event code 288 (BTN_TRIGGER) <- 1=[Blue/X]
# Event code 289 (BTN_THUMB) <- 1=[Red/A]
# Event code 290 (BTN_THUMB2) <- 1=[Yellow/B]
# Event code 291 (BTN_TOP) <- 1=[Green/Y]
# Event code 292 (BTN_TOP2) <- 1=[Frontal left]
# Event code 293 (BTN_PINKIE) <- 1=[Frontal right]
# Event code 294 (BTN_BASE)
# Event code 295 (BTN_BASE2)
# Event code 296 (BTN_BASE3) <- 1=[Centre left]
# Event code 297 (BTN_BASE4) <- 1=[Centre right]
if e.type.value == 1: # Non-Cross events
if e.value == 1: # Simple buttons may act as toggles
if e.code.value == 288: # BTN_TRIGGER
if self.delay <= 0: # As long as we're not infectious ...
self.state = pgc.BTN_TRIGGER # self.state ^ pgc.BTN_TRIGGER
self.color = pgc.COL_BLUE # Infect 'blue'
self.delay = pgc.COLORDELAY # Start infectious time immediately ...
elif e.code.value == 289: # BTN_THUMB
if self.delay <= 0: # As long as we're not infectious ...
self.state = pgc.BTN_THUMB # self.state ^ pgc.BTN_THUMB
self.color = pgc.COL_RED
self.delay = pgc.COLORDELAY
elif e.code.value == 290: # BTN_THUMB2
if self.delay <= 0: # As long as we're not infectious ...
self.state = pgc.BTN_THUMB2 # self.state ^ pgc.BTN_THUMB2
self.color = pgc.COL_YELLOW
self.delay = pgc.COLORDELAY
elif e.code.value == 291: # BTN_TOP
if self.delay <= 0: # As long as we're not infectious ...
self.state = pgc.BTN_TOP # self.state ^ pgc.BTN_TOP
self.color = pgc.COL_GREEN
self.delay = pgc.COLORDELAY
elif e.code.value == 292: # BTN_TOP2
self.state = self.state ^ pgc.BTN_TOP2
elif e.code.value == 293: # BTN_PINKIE
self.state = self.state ^ pgc.BTN_PINKIE
elif e.code.value == 296: # BTN_BASE3
self.state = self.state ^ pgc.BTN_BASE3
elif e.code.value == 297: # BTN_BASE4
self.state = self.state ^ pgc.BTN_BASE4
bChanged = True
# Event type 3 (EV_ABS)
# Event code 0 (ABS_X) <- Cross: 127=Neutral, 0=[Left], 255=[Right]
# Event code 1 (ABS_Y) <- Cross: 127=Neutral, 0=[Top], 255=[Down]
elif e.type.value == 3: # EV_ABS
if e.code.value == 0: # ABS_X
if e.value == 0:
self.delta_x = self.delta_x - 1
elif e.value == 255:
self.delta_x = self.delta_x + 1
else: # 127/Neutral
self.delta_x = 0
else: # ABS_Y
if e.value == 0:
self.delta_y = self.delta_y - 1
elif e.value == 255:
self.delta_y = self.delta_y + 1
else: # 127/Neutral
self.delta_y = 0
bChanged = True
#if bChanged:
# print("State=",self.state, "X=", self.delta_x, "Y=", self.delta_y)
except libevdev.EventsDroppedException:
print("Dropped!")
for e in self.dev.sync():
print_event(e)
return bChanged
def eval_position(self, min_x, max_x):
"""Player movement w/ area restrictions"""
bChanged = False
# Left/right positioning
sum_x = self.x + self.delta_x * 10
if sum_x < min_x:
sum_x = min_x
elif sum_x + self.w > max_x:
sum_x = max_x - self.w
# Top/bottom positioning
sum_y = self.y + self.delta_y * 10
if sum_y < pgv.GAMEAREA_MIN_Y:
sum_y = pgv.GAMEAREA_MIN_Y
elif sum_y + self.h > pgv.GAMEAREA_MAX_Y:
sum_y = pgv.GAMEAREA_MAX_Y - self.h
# Movement indication (TODO: may be removed later ...)
if (sum_x != self.x) or (sum_y != self.y):
bChanged = True
self.x = sum_x
self.y = sum_y
return bChanged
if __name__ == "__main__":
print("***** pong_player has no function, call 'pandemic_pong.py'!")