pygame 多人游戏 jsondecodeerror

问题描述 投票:0回答:1

我正在使用 pygame 开发一款两人多人游戏。
这是服务器代码和客户端代码:

import json
import pygame  # Main module for the game
import pyautogui  # For slightly enhancing control sensitivity
import sys  # For console control
import socket  # Socket for network communication
import threading  # For multithreading
import math

pygame.init()  # Initialize Pygame
pygame.display.set_caption('SERVER')  # Set window title
height = 960  # Window height
width = 1200  # Window width
screen = pygame.display.set_mode((width, height))

class Bullet:
    def __init__(self, img, x, y, dx, dy, w, h, damage, team):
        self.__img = img
        self.__x = x
        self.__y = y
        self.__dx = dx
        self.__dy = dy
        self.__w = w
        self.__h = h
        self.__damage = damage
        self.__team = team

    def getdamage(self):
        return self.__damage

    def getteam(self):
        return self.__team

    def getrect(self):
        nrect = pygame.Rect(0, 0, self.__w, self.__h)
        nrect.center = (self.__x, self.__y)
        return nrect

    def getpos(self):
        return (self.__x, self.__y)

    def move(self):
        self.__x += self.__dx
        self.__y += self.__dy

    def show(self):
        newRect = self.getrect()
        screen.blit(self.__img, newRect)

enemy_img = pygame.image.load('char.png')
enemy_img = pygame.transform.flip(enemy_img, True, False)
bulletimg = pygame.image.load('a_bullet.png')
bulletw = bulletimg.get_size()[0]
bulleth = bulletimg.get_size()[1]
imgw = enemy_img.get_size()[0]
imgh = enemy_img.get_size()[1]
bulletlist = []
enex = 0
eney = imgh
playersize = imgw / 2
playerspeed = 3
enexdirec = 0
eneydirec = 0
playerxdirec = 0
playerydirec = 0
playerHp = 100
eneHp = 100

def getPlayerrect(pos):
    nrect = pygame.Rect(0, 0, imgw, imgh)
    nrect.center = (pos[0], pos[1])
    return nrect

def consoles():
    global enexdirec, eneydirec
    global eneHp, playerHp
    while True:
        msg = client.recv(1024)
        if not msg:
            break  # Connection closed
        decoded_msg = msg.decode()  # Decode message to string
        if decoded_msg == 'up':
            eneydirec = -1
        if decoded_msg == 'down':
            eneydirec = 1
        if decoded_msg == 'left':
            enexdirec = -1
        if decoded_msg == 'right':
            enexdirec = 1
        if decoded_msg == 'endx':
            enexdirec = 0
        if decoded_msg == 'endy':
            eneydirec = 0
        if decoded_msg == 'damaged':
            playerHp -= 10
            if playerHp <= 0:
                print("LOSE")
                quitgame()
        if decoded_msg.startswith('{'):  # If message is in JSON format, process as bullet data
            data = json.loads(decoded_msg)  #ERROR!jsondecodeerror
            if data.get("type") == "bullet":
                # Create and add Bullet object
                bulletlist.append(Bullet(
                    bulletimg,
                    data['x'],
                    data['y'],
                    data['dx'],
                    data['dy'],
                    data['width'],
                    data['height'],
                    data['damage'],
                    'E'
                ))

def acceptC():
    global client, server, addr
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('127.0.0.1', 7777))
    server.listen()
    client, addr = server.accept()

    thr = threading.Thread(target=consoles, args=())
    thr.Daemon = True
    thr.start()

def quitgame():
    pygame.quit()
    sys.exit()

def clamp(x, mi, ma):
    if x > ma:
        return ma
    elif x < mi:
        return mi
    return x

def calcvector(sp, fp):
    direcx = fp[0] - sp[0]
    direcy = fp[1] - sp[1]
    l = math.sqrt(direcx**2 + direcy**2)
    if l == 0:
        return (1, 0)
    else:
        return (direcx / l, direcy / l)

def GameMain():
    global playerHp, eneHp
    global enex, eney
    global playerxdirec, playerydirec
    fps = pygame.time.Clock()

    img = pygame.image.load('char.png')  # Load player image
    imgh = img.get_size()[1]
    imgw = img.get_size()[0]
    x = 0
    y = imgh

    while True:
        screen.fill((255, 255, 255))

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:#send bullet data to client
                    T = pygame.mouse.get_pos()
                    direcvec = calcvector((x, y), T)
                    speed = 8
                    newB = Bullet(bulletimg, x, y, direcvec[0] * speed, direcvec[1] * speed, 10, 10, 10, 'M')
                    bulletlist.append(newB)
                    bullet_data = json.dumps({
                        'type': 'bullet',
                        'x': x,
                        'y': y,
                        'dx': direcvec[0] * speed,
                        'dy': direcvec[1] * speed,
                        'width': 10,
                        'height': 10,
                        'damage': 10
                    })
                    client.sendall(bullet_data.encode())
        keys = pygame.key.get_pressed()
        if not(keys[pygame.K_a] ^ keys[pygame.K_d]):
            playerxdirec = 0
            msg = "endx"
            client.sendall(msg.encode())
        elif keys[pygame.K_a]:
            playerxdirec = -1
            msg = "left"
            client.sendall(msg.encode())
        elif keys[pygame.K_d]:
            playerxdirec = 1
            msg = "right"
            client.sendall(msg.encode())
        if not(keys[pygame.K_w] ^ keys[pygame.K_s]):
            playerydirec = 0
            msg = "endy"
            client.sendall(msg.encode())
        elif keys[pygame.K_w]:
            playerydirec = -1
            msg = "up"
            client.sendall(msg.encode())
        elif keys[pygame.K_s]:
            playerydirec = 1
            msg = "down"
            client.sendall(msg.encode())

        for i in bulletlist:
            i.move()
            bulpos = i.getpos()
            if bulpos[0] > width or bulpos[0] < 0 or bulpos[1] < 0 or bulpos[1] > height:
                bulletlist.remove(i)
                continue
            else:
                i.show()
            if i.getrect().colliderect(getPlayerrect((x, y))) and i.getteam() == 'E':
                bulletlist.remove(i)
                playerHp -= 10
                msg = json.dumps({
                    'type': 'hp_update',
                    'hp': eneHp,
                    'eneHp': playerHp
                })
                print('er')
                client.sendall(msg.encode())
                continue
            if i.getrect().colliderect(getPlayerrect((enex, eney))) and i.getteam() == 'M':
                bulletlist.remove(i)
                eneHp -= 10
                msg = json.dumps({
                    'type': 'hp_update',
                    'hp': eneHp,
                    'eneHp': playerHp
                })
                print('su')
                client.sendall(msg.encode())
                continue

        if eneHp <= 0:
            print('WIN')
            quitgame()
        if playerHp <= 0:
            print('WIN')
            quitgame()

        # Draw enemy HP bar
        enehpposrect = pygame.Rect(0, 0, 30, 8)
        enehpposrect.center = (enex, eney + 20)
        enehpposrect2 = pygame.Rect(enehpposrect.x, enehpposrect.y, 30 * (eneHp / 100), 8)
        pygame.draw.rect(screen, "red", enehpposrect)
        pygame.draw.rect(screen, "green", enehpposrect2)

        # Draw player HP bar
        playerhpposrect = pygame.Rect(0, 0, 30, 8)
        playerhpposrect.center = (x, y + 20)
        playerhpposrect2 = pygame.Rect(playerhpposrect.x, playerhpposrect.y, 30 * (playerHp / 100), 8)
        pygame.draw.rect(screen, "red", playerhpposrect)
        pygame.draw.rect(screen, "green", playerhpposrect2)

        x += playerxdirec * playerspeed
        y += playerydirec * playerspeed
        enex += enexdirec * playerspeed
        eney += eneydirec * playerspeed
        x = clamp(x, 0, width)
        y = clamp(y, 0, height)
        enex = clamp(enex, 0, width)
        eney = clamp(eney, 0, height)

        mRect = pygame.Rect(0, 0, imgw, imgh)
        mRect.center = (x, y)
        screen.blit(img, mRect)
        eRect = pygame.Rect(0, 0, imgw, imgh)
        eRect.center = (enex, eney)
        screen.blit(enemy_img, eRect)
        pygame.display.update()  # Update display
        fps.tick(60)  # Set FPS to 60

if __name__ == '__main__':
    acceptC() 
    GameMain()

import pygame
import pyautogui
import sys
import socket
import threading
import json
import math

pygame.init()
pygame.display.set_caption('CLIENT')
height = 960
width = 1200
screen = pygame.display.set_mode((width, height))

class Bullet:
    def __init__(self, img, x, y, dx, dy, w, h, damage, team):
        self.__img = img
        self.__x = x
        self.__y = y
        self.__dx = dx
        self.__dy = dy
        self.__w = w
        self.__h = h
        self.__damage = damage
        self.__team = team
    def getdamage(self):
        return self.__damage
    def getteam(self):
        return self.__team
    def getrect(self):
        nrect = pygame.Rect(0, 0, self.__w, self.__h)
        nrect.center = (self.__x, self.__y)
        return nrect
    def getpos(self):
        return (self.__x, self.__y)
    def move(self):
        self.__x += self.__dx
        self.__y += self.__dy
    def show(self):
        newRect = self.getrect()
        screen.blit(self.__img, newRect)

enemy_img = pygame.image.load('char.png')
enemy_img = pygame.transform.flip(enemy_img, True, False)
bulletimg = pygame.image.load('a_bullet.png')
bulletw = bulletimg.get_size()[0]
bulleth = bulletimg.get_size()[1]
imgw = enemy_img.get_size()[0]
imgh = enemy_img.get_size()[1]
bulletlist = []
enex = 0
eney = imgh
playersize = imgw / 2
playerspeed = 3
enexdirec = 0
eneydirec = 0
playerxdirec = 0
playerydirec = 0
playerHp = 100
eneHp = 100

def getPlayerrect(pos):
    nrect = pygame.Rect(0, 0, imgw, imgh)
    nrect.center = (pos[0], pos[1])
    return nrect

def consoles():
    global eneHp, playerHp
    global enexdirec, eneydirec
    while True:
        msg = client.recv(1024)
        if not msg:
            break  # If the connection is lost
        decoded_msg = msg.decode()  # Convert message to string
        if decoded_msg == 'up':
            eneydirec = -1
        if decoded_msg == 'down':
            eneydirec = 1
        if decoded_msg == 'left':
            enexdirec = -1
        if decoded_msg == 'right':
            enexdirec = 1
        if decoded_msg == 'endx':
            enexdirec = 0
        if decoded_msg == 'endy':
            eneydirec = 0
        if decoded_msg == 'damaged':
            playerHp -= 10
            if playerHp <= 0:
                print("LOSE")
                quitgame()
        if decoded_msg.startswith('{'):  # If JSON format, treat it as bullet data
            data = json.loads(decoded_msg)   #ERROR!jsondecodeerror
            if data.get("type") == 0:
                print('a')
                playerHp = data["hp"]
                eneHp = data["eneHp"]
            if data.get("type") == 1:
                # Create and add Bullet object
                bulletlist.append(Bullet(
                    bulletimg,
                    data['x'],
                    data['y'],
                    data['dx'],
                    data['dy'],
                    data['width'],
                    data['height'],
                    data['damage'],
                    'E'
                ))

def acceptC():
    global client
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('127.0.0.1', 7777))

    thr = threading.Thread(target=consoles, args=())
    thr.Daemon = True
    thr.start()

def quitgame():
    pygame.quit()
    sys.exit()

def clamp(x, mi, ma):
    if x > ma:
        return ma
    elif x < mi:
        return mi
    return x

def calcvector(sp, fp):
    direcx = fp[0] - sp[0]
    direcy = fp[1] - sp[1]
    l = math.sqrt(direcx ** 2 + direcy ** 2)
    if l == 0:
        return (1, 0)
    else:
        return (direcx / l, direcy / l)

def GameMain():
    global playerHp, eneHp
    global playerxdirec, playerydirec
    global enex, eney
    fps = pygame.time.Clock()

    img = pygame.image.load('char.png')
    imgh = img.get_size()[1]
    imgw = img.get_size()[0]
    x = 0
    y = imgh

    while True:
        screen.fill((255, 255, 255))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:#send bullet data to server
                    T = pygame.mouse.get_pos()
                    direcvec = calcvector((x, y), T)
                    speed = 8
                    newB = Bullet(bulletimg, x, y, direcvec[0] * speed, direcvec[1] * speed, 10, 10, 10, 'M')
                    bulletlist.append(newB)
                    bullet_data = json.dumps({
                        'type': 1,
                        'x': x,
                        'y': y,
                        'dx': direcvec[0] * speed,
                        'dy': direcvec[1] * speed,
                        'width': 10,
                        'height': 10,
                        'damage': 10
                    })
                    client.sendall(bullet_data.encode())

        keys = pygame.key.get_pressed()
        if not(keys[pygame.K_a] ^ keys[pygame.K_d]):
            playerxdirec = 0
            msg = "endx"
            client.sendall(msg.encode())
        elif keys[pygame.K_a]:
            playerxdirec = -1
            msg = "left"
            client.sendall(msg.encode())
        elif keys[pygame.K_d]:
            playerxdirec = 1
            msg = "right"
            client.sendall(msg.encode())
        if not(keys[pygame.K_w] ^ keys[pygame.K_s]):
            playerydirec = 0
            msg = "endy"
            client.sendall(msg.encode())
        elif keys[pygame.K_w]:
            playerydirec = -1
            msg = "up"
            client.sendall(msg.encode())
        elif keys[pygame.K_s]:
            playerydirec = 1
            msg = "down"
            client.sendall(msg.encode())

        for i in bulletlist:
            i.move()
            bulpos = i.getpos()
            if bulpos[0] > width or bulpos[0] < 0 or bulpos[1] < 0 or bulpos[1] > height:
                bulletlist.remove(i)
                continue
            else:
                i.show()
            if i.getrect().colliderect(getPlayerrect((x, y))) and i.getteam() == 'E':
                bulletlist.remove(i)
                continue
            if i.getrect().colliderect(getPlayerrect((enex, eney))) and i.getteam() == 'M':
                bulletlist.remove(i)
                continue
        if playerHp <= 0:
            print('LOSE')
            quitgame()
        if eneHp <= 0:
            print('WIN')
            quitgame()
        enehpposrect = pygame.Rect(0, 0, 30, 8)
        enehpposrect.center = (enex, eney + 20)
        enehpposrect2 = pygame.Rect(enehpposrect.x, enehpposrect.y, 30 * (eneHp / 100), 8)
        pygame.draw.rect(screen, "red", enehpposrect)
        pygame.draw.rect(screen, "green", enehpposrect2)
        playerhpposrect = pygame.Rect(0, 0, 30, 8)
        playerhpposrect.center = (x, y + 20)
        playerhpposrect2 = pygame.Rect(playerhpposrect.x, playerhpposrect.y, 30 * (playerHp / 100), 8)
        pygame.draw.rect(screen, "red", playerhpposrect)
        pygame.draw.rect(screen, "green", playerhpposrect2)

        x += playerxdirec * playerspeed
        y += playerydirec * playerspeed
        enex += enexdirec * playerspeed
        eney += eneydirec * playerspeed
        x = clamp(x, 0, width)
        y = clamp(y, 0, height)
        enex = clamp(enex, 0, width)
        eney = clamp(eney, 0, height)
        mRect = pygame.Rect(0, 0, imgw, imgh)
        mRect.center = (x, y)
        screen.blit(img, mRect)
        eRect = pygame.Rect(0, 0, imgw, imgh)
        eRect.center = (enex, eney)
        screen.blit(enemy_img, eRect)

        pygame.display.update()
        fps.tick(60)

if __name__ == '__main__':
    acceptC()
    GameMain()

当我在电脑上运行这两个代码并玩游戏时,一切正常。

但是,如果我更改IP地址并在两台电脑上运行,播放器移动正常,但是一旦我点击鼠标发射子弹,就会出现以下错误:

json.decoder.JSONDecodeError: Extra data: line 1 column 124 (char 123)

如何解决这个问题?

我尝试使用 pickle 而不是使用 JSON 的解码/编码,但出现以下错误:

_pickle.UnpicklingError: unpickling stack underflow

即使我增加 client.recv 值也会发生同样的错误。

python json python-multithreading multiplayer python-sockets
1个回答
0
投票

def 控制台(): 全球玩家,敌人 而真实: 消息 = 客户端.recv(1024) 如果没有消息: 休息 解码_msgs = msg.decode().split(" ”) 对于decoded_msgs中的decoded_msg: 如果decoded_msg ==“向上”: 敌人.direction_y = -1 elif解码_msg ==“向下”: 敌人.direction_y = 1 elif解码_msg ==“左”: 敌人.direction_x = -1 elif解码_msg ==“正确”: 敌人.direction_x = 1 elif已解码_msg ==“endx”: 敌人.direction_x = 0 elif已解码_msg ==“endy”: 敌人.direction_y = 0 elif解码_msg ==“损坏”: 玩家.take_damage(10) 如果玩家.hp <= 0: print("LOSE") quitgame() elif decoded_msg.startswith("{"): data = json.loads(decoded_msg) if data.get("type") == 1: bulletlist.append(Bullet( bulletimg, data["x"], data["y"], data["dx"], data["dy"], data["width"], data["height"], data["damage"], "E" ))

将consoles()函数替换为以下内容,并在传递数据时为所有数据添加换行符,您的问题将得到解决:

© www.soinside.com 2019 - 2024. All rights reserved.