インベーダーゲームを作ってみた　#100日チャレンジ　に感化されて

#### インベーダーゲーム（のようなもの）を作ってみた
（5/6 難易度設定を追加してみました）
そろそろゲーム以外の制作にも挑戦したい！
#100日チャレンジ　に感化されて

![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668168/8fd893ac-37a6-4d7b-8c35-8557a04eb71b.gif)

```python
import pygame
import random
import sys

def select_difficulty(screen, WHITE, BLACK):
    font = pygame.font.SysFont(None, 50)
    while True:
        screen.fill(BLACK)
        easy_text = font.render("1: Easy", True, WHITE)
        normal_text = font.render("2: Normal", True, WHITE)
        hard_text = font.render("3: Hard", True, WHITE)
        screen.blit(easy_text, (200, 200))
        screen.blit(normal_text, (200, 300))
        screen.blit(hard_text, (200, 400))
        pygame.display.flip()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    return "easy"
                elif event.key == pygame.K_2:
                    return "normal"
                elif event.key == pygame.K_3:
                    return "hard"

def show_end_screen(screen, font, message, BLUE, WHITE):
    text = font.render(message, True, WHITE)
    screen.blit(text, (300 - text.get_width() // 2, 340))

    retry_rect = pygame.Rect(225, 410, 150, 50)
    pygame.draw.rect(screen, BLUE, retry_rect)
    retry_text = font.render("RETRY", True, WHITE)
    screen.blit(retry_text, (retry_rect.x + 25, retry_rect.y + 10))
    pygame.display.flip()

    waiting = True
    while waiting:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN and retry_rect.collidepoint(event.pos):
                waiting = False
                return  # 戻ってrun_gameを再スタートする

def run_game():
    pygame.init()

    WIDTH, HEIGHT = 600, 800
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("Invader Game")
    clock = pygame.time.Clock()

    # 色
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    BLUE = (100, 100, 255)

    # 難易度選択
    difficulty = select_difficulty(screen, WHITE, BLACK)
    if difficulty == "easy":
        enemy_width, enemy_height = 50, 40
    elif difficulty == "normal":
        enemy_width, enemy_height = 40, 30
    else:
        enemy_width, enemy_height = 30, 20

    # フォント
    font_small = pygame.font.SysFont(None, 36)
    font_large = pygame.font.SysFont(None, 60)

    # プレイヤー
    player_img = pygame.Surface((50, 30))
    player_img.fill(WHITE)
    player_rect = player_img.get_rect(center=(WIDTH // 2, HEIGHT - 50))
    player_speed = 5

    # 弾
    bullets = []
    bullet_speed = -10

    # 敵
    enemy_img = pygame.Surface((enemy_width, enemy_height))
    enemy_img.fill((0, 255, 0))
    enemies = []
    enemy_speed_y = 20
    for row in range(4):
        for col in range(6):
            x = 80 + col * 70
            y = 50 + row * 50
            rect = pygame.Rect(x, y, enemy_width, enemy_height)
            direction = random.choice([-1, 1])
            speed = random.randint(1, 3)
            enemies.append({"rect": rect, "dx": direction * speed})

    score = 0
    start_ticks = pygame.time.get_ticks()
    running = True

    while running:
        screen.fill(BLACK)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        # キー入力
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] and player_rect.left > 0:
            player_rect.x -= player_speed
        if keys[pygame.K_RIGHT] and player_rect.right < WIDTH:
            player_rect.x += player_speed
        if keys[pygame.K_SPACE]:
            if len(bullets) < 5:
                bullets.append(pygame.Rect(player_rect.centerx - 2, player_rect.top, 4, 10))

        # 弾移動
        for bullet in bullets[:]:
            bullet.y += bullet_speed
            if bullet.bottom < 0:
                bullets.remove(bullet)

        # 敵移動
        for enemy in enemies:
            rect = enemy["rect"]
            rect.x += enemy["dx"]
            if rect.left < 0 or rect.right > WIDTH:
                rect.y += enemy_speed_y
                enemy["dx"] *= -1

        # 当たり判定
        for bullet in bullets[:]:
            for enemy in enemies[:]:
                if bullet.colliderect(enemy["rect"]):
                    bullets.remove(bullet)
                    enemies.remove(enemy)
                    score += 100
                    break

        # 敵到達でゲームオーバー
        for enemy in enemies:
            if enemy["rect"].bottom > HEIGHT - 100:
                show_end_screen(screen, font_large, "GAME OVER", BLUE, WHITE)
                run_game()
                return

        # 描画
        screen.blit(player_img, player_rect)
        for bullet in bullets:
            pygame.draw.rect(screen, WHITE, bullet)
        for enemy in enemies:
            screen.blit(enemy_img, enemy["rect"])

        # スコアと時間表示
        score_text = font_small.render(f"Score: {score}", True, WHITE)
        screen.blit(score_text, (10, 10))
        elapsed = (pygame.time.get_ticks() - start_ticks) // 1000
        time_text = font_small.render(f"Time: {elapsed}s", True, WHITE)
        screen.blit(time_text, (WIDTH - 150, 10))

        # 勝利判定
        if not enemies:
            show_end_screen(screen, font_large, "YOU WIN!", BLUE, WHITE)
            run_game()
            return

        pygame.display.flip()
        clock.tick(60)

if __name__ == "__main__":
    run_game()
```

気に入った方は，いいね👍お願いします！