Pygameを使って RPGを作る（13. 戦闘画面（その１））

# 概要
戦闘画面作成
1. Battleクラスの追加
1. 戦闘画面にフィールドマップで衝突した敵を表示する
1. 背景、メッセージを表示する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576081/5d149615-a73b-1217-a4c4-f69ea9b1e542.png)

# Battleクラス
このコードは、Pygameを使用してバトル画面を描画する`Battle`クラスの一部です。主に、バトル中に表示する背景、敵キャラクター、メッセージ、そしてフェードイン処理を行っています。コードの各部分について詳しく解説します。

---

### **`__init__`メソッド**
```python
def __init__(self):
    self.display_surface = pg.display.get_surface()
    self.back_ground_img = pg.image.load('../battle/bg.png').convert()
    self.bg_size = self.back_ground_img.get_size()

    self.rect = self.back_ground_img.get_rect()
    self.off_set = pg.Vector2()
    self.off_set.x = -int((self.rect.centerx - WIDTH / 2))
    self.off_set.y = -int((self.rect.centery - HEIGHT / 2))

    self.font = pg.font.Font("../battle/Meiryo.ttf", 24)
```
- **`self.display_surface = pg.display.get_surface()`**:  
  現在の画面（ウィンドウ）を取得します。これに描画します。

- **`self.back_ground_img = pg.image.load('../battle/bg.png').convert()`**:  
  バトル背景画像（`bg.png`）を読み込み、その画像をPygameのSurfaceに変換します。`convert()`は画像を最適化し、描画の効率を向上させます。

- **`self.bg_size = self.back_ground_img.get_size()`**:  
  背景画像のサイズを取得し、`self.bg_size`に格納します。

- **`self.rect = self.back_ground_img.get_rect()`**:  
  背景画像の矩形（`Rect`）オブジェクトを取得します。この矩形を使用して、画像の位置やサイズを管理します。

- **`self.off_set = pg.Vector2()`**:  
  画面の中央を基準に背景をオフセットするための`Vector2`（2Dベクトル）を作成します。これにより、背景画像がスクリーンの中央に表示されるように調整します。

- **`self.font = pg.font.Font("../battle/Meiryo.ttf", 24)`**:  
  メッセージ用のフォントを指定します。`"Meiryo.ttf"`というフォントファイルを指定して、サイズ24のフォントオブジェクトを作成します。

---

### **`draw`メソッド**
```python
def draw(self, player):
    enemy = player.collided_enemy
    mob_pos = ((WIDTH - 128) / 2, HEIGHT / 8)
    self.display_surface.blit(enemy.battle_surface, mob_pos)

    pg.display.set_caption('Battle')

    text_surface = self.font.render(f"  {enemy.name}が現れました!  ", True, (255, 255, 255))
    bg_surface = pg.Surface((self.bg_size[0] * 0.95, self.bg_size[1] * 0.3), pg.SRCALPHA)
    bg_surface.fill((0, 0, 200, 128))  # (R, G, B, Alpha)で透明度を指定（128は50%透明）
    message_rect = bg_surface.get_rect()

    pg.draw.rect(bg_surface, WHITE, message_rect, 3, border_radius=5)

    self.display_surface.blit(bg_surface, (250, 430))
    self.display_surface.blit(text_surface, (250, 430))
```
- **`enemy = player.collided_enemy`**:  
  プレイヤーが現在衝突している敵を取得します。`player.collided_enemy`には、プレイヤーと衝突した敵（`Enemy`オブジェクト）が格納されていると仮定しています。

- **`mob_pos = ((WIDTH - 128) / 2, HEIGHT / 8)`**:  
  敵キャラクターを画面上に描画する位置を計算します。この場合、`mob_pos`は画面の中央（X軸）と上部（Y軸）の少し下に配置されます。

- **`self.display_surface.blit(enemy.battle_surface, mob_pos)`**:  
  `enemy.battle_surface`（敵キャラクターのイメージ）を計算した位置`mob_pos`に描画します。

- **`pg.display.set_caption('Battle')`**:  
  ウィンドウのタイトルバーに「Battle」という文字列を表示します。

- **`text_surface = self.font.render(f"  {enemy.name}が現れました!  ", True, (255, 255, 255))`**:  
  敵の名前と「が現れました!」というメッセージを、白色で描画するための`Surface`を作成します。`self.font.render()`を使ってテキストを描画します。

- **`bg_surface = pg.Surface((self.bg_size[0] * 0.95, self.bg_size[1] * 0.3), pg.SRCALPHA)`**:  
  メッセージ用の背景を作成します。`SRCALPHA`フラグを使うことで、このSurfaceが透明な部分を持つことができます。背景のサイズは画面の95%の幅と30%の高さに設定されています。

- **`bg_surface.fill((0, 0, 200, 128))`**:  
  背景を青色（RGB: 0, 0, 200）で塗りつぶし、`128`のアルファ値を指定して半透明にします。

- **`message_rect = bg_surface.get_rect()`**:  
  メッセージ背景の矩形（`Rect`）を取得します。これにより、背景を描画する位置を指定できます。

- **`pg.draw.rect(bg_surface, WHITE, message_rect, 3, border_radius=5)`**:  
  背景矩形に白い枠線を描画します。枠線の太さは`3`で、角を丸くするために`border_radius=5`を指定しています。

- **`self.display_surface.blit(bg_surface, (250, 430))`**:  
  メッセージ背景を指定した位置（(250, 430)）に描画します。

- **`self.display_surface.blit(text_surface, (250, 430))`**:  
  上で作成したメッセージテキストを、背景の上に描画します。

---

### **`fade_in`メソッド**
```python
def fade_in(self):
    for alpha in range(0, 125, 5):
        temp_surface = self.back_ground_img.copy()
        temp_surface.set_alpha(alpha)
        self.display_surface.blit(temp_surface, self.rect.topleft + self.off_set)
        pg.display.flip()
        pg.time.delay(30)
```
- **`for alpha in range(0, 125, 5)`**:  
  `alpha`（透明度）を0から125まで5ずつ増加させながら、フェードイン効果を作ります。`125`は途中まで透明度を上げるために使用されており、完全に不透明にする前の段階で処理が止まります。

- **`temp_surface = self.back_ground_img.copy()`**:  
  背景画像をコピーして`temp_surface`に格納します。

- **`temp_surface.set_alpha(alpha)`**:  
  コピーした背景画像に対して、現在の透明度（`alpha`）を設定します。

- **`self.display_surface.blit(temp_surface, self.rect.topleft + self.off_set)`**:  
  設定した透明度の背景画像を、オフセットを考慮して画面に描画します。

- **`pg.display.flip()`**:  
  画面を更新して、描画内容を実際に表示します。

- **`pg.time.delay(30)`**:  
  30ミリ秒の遅延を入れて、フェードイン効果が少しずつ進行するようにします。

---

### **まとめ**
この`Battle`クラスは、バトル画面において背景、敵キャラクター、メッセージ、フェードイン効果を描画するための処理を担当しています。`fade_in`メソッドは、バトルの開始時に背景が徐々に表示される効果を作り、`draw`メソッドはバトル中に敵とメッセージを描画します。