【python】pygameでスペースインベーダー風のゲームを作ってみた

## 背景
pygameでスペースインベーダー作りたい。

## スペースインベーダーとは？

流石にこれは有名かな？
https://spaceinvaders.jp/index.html

## ソースコード

```py main.py

import pygame
import random

# Initialize Pygame
pygame.init()

# Set up the display
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Space Invaders")

# Colors and Fonts
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
font = pygame.font.Font(None, 34)

# Game variables
clock = pygame.time.Clock()
enemy_speed = 1
player_speed = 5
bullet_speed = 5

# Load images
enemy_img = pygame.image.load('enemy.png')  # Add path to your enemy image
player_img = pygame.image.load('player.png')  # Add path to your player image
bullet_img = pygame.image.load('bullet.png')  # Add path to your bullet image

# Resize images
enemy_img = pygame.transform.scale(enemy_img, (50, 50))
player_img = pygame.transform.scale(player_img, (50, 50))
bullet_img = pygame.transform.scale(bullet_img, (10, 30))

# Player setup
player_x = width // 2
player_y = height - 60
player_rect = player_img.get_rect(center=(player_x, player_y))

# Enemies setup
enemies = [pygame.Rect(50 + i * 60, 50 + j * 60, 50, 50) for i in range(10) for j in range(3)]

# Bullets setup
bullets = []

# Game states
running = True
game_over = False
game_start = False
game_clear = False

# Functions
def fire_bullet():
    bullets.append(pygame.Rect(player_x + 20, player_y, 10, 30))

def show_text(text, pos, color=white):
    text_surface = font.render(text, True, color)
    text_rect = text_surface.get_rect(center=pos)
    screen.blit(text_surface, text_rect)

# Game loop
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if not game_start or game_over or game_clear:
                # Reset game
                enemies = [pygame.Rect(50 + i * 60, 50 + j * 60, 50, 50) for i in range(10) for j in range(3)]
                bullets = []
                player_x = width // 2
                game_over = False
                game_clear = False
                game_start = True
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                fire_bullet()

    # Game logic
    if game_start and not game_over and not game_clear:
        # Player movement
        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 < width - 50:
            player_x += player_speed
        player_rect.center = (player_x, player_y)

        # Bullet movement
        for bullet in bullets:
            bullet.y -= bullet_speed
            if bullet.y < 0:
                bullets.remove(bullet)

        # Enemy movement
        for enemy in enemies:
            enemy.y += enemy_speed
            if enemy.bottom >= height:
                game_over = True

        # Check for collisions
        for enemy in enemies:
            if enemy.colliderect(player_rect):
                game_over = True
            for bullet in bullets:
                if bullet.colliderect(enemy):
                    enemies.remove(enemy)
                    bullets.remove(bullet)
                    break

        # Check for game clear
        if not enemies:
            game_clear = True

    # Drawing
    screen.fill((0, 0, 0))
    if not game_start:
        show_text("Click to start Space Invaders", (width // 2, height // 2), red)
    elif game_over:
        show_text("Game Over...", (width // 2, height // 2), red)
        show_text("Click to restart", (width // 2, height // 2 + 40), white)
    elif game_clear:
        show_text("Game Clear!", (width // 2, height // 2), green)
        show_text("Click to restart", (width // 2, height // 2 + 40), white)
    else:
        screen.blit(player_img, player_rect)
        for enemy in enemies:
            screen.blit(enemy_img, enemy)
        for bullet in bullets:
            screen.blit(bullet_img, bullet)

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

pygame.quit()



```

## 画像の準備

画像ファイル
 - enemy.png
 - player.png
 - bullet.png

を同じディレクトリに配置するか、それらのパスをpyファイルで指定してください。

※今回は記事用にネットから探した画像を用いております。
※商用利用する方などは権利などしっかり配慮をお願いいたします。

## 実行

```sh
$ python main.py
```

## 説明
- スタート画面
クリックでゲーム開始です。

![スクリーンショット 2024-07-09 13.21.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/013a9e7f-5b51-a038-be24-b109bffb10bb.png)


- インゲーム画面
矢印キーで自機を操作し、スペースキーで球を発射。

![スクリーンショット 2024-07-09 13.21.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/3ab2babe-803a-a291-b112-65e67151d2f7.png)


- ゲームオーバー条件
敵が自機にぶつかるとゲームオーバーになります。
その後、画面をクリックすると再スタート出来ます。

![スクリーンショット 2024-07-09 13.21.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/e608ba26-6561-1f9c-1383-cae4e571d599.png)

- ゲームクリア条件
敵を全部倒すとゲームクリアになります。
その後クリックで再スタート出来ます。

![スクリーンショット 2024-07-09 13.22.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/3097b73a-06e3-fa52-21d8-189145492eab.png)

## まとめ

できた！