Почему моя онлайн-игра pygame зависает и перестает отвечать? - PullRequest
0 голосов
/ 05 августа 2020

Сначала я хочу показать весь код

main.py Это клиентская сторона.

import pygame, sys
import random
from newconstants import *
from components import *
from network import *


win = pygame.display.set_mode((width, height))

pygame.display.set_caption("Client")


def redrawWindow(win, walls, s1,a):

    win.fill((173, 216, 230))
    for w in walls:
        w.draw(win)
    s1.draw(win)
    a.draw(win)
    pygame.display.update()

def main():
    main_run = True
    game_run = True 
    menu_run = True
    clock = pygame.time.Clock()

    while main_run:

        while menu_run:
            clock.tick(60)

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    menu_run = False
                    pygame.quit()
                    sys.exit()
                elif event.type == pygame.KEYDOWN :
                    if event.key == pygame.K_RETURN:
                        try:
                            n = Network()
                        except Exception as e:
                            print(e)
                            pygame.quit()
                            sys.exit()                          

                        id = n.game.id
                        
                        G = n.game.g
                        print(id)

                        while True:
                            try:
                                n.game = n.send(n.game)
                            except Exception as e:
                                print(e)
                                break
                                
                            if n.game.ready:
                                break

                        s1 = n.game.snake[id]
                        s2 = n.game.snake[1 - id]
                        menu_run = False

        # Making Walls and partitions
        walls = [wall(0,0,width, wall_thickness,wall_color),
        wall(0,0,wall_thickness,height,wall_color),
        wall(0,height-wall_thickness,width,wall_thickness,wall_color),
        wall(width-wall_thickness,0,wall_thickness,height,wall_color)]  

        start_x = wall_thickness
        start_y = wall_thickness

        while start_x < width - wall_thickness-cell_thickness:
            start_x += cell_thickness

            # Vertical wall
            vw = wall(start_x,wall_thickness,partition_thickness,height-(2*wall_thickness),partition_color)
            walls.append(vw)

            start_x += partition_thickness
            

        while start_y < height - wall_thickness-cell_thickness:
            start_y += cell_thickness

            # Horizontal wall
            hw = wall(wall_thickness,start_y,width-(2*wall_thickness),partition_thickness,partition_color)
            walls.append(hw)

            start_y += partition_thickness

    


        a = Apple(G)


        while game_run:

            clock.tick(60)

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    game_run = False
                    pygame.quit()
                    sys.exit()

            s1.check_collision(a)
            s1.move()
            redrawWindow(win,walls,s1,a)


main()

server.py Это мой код сервера

import socket, pickle
from _thread import *
from components import *



server = socket.gethostname()
port = 5555

s = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
print("Socket created")

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

s.listen()
print("Waiting for connection Server started")

connected = set()
games = {}
id_count = 0

G = Grid(rows,cols)

start_x = wall_thickness
start_y = wall_thickness

for i in range(0 , G.rows):
    for j in range(0, G.cols):
        G.grid[i][j] = cell(start_x , start_y, cell_thickness,cell_thickness)
        start_x += cell_thickness + partition_thickness
    start_x = wall_thickness
    start_y += cell_thickness + partition_thickness



def threaded_client(conn, p, game_id):
    global id_count, games

    if p == 0 :
        games[game_id].snakes[p] = Snake(random.randint(3,rows//2),random.randint(3,cols//2),snake_head_width,snake_head_height,random.choice(clr_list_1),random.choice(headings),G)
    else:
        games[game_id].snakes[p] = Snake(random.randint(rows//2 + 1, rows - 4),random.randint(cols//2 +1,cols - 4),snake_head_width,snake_head_height,random.choice(clr_list_2),random.choice(headings),G)

    games[game_id].g = G    
    games[game_id].id = p   

    initial_data = pickle.dumps(games[game_id])
    initial_data = bytes(f"{len(initial_data):<{HEADERSIZE}}" , "utf-8")+initial_data
    conn.send(initial_data)

    reply = ""

    while True:
        try:
            # recv data
            full_msg = b""
            new_msg = True

            while True:
                msg = conn.recv(1024)
                if new_msg:
                    msglen = msg[:HEADERSIZE]
                    new_msg = False

                full_msg += msg

                if len(full_msg)-HEADERSIZE == msglen:
                    g = pickle.loads(full_msg[HEADERSIZE:])
                    break

            games[game_id] =  g         

            if game_id in games:
                game = games[game_id]

                if not recieved_data:
                    break
                else:

                    # Send data

                    data = pickle.dumps(games[game_id])
                    data = bytes(f"{len(data):<{HEADERSIZE}}" , "utf-8")+data
                    conn.send(data)                 


            else:
                break
        except Exception as e:
            print(e)
            break

    print("Lost connection")
    try:
        del games[game_id]
        print("Closing Game", game_id)
    except:
        pass
    id_count -= 1
    conn.close()



while True:
    try:
        conn , addr = s.accept()
        print("Connnected to " , addr)

        id_count += 1
        p = 0 
        game_id = (id_count - 1) // 2

        if id_count % 2 == 1:
            games[game_id] = Game(game_id)
            print("Creating a new game")
        else:
            games[game_id].ready = True
            print("Joing on going game")
            p = 1


        start_new_thread(threaded_client , (conn , p, game_id))

    except KeyboardInterrupt as e:
        if conn:  # <---
            conn.close()
        break  # <---

network.py Это класс сети, который клиент использует для подключения к серверу

import socket, pickle
from newconstants import *


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

    def connect(self):
        try:
            self.client.connect(self.addr)  
            full_msg = b""
            new_msg = True

            while True:
                msg = self.client.recv(1024)
                if new_msg:
                    msglen = msg[:HEADERSIZE]
                    new_msg = False

                full_msg += msg

                if len(full_msg)-HEADERSIZE == msglen:
                    self.game = pickle.loads(full_msg[HEADERSIZE:])
                    break

            return self.game

        except Exception as e:
            print("couldn't connect" , e)

    def send(self, send_data):
        try:
            data = pickle.dumps(send_data)
            data = bytes(f"{len(data):<{HEADERSIZE}}" , "utf-8")+data
            self.client.send(data)

            full_msg = b""
            new_msg = True

            while True:
                msg = self.client.recv(1024)
                if new_msg:
                    msglen = msg[:HEADERSIZE]
                    new_msg = False

                full_msg += msg

                if len(full_msg)-HEADERSIZE == msglen:
                    self.game = pickle.loads(full_msg[HEADERSIZE:])
                    break

            return self.game

        except Exception as e:
            print(e)

Есть еще один файл в котором есть все классы, определенные для создания вещей в pygame, не важных для проблемы, но дайте мне знать, если вам это нужно

Теперь я запускаю сервер, он работает нормально, и соединения acepts Затем я запускаю клиент, который он запускает, а затем, вы можете видеть мы должны нажать клавишу ввода, чтобы фактически начать соединение, поэтому, когда я нажимаю клавишу ввода, все застревает. Поскольку эта игра требует, чтобы два клиента делали то же самое с двумя клиентами, результаты не резонируют. На стороне сервера игра создается первым клиентом, а второй клиент подключается, после этого ничего не происходит. Если я принудительно закрываю сервер, я получаю ошибку, указанную ниже

[Errno 9] Плохой дескриптор файла. Потеряно соединение. Неустранимая Python ошибка: не удалось получить блокировку для <_io.BufferedWriter name = ''> в завершение работы интерпретатора, возможно из-за потоков демона Python состояние выполнения: завершение (tstate = 0x173af10)

Поток 0x00007fca7be8e700 (сначала последний вызов): файл «server.py», строка 99 в thread_client

Текущий поток 0x00007fca82c7b740 (сначала последний вызов): Прервано (дамп ядра)

Так что я делаю не так ?? Я вообще этого не понимаю. Пожалуйста, дайте мне знать, если вам нужно что-то еще для решения проблемы. Я впервые работаю с потоками и сокетами, поэтому я новичок ie в этом ваша помощь будет огромной.

Спасибо!

...