A gamepad usage example
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Pandemic_Pong/evalgamepad.py

267 lines
9.2 KiB

#!/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
import libevdev
# 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 = 0
GAMEAREA_MAX_Y = 1080
def init_player(path):
# 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,
"x" : GAMEAREA_MAX_X/2, # Current actual position
"y" : GAMEAREA_MAX_Y/2, # Start at center
"w" : 10,
"h" : 100
}
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" : delta_y,
"x" : x, # Current position
"y" : y,
"w" : w, # Size of object
"h" : h,
}
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
player["state"] = player["state"] ^ BTN_TRIGGER
elif e.code.value == 289: # BTN_THUMB
player["state"] = player["state"] ^ BTN_THUMB
elif e.code.value == 290: # BTN_THUMB2
player["state"] = player["state"] ^ BTN_THUMB2
elif e.code.value == 291: # BTN_TOP
player["state"] = player["state"] ^ BTN_TOP
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):
bChanged = False
sum_x = player["x"] + player["delta_x"]/255
sum_y = player["y"] + player["delta_y"]/255
if sum_x < GAMEAREA_MIN_X:
sum_x = GAMEAREA_MIN_X
elif sum_x + player["w"] > GAMEAREA_MAX_X:
sum_x = GAMEAREA_MAX_X - player["w"]
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):
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"]
elif sum_x + obj["w"] > GAMEAREA_MAX_X:
sum_x = GAMEAREA_MAX_X - obj["w"]
obj["delta_x"] = -obj["delta_x"]
if sum_y < GAMEAREA_MIN_Y:
sum_y = GAMEAREA_MIN_Y
obj["delta_y"] = -obj["delta_y"]
elif sum_y + obj["h"] > GAMEAREA_MAX_Y:
sum_y = GAMEAREA_MAX_Y - obj["h"]
obj["delta_y"] = -obj["delta_y"]
obj["x"] = sum_x
obj["y"] = sum_y
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
else:
print("Player #1: {}h".format(hex(player1["state"])))
bChanged = eval_gamepad(player2) # Exit?
if bChanged:
if (player2["state"] & BTN_BASE4) > 0:
print("Player #2 aborted game")
break
else:
print("Player #2: {}h".format(hex(player2["state"])))
# 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)
def init_gamearea(): # Create base playground
pass
def main(args):
try:
# Initialize
init_gamearea()
ball = init_object(10, 10, 15, 15, 2.0, 1.5)
player1 = init_player(args[1])
player2 = init_player(args[2])
# 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)