PygameでRPG制作　ーーそれっぽい画面を作ってみよう② バトル画面のメニューを作ろう

この記事は、岩手県八幡平市のプログラミング教室「アクセルキャンプ」の公開教材です。
[アクセルキャンプ(フリースペースプラウド)のリンク](https://freespaceproud.com)
教材の作成依頼等も承っております。ご意見等は、リンク先の問い合わせ欄からお願いします。
教材の転用・利用等は自由です  
# 寒っ(半ギレ)
季節の変わり目っていうか、すでに冬な気がしてます。ハワイでは一年中夏で海で泳げますが、やっぱりこの時期は結構寒いです。でもTシャツで過ごせるので、東北とは全く違いますけどね。

もうちょっとすると手がかじかんでコード書くのも辛い時期になってきます。。。

それでは今日もゴリゴリコードを書いていきましょう!!  

# 今日の目標
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732489/2b0175ce-0ca8-df10-c8c3-aaa3dca97e07.png)

こんな感じで、簡単なバトル画面のメニュー表示を作っていきます。今選択しているものを黄色で表示し、なにかのキーを押すと、矢印と一緒に移動します。前回まで習ったことがでほとんどの部分をカバーできる人は、自信あるニキはちょっとやってみてから、以下の説明を読むのも、いいと思います。  

前回のまでのスクリプト
```python
import pygame
from pygame.locals import *
import sys

def main():
    pygame.init()                                   # Pygameの初期化
    screen = pygame.display.set_mode((800,600))    # 400 x 300の大きさの画面を作る
    pygame.display.set_caption("いけめんがつくったげえむ")              # 画面上部に表示するタイトルを設定

    rect_x = 20 #長方形左上のｘ座標
    rect_y = 400  #長方形左上のｘ座標
    rect_width = 800 - (rect_x * 2)  #長方形の幅
    rect_height = 600 - (rect_y + 20) #長方形の高さ
    slyme_image = pygame.image.load("image/slyme.png")

    font = pygame.font.Font("font/DragonQuestFC.ttf", 30)
    while (1):
        screen.fill((0,0,0))  # 画面を黒色に塗りつぶし
        screen.blit(slyme_image, (400 - (400 / 2), 0))

        pygame.draw.rect(screen,(255, 255, 255), Rect(rect_x, rect_y, rect_width, rect_height), 10)
        text = font.render("りっきーが　あらわれた！", True, (255, 255, 255))
        screen.blit(text, (40, 420))
        pygame.display.update()     # 画面を更新
        # イベント処理
        for event in pygame.event.get():
            if event.type == QUIT:  # 閉じるボタンが押されたら終了
                pygame.quit()       # Pygameの終了(画面閉じられる)
                sys.exit()


if __name__ == "__main__":
    main()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732489/8105b04f-d106-bb3d-f264-b448974e5285.png)

こんな感じでスライムリッキーを表示しました。前回までの主な内容は
・四角を表示する
・スライムの画像を表示する
。文字を画像に変換して表示する
といった感じでした。ここらへんのことを応用して、「たたかう」「じゅもん」「にげる」の選択肢を作っていきます。
そしてそれができたら、まず選択肢の色を変えます。そのときに、選択肢の左側に矢印を表示させるのですが、この仕組み、多分皆さんが考えて いるよりも単純です。早速やってみましょう。

# まずは選択肢の配置から
この部分は先週の復習なので、さらっと行きます。文字を表示するときは、
①文字のフォントの設定(フォントの種類と文字の大きさ)
②フォントに(表示したい文字列)(アンチエイリアス=true)(文字の色)を与えて、文字を画像データとして扱えるようにする
③変換した文字の表示
の3ステップを踏みます。それぞれ
```python
font = font.Font("使いたいフォント", フォントの大きさ)
```
```python
text = font.render("表示したい文字列". true, 色)
```
```python
screen.blit(text, (表示位置の座標))
```
みたいな感じです(変数名は実際のコードに合わせてありますが、自由です)

それでは、3つの文字列(たたかう、じゅもん、にげる)を表示してみましょう。

```python
    while (1):
        screen.fill((0,0,0))  # 画面を黒色に塗りつぶし
        screen.blit(slyme_image, (400 - (400 / 2), 0))

        pygame.draw.rect(screen,(255, 255, 255), Rect(rect_x, rect_y, rect_width, rect_height), 10)
        text = font.render("りっきーが　あらわれた！", True, (255, 255, 255))

        #選択肢を画像として格納
        battle_text = font.render("たたかう", True, color0)
        spell_text = font.render("じゅもん", True, color1)
        run_text = font.render("にげる", True, color2)

        screen.blit(text, (40, 420))
        # 表示
        screen.blit(battle_text, (45, 450))
        screen.blit(spell_text, (45, 480))
        screen.blit(run_text, (45, 510))

        pygame.display.update()     # 画面を更新
        # イベント処理
        for event in pygame.event.get():
            if event.type == QUIT:  # 閉じるボタンが押されたら終了
                pygame.quit()       # Pygameの終了(画面閉じられる)
                sys.exit()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732489/bccc85cb-fca8-b4a2-d9ed-f97ff40161d8.png)

しれっと、色の変数(yellow, white)を追加しているの、気づきました?そう、選択されている文字だけ黄色で表示する予定です。とりあえず、デフォルトとして、「たたかう」を黄色くしちゃいましょう
```python
color0 = yellow
```

# 選択している文字を黄色にする  
では、下キーを押して、選択したいものを黄色くなるようにしてみましょう。
選択肢を変更するには、キーを押す、マウスをクリックするなど、それを引き起こすためのトリガーとなる「イベント」が必要になります。コードの下のほうに、「イベント処理」とあるので、その辺に書き足していけば行けそうな感じですね。  
QUITという、Xボタンが押されたときのイベント処理が書いてあるので、その下に処理を追加してみましょう。キーが押されたときのイベントの種類(タイプ=type)は、KEYDOWNとなります。
```python
elif event.type = KEYDOWN:
    #押されたときの処理

```

では、この処理はどのように書いていけばいいでしょう。今回は、action_numberという変数を用いて、黄色く表示する選択肢を決定する仕組みにします。まず、numberに0を代入します。
```python
selected_action = 0
```
そして、キーが押されたとき、selected_actionに1を足します。もしselected_numberが2であったときは、選択肢は3つしかないので、0に戻します。
```python
elif event.type == KEYDOWN:
    if acrion_number == 2:
        acrion_number = 0
    else:
        acrion_number += 1
```
それでは、選択肢番号の処理ができそうなので、それにあわせて選択肢の色を変えて行きましょう。ここで、ちょっとしたテクニックを教えます。  
if文を使って、選択肢の色(color0, color1, color2)を変える処理は、こんな感じで思い浮かべる人がおおいのでは?
```python
if acrion_number == 0:
    color0 = yellow
    color1 = white
    color2 = white
if acrion_number == 1:
    color0 = white
    color1 = yellow
    color2 = white
if acrion_number == 2:
    color0 = white
    color1 = white
    color2 = yellow
```

いいですね!では実行してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732489/e7c27427-7fb2-07e7-7e61-34fbe690d78f.png)

できた!よし!きょうの勉強おわり!

ってなってもいいのですが、ちょっとまってください。このコード、めちゃくちゃ無駄が多いんですよね!特に3つのcolor変数の扱いがひどい!ので、リファクタリングしましょう。複数のデータを扱うときは、リストを使うのが便利です。リストの使い方を忘れちゃった人は、[ここ](https://qiita.com/ricky-sensei/items/62486a8636cbe8ffcbdc)で復習してみてください。  
```python
import pygame
from pygame.locals import *
import sys


def main():
    pygame.init()  # Pygameの初期化
    screen = pygame.display.set_mode((800, 600))  # 400 x 300の大きさの画面を作る
    pygame.display.set_caption("いけめんがつくったげえむ")  # 画面上部に表示するタイトルを設定

    rect_x = 20  # 長方形左上のｘ座標
    rect_y = 400  # 長方形左上のｘ座標
    rect_width = 800 - (rect_x * 2)  # 長方形の幅
    rect_height = 600 - (rect_y + 20)  # 長方形の高さ
    slyme_image = pygame.image.load("image/slyme.png")

    font = pygame.font.Font("font/DragonQuestFC.ttf", 30)

    action_number = 0  # 選択肢の番号
    white = (255, 255, 255)
    yellow = (255, 255, 0)
    """
    メインループ内で決めればいいので、削除
    color0 = white
    color1 = white
    color2 = white
    """

    while (1):

        """
        一度全部白にしてから、指定の部分だけ黄色にする
        """
        colors = [white, white, white]
        colors[action_number] = yellow

        screen.fill((0, 0, 0))  # 画面を黒色に塗りつぶし
        screen.blit(slyme_image, (400 - (400 / 2), 0))

        pygame.draw.rect(screen, (255, 255, 255), Rect(rect_x, rect_y, rect_width, rect_height), 10)
        text = font.render("りっきーが　あらわれた！", True, (255, 255, 255))

        """
        colorsリストから、それぞれの文字の色を取得する
        """
        battle_text = font.render("たたかう", True, colors[0])
        spell_text = font.render("じゅもん", True, colors[1])
        run_text = font.render("にげる", True, colors[2])

        screen.blit(text, (40, 420))
        screen.blit(battle_text, (45, 450))
        screen.blit(spell_text, (45, 480))
        screen.blit(run_text, (45, 510))

        pygame.display.update()  # 画面を更新
        # イベント処理
        for event in pygame.event.get():
            if event.type == QUIT:  # 閉じるボタンが押されたら終了
                pygame.quit()  # Pygameの終了(画面閉じられる)
                sys.exit()

            elif event.type == KEYDOWN:
                if action_number == 2:
                    action_number = 0
                else:
                    action_number += 1


if __name__ == "__main__":
    main()

```
***  
  
# ひさびさの しゅくだい!  
①上のコードでは、どのキーを押しても選択肢が下に移動します。上矢印を打てば上、下矢印を打てば下に移動するようにするには、どうしたらいいでしょうか。  
②一番最初の画像のように、矢印をつけるにはどうしたらいいでしょう?考えてみよう

③上のコードは、一度リファクタリングをしましたが、まだまだキレイなコードとは言えない部分が実はあります。自分で考えて、「ここもっとこうしたほうがよくね?」みたいなところを探して、リファクタリングしてみましょう。
例1)action_numberていう変数名なんかダサくね?
例2)screen.blitのところ、繰り返しとか使ったほうがいんじゃね?
などなど
***  
  
では、また来週!