PS4 控制器 - 值为 1 时光标不移动
PS4 Controller - Cursor not moving when value is 1
我试图编写程序来用我的 PS4 控制器控制我的鼠标,一切正常,我得到了数据,我可以相应地移动我的鼠标。但是,当我将操纵杆固定在任何轴上时,鼠标不会移动,不仅在我按住它时发生,而且在操纵杆值不变时也会发生。有什么办法可以解决这个问题吗?
import pygame
import os
import pyautogui
pygame.init()
pygame.joystick.init
j = pygame.joystick.Joystick(0)
j.init()
data = {}
while True:
for event in pygame.event.get():
if event.type == pygame.JOYAXISMOTION:
data[event.axis] = round(event.value, 2)
if event.type == pygame.JOYBUTTONUP:
data["test"] = "letsgoooo"
if event.type == pygame.JOYBUTTONDOWN:
if "test" in data:
del data["test"]
if 0 in data and 1 in data:
if data[0] > 0.08:
pyautogui.move(5, 0, 0.1)
if data[0] < -0.08:
pyautogui.move(-5, 0, 0.1)
if data[1] > 0.08:
pyautogui.move(0, 10, 0.1)
if data[1] < -0.08:
pyautogui.move(0, -10, 0.1)
if 0 in data and 1 in data and 2 in data and 3 in data and 4 in data and 5 in data:
os.system('cls')
print(f"Left:\nX = {data[0]}, Y = {data[1]}")
print(f"Right:\nX = {data[2]}, Y = {data[3]}")
print(f"Left trigger = {data[5]}, Right trigger = {data[4]}")
print(f"Mouse: X = {pyautogui.position()[0]}, Y = {pyautogui.position()[1]}")
print(data)
else:
print("Move your joystick")
操纵杆发送更新事件。我猜有点像鼠标,如果它没有发出事件,你必须假设鼠标没有改变位置。操纵杆事件是相同的,如果操纵杆说它在 0.753
并且此后没有发生任何事件,那么在那个角度它仍然是 still。
所以你的移动代码需要记住最近的轴值,并将其用作摇杆的当前位置。当一个新事件到来时,你就更新这个值,否则就不会。这样,摇杆就会定位到“完全锁定”(例如:100% 左),无论操纵杆每帧移动的最大量是多少,您都可以继续重新定位。
PS4控制器上的左方向键盘是一个PyGame“帽子”,所以不会产生事件,你必须独立查询它。无论出于何种原因,上下似乎都会产生与正常人所期望的相反的值(无论如何在撰写本文时)。
我制作了一些示例代码,可以在 window 周围移动 3 个十字准线 (sp?)。每根棍子一个,帽子一个。它还将显示按下了哪些按钮。该代码可能需要重新组织。我不喜欢必须将帽子与粘性事件等分开处理的方式。但它很好地展示了它们如何组合在一起。
哦,左右触发器也是单轴操纵杆,但除了 pass
事件之外,我并没有在代码中对它们做太多处理。
import pygame
# Window size
WINDOW_WIDTH = 600
WINDOW_HEIGHT = 600
WINDOW_SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF
DARK_BLUE = ( 3, 5, 54 )
YELLOWISH = ( 255, 245, 145 )
class PS4Joystick:
""" Class that knows about PS4 Controller Buttons, etc. """
BUTTON_CROSS = 0
BUTTON_CIRCLE = 1
BUTTON_TRIANGLE= 2
BUTTON_SQUARE = 3
BUTTON_L1 = 4
BUTTON_R1 = 5
BUTTON_L2 = 6
BUTTON_R2 = 7
BUTTON_SHARE = 8
BUTTON_OPTIONS = 9
BUTTON_PS = 10
AXIS_LEFT_RIGHT = 1
AXIS_UP_DOWN = 2
AXIS_LTRIGGER = 3
AXIS_RTRIGGER = 4
STICK_LEFT = 1
STICK_RIGHT = 2
STICK_LTRIGGER = 3
STICK_RTRIGGER = 4
#PS4ButtNames = [ '⨯', '○', '△', '□', 'L1', 'R1', 'L2', 'R2', 'Share', 'Options', 'PS' ]
PS4ButtNames = [ 'eX', 'Oh', 'Pointy', 'Square', 'L1', 'R1', 'L2', 'R2', 'Share', 'Options', 'PS' ]
PS4AxisNames = [ 'Left E/W', 'Left N/S', 'Left Trig', 'Right E/W', 'Right N/S', 'Right Trig' ]
PS4AxisDir = [ AXIS_LEFT_RIGHT, AXIS_UP_DOWN, AXIS_LTRIGGER, AXIS_LEFT_RIGHT, AXIS_UP_DOWN, AXIS_RTRIGGER ]
@staticmethod
def buttonName( butt_index ):
""" Convert the button index to human-readable name """
if ( butt_index >= 0 and butt_index < len( PS4Joystick.PS4ButtNames ) ):
return PS4Joystick.PS4ButtNames[ butt_index ]
else:
return None # error
@staticmethod
def axisName( axis_index ):
""" Convert the axis index to human-readable name """
if ( axis_index >= 0 and axis_index < len( PS4Joystick.PS4AxisNames ) ):
return PS4Joystick.PS4AxisNames[ axis_index ]
else:
return None # error
@staticmethod
def axisDirection( axis_index ):
""" Convert the axis index to x/y indicator """
if ( axis_index >= 0 and axis_index < len( PS4Joystick.PS4AxisDir ) ):
return PS4Joystick.PS4AxisDir[ axis_index ]
else:
return None # error
@staticmethod
def getStick( axis_index ):
""" Given an axis, work out if it's from the left or right stick """
if ( axis_index == 0 or axis_index == 1):
return PS4Joystick.STICK_LEFT
elif ( axis_index == 3 or axis_index == 4 ):
return PS4Joystick.STICK_RIGHT
elif ( axis_index == 2 ):
return PS4Joystick.STICK_LTRIGGER
elif ( axis_index == 5 ):
return PS4Joystick.STICK_RTRIGGER
else:
return None # error
class CursorSprite( pygame.sprite.Sprite ):
SIZE = 48
SPEED = 5
def __init__( self, colour=( 255, 245, 145 ) ):
pygame.sprite.Sprite.__init__( self )
self.image = pygame.Surface( ( self.SIZE, self.SIZE ), pygame.SRCALPHA )
self.rect = self.image.get_rect( center = ( WINDOW_WIDTH//2, WINDOW_HEIGHT//2 ) )
# Make a centred '+'
pygame.draw.line( self.image, colour, ( self.SIZE//2, 0 ), ( self.SIZE//2, self.SIZE ), 3 )
pygame.draw.line( self.image, colour, ( 0, self.SIZE//2 ), ( self.SIZE, self.SIZE//2 ), 3 )
def move( self, joy_x, joy_y ):
# Joystick events are
self.rect.x += round( joy_x * self.SPEED )
self.rect.y += round( joy_y * self.SPEED )
### initialisation
pygame.init()
pygame.font.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption( "PS4 Joystick Demo" )
### Joystick(s) initialisation
joystick_count = pygame.joystick.get_count()
print( "Initialising %d Joystick(s)" % ( joystick_count ) )
for i in range( joystick_count ):
joystick = pygame.joystick.Joystick(i)
joystick.init()
print( "Joystick %d:" % ( i ) )
print( " name ........... [%s]" % ( joystick.get_name() ) )
print( " axis count ..... [%d]" % ( joystick.get_numaxes() ) )
print( " button count ... [%d]" % ( joystick.get_numbuttons() ) )
print( " hat count ...... [%d]" % ( joystick.get_numhats() ) )
# Just deal with Joystick 0 for now
joystick = pygame.joystick.Joystick( 0 )
left_stick_val_horiz = 0
left_stick_val_vert = 0
right_stick_val_horiz = 0
right_stick_val_vert = 0
hat_val_horiz = 0
hat_val_vert = 0
# cursor to show movement
sprite_group = pygame.sprite.Group()
cursor_sprite_left = CursorSprite( ( 255, 50, 50 ) )
cursor_sprite_right = CursorSprite( ( 50, 255, 50 ) )
cursor_sprite_hat = CursorSprite( ( 50, 55, 255 ) )
sprite_group.add( cursor_sprite_left )
sprite_group.add( cursor_sprite_right )
sprite_group.add( cursor_sprite_hat )
button_text = ''
### Main Loop
clock = pygame.time.Clock()
font = pygame.font.Font( 'Arial_Bold.ttf', 24 )
done = False
while not done:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
# Button pushed
elif ( event.type == pygame.JOYBUTTONDOWN ):
button_name = PS4Joystick.buttonName( event.button )
button_text += ' ' + button_name
print( "Button %s pressed" % ( button_name ) )
# Button released
elif ( event.type == pygame.JOYBUTTONUP ):
button_name = PS4Joystick.buttonName( event.button )
button_text = button_text.replace( ' ' + button_name, '' )
print( "Button %s released" % ( button_name ) )
# Position update form PS4-stick(s)
elif ( event.type == pygame.JOYAXISMOTION ):
stick = PS4Joystick.getStick( event.axis )
axis = PS4Joystick.axisDirection( event.axis )
#name = PS4Joystick.axisName( event.axis )
if ( stick == PS4Joystick.STICK_LEFT ):
if ( axis == PS4Joystick.AXIS_LEFT_RIGHT ):
left_stick_val_horiz = event.value
else:
left_stick_val_vert = event.value
elif ( stick == PS4Joystick.STICK_RIGHT ):
if ( axis == PS4Joystick.AXIS_LEFT_RIGHT ):
right_stick_val_horiz = event.value
else:
right_stick_val_vert = event.value
# The left and right triggers are also relative-positioned sticks
elif ( stick == PS4Joystick.STICK_LTRIGGER ):
pass
elif ( stick == PS4Joystick.STICK_RTRIGGER ):
pass
#if ( event.value > 0.01 or event.value < -0.01 ):
#print( "AXIS: %s=%6.8f" % ( name, event.value ) )
# The Joystick "Hat" is not handled via events
if ( joystick.get_numhats() > 0 ):
hat_vals = joystick.get_hat( 0 )
hat_val_horiz = hat_vals[0]
hat_val_vert = -hat_vals[1] # up/down reversed for some reason
# Update the on-screen tracker cursors
cursor_sprite_left.move( left_stick_val_horiz, left_stick_val_vert )
cursor_sprite_right.move( right_stick_val_horiz, right_stick_val_vert )
cursor_sprite_hat.move( hat_val_horiz, hat_val_vert )
# Update the window, but not more than 60fps
window.fill( DARK_BLUE )
if ( len( button_text ) > 0 ):
button_display = font.render( button_text+' ', True, DARK_BLUE, YELLOWISH )
window.blit( button_display, ( 50, WINDOW_HEIGHT-50-button_display.get_height() ) )
sprite_group.update()
sprite_group.draw( window )
pygame.display.flip()
# Clamp FPS
clock.tick_busy_loop(60)
pygame.quit()
我试图编写程序来用我的 PS4 控制器控制我的鼠标,一切正常,我得到了数据,我可以相应地移动我的鼠标。但是,当我将操纵杆固定在任何轴上时,鼠标不会移动,不仅在我按住它时发生,而且在操纵杆值不变时也会发生。有什么办法可以解决这个问题吗?
import pygame
import os
import pyautogui
pygame.init()
pygame.joystick.init
j = pygame.joystick.Joystick(0)
j.init()
data = {}
while True:
for event in pygame.event.get():
if event.type == pygame.JOYAXISMOTION:
data[event.axis] = round(event.value, 2)
if event.type == pygame.JOYBUTTONUP:
data["test"] = "letsgoooo"
if event.type == pygame.JOYBUTTONDOWN:
if "test" in data:
del data["test"]
if 0 in data and 1 in data:
if data[0] > 0.08:
pyautogui.move(5, 0, 0.1)
if data[0] < -0.08:
pyautogui.move(-5, 0, 0.1)
if data[1] > 0.08:
pyautogui.move(0, 10, 0.1)
if data[1] < -0.08:
pyautogui.move(0, -10, 0.1)
if 0 in data and 1 in data and 2 in data and 3 in data and 4 in data and 5 in data:
os.system('cls')
print(f"Left:\nX = {data[0]}, Y = {data[1]}")
print(f"Right:\nX = {data[2]}, Y = {data[3]}")
print(f"Left trigger = {data[5]}, Right trigger = {data[4]}")
print(f"Mouse: X = {pyautogui.position()[0]}, Y = {pyautogui.position()[1]}")
print(data)
else:
print("Move your joystick")
操纵杆发送更新事件。我猜有点像鼠标,如果它没有发出事件,你必须假设鼠标没有改变位置。操纵杆事件是相同的,如果操纵杆说它在 0.753
并且此后没有发生任何事件,那么在那个角度它仍然是 still。
所以你的移动代码需要记住最近的轴值,并将其用作摇杆的当前位置。当一个新事件到来时,你就更新这个值,否则就不会。这样,摇杆就会定位到“完全锁定”(例如:100% 左),无论操纵杆每帧移动的最大量是多少,您都可以继续重新定位。
PS4控制器上的左方向键盘是一个PyGame“帽子”,所以不会产生事件,你必须独立查询它。无论出于何种原因,上下似乎都会产生与正常人所期望的相反的值(无论如何在撰写本文时)。
我制作了一些示例代码,可以在 window 周围移动 3 个十字准线 (sp?)。每根棍子一个,帽子一个。它还将显示按下了哪些按钮。该代码可能需要重新组织。我不喜欢必须将帽子与粘性事件等分开处理的方式。但它很好地展示了它们如何组合在一起。
哦,左右触发器也是单轴操纵杆,但除了 pass
事件之外,我并没有在代码中对它们做太多处理。
import pygame
# Window size
WINDOW_WIDTH = 600
WINDOW_HEIGHT = 600
WINDOW_SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF
DARK_BLUE = ( 3, 5, 54 )
YELLOWISH = ( 255, 245, 145 )
class PS4Joystick:
""" Class that knows about PS4 Controller Buttons, etc. """
BUTTON_CROSS = 0
BUTTON_CIRCLE = 1
BUTTON_TRIANGLE= 2
BUTTON_SQUARE = 3
BUTTON_L1 = 4
BUTTON_R1 = 5
BUTTON_L2 = 6
BUTTON_R2 = 7
BUTTON_SHARE = 8
BUTTON_OPTIONS = 9
BUTTON_PS = 10
AXIS_LEFT_RIGHT = 1
AXIS_UP_DOWN = 2
AXIS_LTRIGGER = 3
AXIS_RTRIGGER = 4
STICK_LEFT = 1
STICK_RIGHT = 2
STICK_LTRIGGER = 3
STICK_RTRIGGER = 4
#PS4ButtNames = [ '⨯', '○', '△', '□', 'L1', 'R1', 'L2', 'R2', 'Share', 'Options', 'PS' ]
PS4ButtNames = [ 'eX', 'Oh', 'Pointy', 'Square', 'L1', 'R1', 'L2', 'R2', 'Share', 'Options', 'PS' ]
PS4AxisNames = [ 'Left E/W', 'Left N/S', 'Left Trig', 'Right E/W', 'Right N/S', 'Right Trig' ]
PS4AxisDir = [ AXIS_LEFT_RIGHT, AXIS_UP_DOWN, AXIS_LTRIGGER, AXIS_LEFT_RIGHT, AXIS_UP_DOWN, AXIS_RTRIGGER ]
@staticmethod
def buttonName( butt_index ):
""" Convert the button index to human-readable name """
if ( butt_index >= 0 and butt_index < len( PS4Joystick.PS4ButtNames ) ):
return PS4Joystick.PS4ButtNames[ butt_index ]
else:
return None # error
@staticmethod
def axisName( axis_index ):
""" Convert the axis index to human-readable name """
if ( axis_index >= 0 and axis_index < len( PS4Joystick.PS4AxisNames ) ):
return PS4Joystick.PS4AxisNames[ axis_index ]
else:
return None # error
@staticmethod
def axisDirection( axis_index ):
""" Convert the axis index to x/y indicator """
if ( axis_index >= 0 and axis_index < len( PS4Joystick.PS4AxisDir ) ):
return PS4Joystick.PS4AxisDir[ axis_index ]
else:
return None # error
@staticmethod
def getStick( axis_index ):
""" Given an axis, work out if it's from the left or right stick """
if ( axis_index == 0 or axis_index == 1):
return PS4Joystick.STICK_LEFT
elif ( axis_index == 3 or axis_index == 4 ):
return PS4Joystick.STICK_RIGHT
elif ( axis_index == 2 ):
return PS4Joystick.STICK_LTRIGGER
elif ( axis_index == 5 ):
return PS4Joystick.STICK_RTRIGGER
else:
return None # error
class CursorSprite( pygame.sprite.Sprite ):
SIZE = 48
SPEED = 5
def __init__( self, colour=( 255, 245, 145 ) ):
pygame.sprite.Sprite.__init__( self )
self.image = pygame.Surface( ( self.SIZE, self.SIZE ), pygame.SRCALPHA )
self.rect = self.image.get_rect( center = ( WINDOW_WIDTH//2, WINDOW_HEIGHT//2 ) )
# Make a centred '+'
pygame.draw.line( self.image, colour, ( self.SIZE//2, 0 ), ( self.SIZE//2, self.SIZE ), 3 )
pygame.draw.line( self.image, colour, ( 0, self.SIZE//2 ), ( self.SIZE, self.SIZE//2 ), 3 )
def move( self, joy_x, joy_y ):
# Joystick events are
self.rect.x += round( joy_x * self.SPEED )
self.rect.y += round( joy_y * self.SPEED )
### initialisation
pygame.init()
pygame.font.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption( "PS4 Joystick Demo" )
### Joystick(s) initialisation
joystick_count = pygame.joystick.get_count()
print( "Initialising %d Joystick(s)" % ( joystick_count ) )
for i in range( joystick_count ):
joystick = pygame.joystick.Joystick(i)
joystick.init()
print( "Joystick %d:" % ( i ) )
print( " name ........... [%s]" % ( joystick.get_name() ) )
print( " axis count ..... [%d]" % ( joystick.get_numaxes() ) )
print( " button count ... [%d]" % ( joystick.get_numbuttons() ) )
print( " hat count ...... [%d]" % ( joystick.get_numhats() ) )
# Just deal with Joystick 0 for now
joystick = pygame.joystick.Joystick( 0 )
left_stick_val_horiz = 0
left_stick_val_vert = 0
right_stick_val_horiz = 0
right_stick_val_vert = 0
hat_val_horiz = 0
hat_val_vert = 0
# cursor to show movement
sprite_group = pygame.sprite.Group()
cursor_sprite_left = CursorSprite( ( 255, 50, 50 ) )
cursor_sprite_right = CursorSprite( ( 50, 255, 50 ) )
cursor_sprite_hat = CursorSprite( ( 50, 55, 255 ) )
sprite_group.add( cursor_sprite_left )
sprite_group.add( cursor_sprite_right )
sprite_group.add( cursor_sprite_hat )
button_text = ''
### Main Loop
clock = pygame.time.Clock()
font = pygame.font.Font( 'Arial_Bold.ttf', 24 )
done = False
while not done:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
# Button pushed
elif ( event.type == pygame.JOYBUTTONDOWN ):
button_name = PS4Joystick.buttonName( event.button )
button_text += ' ' + button_name
print( "Button %s pressed" % ( button_name ) )
# Button released
elif ( event.type == pygame.JOYBUTTONUP ):
button_name = PS4Joystick.buttonName( event.button )
button_text = button_text.replace( ' ' + button_name, '' )
print( "Button %s released" % ( button_name ) )
# Position update form PS4-stick(s)
elif ( event.type == pygame.JOYAXISMOTION ):
stick = PS4Joystick.getStick( event.axis )
axis = PS4Joystick.axisDirection( event.axis )
#name = PS4Joystick.axisName( event.axis )
if ( stick == PS4Joystick.STICK_LEFT ):
if ( axis == PS4Joystick.AXIS_LEFT_RIGHT ):
left_stick_val_horiz = event.value
else:
left_stick_val_vert = event.value
elif ( stick == PS4Joystick.STICK_RIGHT ):
if ( axis == PS4Joystick.AXIS_LEFT_RIGHT ):
right_stick_val_horiz = event.value
else:
right_stick_val_vert = event.value
# The left and right triggers are also relative-positioned sticks
elif ( stick == PS4Joystick.STICK_LTRIGGER ):
pass
elif ( stick == PS4Joystick.STICK_RTRIGGER ):
pass
#if ( event.value > 0.01 or event.value < -0.01 ):
#print( "AXIS: %s=%6.8f" % ( name, event.value ) )
# The Joystick "Hat" is not handled via events
if ( joystick.get_numhats() > 0 ):
hat_vals = joystick.get_hat( 0 )
hat_val_horiz = hat_vals[0]
hat_val_vert = -hat_vals[1] # up/down reversed for some reason
# Update the on-screen tracker cursors
cursor_sprite_left.move( left_stick_val_horiz, left_stick_val_vert )
cursor_sprite_right.move( right_stick_val_horiz, right_stick_val_vert )
cursor_sprite_hat.move( hat_val_horiz, hat_val_vert )
# Update the window, but not more than 60fps
window.fill( DARK_BLUE )
if ( len( button_text ) > 0 ):
button_display = font.render( button_text+' ', True, DARK_BLUE, YELLOWISH )
window.blit( button_display, ( 50, WINDOW_HEIGHT-50-button_display.get_height() ) )
sprite_group.update()
sprite_group.draw( window )
pygame.display.flip()
# Clamp FPS
clock.tick_busy_loop(60)
pygame.quit()