Участник:Prionosuchus
Prionosuchus — древняя амфибия, жившая в пермском периоде (т.е. до Хренозоя).
Коды для игр[править]
(потом перемещу их в нужную статью, а пока проверяю их здесь)
import pygame
import random
import math
pygame.init()
WIDTH, HEIGHT = 1400, 1000
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Щучье озеро (вид сверху)")
clock = pygame.time.Clock()
FPS = 60
SAND_COLOR = (210, 180, 140)
WATER_CENTER_COLOR = (20, 80, 180)
BLUE = (50, 150, 250)
GREEN = (0, 150, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (200, 0, 0)
DARK_GREEN = (0, 100, 0)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
MAX_LEECHES = 1000
MAX_EGGS = 3000
EGG_LIFETIME = 10000
GRID_DISPLAY_TIME = 1000
STARVATION_TIME = 60000
DEATH_SPAWN_EGGS = 20
SHORE_WIDTH = 80
SHORE_WIDTH_SMALL = 20
DARKEN_RECT_W = 340
DARKEN_RECT_H = 300
DARKEN_ALPHA = 80
DARKEN_RECT = pygame.Rect(
WIDTH // 2 - DARKEN_RECT_W // 2,
HEIGHT // 2 - DARKEN_RECT_H // 2,
DARKEN_RECT_W,
DARKEN_RECT_H
)
font = pygame.font.SysFont("Arial", 20)
big_font = pygame.font.SysFont("Arial", 36)
speech_font = pygame.font.SysFont("Arial", 18)
help_font = pygame.font.SysFont("Arial", 16)
PHRASES_EAT_LEECH = ["Вкуснятина!", "Ням-ням!", "Пиявка - вкусно!", "Ммм, пиявка!"]
PHRASES_EAT_PIKE = ["Ты слишком мал!", "Каннибализм!", "Я сильнее!", "Ай, как нехорошо!"]
PHRASES_EAT_EGG = ["Икорка!", "Вкусные яйца!", "Ням!"]
PHRASES_SPAWN = ["Потомство будет!", "Я папа!", "Я мама!", "Пора размножаться!"]
PHRASES_DEATH_OLD = ["Я устал, ухожу...", "Прощайте, потомки!", "Старость не радость...", "Тима раков, я ливаю!"]
PHRASES_DEATH_STARVE = ["Я голодал...", "Нет еды...", "Помогите!"]
PHRASES_CAUGHT = ["Ой, блесна!", "Попался!", "Твою дивизию!"]
PHRASES_WINTER = ["Капеееееец", "В спячку!", "Зима близко!", "Холодно"]
PHRASES_POST_WINTER = ["Весна пришла!", "Пора нереститься!", "Рота подъём!!!"]
PHRASES_FLEE = ["Я сделал дело, ухожу!", "Пока!", "Ну его нафиг!"]
PHRASES_RANDOM = ["Где еда?", "Я голоден", "Плыву", "Ой, что-то блестит", "Хочу пиявку", "Кто там?"]
PHRASES_FRY_SPAWN = ["Новая жизнь!", "Вперёд!!!", "Я родился!"]
MAX_MESSAGES = 5
messages = []
def add_message(text, x, y, duration=2000, probability=1.0):
if random.random() > probability:
return
global messages
if len(messages) >= MAX_MESSAGES:
messages.pop(0)
messages.append({'text': text, 'x': x, 'y': y, 'timer': pygame.time.get_ticks() + duration})
def random_leech_position():
if random.random() < 0.7:
side = random.randint(0, 3)
if side == 0:
x = random.uniform(SHORE_WIDTH, 2 * SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
elif side == 1:
x = random.uniform(WIDTH - 2 * SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
elif side == 2:
x = random.uniform(SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, 2 * SHORE_WIDTH)
else:
x = random.uniform(SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(HEIGHT - 2 * SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
else:
x = random.uniform(2 * SHORE_WIDTH, WIDTH - 2 * SHORE_WIDTH)
y = random.uniform(2 * SHORE_WIDTH, HEIGHT - 2 * SHORE_WIDTH)
return x, y
def random_water_position(small=False):
limit = SHORE_WIDTH_SMALL if small else SHORE_WIDTH
x = random.uniform(limit, WIDTH - limit)
y = random.uniform(limit, HEIGHT - limit)
return x, y
def create_water_surface(width, height, shore_width):
surf = pygame.Surface((width, height), pygame.SRCALPHA)
water_color = WATER_CENTER_COLOR
surf.fill((water_color[0], water_color[1], water_color[2], 255))
for y in range(height):
for x in range(width):
dx = min(x, width - 1 - x)
dy = min(y, height - 1 - y)
d = min(dx, dy)
if d < shore_width:
alpha = int(255 * (d / shore_width))
surf.set_at((x, y), (water_color[0], water_color[1], water_color[2], alpha))
return surf
sand_surf = pygame.Surface((WIDTH, HEIGHT))
sand_surf.fill(SAND_COLOR)
water_surf = create_water_surface(WIDTH, HEIGHT, SHORE_WIDTH)
winter_active = False
ice_surf = None
def create_ice_surface(width, height):
"""Создаёт полупрозрачную ледяную поверхность."""
surf = pygame.Surface((width, height), pygame.SRCALPHA)
surf.fill((200, 230, 255, 80))
for _ in range(500):
x = random.randint(0, width - 1)
y = random.randint(0, height - 1)
alpha = random.randint(30, 100)
surf.set_at((x, y), (255, 255, 255, alpha))
return surf
def toggle_winter():
global winter_active, ice_surf, leeches, pikes, eggs
if not winter_active:
winter_active = True
ice_surf = create_ice_surface(WIDTH, HEIGHT)
if leeches:
leeches = random.sample(leeches, max(1, int(len(leeches) * 0.2)))
pikes = [p for p in pikes if p.length >= 70]
center_rect = DARKEN_RECT
for pike in pikes:
pike.state = "wintering"
pike.target_point = (
random.uniform(center_rect.left, center_rect.right),
random.uniform(center_rect.top, center_rect.bottom)
)
pike.current_speed = pike.base_speed
pike.target = None
pike.has_post_winter_spawned = False
add_message(random.choice(PHRASES_WINTER), pike.x, pike.y, probability=1.0)
else:
winter_active = False
ice_surf = None
for pike in pikes:
if pike.state == "wintering":
pike.state = "post_winter"
side = random.randint(0, 3)
if side == 0:
x = random.uniform(SHORE_WIDTH, 2 * SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
elif side == 1:
x = random.uniform(WIDTH - 2 * SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
elif side == 2:
x = random.uniform(SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(SHORE_WIDTH, 2 * SHORE_WIDTH)
else:
x = random.uniform(SHORE_WIDTH, WIDTH - SHORE_WIDTH)
y = random.uniform(HEIGHT - 2 * SHORE_WIDTH, HEIGHT - SHORE_WIDTH)
pike.target_point = (x, y)
pike.current_speed = pike.base_speed
pike.target = None
pike.has_post_winter_spawned = False
add_message(random.choice(PHRASES_POST_WINTER), pike.x, pike.y, probability=1.0)
class Leech:
def __init__(self, x, y):
self.x = x
self.y = y
self.length = random.randint(2, 15)
self.angle = random.uniform(0, 2 * math.pi)
self.speed = 0.9
self.segments = 4
self.time = random.random() * 100
def update(self):
if random.random() < 0.02:
self.angle += random.uniform(-0.5, 0.5)
self.x += self.speed * math.cos(self.angle)
self.y += self.speed * math.sin(self.angle)
if self.x < 0:
self.x = 0
self.angle = math.pi - self.angle
if self.x > WIDTH:
self.x = WIDTH
self.angle = math.pi - self.angle
if self.y < 0:
self.y = 0
self.angle = -self.angle
if self.y > HEIGHT:
self.y = HEIGHT
self.angle = -self.angle
self.time += 0.1
def draw(self, screen):
points = []
step = self.length / self.segments
x, y = self.x, self.y
angle = self.angle
for i in range(self.segments + 1):
points.append((x, y))
bend = 0.3 * math.sin(self.time + i * 0.5)
angle += bend * 0.1
x += step * math.cos(angle)
y += step * math.sin(angle)
if len(points) > 1:
pygame.draw.lines(screen, BLACK, False, points, 1)
class Egg:
def __init__(self, x, y):
self.x = x
self.y = y
self.radius = 3
self.born_time = pygame.time.get_ticks()
def update(self, pikes):
if pygame.time.get_ticks() - self.born_time >= EGG_LIFETIME:
fry_x = max(SHORE_WIDTH_SMALL, min(WIDTH - SHORE_WIDTH_SMALL, self.x))
fry_y = max(SHORE_WIDTH_SMALL, min(HEIGHT - SHORE_WIDTH_SMALL, self.y))
fry = Pike(fry_x, fry_y, initial_length=8, state="fleeing_from_spawn")
angle = random.uniform(0, 2 * math.pi)
dist = 50
fry.target_point = (fry_x + dist * math.cos(angle), fry_y + dist * math.sin(angle))
pikes.append(fry)
add_message(random.choice(PHRASES_FRY_SPAWN), fry.x, fry.y, probability=1.0)
return True
return False
def draw(self, screen):
surf = pygame.Surface((self.radius * 2, self.radius * 2), pygame.SRCALPHA)
pygame.draw.circle(surf, (0, 200, 0, 128), (self.radius, self.radius), self.radius)
pygame.draw.circle(surf, (0, 100, 0), (self.radius, self.radius), self.radius, 1)
screen.blit(surf, (self.x - self.radius, self.y - self.radius))
class Bait:
def __init__(self, x, y):
self.x = x
self.y = y
self.width = 12
self.height = 8
self.speed = 5
def update(self, keys):
if keys[pygame.K_UP]:
self.y -= self.speed
if keys[pygame.K_DOWN]:
self.y += self.speed
if keys[pygame.K_LEFT]:
self.x -= self.speed
if keys[pygame.K_RIGHT]:
self.x += self.speed
self.x = max(SHORE_WIDTH + self.width // 2, min(WIDTH - SHORE_WIDTH - self.width // 2, self.x))
self.y = max(SHORE_WIDTH + self.height // 2, min(HEIGHT - SHORE_WIDTH - self.height // 2, self.y))
def draw(self, screen):
pygame.draw.ellipse(screen, RED, (self.x - self.width // 2, self.y - self.height // 2, self.width, self.height))
class Pike:
def __init__(self, x, y, initial_length=12, state="normal"):
self.x = x
self.y = y
self.length = initial_length
self.width = max(5, self.length / 7)
self.angle = random.uniform(0, 2 * math.pi)
self.base_speed = self.calc_base_speed(initial_length)
self.current_speed = self.base_speed
self.target = None
self.state = state
self.target_point = None
self.max_length_reached = False
self.time_at_max = 0
self.last_eat_egg_time = 0
self.last_meal_time = pygame.time.get_ticks()
self.last_update_time = pygame.time.get_ticks()
self.has_spawned_on_death = False
self.has_post_winter_spawned = False
self.last_random_speech = random.randint(0, 5000)
self.generate_sprite()
def calc_base_speed(self, length):
return 3.0 - (length - 8) / 152 * 1.0
def get_shore_limit(self):
return SHORE_WIDTH_SMALL if self.length <= 29 else SHORE_WIDTH
def generate_sprite(self):
w = int(self.length)
h = int(self.width)
if w < 5 or h < 3:
surf = pygame.Surface((w, h), pygame.SRCALPHA)
pygame.draw.ellipse(surf, GREEN, (0, 0, w, h))
self.sprite = surf
return
surf = pygame.Surface((w, h), pygame.SRCALPHA)
body_color = (30, 80, 30)
pygame.draw.ellipse(surf, body_color, (0, 0, w, h))
spine_color = (20, 60, 20)
belly_color = (30, 80, 30)
spine_rect = pygame.Rect(0, 0, w, h // 2 + 2)
pygame.draw.ellipse(surf, spine_color, spine_rect)
belly_rect = pygame.Rect(0, h // 2 - 2, w, h // 2 + 2)
pygame.draw.ellipse(surf, belly_color, belly_rect)
eye_radius = max(2, int(0.09 * h))
pupil_radius = max(1, int(0.05 * h))
eye_x = int(0.8 * w)
eye_y1 = int(0.35 * h)
eye_y2 = int(0.65 * h)
pygame.draw.circle(surf, WHITE, (eye_x, eye_y1), eye_radius)
pygame.draw.circle(surf, WHITE, (eye_x, eye_y2), eye_radius)
pupil_offset = int(0.2 * eye_radius)
pygame.draw.circle(surf, BLACK, (eye_x + pupil_offset, eye_y1), pupil_radius)
pygame.draw.circle(surf, BLACK, (eye_x + pupil_offset, eye_y2), pupil_radius)
dorsal_color = (20, 60, 20)
dorsal_x = int(0.2 * w)
dorsal_w = int(0.5 * w)
dorsal_h = max(2, int(h * 0.25))
pygame.draw.ellipse(surf, dorsal_color, (dorsal_x, 0, dorsal_w, dorsal_h))
pectoral_color = (20, 60, 20)
pect_w = int(0.06 * w)
pect_h = int(0.15 * h)
pygame.draw.ellipse(surf, pectoral_color, (int(0.6 * w), int(0.05 * h), pect_w, pect_h))
pygame.draw.ellipse(surf, pectoral_color, (int(0.6 * w), int(0.8 * h), pect_w, pect_h))
tail_color = ORANGE
tail_w = int(0.3 * w)
tail_h = int(0.9 * h)
tail_x = -tail_w // 2
tail_y = (h - tail_h) // 2
pygame.draw.ellipse(surf, tail_color, (tail_x, tail_y, tail_w, tail_h))
num_spots = random.randint(3, 6)
for _ in range(num_spots):
cx = random.uniform(0.2, 0.8) * w
cy = random.uniform(0.15, 0.4) * h
rx = random.uniform(0.02, 0.08) * w
ry = random.uniform(0.02, 0.08) * h
color = random.choice([(0, 30, 0), (10, 50, 10), (20, 70, 20)])
pygame.draw.ellipse(surf, color, (int(cx - rx / 2), int(cy - ry / 2), int(rx), int(ry)))
pygame.draw.ellipse(surf, color, (int(cx - rx / 2), int(h - cy - ry / 2), int(rx), int(ry)))
for _ in range(random.randint(2, 4)):
cx = random.uniform(0.3, 0.7) * w
cy = random.uniform(0.05, 0.2) * h
rx = random.uniform(0.02, 0.06) * w
ry = random.uniform(0.01, 0.04) * h
pygame.draw.ellipse(surf, (0, 20, 0), (int(cx - rx / 2), int(cy - ry / 2), int(rx), int(ry)))
self.sprite = surf
def get_tint(self):
if DARKEN_RECT.collidepoint(self.x, self.y):
return (0, 0, 0, DARKEN_ALPHA)
return (0, 0, 0, 0)
def find_target(self, leeches, pikes, eggs, bait):
if self.state != "normal":
self.target = None
return
if self.length >= 160 and bait is not None:
self.target = bait
return
min_dist = float('inf')
target = None
if self.length < 40:
for leech in leeches:
dist = math.hypot(self.x - leech.x, self.y - leech.y)
if dist < min_dist:
min_dist = dist
target = leech
if self.length >= 30:
for other in pikes:
if other is self:
continue
if other.length < self.length / 2:
dist = math.hypot(self.x - other.x, self.y - other.y)
if dist < min_dist:
min_dist = dist
target = other
if min_dist == float('inf') or min_dist > 200:
for egg in eggs:
dist = math.hypot(self.x - egg.x, self.y - egg.y)
if dist < min_dist:
min_dist = dist
target = egg
self.target = target
def update(self, leeches, pikes, eggs, bait, current_time):
dt = current_time - self.last_update_time
self.last_update_time = current_time
limit = self.get_shore_limit()
if self.state == "wintering":
if self.target_point is not None:
tx, ty = self.target_point
dx = tx - self.x
dy = ty - self.y
dist = math.hypot(dx, dy)
if dist > 0:
self.angle = math.atan2(dy, dx)
if dist < self.current_speed:
self.x = tx
self.y = ty
self.current_speed = 0
else:
self.x += self.current_speed * dx / dist
self.y += self.current_speed * dy / dist
self.x = max(limit, min(WIDTH - limit, self.x))
self.y = max(limit, min(HEIGHT - limit, self.y))
return
if self.state == "post_winter":
if self.target_point is not None:
tx, ty = self.target_point
dx = tx - self.x
dy = ty - self.y
dist = math.hypot(dx, dy)
if dist > 0:
self.angle = math.atan2(dy, dx)
if dist < self.current_speed:
self.x = tx
self.y = ty
if not self.has_post_winter_spawned:
if self.length >= 50 and len(eggs) < MAX_EGGS:
num_eggs = int(0.5 * self.length)
for _ in range(num_eggs):
angle = random.uniform(0, 2 * math.pi)
dist2 = random.uniform(10, 30)
ex = self.x + dist2 * math.cos(angle)
ey = self.y + dist2 * math.sin(angle)
ex = max(SHORE_WIDTH + 5, min(WIDTH - SHORE_WIDTH - 5, ex))
ey = max(SHORE_WIDTH + 5, min(HEIGHT - SHORE_WIDTH - 5, ey))
eggs.append(Egg(ex, ey))
add_message(random.choice(PHRASES_SPAWN), self.x, self.y, probability=1.0)
self.has_post_winter_spawned = True
self.state = "normal"
self.target_point = None
self.current_speed = self.base_speed
else:
self.x += self.current_speed * dx / dist
self.y += self.current_speed * dy / dist
self.x = max(limit, min(WIDTH - limit, self.x))
self.y = max(limit, min(HEIGHT - limit, self.y))
return
if self.state in ("fleeing_from_spawn", "fleeing_from_eggs"):
if self.target_point is not None:
tx, ty = self.target_point
dx = tx - self.x
dy = ty - self.y
dist = math.hypot(dx, dy)
if dist > 0:
self.angle = math.atan2(dy, dx)
if dist < self.current_speed:
self.x = tx
self.y = ty
else:
self.x += self.current_speed * dx / dist
self.y += self.current_speed * dy / dist
if dist <= self.current_speed + 2:
self.state = "normal"
self.target_point = None
self.current_speed = self.base_speed
else:
self.state = "normal"
self.x = max(limit, min(WIDTH - limit, self.x))
self.y = max(limit, min(HEIGHT - limit, self.y))
return
self.find_target(leeches, pikes, eggs, bait)
if self.target is not None:
dx = self.target.x - self.x
dy = self.target.y - self.y
dist = math.hypot(dx, dy)
if dist > 0:
self.angle = math.atan2(dy, dx)
if dist < self.current_speed:
self.x = self.target.x
self.y = self.target.y
else:
self.x += self.current_speed * dx / dist
self.y += self.current_speed * dy / dist
self.x = max(limit, min(WIDTH - limit, self.x))
self.y = max(limit, min(HEIGHT - limit, self.y))
if self.state == "normal" and current_time - self.last_random_speech > 5000:
if random.random() < 0.01:
phrase = random.choice(PHRASES_RANDOM)
add_message(phrase, self.x, self.y, duration=1500, probability=1.0)
self.last_random_speech = current_time
def check_eat(self, leeches, pikes, eggs, bait, current_time):
if self.state != "normal":
return False
if self.length >= 160 and bait is not None:
dist = math.hypot(self.x - bait.x, self.y - bait.y)
if dist < max(10, self.length / 2 + 5):
add_message(random.choice(PHRASES_CAUGHT), self.x, self.y, probability=1.0)
return "bait_eaten"
if self.length < 40:
for leech in leeches:
dist = math.hypot(self.x - leech.x, self.y - leech.y)
if dist < max(10, self.length / 2 + 5):
leeches.remove(leech)
self.last_meal_time = current_time
if not self.max_length_reached:
self.length += leech.length
self.width = max(5, self.length / 7)
self.generate_sprite()
prob = 1.0 if self.length > 50 else 0.5
add_message(random.choice(PHRASES_EAT_LEECH), self.x, self.y, probability=prob)
return True
if self.length >= 30:
for other in pikes:
if other is self:
continue
if other.length < self.length / 2:
dist = math.hypot(self.x - other.x, self.y - other.y)
if dist < max(10, self.length / 2 + 5):
pikes.remove(other)
self.last_meal_time = current_time
if not self.max_length_reached:
self.length += other.length
self.width = max(5, self.length / 7)
self.generate_sprite()
prob = 1.0 if self.length > 50 else 0.5
add_message(random.choice(PHRASES_EAT_PIKE), self.x, self.y, probability=prob)
return True
if current_time - self.last_eat_egg_time >= 1000:
for egg in eggs:
dist = math.hypot(self.x - egg.x, self.y - egg.y)
if dist < max(10, self.length / 2 + 5):
eggs.remove(egg)
self.last_eat_egg_time = current_time
self.last_meal_time = current_time
if not self.max_length_reached:
self.length += 1
self.width = max(5, self.length / 7)
self.generate_sprite()
prob = 1.0 if self.length > 50 else 0.5
add_message(random.choice(PHRASES_EAT_EGG), self.x, self.y, probability=prob)
return True
return False
def draw(self, screen):
if self.sprite is None:
return
rotated = pygame.transform.rotate(self.sprite, -math.degrees(self.angle))
rect = rotated.get_rect(center=(self.x, self.y))
tint = self.get_tint()
if tint[3] > 0:
tint_surf = pygame.Surface(rotated.get_size(), pygame.SRCALPHA)
tint_surf.fill(tint)
rotated.blit(tint_surf, (0, 0), special_flags=pygame.BLEND_RGBA_MULT)
screen.blit(rotated, rect)
def draw_help_panel(screen):
panel_x = WIDTH - 260
panel_y = 20
panel_w = 240
panel_h = 300
s = pygame.Surface((panel_w, panel_h), pygame.SRCALPHA)
s.fill((0, 0, 0, 80))
screen.blit(s, (panel_x, panel_y))
pygame.draw.rect(screen, WHITE, (panel_x, panel_y, panel_w, panel_h), 1)
lines = [
("Управление:", WHITE),
("Щ - создать щуку", YELLOW),
("1 - установить приманку", YELLOW),
("Стрелки - управлять приманкой", YELLOW),
("И - создать икру", YELLOW),
("З - зима/лето", YELLOW),
("Выделение мышью - поймать", YELLOW),
("существ в области", YELLOW),
]
y_offset = panel_y + 10
for text, color in lines:
surf = help_font.render(text, True, color)
screen.blit(surf, (panel_x + 10, y_offset))
y_offset += 22
leeches = []
for _ in range(100):
x, y = random_leech_position()
leeches.append(Leech(x, y))
pikes = []
eggs = []
bait = None
last_spawn_time = pygame.time.get_ticks()
spawn_interval = 10000
last_reproduction_time = pygame.time.get_ticks()
reproduction_interval = 15000
catch_message = ""
catch_message_timer = 0
selecting = False
select_start = None
select_end = None
grid_rect = None
grid_timer = 0
running = True
while running:
current_time = pygame.time.get_ticks()
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.unicode == 'щ':
x, y = random_water_position(small=True)
pikes.append(Pike(x, y))
if event.key == pygame.K_ESCAPE:
running = False
if event.key == pygame.K_1:
mx, my = pygame.mouse.get_pos()
mx = max(SHORE_WIDTH, min(WIDTH - SHORE_WIDTH, mx))
my = max(SHORE_WIDTH, min(HEIGHT - SHORE_WIDTH, my))
bait = Bait(mx, my)
if event.key == pygame.K_b:
mx, my = pygame.mouse.get_pos()
mx = max(SHORE_WIDTH, min(WIDTH - SHORE_WIDTH, mx))
my = max(SHORE_WIDTH, min(HEIGHT - SHORE_WIDTH, my))
for _ in range(40):
if len(eggs) < MAX_EGGS:
angle = random.uniform(0, 2 * math.pi)
dist = random.uniform(10, 30)
x = mx + dist * math.cos(angle)
y = my + dist * math.sin(angle)
x = max(SHORE_WIDTH + 5, min(WIDTH - SHORE_WIDTH - 5, x))
y = max(SHORE_WIDTH + 5, min(HEIGHT - SHORE_WIDTH - 5, y))
eggs.append(Egg(x, y))
if event.key == pygame.K_p:
toggle_winter()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
selecting = True
select_start = event.pos
select_end = event.pos
if event.type == pygame.MOUSEMOTION and selecting:
select_end = event.pos
if event.type == pygame.MOUSEBUTTONUP and event.button == 1 and selecting:
selecting = False
x1, y1 = select_start
x2, y2 = select_end
left = min(x1, x2)
right = max(x1, x2)
top = min(y1, y2)
bottom = max(y1, y2)
rect = pygame.Rect(left, top, right - left, bottom - top)
for pike in pikes[:]:
if rect.collidepoint(pike.x, pike.y):
pikes.remove(pike)
for egg in eggs[:]:
if rect.collidepoint(egg.x, egg.y):
eggs.remove(egg)
for leech in leeches[:]:
if rect.collidepoint(leech.x, leech.y):
leeches.remove(leech)
grid_rect = rect
grid_timer = current_time + GRID_DISPLAY_TIME
if not winter_active and current_time - last_spawn_time >= spawn_interval:
last_spawn_time = current_time
current_count = len(leeches)
if current_count < MAX_LEECHES:
new_count = min(current_count * 3, MAX_LEECHES)
for _ in range(new_count - current_count):
x, y = random_leech_position()
leeches.append(Leech(x, y))
if not winter_active and current_time - last_reproduction_time >= reproduction_interval:
last_reproduction_time = current_time
mature = [p for p in pikes if p.length >= 50 and p.state == "normal"]
if len(mature) >= 2:
parent = random.choice(mature)
spawn_x, spawn_y = parent.x, parent.y
num_eggs = int(1 * parent.length)
if len(eggs) + num_eggs <= MAX_EGGS:
for _ in range(num_eggs):
angle = random.uniform(0, 2 * math.pi)
dist = random.uniform(10, 30)
x = spawn_x + dist * math.cos(angle)
y = spawn_y + dist * math.sin(angle)
x = max(SHORE_WIDTH + 5, min(WIDTH - SHORE_WIDTH - 5, x))
y = max(SHORE_WIDTH + 5, min(HEIGHT - SHORE_WIDTH - 5, y))
eggs.append(Egg(x, y))
add_message(random.choice(PHRASES_SPAWN), parent.x, parent.y, probability=1.0)
parent.state = "fleeing_from_eggs"
angle = random.uniform(0, 2 * math.pi)
target_x = spawn_x + 500 * math.cos(angle)
target_y = spawn_y + 500 * math.sin(angle)
target_x = max(SHORE_WIDTH, min(WIDTH - SHORE_WIDTH, target_x))
target_y = max(SHORE_WIDTH, min(HEIGHT - SHORE_WIDTH, target_y))
parent.target_point = (target_x, target_y)
parent.target = None
add_message(random.choice(PHRASES_FLEE), parent.x, parent.y, probability=1.0)
for egg in eggs[:]:
if egg.update(pikes):
eggs.remove(egg)
if bait is not None:
bait.update(keys)
for leech in leeches:
leech.update()
for pike in pikes:
pike.update(leeches, pikes, eggs, bait, current_time)
for pike in pikes[:]:
if pike in pikes:
result = pike.check_eat(leeches, pikes, eggs, bait, current_time)
if result == "bait_eaten":
pikes.remove(pike)
bait = None
catch_message = "Рыба выловлена!"
catch_message_timer = current_time + 3000
for pike in pikes[:]:
if pike.state in ("wintering", "post_winter"):
continue
if not pike.max_length_reached and pike.length >= 160:
pike.max_length_reached = True
pike.time_at_max = current_time
if pike.max_length_reached and (current_time - pike.time_at_max) > 6000:
if not pike.has_spawned_on_death:
pike.has_spawned_on_death = True
for _ in range(DEATH_SPAWN_EGGS):
if len(eggs) < MAX_EGGS:
angle = random.uniform(0, 2 * math.pi)
dist = random.uniform(10, 30)
x = pike.x + dist * math.cos(angle)
y = pike.y + dist * math.sin(angle)
x = max(SHORE_WIDTH + 5, min(WIDTH - SHORE_WIDTH - 5, x))
y = max(SHORE_WIDTH + 5, min(HEIGHT - SHORE_WIDTH - 5, y))
eggs.append(Egg(x, y))
add_message(random.choice(PHRASES_DEATH_OLD), pike.x, pike.y, probability=1.0)
pikes.remove(pike)
continue
if pike.length < 160 and (current_time - pike.last_meal_time) > STARVATION_TIME:
add_message(random.choice(PHRASES_DEATH_STARVE), pike.x, pike.y, probability=1.0)
pikes.remove(pike)
screen.blit(sand_surf, (0, 0))
screen.blit(water_surf, (0, 0))
if ice_surf is not None:
screen.blit(ice_surf, (0, 0))
for leech in leeches:
leech.draw(screen)
for egg in eggs:
egg.draw(screen)
if bait is not None:
bait.draw(screen)
for pike in pikes:
pike.draw(screen)
# Отрисовка панели подсказок (поверх всего)
draw_help_panel(screen)
messages = [msg for msg in messages if msg['timer'] > current_time]
if len(messages) > MAX_MESSAGES:
messages = messages[-MAX_MESSAGES:]
for msg in messages:
text_surf = speech_font.render(msg['text'], True, WHITE)
outline_surf = speech_font.render(msg['text'], True, BLACK)
x_pos = msg['x'] - text_surf.get_width() // 2
y_pos = msg['y'] - 30 - text_surf.get_height() // 2
for dx, dy in [(-1, -1), (-1, 1), (1, -1), (1, 1)]:
screen.blit(outline_surf, (x_pos + dx, y_pos + dy))
screen.blit(text_surf, (x_pos, y_pos))
if selecting and select_start and select_end:
x1, y1 = select_start
x2, y2 = select_end
left = min(x1, x2)
right = max(x1, x2)
top = min(y1, y2)
bottom = max(y1, y2)
s = pygame.Surface((right - left, bottom - top), pygame.SRCALPHA)
s.fill((255, 255, 255, 30))
screen.blit(s, (left, top))
pygame.draw.rect(screen, WHITE, (left, top, right - left, bottom - top), 1)
if grid_rect and current_time < grid_timer:
left, top, w, h = grid_rect
cell_size = 4
for y in range(top, top + h + 1, cell_size):
if y <= HEIGHT:
pygame.draw.line(screen, BLACK, (left, y), (left + w, y), 1)
for x in range(left, left + w + 1, cell_size):
if x <= WIDTH:
pygame.draw.line(screen, BLACK, (x, top), (x, top + h), 1)
if grid_rect and current_time >= grid_timer:
grid_rect = None
text = font.render(f"Пиявок: {len(leeches)} Щук: {len(pikes)} Икринок: {len(eggs)}", True, WHITE)
screen.blit(text, (10, 10))
if catch_message and current_time < catch_message_timer:
msg_surf = big_font.render(catch_message, True, YELLOW)
screen.blit(msg_surf, (WIDTH // 2 - msg_surf.get_width() // 2, 50))
elif catch_message:
catch_message = ""
pygame.display.flip()
clock.tick(FPS)
pygame.quit()