You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Python Socket双玩家游戏代码以支持多客户端?

从双玩家到多玩家:Python Socket游戏改造方案

原教程仅支持双玩家,要扩展为多玩家,核心是让服务器维护完整的玩家列表,并将所有其他玩家的数据同步给每个客户端。以下是具体修改步骤:

1. 改造Server.py(核心修改)

  • 调整监听连接数,支持更多玩家接入
  • 动态创建新玩家,不再固定初始两个玩家
  • 同步时返回当前玩家以外的所有玩家列表,而非单个玩家

修改后的server.py代码:

import socket
from _thread import *
from player import Player
import pickle
import random

server = "10.11.250.207"
port = 5555

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.bind((server, port))
except socket.error as e:
    print(str(e))

# 调整监听数,支持更多玩家(示例设为10人)
s.listen(10)
print("Waiting for connections, Server Started")

players = []

def threaded_client(conn, player_id):
    # 给新玩家生成随机初始位置和颜色
    x = random.randint(50, 400)
    y = random.randint(50, 400)
    color = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
    new_player = Player(x, y, 50, 50, color)
    players.append(new_player)
    
    # 先把当前玩家的数据发给客户端
    conn.send(pickle.dumps(new_player))
    
    while True:
        try:
            # 接收客户端发来的自己的最新状态
            data = pickle.loads(conn.recv(2048))
            if not data:
                print(f"Player {player_id} disconnected")
                break
            # 更新服务器上的玩家状态
            players[player_id] = data
            
            # 准备回复:除了当前玩家之外的所有玩家
            reply = [p for idx, p in enumerate(players) if idx != player_id]
            conn.sendall(pickle.dumps(reply))
            
        except Exception as e:
            print(f"Error: {e}")
            break
    
    # 玩家断开,从列表移除
    del players[player_id]
    print(f"Player {player_id} removed from list")
    conn.close()

current_player_id = 0
while True:
    conn, addr = s.accept()
    print(f"Connected to: {addr}, Player ID: {current_player_id}")
    
    start_new_thread(threaded_client, (conn, current_player_id))
    current_player_id += 1

2. 调整Network.py(适配返回列表)

无需大幅修改,只需确保客户端能正确接收列表格式的数据,原代码可直接使用:

import socket
import pickle

class Network:
    def __init__(self):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server = "10.11.250.207"
        self.port = 5555
        self.addr = (self.server, self.port)
        self.p = self.connect()

    def getP(self):
        return self.p

    def connect(self):
        try:
            self.client.connect(self.addr)
            return pickle.loads(self.client.recv(2048))
        except Exception as e:
            print(e)

    def send(self, data):
        try:
            self.client.send(pickle.dumps(data))
            return pickle.loads(self.client.recv(2048))
        except socket.error as e:
            print(e)

3. 修改Client.py(渲染所有玩家)

  • 更新窗口渲染函数,遍历所有其他玩家进行绘制
  • 调整主循环逻辑,处理服务器返回的玩家列表

修改后的client.py代码:

import pygame
from network import Network
from player import Player

width = 500
height = 500
win = pygame.display.set_mode((width, height))
pygame.display.set_caption("Multiplayer Client")

def redrawWindow(win, self_player, other_players):
    win.fill((255,255,255))
    # 先画自己
    self_player.draw(win)
    # 遍历画所有其他玩家
    for player in other_players:
        player.draw(win)
    pygame.display.update()

def main():
    run = True
    n = Network()
    self_player = n.getP()
    clock = pygame.time.Clock()

    while run:
        clock.tick(60)
        # 发送自己的状态,接收其他玩家列表
        other_players = n.send(self_player)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()

        self_player.move()
        redrawWindow(win, self_player, other_players)

if __name__ == "__main__":
    main()

4. Player.py(可选优化)

可以给Player类添加id属性方便后续扩展(比如区分玩家),基础版无需修改,原代码可直接使用:

import pygame

class Player():
    def __init__(self, x, y, width, height, color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.rect = (x,y,width,height)
        self.vel = 3

    def draw(self, win):
        pygame.draw.rect(win, self.color, self.rect)

    def move(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_LEFT]:
            self.x -= self.vel

        if keys[pygame.K_RIGHT]:
            self.x += self.vel

        if keys[pygame.K_UP]:
            self.y -= self.vel

        if keys[pygame.K_DOWN]:
            self.y += self.vel

        self.update()

    def update(self):
        self.rect = (self.x, self.y, self.width, self.height)

核心改动说明

  • 服务器不再固定初始玩家,而是为每个新连接动态生成玩家并加入列表
  • 同步逻辑从“返回单个对手”改成“返回所有其他玩家”
  • 客户端渲染逻辑从绘制两个玩家改成绘制自己+所有其他玩家
  • 增加了玩家断开后的列表清理逻辑

内容的提问来源于stack exchange,提问作者Justin Cheng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:02:37