В вашем клиентском коде есть некоторые проблемы, которые затрудняют интеграцию в среду, которая, насколько я понимаю, имеет собственный цикл обработки событий (то есть pygame, который я никогда не использовал):
self.sock.send(bytes(input(''), 'utf-8'))
блокирует input
, таким образом блокируя цикл игровых событий. Вы пытаетесь избежать этого, помещая его в собственный поток, но теперь вы полностью переместили клавиатуру в этот другой поток. Другое дело, что
data = self.sock.recv(1024)
также блокирует. Теперь поток, который вы только что освободили от блокировки на input
, заблокирован socket.recv
.
Ваша идея использования UDP действительно многообещающая. Теперь вы можете создать игровой клиентский класс с двумя (почти) неблокирующими методами send_message()
и check_message()
:
import socket
import json
class GameClient:
def __init__(self, server=("127.0.0.1", 12000)):
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.client_socket.settimeout(0.1)
self.server = server
def send_message(self, msg):
""" JSON-encode and send msg to server. """
message = json.dumps(msg).encode("utf8")
self.client_socket.sendto(message, self.server)
def check_message(self):
""" Check if there's a message from the server and return it, or None. """
try:
message, address = self.client_socket.recvfrom(1024)
return json.loads(message.decode("utf8"))
except socket.timeout:
pass # this passes as "non-blocking" for now
return None
Поскольку я не знаю pygame, я взломал свой собственный примитивный игровой цикл, который обрабатывает мою позицию (my_x, my_y
) и других игроков (positions
) и перемещает моего игрока в случайном направлении один раз в некоторое время, отправляя и получая в качестве сообщений позиции игроков в виде диктов в виде `{" playername ": [xpos, ypos]} ':
import random
import time
def game(player):
me = GameClient()
positions = {}
my_x = my_y = 0
me.send_message({player: [my_x, my_y]})
while True:
move = random.randrange(80)
if move == 0:
my_x -= 1
elif move == 1:
my_x += 1
elif move == 2:
my_y -= 1
elif move == 3:
my_y += 1
if move < 4:
me.send_message({player: [my_x, my_y]})
print("me: {}".format([my_x, my_y]))
updates = me.check_message()
while updates:
positions.update(updates)
print("updates: {}".format(updates))
print("positions: {}".format(positions))
updates = me.check_message()
time.sleep(0.1)
Сам сервер просто передает каждое полученное сообщение всем другим клиентам, о которых он когда-либо слышал:
import socket
import json
def game_server():
positions = {}
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('', 12000))
while True:
message, address = server_socket.recvfrom(1024)
print("update from {}".format(address))
positions[address] = json.loads(message.decode("utf8"))
for client in positions.keys():
if client != address:
server_socket.sendto(message, client)
print("game positions: {}".format(positions))
Вы должны будете каким-то образом вписать идею функции game()
в цикл событий Pygame. Я желаю вам удачи.