Python Pygame:函数使用时间轮询REST响应。睡眠延迟冻结游戏窗口
实际上,我正在编写一个多用户pygame游戏,其中客户端通过REST请求与服务器通信。我得到了一个函数,在这个函数中,游戏必须等待另一个玩家进入服务器上的“队列”,才能开始一个新游戏。为此,我使用get请求(使用请求完成)轮询服务器,中间有一个time.sleep-delay。但这次,睡眠也会导致我的游戏循环停止,并在等待时冻结我的游戏窗口。但是我想让用户在等待期间离开游戏队列。这是不可能的,因为我的屏幕被冻结,变成了“离开队列”对话框,用户无法单击此按钮或右上角的“x”离开队列Python Pygame:函数使用时间轮询REST响应。睡眠延迟冻结游戏窗口,python,rest,pygame,wait,sleep,Python,Rest,Pygame,Wait,Sleep,实际上,我正在编写一个多用户pygame游戏,其中客户端通过REST请求与服务器通信。我得到了一个函数,在这个函数中,游戏必须等待另一个玩家进入服务器上的“队列”,才能开始一个新游戏。为此,我使用get请求(使用请求完成)轮询服务器,中间有一个time.sleep-delay。但这次,睡眠也会导致我的游戏循环停止,并在等待时冻结我的游戏窗口。但是我想让用户在等待期间离开游戏队列。这是不可能的,因为我的屏幕被冻结,变成了“离开队列”对话框,用户无法单击此按钮或右上角的“x”离开队列 我已经尝试以线
我已经尝试以线程的形式启动轮询功能,但这并不能解决屏幕冻结/游戏循环停止的问题。关于如何实现此功能的几个关键点:
- 在一个线程中处理所有套接字I/O
- 发生套接字事件时发送回主循环
- 不要睡觉或延迟pygame主事件循环。永远
import threading
import pygame
import random
import enum
import socket
import select
import time
### Event types that are sent to the main event loop
class NetworkEvents( enum.IntEnum ):
EVENT_HANGUP = pygame.USEREVENT + 1
EVENT_COMMAND = pygame.USEREVENT + 2
### Socket-listener thread that reads commands from the server
### and does the parsing and posting of commands to the main event-loop
class ConversationHandlerThread( threading.Thread ):
""" A thread that handles a conversation with a single remote server.
Accepts commands of 'close', 'red', 'green' or 'blue', and posts messages
to the main PyGame thread for processing """
def __init__( self, server_address, server_port ):
threading.Thread.__init__(self)
self.server_address = server_address
self.server_port = server_port
self.server_socket = None
self.data_buffer = ''
self.daemon = True # exit with parent
self.done = False
def stop( self ):
self.done = True
def connect( self ):
self.server_socket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
while True:
try:
self.server_socket.connect( ( self.server_address, self.server_port ) )
break;
except:
print( "Failed to connect %s:%d, will retry" % ( self.server_address, self.server_port ) )
time.sleep( 12 )
def run( self ):
""" Connects to Server, then Loops until the server hangs-up """
self.connect()
# Now we're connected, start reading commands
read_events_on = [ self.server_socket ]
while ( not self.done ):
# Wait for incoming data, or errors, or 0.5 seconds
(read_list, write_list, except_list) = select.select( read_events_on, [], [], 0.5 )
if ( len( read_list ) > 0 ):
# New data arrived, read it
incoming = self.server_socket.recv( 8192 )
if ( len(incoming) == 0):
# Socket has closed
new_event = pygame.event.Event( NetworkEvents.EVENT_HANGUP, { "address" : self.server_address } )
pygame.event.post( new_event )
self.server_socket.close()
self.done = True
else:
# Data has arrived
try:
new_str = incoming.decode('utf-8')
self.data_buffer += new_str
except:
pass # don't understand buffer
# Parse incoming message (trivial parser, not high quality)
# commands are '\n' separated
if (self.data_buffer.find('\n') != -1 ):
for command in self.data_buffer.split('\n'):
command = line.strip()
# client disconnect command
if ( command == 'close' ):
new_event = pygame.event.Event( NetworkEvents.EVENT_HANGUP, { "address" : self.server_address } )
pygame.event.post( new_event )
self.server_socket.close()
self.done = True
# only make events for valid commands
elif ( command in ( 'red', 'green', 'blue' ) ):
new_event = pygame.event.Event( NetworkEvents.EVENT_COMMAND, { "address" : self.server_address, "message" : command } )
pygame.event.post( new_event )
self.data_buffer = '' # all used-up
### MAIN
# Start the connection-listener thread
thread1 = ConversationHandlerThread( '127.0.0.1', 5555 )
thread1.start()
线程运行后,将在主循环中接收事件,与任何其他PyGame事件相同:
# Main paint / update / event loop
done = False
while ( not done ):
SPRITES.update()
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
elif ( event.type == NetworkEvents.EVENT_HANGUP ):
print(" CLIENT DISCONNECTED %s " % ( str(event.address) ) )
elif ( event.type == NetworkEvents.EVENT_COMMAND ):
print(" CLIENT MESSAGE FROM %s - %s " % ( str(event.address), event.message ) )
if ( event.message == 'red' ):
new_sprite = AlienSprite( RED )
SPRITES.add( new_sprite )
# ... etc.
如果您的套接字I/O在线程中处理,并且主事件循环从不休眠,那么您应该能够使用PyGame制作一个流畅的程序。保持您的网络流量小而简洁。嘿,金斯利,谢谢您的详细回答。因为我必须使用REST通信(这是一个给定的要求)。我不确定这种方法是否适合我。但是你关于使用userevents的提示给了我一个不同的想法,我将尝试一下。我不久前用过,但我完全忘了:)