Files
autopon/patapon.py
2025-01-30 03:01:47 -06:00

89 lines
3.0 KiB
Python
Executable File

#! /usr/bin/env python3
import argparse
import subprocess
import time
def ydotool(key):
subprocess.run([
"ydotool",
"type",
str(key)
])
def main():
# A list of all possible songs, expressed as their cardinal directions
# We'll map these to keystrokes later
songs = [
# March of Mobility
"L-L-L-R-",
# Aria of Attack
"R-R-L-R-",
# Lament of Defense
"U-U-L-R-",
# Hold-Tight Hoe-Down/Concerto of Charge
"R-R-U-U-",
# Melody with a Bounce/Jingle of Jump
"D-D-U-U-",
# Ballad of 1999/Pizzicato of Party
"L-R-D-U-",
# Song of Miracles (Djinn)
"D-DD-DD-",
# Leisurely Lullaby
# Not sure why you'd want to cast this on repeat, but you can I guess
"L-R-L-R-",
# Step Back Strut
"U-L-U-L-"
]
# A mapping of characters in our encoded songs to keys to send to ydotool
# These should be the default bindings for PPSSPP
keymapping = {
"U": "s",
"D": "z",
"L": "a",
"R": "x"
}
drummapping = {
"U": '\033[32mCHAKA\033[0m',
"D": '\033[33mDON\033[0m',
"L": '\033[31mPATA\033[0m',
"R": '\033[34mPON\033[0m'
}
parser = argparse.ArgumentParser(
description="Play a sequence of Patapon commands on repeat forever"
)
parser.add_argument('song',default="R-R-L-R-",nargs="+",choices=songs,help="The song to play. Defaults to Aria of Attack. When expressing a song, use eighth notes, dashes, and cardinal directions to designate the drums. For example, party would be \"L-R-D-U-\", and djinn would be \"D-DD-DD-\"")
parser.add_argument('--bpm',type=int,default=120,help="The BPM of Patapon. Change if you're running the game at a higher speed")
parser.add_argument('--iterations',type=int,default=10000,help="Number of iterations of the sequence to run. Defaults to 10,000")
args = parser.parse_args()
# Schedule out our beat interval
beat_interval = 60 / (args.bpm * 2)
print(f"Beat interval: {beat_interval}")
# Set up the environment
sequence='--------' + '--------'.join(args.song)
print(f"Song sequence: {sequence}")
remaining_iterations = args.iterations
lastbeat = 0
# Wait for user confirmation
input("Press enter on-beat to sync up with Patapon...")
synctime = time.perf_counter()
# Play da notes
while remaining_iterations > 0:
for i, key in enumerate(sequence):
while time.perf_counter() < synctime + lastbeat:
pass
lastbeat += beat_interval
button = keymapping.get(key, '-')
if button != '-':
ydotool(button)
print(drummapping.get(key, '-'), end="", flush=True)
else:
print(" ", end="", flush=True)
remaining_iterations -= 1
print(f"~ ({remaining_iterations} remaining)")
main()