Полный код Space Invaders
Движение, выстрелы, коллизии, победа и поражение — всё вместе
keyboard Управление в игре
Стрелки
Движение корабля влево/вправо
Пробел
Выстрел (максимум 3 пули)
Закрыть окно
Выход из игры
1 Импорты и константы
Начнём файл с импортов и всех настроек игры.
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 Создание объектов и функции отрисовки
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.
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 Движение пришельцев
Пришельцы движутся горизонтально всей группой. Когда кто-то касается края — вся группа спускается вниз и меняет направление.
# Направление и таймер движения 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 Инициализация и главный игровой цикл
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
# ── 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 - 🌟 Звёзды — нарисуйте случайные точки как фон космоса
- 📈 Уровни — ускоряйте пришельцев с каждой волной
- 🛡️ Щиты — добавьте укрытия из зелёных блоков
- 💾 Рекорды — сохраняйте лучший счёт в файл
- 👾 Виды пришельцев — разные цвета дают разные очки