Загрузка данных
import pygame, random, math
pygame.init()
W, H = 900, 650
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("Neon Survival")
clock = pygame.time.Clock()
font_big = pygame.font.SysFont("arial", 70, bold=True)
font = pygame.font.SysFont("arial", 30)
font_small = pygame.font.SysFont("arial", 22)
# ---------- ЦВЕТА ----------
BG_TOP = (10, 8, 30)
BG_BOTTOM = (30, 10, 50)
PLAYER_COLOR = (80, 220, 255)
ENEMY_COLOR = (255, 60, 100)
GEM_COLOR = (255, 220, 60)
def lerp(a, b, t):
return a + (b - a) * t
def gradient_background(surf):
for y in range(H):
t = y / H
r = lerp(BG_TOP[0], BG_BOTTOM[0], t)
g = lerp(BG_TOP[1], BG_BOTTOM[1], t)
b = lerp(BG_TOP[2], BG_BOTTOM[2], t)
pygame.draw.line(surf, (r, g, b), (0, y), (W, y))
bg_surface = pygame.Surface((W, H))
gradient_background(bg_surface)
# статичные "звёзды" на фоне
stars = [(random.randint(0, W), random.randint(0, H), random.randint(1, 3)) for _ in range(120)]
def draw_glow_circle(surf, color, pos, radius, glow_strength=3):
"""Рисует круг со свечением (несколько полупрозрачных слоёв)"""
glow_surf = pygame.Surface((radius*4, radius*4), pygame.SRCALPHA)
cx, cy = radius*2, radius*2
for i in range(glow_strength, 0, -1):
alpha = int(40 / i)
r = radius + i * 5
pygame.draw.circle(glow_surf, (*color, alpha), (cx, cy), r)
pygame.draw.circle(glow_surf, (*color, 255), (cx, cy), radius)
surf.blit(glow_surf, (pos[0] - radius*2, pos[1] - radius*2), special_flags=pygame.BLEND_RGBA_ADD)
class Particle:
def __init__(self, x, y, color):
self.x, self.y = x, y
angle = random.uniform(0, math.pi * 2)
speed = random.uniform(1, 4)
self.vx = math.cos(angle) * speed
self.vy = math.sin(angle) * speed
self.life = random.uniform(20, 40)
self.max_life = self.life
self.color = color
self.radius = random.uniform(2, 4)
def update(self):
self.x += self.vx
self.y += self.vy
self.vx *= 0.96
self.vy *= 0.96
self.life -= 1
def draw(self, surf):
if self.life > 0:
alpha = int(255 * (self.life / self.max_life))
s = pygame.Surface((int(self.radius*2)+2, int(self.radius*2)+2), pygame.SRCALPHA)
pygame.draw.circle(s, (*self.color, alpha), (int(self.radius), int(self.radius)), int(self.radius))
surf.blit(s, (self.x - self.radius, self.y - self.radius))
class Player:
def __init__(self):
self.x, self.y = W // 2, H // 2
self.radius = 14
self.trail = []
def update(self, keys):
speed = 5.5
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
self.x -= speed
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
self.x += speed
if keys[pygame.K_UP] or keys[pygame.K_w]:
self.y -= speed
if keys[pygame.K_DOWN] or keys[pygame.K_s]:
self.y += speed
self.x = max(self.radius, min(W - self.radius, self.x))
self.y = max(self.radius, min(H - self.radius, self.y))
self.trail.append((self.x, self.y))
if len(self.trail) > 15:
self.trail.pop(0)
def draw(self, surf):
for i, (tx, ty) in enumerate(self.trail):
alpha_r = int(self.radius * (i / len(self.trail)))
if alpha_r > 0:
s = pygame.Surface((alpha_r*2, alpha_r*2), pygame.SRCALPHA)
a = int(120 * (i / len(self.trail)))
pygame.draw.circle(s, (*PLAYER_COLOR, a), (alpha_r, alpha_r), alpha_r)
surf.blit(s, (tx - alpha_r, ty - alpha_r))
draw_glow_circle(surf, PLAYER_COLOR, (self.x, self.y), self.radius, glow_strength=4)
class Enemy:
def __init__(self, difficulty):
side = random.choice(["top", "bottom", "left", "right"])
if side == "top":
self.x, self.y = random.randint(0, W), -20
elif side == "bottom":
self.x, self.y = random.randint(0, W), H + 20
elif side == "left":
self.x, self.y = -20, random.randint(0, H)
else:
self.x, self.y = W + 20, random.randint(0, H)
angle = math.atan2(H/2 - self.y, W/2 - self.x)
angle += random.uniform(-0.5, 0.5)
speed = random.uniform(1.5, 2.5) + difficulty * 0.35
self.vx = math.cos(angle) * speed
self.vy = math.sin(angle) * speed
self.radius = random.randint(10, 18)
self.pulse = random.uniform(0, math.pi*2)
def update(self):
self.x += self.vx
self.y += self.vy
self.pulse += 0.15
def draw(self, surf):
r = self.radius + math.sin(self.pulse) * 2
draw_glow_circle(surf, ENEMY_COLOR, (self.x, self.y), int(r), glow_strength=3)
def offscreen(self):
return self.x < -60 or self.x > W + 60 or self.y < -60 or self.y > H + 60
class Gem:
def __init__(self):
self.x = random.randint(40, W - 40)
self.y = random.randint(40, H - 40)
self.radius = 9
self.pulse = random.uniform(0, math.pi*2)
def update(self):
self.pulse += 0.1
def draw(self, surf):
r = self.radius + math.sin(self.pulse) * 2
draw_glow_circle(surf, GEM_COLOR, (self.x, self.y), int(r), glow_strength=3)
player = Player()
enemies = []
gems = [Gem() for _ in range(4)]
particles = []
score = 0
survival_time = 0
spawn_timer = 0
game_over = False
shake = 0
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN and event.key == pygame.K_r and game_over:
player = Player()
enemies = []
gems = [Gem() for _ in range(4)]
particles = []
score = 0
survival_time = 0
spawn_timer = 0
game_over = False
keys = pygame.key.get_pressed()
if not game_over:
survival_time += 1 / 60
difficulty = survival_time / 10
player.update(keys)
spawn_timer += 1
spawn_rate = max(15, 45 - int(difficulty * 3))
if spawn_timer > spawn_rate:
spawn_timer = 0
enemies.append(Enemy(difficulty))
for e in enemies[:]:
e.update()
if e.offscreen():
enemies.remove(e)
dist = math.hypot(e.x - player.x, e.y - player.y)
if dist < e.radius + player.radius - 4:
game_over = True
shake = 25
for _ in range(40):
particles.append(Particle(player.x, player.y, ENEMY_COLOR))
for g in gems[:]:
g.update()
dist = math.hypot(g.x - player.x, g.y - player.y)
if dist < g.radius + player.radius:
score += 10
for _ in range(15):
particles.append(Particle(g.x, g.y, GEM_COLOR))
gems.remove(g)
gems.append(Gem())
for p in particles[:]:
p.update()
if p.life <= 0:
particles.remove(p)
# ---------- ОТРИСОВКА ----------
offset_x = random.randint(-shake, shake) if shake > 0 else 0
offset_y = random.randint(-shake, shake) if shake > 0 else 0
if shake > 0:
shake -= 1
screen.blit(bg_surface, (offset_x, offset_y))
for (sx, sy, sr) in stars:
pygame.draw.circle(screen, (200, 200, 255), (sx + offset_x, sy + offset_y), sr)
for g in gems:
g.draw(screen)
for e in enemies:
e.draw(screen)
for p in particles:
p.draw(screen)
if not game_over:
player.draw(screen)
score_text = font.render(f"Счёт: {score}", True, (255, 255, 255))
time_text = font_small.render(f"Время: {survival_time:.1f}с", True, (200, 200, 220))
screen.blit(score_text, (20, 20))
screen.blit(time_text, (20, 55))
if game_over:
overlay = pygame.Surface((W, H), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 150))
screen.blit(overlay, (0, 0))
over_text = font_big.render("ИГРА ОКОНЧЕНА", True, (255, 60, 100))
screen.blit(over_text, (W//2 - over_text.get_width()//2, H//2 - 100))
final_score = font.render(f"Финальный счёт: {score}", True, (255, 255, 255))
screen.blit(final_score, (W//2 - final_score.get_width()//2, H//2))
restart = font_small.render("Нажми R чтобы начать заново", True, (200, 200, 220))
screen.blit(restart, (W//2 - restart.get_width()//2, H//2 + 50))
pygame.display.flip()
pygame.quit()