87 lines
2.7 KiB
Python
87 lines
2.7 KiB
Python
import pygame
|
||
import math
|
||
|
||
pygame.init()
|
||
pygame.joystick.init()
|
||
|
||
if pygame.joystick.get_count() == 0:
|
||
raise SystemExit("No controller detected. Plug in DualSense via USB first (recommended).")
|
||
|
||
js = pygame.joystick.Joystick(0)
|
||
js.init()
|
||
|
||
W, H = 900, 500
|
||
screen = pygame.display.set_mode((W, H))
|
||
pygame.display.set_caption(f"Controller Visualizer: {js.get_name()}")
|
||
clock = pygame.time.Clock()
|
||
font = pygame.font.SysFont(None, 24)
|
||
|
||
def clamp01(x): return max(0.0, min(1.0, x))
|
||
|
||
def draw_text(x, y, s):
|
||
screen.blit(font.render(s, True, (230, 230, 230)), (x, y))
|
||
|
||
def draw_stick(cx, cy, r, x, y, label):
|
||
# x,y expected in [-1,1]
|
||
pygame.draw.circle(screen, (80,80,80), (cx, cy), r, 2)
|
||
px = int(cx + x * (r - 6))
|
||
py = int(cy + y * (r - 6))
|
||
pygame.draw.circle(screen, (200,200,200), (px, py), 6)
|
||
draw_text(cx - r, cy + r + 8, f"{label}: x={x:+.2f} y={y:+.2f}")
|
||
|
||
def draw_bar(x, y, w, h, v, label):
|
||
# v in [0,1]
|
||
pygame.draw.rect(screen, (80,80,80), (x,y,w,h), 2)
|
||
fill = int(w * clamp01(v))
|
||
pygame.draw.rect(screen, (200,200,200), (x,y,fill,h))
|
||
draw_text(x, y - 22, f"{label}: {v:.2f}")
|
||
|
||
def draw_button(x, y, on, label):
|
||
col = (70,200,90) if on else (100,100,100)
|
||
pygame.draw.circle(screen, col, (x, y), 14)
|
||
draw_text(x + 22, y - 10, label)
|
||
|
||
# Axis indices vary by OS/driver. We’ll read a bunch and print them.
|
||
print("Axes:", js.get_numaxes(), "Buttons:", js.get_numbuttons(), "Hats:", js.get_numhats())
|
||
|
||
running = True
|
||
while running:
|
||
for e in pygame.event.get():
|
||
if e.type == pygame.QUIT:
|
||
running = False
|
||
|
||
pygame.event.pump()
|
||
screen.fill((20, 20, 24))
|
||
|
||
# Common mappings (may differ):
|
||
lx = js.get_axis(0)
|
||
ly = js.get_axis(1)
|
||
rx = js.get_axis(2) if js.get_numaxes() > 2 else 0.0
|
||
ry = js.get_axis(3) if js.get_numaxes() > 3 else 0.0
|
||
|
||
# Triggers sometimes appear as axes, sometimes buttons; try axes 4/5 if present:
|
||
lt = (js.get_axis(4) + 1) / 2 if js.get_numaxes() > 4 else 0.0
|
||
rt = (js.get_axis(5) + 1) / 2 if js.get_numaxes() > 5 else 0.0
|
||
|
||
draw_stick(200, 220, 90, lx, ly, "Left stick")
|
||
draw_stick(450, 220, 90, rx, ry, "Right stick")
|
||
draw_bar(650, 150, 200, 24, lt, "L2")
|
||
draw_bar(650, 220, 200, 24, rt, "R2")
|
||
|
||
# Buttons (indices vary). We'll show first 12 if present:
|
||
for i in range(min(12, js.get_numbuttons())):
|
||
on = bool(js.get_button(i))
|
||
draw_button(650 + (i % 6) * 40, 300 + (i // 6) * 50, on, str(i))
|
||
|
||
# Hat (D-pad)
|
||
if js.get_numhats() > 0:
|
||
hx, hy = js.get_hat(0)
|
||
draw_text(650, 400, f"D-pad (hat0): {hx},{hy}")
|
||
|
||
draw_text(20, 20, f"Device: {js.get_name()}")
|
||
draw_text(20, 46, "Tip: If axes look wrong, mapping differs on your OS. USB is easiest.")
|
||
|
||
pygame.display.flip()
|
||
clock.tick(60)
|
||
|
||
pygame.quit()
|