Загрузка данных


import pygame
import random
import math

pygame.init()

WIDTH = 800
HEIGHT = 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Cyber Void: Star Defender DX")
clock = pygame.time.Clock()
FPS = 60

# Цвета
BLACK = (10, 10, 20)
WHITE = (255, 255, 255)
CYAN = (0, 255, 255)
RED = (255, 60, 60)
ORANGE = (255, 160, 20)
YELLOW = (255, 230, 80)
GREEN = (50, 255, 100)
BLUE = (80, 150, 255)
PURPLE = (180, 50, 255)

font = pygame.font.Font(None, 28)
big_font = pygame.font.Font(None, 60)

class Player:
    def __init__(self):
        self.x = WIDTH // 2
        self.y = HEIGHT - 70
        self.speed = 7
        self.size = 20
        self.cooldown = 0
        self.shield = 0
        self.triple_shot_timer = 0

    def update(self, keys):
        if (keys[pygame.K_LEFT] or keys[pygame.K_a]) and self.x > self.size:
            self.x -= self.speed
        if (keys[pygame.K_RIGHT] or keys[pygame.K_d]) and self.x < WIDTH - self.size:
            self.x += self.speed
        if (keys[pygame.K_UP] or keys[pygame.K_w]) and self.y > self.size:
            self.y -= self.speed
        if (keys[pygame.K_DOWN] or keys[pygame.K_s]) and self.y < HEIGHT - self.size:
            self.y += self.speed

        if self.cooldown > 0:
            self.cooldown -= 1
        if self.triple_shot_timer > 0:
            self.triple_shot_timer -= 1

    def draw(self, surface):
        points = [
            (self.x, self.y - self.size),
            (self.x - self.size, self.y + self.size),
            (self.x, self.y + self.size // 2),
            (self.x + self.size, self.y + self.size)
        ]
        pygame.draw.polygon(surface, CYAN, points)
        pygame.draw.circle(surface, WHITE, (int(self.x), int(self.y)), 4)

        if self.shield > 0:
            pygame.draw.circle(surface, BLUE, (int(self.x), int(self.y)), self.size + 10, 2)

class Laser:
    def __init__(self, x, y, dx=0, dy=-12, color=YELLOW):
        self.x = x
        self.y = y
        self.dx = dx
        self.dy = dy
        self.radius = 4
        self.color = color

    def update(self):
        self.x += self.dx
        self.y += self.dy

    def draw(self, surface):
        pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)

class PowerUp:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.type = random.choice(["triple", "shield"])
        self.color = GREEN if self.type == "triple" else BLUE
        self.speed = 2
        self.radius = 10

    def update(self):
        self.y += self.speed

    def draw(self, surface):
        pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)
        pygame.draw.circle(surface, WHITE, (int(self.x), int(self.y)), self.radius, 2)

class Boss:
    def __init__(self):
        self.x = WIDTH // 2
        self.y = -100
        self.target_y = 120
        self.max_hp = 60
        self.hp = self.max_hp
        self.radius = 45
        self.shoot_timer = 0
        self.dx = 3

    def update(self, boss_bullets):
        if self.y < self.target_y:
            self.y += 2
        else:
            self.x += self.dx
            if self.x < self.radius + 20 or self.x > WIDTH - self.radius - 20:
                self.dx = -self.dx

            self.shoot_timer += 1
            if self.shoot_timer >= 40:
                self.shoot_timer = 0
                for angle in [-0.5, 0, 0.5]:
                    bx = math.sin(angle) * 5
                    by = math.cos(angle) * 5
                    boss_bullets.append(Laser(self.x, self.y + self.radius, bx, by, PURPLE))

    def draw(self, surface):
        pygame.draw.circle(surface, PURPLE, (int(self.x), int(self.y)), self.radius)
        pygame.draw.circle(surface, RED, (int(self.x), int(self.y)), self.radius - 8)
        # HP Bar
        bar_w = 120
        bar_h = 10
        fill = int((self.hp / self.max_hp) * bar_w)
        pygame.draw.rect(surface, RED, (self.x - bar_w // 2, self.y - self.radius - 20, bar_w, bar_h))
        pygame.draw.rect(surface, GREEN, (self.x - bar_w // 2, self.y - self.radius - 20, fill, bar_h))

class Enemy:
    def __init__(self, speed_mult=1.0):
        self.x = random.randint(30, WIDTH - 30)
        self.y = random.randint(-100, -30)
        self.radius = random.randint(15, 26)
        self.speed = random.uniform(2.0, 4.5) * speed_mult
        self.hp = 2 if self.radius > 22 else 1

    def update(self):
        self.y += self.speed

    def draw(self, surface):
        color = RED if self.hp == 1 else (255, 100, 100)
        pygame.draw.circle(surface, color, (int(self.x), int(self.y)), self.radius)
        pygame.draw.circle(surface, BLACK, (int(self.x), int(self.y)), self.radius - 4)

class Particle:
    def __init__(self, x, y, color):
        self.x = x
        self.y = y
        self.color = color
        angle = random.uniform(0, math.pi * 2)
        speed = random.uniform(2, 6)
        self.vx = math.cos(angle) * speed
        self.vy = math.sin(angle) * speed
        self.life = 20

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.life -= 1

    def draw(self, surface):
        if self.life > 0:
            pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), max(1, self.life // 4))

def main():
    player = Player()
    lasers = []
    enemies = []
    particles = []
    powerups = []
    boss_bullets = []
    boss = None

    stars = [[random.randint(0, WIDTH), random.randint(0, HEIGHT), random.randint(1, 3)] for _ in range(60)]
    score = 0
    next_boss_score = 150
    game_over = False
    spawn_timer = 0
    shake_timer = 0

    running = True
    while running:
        clock.tick(FPS)
        keys = pygame.key.get_pressed()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.KEYDOWN and game_over and event.key == pygame.K_r:
                main()
                return

        if not game_over:
            player.update(keys)

            # Стрельба игрока
            if (keys[pygame.K_SPACE] or keys[pygame.K_j]) and player.cooldown == 0:
                if player.triple_shot_timer > 0:
                    lasers.append(Laser(player.x, player.y - player.size, 0, -12))
                    lasers.append(Laser(player.x, player.y - player.size, -3, -11))
                    lasers.append(Laser(player.x, player.y - player.size, 3, -11))
                else:
                    lasers.append(Laser(player.x, player.y - player.size, 0, -12))
                player.cooldown = 11

            # Появление босса
            if score >= next_boss_score and boss is None:
                boss = Boss()
                next_boss_score += 200

            # Спавн обычных врагов
            spawn_timer += 1
            if spawn_timer >= 40 and boss is None:
                enemies.append(Enemy(1.0 + score / 500))
                spawn_timer = 0

            # Обновление пуль
            for laser in lasers[:]:
                laser.update()
                if laser.y < -10 or laser.x < 0 or laser.x > WIDTH:
                    lasers.remove(laser)

            for b in boss_bullets[:]:
                b.update()
                if math.hypot(b.x - player.x, b.y - player.y) < player.size:
                    boss_bullets.remove(b)
                    if player.shield > 0:
                        player.shield -= 1
                    else:
                        game_over = True
                        shake_timer = 20
                elif b.y > HEIGHT + 10:
                    boss_bullets.remove(b)

            # Обновление босса
            if boss:
                boss.update(boss_bullets)
                for laser in lasers[:]:
                    if math.hypot(boss.x - laser.x, boss.y - laser.y) < boss.radius:
                        boss.hp -= 1
                        lasers.remove(laser)
                        if boss.hp <= 0:
                            for _ in range(50):
                                particles.append(Particle(boss.x, boss.y, PURPLE))
                            score += 100
                            boss = None
                            shake_timer = 25
                            break

            # Обновление бонусов
            for p in powerups[:]:
                p.update()
                if math.hypot(p.x - player.x, p.y - player.y) < player.size + p.radius:
                    if p.type == "triple":
                        player.triple_shot_timer = 400
                    elif p.type == "shield":
                        player.shield = 1
                    powerups.remove(p)
                elif p.y > HEIGHT:
                    powerups.remove(p)

            # Враги и коллизии
            for enemy in enemies[:]:
                enemy.update()

                if math.hypot(enemy.x - player.x, enemy.y - player.y) < enemy.radius + player.size - 5:
                    if player.shield > 0:
                        player.shield -= 1
                        enemies.remove(enemy)
                        shake_timer = 10
                    else:
                        game_over = True
                        shake_timer = 20

                for laser in lasers[:]:
                    if math.hypot(enemy.x - laser.x, enemy.y - laser.y) < enemy.radius + laser.radius:
                        enemy.hp -= 1
                        lasers.remove(laser)
                        if enemy.hp <= 0:
                            for _ in range(16):
                                particles.append(Particle(enemy.x, enemy.y, ORANGE))
                            if random.random() < 0.25:
                                powerups.append(PowerUp(enemy.x, enemy.y))
                            enemies.remove(enemy)
                            score += 10
                        break

                if enemy.y > HEIGHT + 40 and enemy in enemies:
                    enemies.remove(enemy)

        # Тряска экрана
        render_offset = [0, 0]
        if shake_timer > 0:
            shake_timer -= 1
            render_offset = [random.randint(-4, 4), random.randint(-4, 4)]

        # Фоновые звёзды и частицы
        for p in particles[:]:
            p.update()
            if p.life <= 0:
                particles.remove(p)

        for s in stars:
            s[1] += s[2] * 0.8
            if s[1] > HEIGHT:
                s[1] = 0
                s[0] = random.randint(0, WIDTH)

        # Отрисовка на виртуальную поверхность для тряски
        canvas = pygame.Surface((WIDTH, HEIGHT))
        canvas.fill(BLACK)

        for s in stars:
            pygame.draw.circle(canvas, (180, 180, 220), (int(s[0]), int(s[1])), s[2] // 2 + 1)
        for p in particles:
            p.draw(canvas)
        for p in powerups:
            p.draw(canvas)
        for laser in lasers:
            laser.draw(canvas)
        for b in boss_bullets:
            b.draw(canvas)
        for enemy in enemies:
            enemy.draw(canvas)
        if boss:
            boss.draw(canvas)

        if not game_over:
            player.draw(canvas)
        else:
            text_go = big_font.render("GAME OVER", True, RED)
            text_restart = font.render("Press 'R' to Restart", True, WHITE)
            canvas.blit(text_go, (WIDTH // 2 - text_go.get_width() // 2, HEIGHT // 2 - 40))
            canvas.blit(text_restart, (WIDTH // 2 - text_restart.get_width() // 2, HEIGHT // 2 + 25))

        # UI
        score_surf = font.render(f"SCORE: {score}", True, CYAN)
        canvas.blit(score_surf, (20, 20))
        if player.triple_shot_timer > 0:
            bonus_surf = font.render("TRIPLE SHOT ACTIVE!", True, GREEN)
            canvas.blit(bonus_surf, (20, 50))

        screen.blit(canvas, render_offset)
        pygame.display.flip()

    pygame.quit()

if __name__ == "__main__":
    main()