我一般对python和编程都不熟悉,并且想知道如何为pygame制作的单人游戏添加多人游戏功能。我已经制作了一个可以接受多个连接的功能服务器,还制作了一个客户端,以制作可以用来发送消息的系统。我试图制作一个可以运行游戏的客户端,并将各种游戏数据(例如x位置)发送到服务器,同时还从其他客户端接收此类数据,但无济于事。 这是我的消息传递客户端代码:
import socket
import threading
class Client:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def sendMSG(self):
while True:
self.sock.send(bytes(input(''), 'utf-8'))
def __init__(self):
port = 12345
self.sock.connect(('127.0.0.1', port))
iThread = threading.Thread(target=self.sendMSG)
iThread.daemon = True
iThread.start()
while True:
data = self.sock.recv(1024)
if not data:
break
print(str(data, 'utf-8'))
client = Client()
它的用途非常好,但是我无法将其与单人游戏代码结合使用。我尝试更改sendMSG函数的功能并将其视为游戏循环。我能够到达这样的地步:当按下方向键并更改了值时,客户端发送了位置数据,但是在尝试接收该数据时遇到了麻烦。我使用了线程,但由于某种原因,它无法运行游戏并不能同时接收数据。也许我的思考过程错了?如果您能帮助我确定如何将游戏循环添加到客户端,我将不胜感激。谢谢。
答案 0 :(得分:0)
您的客户端代码存在一些问题,导致难以集成到据我所知具有其自己的事件循环(即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
)并将我的玩家移动到偶尔随机定向,以消息形式发送和接收玩家的位置,形式为“ {“玩家名”:[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)
服务器本身只是将收到的每条消息回传给它曾经听说过的所有 other 客户端:
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事件循环。祝你好运。