Не работает функция масштабирования в игре Агарио python pygame

server.py

import socket
import time
import pygame
import random
import room
import settings
import math


def new_radius(R, r):
    return math.sqrt(R**2 + r**2)


def find(vec):
    """ Форматирует получанные данные """

    otkr = None # Открывающая скобка

    for i in range(len(vec)):
        if vec[i] == '<':
            otkr = i
        if vec[i] == '>' and otkr != None:
            zakr = i

            value = vec[otkr+1:zakr]
            value = list(map(int, value.split(',')))
            return value
    return ''

class Microbe():
    def __init__(self, x, y, radius, color):
        self.position_x = x
        self.position_y = y
        self.radius = radius
        self.color = color


class Player():
    def __init__(self, connection, address, x, y, radius, color):
        self.connection = connection
        self.address = address
        self.position_x = x
        self.position_y = y
        self.radius = radius
        self.color = color
        self.scale = 1
        
        self.WIDTH_WINDOW = 1000
        self.HEIGHT_WINDOW = 800
        self.width_vision = 1000
        self.height_vision = 800
        self.errors = 0

        self.abs_speed = 30 / math.sqrt(self.radius)
        self.speed_x = 0
        self.speed_y = 0


    def change_speed(self, vector):
        """ Изменение скорости игрока """

        if (vector[0] == 0) and (vector[1] == 0):
            self.speed_x = 0
            self.speed_y = 0

        else:
            lenv = math.sqrt((vector[0]**2 + vector[1]**2))
            vector = (vector[0] / lenv, vector[1] / lenv)
            vector = (vector[0] * self.abs_speed, vector[1] * self.abs_speed)

            self.speed_x = vector[0]
            self.speed_y = vector[1]


    def update(self):
        if self.position_x - self.radius <= 0:
            if self.speed_x >= 0:
                self.position_x += self.speed_x
        else:
            if self.position_x + self.radius >= settings.WIDTH_ROOM:
                if self.speed_x <= 0:
                    self.position_x += self.speed_x
            else:
                    self.position_x += self.speed_x


        if self.position_y - self.radius <= 0:
            if self.speed_y >= 0:
                self.position_y += self.speed_y
        else:
            if self.position_y + self.radius >= settings.HEIGHT_ROOM:
                if self.speed_y <= 0:
                    self.position_y += self.speed_y
            else:
                    self.position_y += self.speed_y

        # abs_speed
        self.abs_speed = 30 / math.sqrt(self.radius)

        # Уменьшение радиуса большой бактерии со временем
        if self.radius >= 100:
            self.radius -= self.radius / 18000

        # scale
        if (self.radius >= self.width_vision / 4) or (self.radius >= self.height_vision / 4):
            if (self.width_vision <= settings.WIDTH_ROOM) or (self.height_vision <= settings.HEIGHT_ROOM):
                self.scale *= 2
                self.width_vision = self.WIDTH_WINDOW * self.scale
                self.height_vision = self.HEIGHT_WINDOW * self.scale

        if (self.radius < self.width_vision / 8) and (self.radius < self.height_vision / 8):
            if self.scale > 1:
                self.scale = self.scale // 2
                self.width_vision = self.WIDTH_WINDOW * self.scale
                self.height_vision = self.HEIGHT_WINDOW * self.scale






# Создание сокета
main_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
main_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
main_socket.bind(("localhost", 10000))
main_socket.setblocking(0)
main_socket.listen(5)


# Создание стартового набора мобов
players = [Player(None, None,
                  random.randint(0, settings.WIDTH_ROOM),
                  random.randint(0, settings.HEIGHT_ROOM),
                  random.randint(10, 100),
                  str(random.randint(0, 5)))
           for i in range(settings.MOBS_QUANTITY)
           ]


# Создание стартового набора микробов - корма
microbs = [Microbe(random.randint(0, settings.WIDTH_ROOM),
                   random.randint(0, settings.HEIGHT_ROOM),
                   settings.MICROBE_RADIUS,
                   str(random.randint(0, 5)))
           for i in range(settings.MICROBE_QUANTITY)
           ]


tick = -1
server_work = True


while server_work:
    tick += 1

    # FPS
    clock = room.Win.clock
    clock.tick(settings.FPS)

    if tick == 200:
        tick = 0
        try:
            new_socket, address = main_socket.accept()
            print("Подключился ", address)
            new_socket.setblocking(0)
            spawn = random.choice(microbs)
            if len(microbs) != 0:
                new_player = Player(new_socket,
                                    address,
                                    spawn.position_x,
                                    spawn.position_y,
                                    settings.START_PLAYER_RADIUS,
                                    str(random.randint(0, 5)))
                microbs.remove(spawn)

                message = str(new_player.radius) + ' ' + new_player.color
                new_player.connection.send(message.encode())
                players.append(new_player)
        except:
            pass

        # Дополняем список мобов
        for i in range(settings.MOBS_QUANTITY - len(players)):
            if len(microbs) != 0:
                spawn = random.choice(microbs)
                players.append(Player(None, None,
                                      spawn.position_x,
                                      spawn.position_y,
                                      random.randint(10, 100),
                                      str(random.randint(0, 5))
                                      )
                               )
                microbs.remove(spawn)

        # Дополняем список микробов - корма
        new_microbs = [Microbe(random.randint(0, settings.WIDTH_ROOM),
                           random.randint(0, settings.HEIGHT_ROOM),
                           settings.MICROBE_RADIUS,
                           str(random.randint(0, 5)))
                       for i in range(settings.MICROBE_QUANTITY - len(microbs))
                       ]

        microbs = microbs + new_microbs



    # Считываем команды игроков
    for player in players:
        if player.connection != None:
            try:
                data = player.connection.recv(1024)
                data = data.decode()
                data = find(data)

                # Обработка команд
                player.change_speed(data)
            except:
                pass
        else:
            if tick == 100:
                data = [random.randint(-100, 100), random.randint(-100, 100)]
                player.change_speed(data)

        player.update()


    # Определим, что видит каждый игрок
    visible_balls = [[] for i in range(len(players))]
    for i in range(len(players)):
        # Каких микробов видит i игрок
        for microb in range(len(microbs)):
            distance_x = microbs[microb].position_x - players[i].position_x
            distance_y = microbs[microb].position_y - players[i].position_y

            # i видит микроба
            if (
                    abs(distance_x) <= players[i].width_vision // 2 + microbs[microb].radius
                    and abs(distance_y) <= players[i].height_vision // 2 + microbs[microb].radius
            ):
                # i может съесть микроба
                if (math.sqrt(distance_x**2 + distance_y**2) <= players[i].radius):
                    # Изменим размер i игрока
                    players[i].radius =  new_radius(players[i].radius, microbs[microb].radius)
                    microbs[microb].radius = 0

                if (players[i].connection != None) and (microbs[microb].radius != 0):
                    # Подготовим данные к добавлению в список видимых шаров
                    x_ = str(round(distance_x / players[i].scale))
                    y_ = str(round(distance_y / players[i].scale))
                    radius_ = str(round(microbs[microb].radius / players[i].scale))
                    color_ = str(microbs[microb].color)

                    visible_balls[i].append(x_ + " " + y_ + " " + radius_ + " " + color_)




        for j in range(i+1, len(players)):
            # Рассматриваем пару i и j игрока
            distance_x = players[j].position_x - players[i].position_x
            distance_y = players[j].position_y - players[i].position_y

            # i видит j
            if (
                    abs(distance_x) <= players[i].width_vision // 2 + players[j].radius
                and abs(distance_y) <= players[i].height_vision // 2 + players[j].radius
            ):
                # i может съесть j
                if (math.sqrt(distance_x ** 2 + distance_y ** 2) <= players[i].radius and players[i].radius > players[j].radius * 1.1):
                    # Изменим размер i игрока
                    players[i].radius = new_radius(players[i].radius, players[j].radius)

                    players[j].radius = 0
                    players[j].abs_speed = 0
                    players[j].speed_x = 0
                    players[j].speed_y = 0


                if players[i].connection != None:
                    # Подготовим данные к добавлению в список видимых шаров
                    x_ = str(round(distance_x / players[i].scale))
                    y_ = str(round(distance_y / players[i].scale))
                    radius_ = str(round(players[j].radius / players[i].scale))
                    color_ = str(players[j].color)

                    visible_balls[i].append(x_ + " " + y_ + " " + radius_ + " " + color_)


            # j видит i
            if (
                    abs(distance_x) <= players[j].width_vision // 2 + players[i].radius
                and abs(distance_y) <= players[j].height_vision // 2 + players[i].radius
            ):
                # j может съесть i
                if (math.sqrt(distance_x ** 2 + distance_y ** 2) <= players[j].radius and players[j].radius > players[i].radius * 1.1):
                    # Изменим размер j игрока
                    players[j].radius = new_radius(players[j].radius, players[i].radius)

                    players[i].radius = 0
                    players[i].abs_speed = 0
                    players[i].speed_x = 0
                    players[i].speed_y = 0



                if players[j].connection != None:
                    # Подготовим данные к добавлению в список видимых шаров
                    x_ = str(round(-distance_x / players[j].scale))
                    y_ = str(round(-distance_y / players[j].scale))
                    radius_ = str(round(players[i].radius / players[j].scale))
                    color_ = str(players[i].color)

                    visible_balls[j].append(x_ + " " + y_ + " " + radius_ + " " + color_)

    # Формируем ответ каждому игроку
    otvets = ['' for i in range(len(players))]
    for i in range(len(players)):
        my_radiuse = str(round(players[i].radius // players[i].scale))
        visible_balls[i] = [my_radiuse] + visible_balls[i]
        otvets[i] = '<' + (','.join(visible_balls[i])) + '>'



    # Отправляем новое состояние игрового поля
    for i in range(len(players)):
        if players[i].connection != None:
            try:
                players[i].connection.send(otvets[i].encode())
                players[i].errors = 0
            except:
                players[i].errors += 1

    # Чистим список от отвалившихся игроков
    for player in players:
        if (player.errors == 500) or (player.radius == 0):
            if player.connection != None:
                player.connection.close()
            players.remove(player)

    # Чистим список от съеденных микробов
    for microb in microbs:
        if microb.radius == 0:
            microbs.remove(microb)




    # Нарисуем состояние комнаты
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            server_work = False

    room.Win.screen.fill("GRAY")
    for player in players:
        position_x = round(player.position_x * room.WIDTH_SERVER_WINDOW / settings.WIDTH_ROOM)
        position_y = round(player.position_y * room.HEIGHT_SERVER_WINDOW / settings.HEIGHT_ROOM)
        radius = round(player.radius * room.WIDTH_SERVER_WINDOW / settings.WIDTH_ROOM)
        color = settings.PLAYER_COLORS[player.color]
        pygame.draw.circle(room.Win.screen, color, (position_x, position_y), radius)

    pygame.display.update()


pygame.quit()
main_socket.close()

client.py

import socket
import pygame
import math
import settings


WIDTH = settings.WIDTH
HEIGHT = settings.HEIGHT
COLORS = settings.PLAYER_COLORS


class Me():
    def __init__(self, data):
        data = data.split()
        self.radiuse = int(data[0])
        self.color = data[1]

    def update(self, new_radiuse):
        self.radiuse = new_radiuse

    def draw(self):
        if self.radiuse != 0:
            pygame.draw.circle(
                screen,
                COLORS[self.color],
                (WIDTH // 2, HEIGHT // 2),
                self.radiuse
            )



# Подключение к серверу
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
sock.connect(("localhost", 10000))

data = sock.recv(64).decode()
me = Me(data)

def find(vec):
    """ Форматирует получанные данные """

    otkr = None

    for i in range(len(vec)):
        if vec[i] == '<':
            otkr = i
        if vec[i] == '>' and otkr != None:
            zakr = i

            value = vec[otkr + 1:zakr]
            return value
    return ''



def draw_players(data):
    for i in range(len(data)):
        j = data[i].split(' ')

        position_x = WIDTH // 2 + int(j[0])
        position_y = HEIGHT // 2 + int(j[1])
        size = int(j[2])
        color = COLORS[j[3]]


        pygame.draw.circle(
            screen,
            color,
            (position_x, position_y),
            size
        )


# Создание окна игры
pygame.init()
screen = pygame.display.set_mode((settings.WIDTH, settings.HEIGHT))
pygame.display.set_caption(settings.NAME_GAME)


old_vector = (0, 0)
running = True

while running:

    # Считываем команды
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False


    # Считываем положение мыши игрока
    vector = (0, 0)
    if pygame.mouse.get_focused():
        position = pygame.mouse.get_pos()
        vector = (position[0] - WIDTH // 2, position[1] - HEIGHT // 2)

        if math.sqrt((vector[0])**2 + (vector[1])**2) <= me.radiuse:
            vector = (0, 0)


    # Отправляем вектор если он поменялся
    if vector != old_vector:
        old_vector = vector
        message = f"<{str(vector[0])},{str(vector[1])}>"
        sock.send(message.encode())


    # Получаем от севрера новое состояние игрового поля
    data = sock.recv(20**2)
    data = data.decode()
    data = find(data)
    data = data.split(',')


    # Рисуем новое состояние игрового поля
    screen.fill(settings.BG_COLOR)

    if data != ['']:
        me.update(int(data[0]))
        draw_players(data[1:])
        me.draw()


    pygame.display.update()


pygame.quit()

room.py

import socket
import settings
import pygame


WIDTH_ROOM = settings.WIDTH_ROOM
HEIGHT_ROOM = settings.HEIGHT_ROOM

WIDTH_SERVER_WINDOW = settings.WIDTH_SERVER_WINDOW
HEIGHT_SERVER_WINDOW = settings.HEIGHT_SERVER_WINDOW

pygame.init()

# Создание графического окна сервера
class Window():
    """ Графическое окно сервера """

    def __init__(self):
        self.screen = pygame.display.set_mode((WIDTH_SERVER_WINDOW, HEIGHT_SERVER_WINDOW))
        self.clock = pygame.time.Clock()


Win = Window()

settings.py

""" Файл со всеми настройками в игре"""


WIDTH = 1000
HEIGHT = 800

NAME_GAME = "Agar.IO"

BG_COLOR = (100, 100, 100)
PLAYER_COLORS = {'0': (255, 0, 0),
                 '1': (0, 255, 0),
                 '2': (0, 0, 255),
                 '3': (255, 255, 0),
                 '4': (0, 255, 255),
                 '5': (255, 0, 255)}

START_PLAYER_RADIUS = 50
RADIUS = 50


WIDTH_ROOM = 4000
HEIGHT_ROOM = 4000

WIDTH_SERVER_WINDOW = 300
HEIGHT_SERVER_WINDOW = 300

WIDTH_VISION = 1000
HEIGHT_VISION = 800

FPS = 120


MOBS_QUANTITY = 25

MICROBE_RADIUS = 15
MICROBE_QUANTITY = (WIDTH_ROOM * HEIGHT_ROOM) // 80000

ОШИБКА в server.py на 104 строке, именно после добавления этой части кода программа работает некорректно, а именно после того как игрок становится очень большим, то чтобы он поместился в игровое окно он уменьшается вместе со всеми предметами, но только на клиенте. Так вот, ошибка в том, то после того как объекты обмасштабировались, объекты начинают мерцать и пропадать, после того как ты стал еще больше, то объекты вовсе пропали и не появляются!!!

Сначала запускать srver.py, потом уже client.py

Пожалуйста помогите мне, я делал все как в видео ролике: https://www.youtube.com/watch?v=bqomWX1nucQ&list=PLtckA7rmuGOieyToagrhf8dOQhiJOHHbF&index=8

тайм код 20:45


Ответы (0 шт):