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

多人Pong游戏分数更新后立即重置为初始值问题求助

多人Pong游戏分数重置问题

我正在开发一款多人Pong游戏,核心功能正常,但分数无法正常更新。服务端通过Ball类的score()函数更新玩家分数并同步给客户端:满足得分条件时分数会加1,但下一次循环迭代时分数就被重置为0。

相关代码

Ball类的分数检测函数

def score(self, p):
    if self.x <= 10:  
        print('true')
        p.score += 1
    elif self.x >= 890:
        print('true')
        p.score += 1

Player类定义

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 = 7
        self.score = 0

服务端调用分数函数的代码片段

while True:
    if current_player > 0:
        clock = pygame.time.Clock()
        clock.tick(60)
        print(players[current_player].score)
        ball.score(players[current_player])
        print(players[current_player].score)
        ball_data = ball.move(players[0], players[1])

完整服务端相关代码

players = [
    Player(10, 300 - PLAYER_HEIGHT/2, PLAYER_WIDTH, PLAYER_HEIGHT, WHITE), 
    Player(880, 300 - PLAYER_HEIGHT/2, PLAYER_WIDTH, PLAYER_HEIGHT, WHITE)
    ]

ball = Ball(WIDTH, HEIGHT, 10, WHITE)

def handle_client(conn, current_player):
    print(f'[NEW CONNECTION] {addr} connected')
    conn.send(pickle.dumps([players[current_player], ball])) # 0 is player and 1 is ball
    reply = ''
    ball_data = ball

    while True:
        if current_player > 0:
            clock = pygame.time.Clock()
            clock.tick(60)
            print(players[current_player].score)
            ball.score(players[current_player])
            print(players[current_player].score)
            ball_data = ball.move(players[0], players[1])

        try:
            data = pickle.loads(conn.recv(2048))
            players[current_player] = data

            if not data:
                print('DISCONNETED')
                break
            else:
                if current_player == 0:
                    reply = [players[1], ball_data]
                else:
                    reply = [players[0], ball_data]

            conn.sendall(pickle.dumps(reply))
        except:
            remove_player()
            player_reset()
            ball_reset()
            break
        
    print('Lost connection')
    conn.close()

调试输出

调试输出

问题原因及修复方案

核心问题

每次服务端接收客户端数据时,执行players[current_player] = data,而客户端传回的Player对象是初始化状态(score为0),直接覆盖了服务端已更新分数的实例,导致下一次循环分数被重置。

修复步骤

  1. 避免直接覆盖Player实例:只同步客户端需要更新的属性(位置、速度等),保留服务端维护的分数状态:
try:
    data = pickle.loads(conn.recv(2048))
    # 仅更新客户端同步的属性,保留score
    players[current_player].x = data.x
    players[current_player].y = data.y
    players[current_player].rect = data.rect
    players[current_player].vel = data.vel

    if not data:
        print('DISCONNETED')
        break
    else:
        if current_player == 0:
            reply = [players[1], ball_data]
        else:
            reply = [players[0], ball_data]

    conn.sendall(pickle.dumps(reply))
except:
    remove_player()
    player_reset()
    ball_reset()
    break
  1. 修正得分逻辑:原score()函数会给当前玩家加分数,不符合Pong规则(左边界触球应让右方玩家得分,右边界触球应让左方玩家得分):
def score(self, players):
    scored = False
    if self.x <= 10:
        # 球碰左边界,右侧玩家(索引1)得分
        players[1].score += 1
        scored = True
    elif self.x >= 890:
        # 球碰右边界,左侧玩家(索引0)得分
        players[0].score += 1
        scored = True
    if scored:
        # 得分后重置球位置
        self.reset()
        print('得分!')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:06:28