python - 通过将操纵杆值发送到数组来通过套接字流式传输 pygame 操纵杆输入
问题描述
我正在尝试构建一个机器人,它将通过在 python 中使用套接字和操纵杆来控制。我一直在尝试将 Pygame 示例代码中的操纵杆读数发送到一个数组中,但是当我打印数组时,我在移动轴并按下按钮后得到了空白值。这些值出现在数组之外,但显然没有存储在数组中。下面的代码将在用于向机器人传输命令的计算机上运行。我已经引用了会导致看不到服务器错误的行。请帮我弄清楚为什么我不能将操纵杆的读数放入数组中,并请发布代码片段,而不仅仅是单词描述。
import socket #send data between server and client
import os #gain control of command prompt features
import keyboard #read keystrokes
import pygame #Read Joystick data
os.system('title client') #rename command prompt
os.system('cls') #clear command prompt screen
# client = socket.socket() #constructor
# hostname = '127.0.0.1' #server ip
# port = 8080 #server open communication port
# client.connect((hostname,port)) #create connection
# Define some colors.
BLACK = pygame.Color('black')
WHITE = pygame.Color('white')
# This is a simple class that will help us print to the screen.
# It has nothing to do with the joysticks, just outputting the
# information.
class TextPrint(object):
def __init__(self):
self.reset()
self.font = pygame.font.Font(None, 20)
def tprint(self, screen, textString):
textBitmap = self.font.render(textString, True, BLACK)
screen.blit(textBitmap, (self.x, self.y))
self.y += self.line_height
def reset(self):
self.x = 10
self.y = 10
self.line_height = 15
def indent(self):
self.x += 10
def unindent(self):
self.x -= 10
pygame.init()
# Set the width and height of the screen (width, height).
screen = pygame.display.set_mode((500, 700))
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates.
clock = pygame.time.Clock()
# Initialize the joysticks.
pygame.joystick.init()
# Get ready to print.
textPrint = TextPrint()
message = []
# -------- Main Program Loop -----------
while not done:
#
# EVENT PROCESSING STEP
#
# Possible joystick actions: JOYAXISMOTION, JOYBALLMOTION, JOYBUTTONDOWN,
# JOYBUTTONUP, JOYHATMOTION
for event in pygame.event.get(): # User did something.
if event.type == pygame.QUIT: # If user clicked close.
done = True # Flag that we are done so we exit this loop.
elif event.type == pygame.JOYBUTTONDOWN:
print("Joystick button pressed.")
elif event.type == pygame.JOYBUTTONUP:
print("Joystick button released.")
#
# DRAWING STEP
#
# First, clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
screen.fill(WHITE)
textPrint.reset()
# Get count of joysticks.
joystick_count = pygame.joystick.get_count()
textPrint.tprint(screen, "Number of joysticks: {}".format(joystick_count))
textPrint.indent()
# For each joystick:
for i in range(joystick_count):
joystick = pygame.joystick.Joystick(i)
joystick.init()
try:
jid = joystick.get_instance_id()
except AttributeError:
# get_instance_id() is an SDL2 method
jid = joystick.get_id()
textPrint.tprint(screen, "Joystick {}".format(jid))
textPrint.indent()
# Get the name from the OS for the controller/joystick.
name = joystick.get_name()
textPrint.tprint(screen, "Joystick name: {}".format(name))
# try:
# guid = joystick.get_guid()
# except AttributeError:
# # get_guid() is an SDL2 method
# pass
# else:
# textPrint.tprint(screen, "GUID: {}".format(guid))
# Usually axis run in pairs, up/down for one, and left/right for
# the other.
axes = joystick.get_numaxes()
textPrint.tprint(screen, "Number of axes: {}".format(axes))
textPrint.indent()
for i in range(axes):
axis = joystick.get_axis(i)
textPrint.tprint(screen, "Axis {} value: {:>6.3f}".format(i, axis))
message.append(joystick.get_axis(i))
textPrint.unindent()
buttons = joystick.get_numbuttons()
textPrint.tprint(screen, "Number of buttons: {}".format(buttons))
textPrint.indent()
for i in range(buttons):
button = joystick.get_button(i)
textPrint.tprint(screen, "Button {:>2} value: {}".format(i, button))
message.append(button)
textPrint.unindent()
hats = joystick.get_numhats()
textPrint.tprint(screen, "Number of hats: {}".format(hats))
textPrint.indent()
# Hat position. All or nothing for direction, not a float like
# get_axis(). Position is a tuple of int values (x, y).
for i in range(hats):
hat = joystick.get_hat(i)
textPrint.tprint(screen, "Hat {} value: {}".format(i, str(hat)))
textPrint.unindent()
textPrint.unindent()
#Display values recorded in array
for i in message:
value = message[int(i)]
textPrint.tprint(screen,"values: {}".format(value))
#
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
#
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Limit to 20 frames per second.
clock.tick(20)
# Close the window and quit.
# If you forget this line, the program will 'hang'
# on exit if running from IDLE.
pygame.quit()
# Send to server
# x = keyboard.read_key() #read key on keyboard
# client.send(x.encode()) #send recorded key to server
# print("You Pressed ", x) #print on client screen the key they pressed
解决方案
问题解决了!问题是由于“消息”数组不断添加到自身而导致的无限循环,因为它在循环之外。通过在“while not done:”循环中声明数组,它会自行擦除并在需要的地方添加值。代码现在可以工作了。现在我唯一担心的是值“hat”不会引起问题,因为它返回 2 个值而不是 1 个。我会将这个案例标记为已解决!固定代码如下,以防有人想知道我到目前为止的位置!
import socket #send data between server and client
import os #gain control of command prompt features
import keyboard #read keystrokes
import pygame #Read Joystick data
import array
os.system('title client') #rename command prompt
os.system('cls') #clear command prompt screen
# client = socket.socket() #constructor
# hostname = '127.0.0.1' #server ip
# port = 8080 #server open communication port
# client.connect((hostname,port)) #create connection
# Define some colors.
BLACK = pygame.Color('black')
WHITE = pygame.Color('white')
# This is a simple class that will help us print to the screen.
# It has nothing to do with the joysticks, just outputting the
# information.
class TextPrint(object):
def __init__(self):
self.reset()
self.font = pygame.font.Font(None, 20)
def tprint(self, screen, textString):
textBitmap = self.font.render(textString, True, BLACK)
screen.blit(textBitmap, (self.x, self.y))
self.y += self.line_height
def reset(self):
self.x = 10
self.y = 10
self.line_height = 15
def indent(self):
self.x += 10
def unindent(self):
self.x -= 10
pygame.init()
# Set the width and height of the screen (width, height).
screen = pygame.display.set_mode((500, 700))
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates.
clock = pygame.time.Clock()
# Initialize the joysticks.
pygame.joystick.init()
# Get ready to print.
textPrint = TextPrint()
#message = array.array('d',[])
# -------- Main Program Loop -----------
while not done:
#clear message
message = array.array('d',[])
#
# EVENT PROCESSING STEP
#
# Possible joystick actions: JOYAXISMOTION, JOYBALLMOTION, JOYBUTTONDOWN,
# JOYBUTTONUP, JOYHATMOTION
for event in pygame.event.get(): # User did something.
if event.type == pygame.QUIT: # If user clicked close.
done = True # Flag that we are done so we exit this loop.
elif event.type == pygame.JOYBUTTONDOWN:
print("Joystick button pressed.")
elif event.type == pygame.JOYBUTTONUP:
print("Joystick button released.")
#
# DRAWING STEP
#
# First, clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
screen.fill(WHITE)
textPrint.reset()
# Get count of joysticks.
joystick_count = pygame.joystick.get_count()
textPrint.tprint(screen, "Number of joysticks: {}".format(joystick_count))
textPrint.indent()
# For each joystick:
for i in range(joystick_count):
joystick = pygame.joystick.Joystick(i)
joystick.init()
try:
jid = joystick.get_instance_id()
except AttributeError:
# get_instance_id() is an SDL2 method
jid = joystick.get_id()
textPrint.tprint(screen, "Joystick {}".format(jid))
textPrint.indent()
# Get the name from the OS for the controller/joystick.
name = joystick.get_name()
textPrint.tprint(screen, "Joystick name: {}".format(name))
# try:
# guid = joystick.get_guid()
# except AttributeError:
# # get_guid() is an SDL2 method
# pass
# else:
# textPrint.tprint(screen, "GUID: {}".format(guid))
# Usually axis run in pairs, up/down for one, and left/right for
# the other.
axes = joystick.get_numaxes()
textPrint.tprint(screen, "Number of axes: {}".format(axes))
textPrint.indent()
for i in range(axes):
axis = joystick.get_axis(i)
textPrint.tprint(screen, "Axis {} value: {:>6.3f}".format(i, axis))
message.append(joystick.get_axis(i))
textPrint.unindent()
buttons = joystick.get_numbuttons()
textPrint.tprint(screen, "Number of buttons: {}".format(buttons))
textPrint.indent()
for i in range(buttons):
button = joystick.get_button(i)
textPrint.tprint(screen, "Button {:>2} value: {}".format(i, button))
message.append(button)
textPrint.unindent()
hats = joystick.get_numhats()
textPrint.tprint(screen, "Number of hats: {}".format(hats))
textPrint.indent()
# Hat position. All or nothing for direction, not a float like
# get_axis(). Position is a tuple of int values (x, y).
for i in range(hats):
hat = joystick.get_hat(i)
textPrint.tprint(screen, "Hat {} value: {}".format(i, str(hat)))
textPrint.unindent()
textPrint.unindent()
i = range(len(message))
textPrint.tprint(screen, "array length {}".format(i))
for i in range(len(message)):
value = message[int(i)]
textPrint.tprint(screen, "value {}: {}".format(i, value))
#
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
#
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Limit to 20 frames per second.
clock.tick(20)
# Close the window and quit.
# If you forget this line, the program will 'hang'
# on exit if running from IDLE.
pygame.quit()
# Send to server
# x = keyboard.read_key() #read key on keyboard
# client.send(x.encode()) #send recorded key to server
# print("You Pressed ", x) #print on client screen the key they pressed
推荐阅读
- javascript - 使用反应切换钩子在两个组件/按钮之间切换{显示一个组件并隐藏另一个}
- google-apps-script - Google 表格脚本 - 在特定表格上运行的更简洁的代码
- c# - `#nullable disable` 时使用 NotNullWhenAttribute
- java - session.getStderr() 什么时候在 ganymed-ssh2 jar 中执行?
- java - TransientPropertyValueException: object references an unsaved transient instance - 在刷新之前保存瞬态实例:
- bash - 如何将值存储到变量中
- r - if 语句在每个分支上返回一个不同的变量,如何仅使用一个 <- 运算符对该变量进行子分配?
- javascript - 仅从字符串中提取 cookie 的值
- python - 使用 DFS 在图中查找路径
- prometheus - 启动普罗米修斯服务时遇到错误