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()