@LanskoyGames
У модераторов первое место, но только с конца...

Почему код работает, только, если замедлять сервер до 5 кадров секунду?

Сервер

import socket
import pygame, sys, random
from pygame.locals import *
import time
# Создаем сокет
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', 2000))  # Устанавливаем IP-адрес и порт для прослушивания
server_socket.listen()

print("Сервер запущен и ожидает подключения...")

# Ожидаем подключения клиента
client_socket, client_address = server_socket.accept()
print(f"Подключен клиент: {client_address}")

# Получаем данные от клиента
data = client_socket.recv(1024).decode()
print(f"Получено от клиента: {data}")

# Отправляем ответ клиенту
client_socket.send("Сообщение получено".encode())

pygame.init()
mainClock = pygame.time.Clock()
WINDOWWIDTH = 400
WINDOWHEIGHT = 400
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Hungry Square')
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
WHITE = (255, 255, 255)
foodCounter = 0
NEWFOOD = 40
FOODSIZE = 20
player = pygame.Rect(300, 100, 50, 50)
foods = []
for i in range(20):
    foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - FOODSIZE), random.randint(0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE))
moveLeft = False
moveRight = False
moveUp = False
moveDown = False
MOVESPEED = 6
foodSend = []
for food in foods:
    foodSend.append(food.x)
    foodSend.append(food.y)
print(str(foodSend))
client_socket.send(str(foodSend).encode('utf-8'))
abc = 0
for i in range(100):
    abc += 1
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_LEFT or event.key == K_a:
                moveRight = False
                moveLeft = True
            if event.key == K_RIGHT or event.key == K_d:
                moveLeft = False
                moveRight = True
            if event.key == K_UP or event.key == K_w:
                moveDown = False
                moveUp = True
            if event.key == K_DOWN or event.key == K_s:
                moveUp = False
                moveDown = True
        if event.type == KEYUP:
            if event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()
            if event.key == K_LEFT or event.key == K_a:
                moveLeft = False
            if event.key == K_RIGHT or event.key == K_d:
                moveRight = False
            if event.key == K_UP or event.key == K_w:
                moveUp = False
            if event.key == K_DOWN or event.key == K_s:
                moveDown = False
            if event.key == K_x:
                player.top = random.randint(0, WINDOWHEIGHT - player.height)
                player.left = random.randint(0, WINDOWWIDTH - player.width)
        if event.type == MOUSEBUTTONUP:
            foods.append(pygame.Rect(event.pos[0], event.pos[1], FOODSIZE, FOODSIZE))
    foodCounter += 1
    if foodCounter >= NEWFOOD:
        foodCounter = 0
        foods.append(pygame.Rect(random.randint(0, WINDOWWIDTH - FOODSIZE), random.randint(0, WINDOWHEIGHT-FOODSIZE), FOODSIZE, FOODSIZE))
    windowSurface.fill(WHITE)
    if moveDown and player.bottom < WINDOWHEIGHT:
        player.top += MOVESPEED
    if moveUp and player.top > 0:
        player.top -= MOVESPEED
    if moveLeft and player.left > 0:
        player.left -= MOVESPEED
    if moveRight and player.right < WINDOWWIDTH:
        player.right += MOVESPEED
    pygame.draw.rect(windowSurface, BLACK, player)
    for food in foods[:]:
        if player.colliderect(food):
            foods.remove(food)
    if(abc >=100):
        getData = client_socket.recv(1024).decode('utf-8').split(' ')
        a = 0
        if(getData != ''):
            for i in range (int(len(getData) / 2)):
                for food in foods[:]:
                    if food.x == getData[i] and food.y == getData[i+1]:
                        foods.remove(food)
    for i in range(len(foods)):
        pygame.draw.rect(windowSurface, GREEN, foods[i])
    pygame.display.update()
    foodSend = []
    for food in foods:
        foodSend.append(food.x)
        foodSend.append(food.y)
    client_socket.send(str(foodSend).encode('utf-8'))
    time.sleep(0.2)
    mainClock.tick(40)
# Закрываем соединение
client_socket.close()
server_socket.close()
time.sleep(3)
pygame.quit()
sys.exit()

Клиент

import socket
import pygame, sys, random
from pygame.locals import *
import time
pygame.init()
mainClock = pygame.time.Clock()
# Создаем сокет
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('xxx.xxx.xxx.xxx', 2000))  # Замените IP-адрес на IP вашего сервера

# Отправляем данные серверу
message = "Привет, сервер!"
client_socket.send(message.encode())

# Получаем ответ от сервера
response = client_socket.recv(1024).decode()
print(f"Ответ от сервера: {response}")
WINDOWWIDTH = 400
WINDOWHEIGHT = 400
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Hungry Square')
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
WHITE = (255, 255, 255)
foodCounter = 0
NEWFOOD = 40
FOODSIZE = 20
player = pygame.Rect(300, 100, 50, 50)
foods = []
moveLeft = False
moveRight = False
moveUp = False
moveDown = False
MOVESPEED = 6
response = client_socket.recv(4096).decode('utf-8')
foodSend  = (response[1:-1]).split(", ")
a = 0
for i in range(20):
    foods.append(pygame.Rect(int(foodSend[a]), int(foodSend[a+1]), FOODSIZE, FOODSIZE))
    a +=2
sendTo = ''
client_socket.send(sendTo.encode('utf-8'))
for i in range(100):
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_LEFT or event.key == K_a:
                moveRight = False
                moveLeft = True
            if event.key == K_RIGHT or event.key == K_d:
                moveLeft = False
                moveRight = True
            if event.key == K_UP or event.key == K_w:
                moveDown = False
                moveUp = True
            if event.key == K_DOWN or event.key == K_s:
                moveUp = False
                moveDown = True
        if event.type == KEYUP:
            if event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()
            if event.key == K_LEFT or event.key == K_a:
                moveLeft = False
            if event.key == K_RIGHT or event.key == K_d:
                moveRight = False
            if event.key == K_UP or event.key == K_w:
                moveUp = False
            if event.key == K_DOWN or event.key == K_s:
                moveDown = False
            if event.key == K_x:
                player.top = random.randint(0, WINDOWHEIGHT - player.height)
                player.left = random.randint(0, WINDOWWIDTH - player.width)
        if event.type == MOUSEBUTTONUP:
            foods.append(pygame.Rect(event.pos[0], event.pos[1], FOODSIZE, FOODSIZE))
    windowSurface.fill(WHITE)
    if moveDown and player.bottom < WINDOWHEIGHT:
        player.top += MOVESPEED
    if moveUp and player.top > 0:
        player.top -= MOVESPEED
    if moveLeft and player.left > 0:
        player.left -= MOVESPEED
    if moveRight and player.right < WINDOWWIDTH:
        player.right += MOVESPEED
    pygame.draw.rect(windowSurface, BLACK, player)
    sendTo = ''
    for food in foods[:]:
        if player.colliderect(food):
            sendTo += str(food.x)
            sendTo += ' '
            sendTo += str(food.y)
            sendTo += ' '
    client_socket.send(sendTo.encode('utf-8'))
    response = 0
    response = client_socket.recv(8192).decode('utf-8')
    foodSend  = (response[1:-1]).split(", ")
    a = 0
    foods = []
    for i in range(int(len(foodSend)/ 2)):
        foods.append(pygame.Rect(int(foodSend[a]), int(foodSend[a+1]), FOODSIZE, FOODSIZE))
        a +=2
    for i in range(len(foods)):
        pygame.draw.rect(windowSurface, GREEN, foods[i])
    pygame.display.update()
    mainClock.tick(40 )
client_socket.close()
pygame.quit()
sys.exit()

То же самое приходится делать (замедлять до 5 с помощью sleep), если я начинаю пытаться отправлять информацию с клиента на сервер. Как это исправить или вообще нужно полностью менять отправку информации? Он как-то не успевает обработать и слепляет первое и второе сообщение, а потом оказывается, что "[" он не может привести к типу int (но это уже начало следующего кадра).
  • Вопрос задан
  • 2888 просмотров
Решения вопроса 2
Vindicar
@Vindicar
RTFM!
Во-первых, как именно не работает? Комп встаёт со стола и идёт искать Сару Коннор?
Во-вторых,
getData = client_socket.recv(1024).decode('utf-8').split(' ')

А если клиент не прислал данные, то сервер будет стоять и ждать на этой строке, пока хоть что-то не придёт. Хуже, recv() в общем-то не гарантирует, что данные придут одной порцией. На это можно полагаться до килобайта, но выше может быть фрагментация.
Ну и наконец, ты сейчас пытаешься каждый кадр передавать полную информацию о происходящем в игре. Это может и надёжно, но не быстро.
Ответ написан
MANAB
@MANAB
Разрабатываю на C#: Web, Desktop, Gamedev
Может вот тут
data = client_socket.recv(1024).decode()
ждет пока придет 1024 байта от клиента? А отправляется же только лишь столько, сколько есть. Скорее всего немного, вот и копятся 200 мс. Ну это так, предположение.
Выше впм все правильно сказали - нужно сделать протокол общения между клиентом и сервером с учетом особенности работы сети, т.е. отправивнесколько сообщений серверу можно быть уверенным только в том, что данные придутв том же порядке или не придут. Но они могут быть склеенелибо наоборот фрагментированы как угодно в общем случае.
Я обычно формирую заголовок типа 2 байта - длина пакета данных (включая этот заголовок) и 2 байта идентификатор типа пакета (пакет user input отличается от пакета ping по структуре данных). Я читаю сначала 2 байта, превращаю в 16бит число, потом оставшееся количество ожидаемых данных (или жду, пока они не придут)
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@Borjomy
Можно попробовать перед посылкой сообщения отправлять его длину. И на стороне клиента и на стороне сервера. Тогда первым делом вычитывается длина, а далее вы вычитываете не 4096 (например), а конкретное число байт из сокета. И не будет задержек по таймауту. Когда сервер принимает первое сообщение от клиента, его длина ему неизвестна. Заказано 1024 байт, а приходит сколько? Сокет ждет, пока не вывалится по таймауту и только тогда отправляет в программу данные. Тут задержка. Когда ответ оправлен, сервер рвет соединение и сокет на клиенте понимает, что всё. Но тоже, вопрос быстродействия. Лучше все-таки оперировать известными размерами посылки.
Ответ написан
@SIROJA04
Почему gameloop через For и там всего 100кадров?
Естествено твоя програма без использования sleep отработает эти 100 кадров за пару секунд, и твоя игра "перестанет работать".
Если твоей идеей было обнулять переменую при достижении 100кадра, ти обнуляеш "a" а не "abc"(что за глупый нейминг? Ты же сам себя запутаеш).
+почему ты используеш внутри цыкла с переменой і, другой цыкл с переменой і. Изменения і при прохождении вложеного цыкла будут влиять на і внешнего цыкла
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы