Day ３: python初心者がダンジョンゲーム作成してみる

# [Day 3: 衝突検出とアニメーション](https://qiita.com/tsuyoron515/items/78cc6d949123beea6f71#day-3-%E8%A1%9D%E7%AA%81%E6%A4%9C%E5%87%BA%E3%81%A8%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3:~:text=%E3%82%92%E5%AD%A6%E3%81%B3%E3%81%BE%E3%81%99%E3%80%82-,Day%203%3A%20%E8%A1%9D%E7%AA%81%E6%A4%9C%E5%87%BA%E3%81%A8%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3,-%E8%A1%9D%E7%AA%81%E6%A4%9C%E5%87%BA%E3%81%AE)

## 全体のコード

```python
import pygame
import random

# pygameモジュールの初期化
pygame.init()

# ゲームの設定
# 画面の幅と高さ
screen_width = 800
screen_height = 600

# 共通のサイズ
common_width = 50
common_height = 50

# 画面の作成
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("My Game")

# Playerクラスの定義
class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("player.png")
        self.image = pygame.transform.scale(self.image, (common_width, common_height))
        self.rect = self.image.get_rect()
        self.rect.center = (screen_width // 2, screen_height // 2)
        self.speed = 1

        # アニメーションの初期化
        self.images = [
            pygame.image.load("frame1.png"),
            pygame.image.load("frame2.png"),
            pygame.image.load("frame3.png"),
            # 追加のフレーム画像を読み込む
        ]
        self.current_frame = 0
        self.animation_timer = pygame.time.get_ticks()
        self.animation_delay = 200  # フレームの更新間隔（ミリ秒）

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.rect.x -= self.speed
        if keys[pygame.K_RIGHT]:
            self.rect.x += self.speed
        if keys[pygame.K_UP]:
            self.rect.y -= self.speed
        if keys[pygame.K_DOWN]:
            self.rect.y += self.speed

    def check_collision(self, enemies, items):
        # プレイヤーと敵の衝突検出
        enemy_collisions = pygame.sprite.spritecollide(self, enemies, True)
        # 衝突した敵の処理を記述

        # プレイヤーとアイテムの衝突検出
        item_collisions = pygame.sprite.spritecollide(self, items, True)
        # 衝突したアイテムの処理を記述

    def animate(self):
        now = pygame.time.get_ticks()
        if now - self.animation_timer > self.animation_delay:
            self.current_frame = (self.current_frame + 1) % len(self.images)
            self.image = self.images[self.current_frame]
            self.animation_timer = now


# Enemyクラスの定義
class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("enemy.png")
        self.image = pygame.transform.scale(self.image, (common_width, common_height))
        self.rect = self.image.get_rect()
        self.rect.center = (random.randint(0, screen_width), random.randint(0, screen_height))
        self.speed = 1

    def update(self):
        self.rect.x += self.speed
        if self.rect.left > screen_width:
            self.rect.right = 0
            self.rect.bottom = random.randint(0, screen_height)

    def animate(self):
        pass
    
# Itemクラスの定義
class Item(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("item.png")
        self.image = pygame.transform.scale(self.image, (100, common_height))
        self.rect = self.image.get_rect()
        self.rect.center = (random.randint(0, screen_width), random.randint(0, screen_height))
        self.speed = 1

        # アニメーションの初期化
        self.images = [
            pygame.image.load("item_frame1.png"),
            pygame.image.load("item_frame2.png"),
            pygame.image.load("item_frame3.png"),
            # 追加のフレーム画像を読み込む
        ]
        self.current_frame = 0
        self.animation_timer = pygame.time.get_ticks()
        self.animation_delay = 200  # フレームの更新間隔（ミリ秒）

    def update(self):
        self.rect.x += self.speed
        if self.rect.left > screen_width:
            self.rect.right = 0

    def animate(self):
        now = pygame.time.get_ticks()
        if now - self.animation_timer > self.animation_delay:
            self.current_frame = (self.current_frame + 1) % len(self.images)
            self.image = self.images[self.current_frame]
            self.animation_timer = now

# プレイヤーの作成
player = Player()

# 敵の作成
enemies = pygame.sprite.Group()
for _ in range(5):
    enemy = Enemy()
    enemies.add(enemy)

# アイテムの作成
items = pygame.sprite.Group()
for _ in range(10):
    item = Item()
    items.add(item)

# ゲームループ
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    player.update()
    player.check_collision(enemies, items)
    player.animate()

    enemies.update()
    items.update()

    screen.fill((0, 0, 0))

    screen.blit(player.image, player.rect)
    for enemy in enemies:
        screen.blit(enemy.image, enemy.rect)
        enemy.animate()
    for item in items:
        screen.blit(item.image, item.rect)
        item.animate()

    pygame.display.flip()

# ゲームの終了
pygame.quit()
```

## 今回の追加

### 衝突検出について

```python
def check_collision(self, enemies, items):
    enemy_collisions = pygame.sprite.spritecollide(self, enemies, True)
    item_collisions = pygame.sprite.spritecollide(self, items, True)
```

- `check_collision`メソッドは、プレイヤーと敵、アイテムとの衝突を検出します。

- `pygame.sprite.spritecollide()`関数を使用して、プレイヤーと敵、アイテムとの衝突をチェックします。衝突した敵とアイテムはグループから削除されます（`True`パラメータによって指定）。

- 衝突した敵やアイテムの処理はまだ記述されていませんので、必要に応じてこのメソッドを拡張してください。

### アニメーションについて


```python
def animate(self):
    now = pygame.time.get_ticks()
    if now - self.animation_timer > self.animation_delay:
        self.current_frame = (self.current_frame + 1) % len(self.images)
        self.image = self.images[self.current_frame]
        self.animation_timer = now
```


- `animate`メソッドは、プレイヤーのアニメーションを制御します。

- `pygame.time.get_ticks()`関数を使用して現在の時刻を取得し、アニメーションの更新間隔を超えた場合にアニメーションを進めます。

- `current_frame`を更新し、次のフレームのインデックスを計算します。`len(self.images)`でフレーム数を取得し、リスト内を循環させるために`%`演算子を使用しています。

- `current_frame`に応じて適切なフレームのイメージを取得し、プレイヤーのイメージを更新します。

- 最後に、`animation_timer`を現在の時刻に更新します。

これにより、プレイヤーのアニメーションが指定されたフレーム更新間隔で再生されます。


## まとめ
衝突時の処理については、`def check_collision(self, enemies, items):`　に追加で書く必要がありそうです…
animatiionをさらに滑らかにする作業はまだ先でも良さそうだと思いました。いずれ、エフェクトもつけれるようにしたいです。