Не работает функция масштабирования в игре Агарио 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