🐍
sports_esportsШаг 4 из 4

Полный код Space Invaders

Движение, выстрелы, коллизии, победа и поражение — всё вместе

keyboard Управление в игре

⬅️ ➡️

Стрелки

Движение корабля влево/вправо

Пробел

Выстрел (максимум 3 пули)

Закрыть окно

Выход из игры

1 Импорты и константы

Начнём файл с импортов и всех настроек игры.

space_invaders.py — часть 1/6 editВведите вручную
import pygame
import random

# ── Размер окна и FPS ─────────────────────────
WIDTH, HEIGHT = 800, 600
FPS = 60

# ── Скорости ──────────────────────────────────
PLAYER_SPEED = 5
BULLET_SPEED = 8

# ── Пришельцы ─────────────────────────────────
ALIEN_W, ALIEN_H = 36, 24
ALIEN_COLS = 11
ALIEN_ROWS = 5

# ── Цвета ─────────────────────────────────────
WHITE  = (255, 255, 255)
BLACK  = (0,   0,   0  )
GREEN  = (0,   230, 118)
CYAN   = (0,   220, 255)
RED    = (255, 60,  60 )
YELLOW = (255, 230, 0  )

2 Создание объектов и функции отрисовки

space_invaders.py — часть 2/6 editВведите вручную
def new_player():
    return {'x': WIDTH//2-20, 'y': HEIGHT-60, 'w': 40, 'h': 20, 'lives': 3}

def new_aliens():
    return [[{'x': 60+c*52, 'y': 80+r*40, 'alive': True}
              for c in range(ALIEN_COLS)] for r in range(ALIEN_ROWS)]

def alive_list(aliens):
    """Возвращает плоский список живых пришельцев"""
    return [a for row in aliens for a in row if a['alive']]

def draw_player(screen, p):
    pygame.draw.rect(screen, GREEN, (p['x'], p['y'], p['w'], p['h']))
    pygame.draw.rect(screen, GREEN, (p['x']+15, p['y']-10, 10, 10))

def draw_aliens(screen, aliens):
    for row in aliens:
        for a in row:
            if a['alive']:
                pygame.draw.rect(screen, CYAN,
                    (a['x'], a['y'], ALIEN_W, ALIEN_H))
                pygame.draw.rect(screen, BLACK,
                    (a['x']+6,  a['y']+6, 6, 6))
                pygame.draw.rect(screen, BLACK,
                    (a['x']+24, a['y']+6, 6, 6))

def draw_bullets(screen, p_bullets, a_bullets):
    for b in p_bullets:
        pygame.draw.rect(screen, YELLOW, (b['x'], b['y'], 4, 12))
    for b in a_bullets:
        pygame.draw.rect(screen, RED,    (b['x'], b['y'], 4, 12))

def draw_hud(screen, font, score, lives):
    screen.blit(font.render(f"Счёт: {score}",   True, WHITE), (10, 10))
    screen.blit(font.render(f"Жизни: {lives}", True, WHITE), (WIDTH-130, 10))

3 Проверка попадания (коллизии)

Коллизия — перекрытие двух прямоугольников. Это ключевая механика Space Invaders. Используем if/elif/else из ЛР №3.

space_invaders.py — часть 3/6 editВведите вручную
def rects_overlap(ax, ay, aw, ah, bx, by, bw, bh):
    """Проверяем — пересекаются ли два прямоугольника?"""
    return (ax < bx + bw and  # левый край A левее правого B
            ax + aw > bx and    # правый край A правее левого B
            ay < by + bh and    # верхний край A выше нижнего B
            ay + ah > by)         # нижний край A ниже верхнего B

# Пример использования:
# Пуля игрока попала в пришельца?
if rects_overlap(
    b['x'], b['y'], 4, 12,           # пуля
    a['x'], a['y'], ALIEN_W, ALIEN_H  # пришелец
):
    a['alive'] = False  # убиваем пришельца
    score += 10          # добавляем очки

Связь с ЛР №3: условие ax < bx + bw and ax + aw > bx and ... — это серия проверок if/and, как в лабораторной №3!

4 Движение пришельцев

Пришельцы движутся горизонтально всей группой. Когда кто-то касается края — вся группа спускается вниз и меняет направление.

space_invaders.py — часть 4/6 editВведите вручную
# Направление и таймер движения
alien_dx   = 2    # начальное направление: вправо
move_timer = 0
move_delay = 600  # мс между шагами пришельцев

# ... в главном цикле:
if move_timer >= move_delay:
    move_timer = 0

    # Проверяем: кто-то из живых достигнет края?
    hit_edge = any(
        a['x'] + alien_dx + ALIEN_W > WIDTH or
        a['x'] + alien_dx < 0
        for a in alive_list(aliens)
    )

    if hit_edge:
        # Меняем направление и двигаем вниз
        alien_dx = -alien_dx
        for row in aliens:
            for a in row:
                a['y'] += 20  # шаг вниз
    else:
        # Двигаем горизонтально
        for row in aliens:
            for a in row:
                a['x'] += alien_dx

5 Инициализация и главный игровой цикл

space_invaders.py — часть 5/6 editВведите вручную
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Space Invaders")
clock  = pygame.time.Clock()
font   = pygame.font.SysFont(None, 32)

player    = new_player()
aliens    = new_aliens()
p_bullets = []
a_bullets = []
score     = 0

alien_dx   = 2
move_timer = 0
move_delay = 600
running    = True

while running:
    dt = clock.tick(FPS)
    move_timer += dt

    # ── 1. Обработка событий ──────────────────
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE and len(p_bullets) < 3:
                p_bullets.append({
                    'x': player['x'] + 18,
                    'y': player['y'] - 12,
                })

    # ── 2. Движение игрока ────────────────────
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]  and player['x'] > 0:
        player['x'] -= PLAYER_SPEED
    if keys[pygame.K_RIGHT] and player['x'] + player['w'] < WIDTH:
        player['x'] += PLAYER_SPEED

    # ── 3. Движение пуль ──────────────────────
    for b in p_bullets: b['y'] -= BULLET_SPEED
    for b in a_bullets: b['y'] += BULLET_SPEED
    p_bullets = [b for b in p_bullets if b['y'] > 0]
    a_bullets = [b for b in a_bullets if b['y'] < HEIGHT]

6 Выстрелы пришельцев, коллизии, победа и Game Over

space_invaders.py — часть 6/6 (финал) editВведите вручную
    # ── 4. Движение пришельцев ────────────────
    if move_timer >= move_delay:
        move_timer = 0
        hit_edge = any(
            a['x'] + alien_dx + ALIEN_W > WIDTH or
            a['x'] + alien_dx < 0
            for a in alive_list(aliens)
        )
        if hit_edge:
            alien_dx = -alien_dx
            for row in aliens:
                for a in row:
                    a['y'] += 20
        else:
            for row in aliens:
                for a in row:
                    a['x'] += alien_dx

    # ── 5. Случайный выстрел пришельца ───────
    alive = alive_list(aliens)
    if alive and random.random() < 0.003:
        shooter = random.choice(alive)
        a_bullets.append({
            'x': shooter['x'] + ALIEN_W//2 - 2,
            'y': shooter['y'] + ALIEN_H,
        })

    # ── 6. Коллизии: пули игрока → пришельцы ─
    for b in p_bullets[:]:
        for row in aliens:
            for a in row:
                if a['alive'] and rects_overlap(
                    b['x'], b['y'], 4, 12,
                    a['x'], a['y'], ALIEN_W, ALIEN_H
                ):
                    a['alive'] = False
                    p_bullets.remove(b)
                    score += 10
                    break

    # ── 7. Коллизии: пули пришельцев → игрок ─
    for b in a_bullets[:]:
        if rects_overlap(b['x'], b['y'], 4, 12,
                         player['x'], player['y'],
                         player['w'], player['h']):
            a_bullets.remove(b)
            player['lives'] -= 1
            if player['lives'] <= 0:
                running = False

    # ── 8. Условия завершения ─────────────────
    if not alive_list(aliens):      # победа!
        running = False
    if any(a['y'] + ALIEN_H >= player['y']
           for a in alive_list(aliens)):  # пришельцы достигли низа
        running = False

    # ── 9. Отрисовка ──────────────────────────
    screen.fill(BLACK)
    draw_player(screen, player)
    draw_aliens(screen, aliens)
    draw_bullets(screen, p_bullets, a_bullets)
    draw_hud(screen, font, score, player['lives'])
    pygame.display.flip()

# ── Финальный экран ───────────────────────
screen.fill(BLACK)
msg = "Победа!" if not alive_list(aliens) else "Game Over!"
text = font.render(f"{msg}  Счёт: {score}", True, WHITE)
screen.blit(text, (WIDTH//2 - 130, HEIGHT//2))
pygame.display.flip()
pygame.time.wait(3000)
pygame.quit()

List comprehension из ЛР №7: строки [b for b in p_bullets if b['y'] > 0] и [a for row in aliens for a in row if a['alive']] — фильтрация и «выпрямление» двумерного списка!

🎉

Поздравляем! Вы написали Space Invaders на Python!

Теперь у вас есть настоящая аркадная игра. Попробуйте улучшить её самостоятельно:

  • 🎵 Звук — добавьте выстрел через pygame.mixer
  • 🌟 Звёзды — нарисуйте случайные точки как фон космоса
  • 📈 Уровни — ускоряйте пришельцев с каждой волной
  • 🛡️ Щиты — добавьте укрытия из зелёных блоков
  • 💾 Рекорды — сохраняйте лучший счёт в файл
  • 👾 Виды пришельцев — разные цвета дают разные очки
home На главную