ｐygameでRPG（描画メイン）



[新RPGの目次](https://qiita.com/hijpa/items/31900e327315fa8e4eea)

# キーハンドラー

<details><summary>ここをクリックしてください</summary>

FileNotFoundError: No such file or directory:
というエラーが出たらパスの前に　r　をつけましょう。

```python:

import pygame
import sys
from pygame.locals import *
    
pygame.init()
screen = pygame.display.set_mode((320,160))
#ここにフォントのパスを貼り付ける
font = pygame.font.Font(, 20)
white = (255,255,255)
black = (0,0,0)
phase = 0
message = "モンスターがあらわれた！"

clock = pygame.time.Clock()
running = True
while running:
    clock.tick(60)

    screen.fill(black)    
    message_surface = font.render(message, True, white)
    screen.blit(message_surface, (10 , 50))
    pygame.display.update()    

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_z:
                if phase == 0:
                    message = "プレイヤーのこうげき"
                    phase = 1
                elif phase == 1:
                    message = "モンスターに　～のダメージ"
                    phase = 0


```
</details>


# カーソル画像作成

<details><summary>ここをクリックしてください</summary>

```python:
import numpy as np
import cv2

# キャンバスのサイズ
canvas_size = (25, 25)

# キャンバスを作成（透明にするためにアルファチャンネルを使用）
canvas = np.zeros((canvas_size[1], canvas_size[0], 4), dtype=np.uint8)

# 三角形の頂点座標
triangle_vertices = np.array([[12, 5], [5, 15], [19, 15]], np.int32)
triangle_vertices = triangle_vertices.reshape((-1, 1, 2))

# 三角形を描画（白色で）色の指定が右端と左端でpygameとは逆になってる
cv2.fillPoly(canvas, [triangle_vertices], (255, 255, 255, 255))
rotated_cw90 = cv2.rotate(canvas, cv2.ROTATE_90_CLOCKWISE)
# 画像を保存
output_path = "cursor.png"
cv2.imwrite(output_path, rotated_cw90)

print(f"画像が{output_path}に保存されました。")


```

cv2.fillPoly(canvas, [triangle_vertices], (255, 255, 255, 255))
cv2の色の順序はBGR
pygameの色の順序はRGB
透明度もcv2は０ではなく２５５が透明

</details> 

# 描画メイン

<details><summary>ここをクリックしてください</summary>

コード概要
1.インポート
          
2.関数
　(テキスト改行)
          
3.セットアップ
　(色、初期ステータス、パス、ゲーム状態の管理、バトルメッセージ、
　　カーソル)
          
4.メインループ
　(ステータスウィンドゥ、メッセージウィンドゥ、コマンドウィンドゥ、
　　魔物選択ウィンドゥ)
          
5.キーハンドラー
　(Zキー)

---------------------------------------------------------------------------------------------------
          
1. **`phase = 0`**  
   - 戦闘の進行状況を管理する変数  
   - 戦闘の段階（フェーズ）を数値で表す

2. **`battle_message = True`**  
   - メッセージウィンドウの表示状態を管理するフラグ  
   - `True` の場合、メッセージウィンドウを表示する

3. **`command = False`**  
   - コマンドウィンドウの表示状態を管理するフラグ  
   - `True` の場合、コマンドウィンドウを表示する

4. **`select = False`**  
   - 魔物選択ウィンドウの表示状態を管理するフラグ  
   - `True` の場合、魔物選択ウィンドウを表示する

5. **`alpha = 220`**  
   - カーソルの透明度を表す数値  
   - 120（半透明）〜255（完全不透明）の範囲で設定する

6. **`delta = 5`**  
   - カーソルの透明度を増減させる値  
   - `alpha` の変化量として使用される

   
---------------------------------------------------------------------------------------------------

```python:

import pygame
from pygame import *
import sys

# テキストを改行して描画する関数
def draw_text(surface, message, pos, font, color=(255, 255, 255)):
    lines = message.split('\n')
    x, y = pos
    for line in lines:
        text_surface = font.render(line, True, color)
        surface.blit(text_surface, (x, y))
        y += text_surface.get_height() + 9

# セットアップ
pygame.init()
width, height = 640, 480
screen=pygame.display.set_mode((width, height))
pygame.display.set_caption('battle')

# 色
white = (255,255,255)
black = (0,0,0)

# 初期ステータス
Max_HP = 53
player_HP = 53
Max_MP = 0
player_MP = 0
Level = 1

# ここにフォントのパスを貼り付ける
font = pygame.font.Font(, 18)
# ここにカーソル画像のパスを貼り付ける
cursor = pygame.image.load()

# ゲームの状態管理

phase = 0 # 戦闘の段階を管理
battle_message = True
command = False
select = False

# バトルメッセージ
message = "モンスターが　あらわれた！"

# カーソル
cursor_x = 30
cursor_y = 368
alpha = 220 # 透明度
delta = 5   # 透明度の増減

clock = pygame.time.Clock()
running = True

# ゲームのメインループ
while running:
    clock.tick(60)
    # 画面を黒色に塗りつぶし
    screen.fill((0, 0, 0))

    # ステータスウィンドゥ
    # 白いヨコ線
    pygame.draw.line(screen, white, (20, 58),(118, 58))
    # ステータスウィンドゥの枠
    pygame.draw.rect(screen, white, (20, 20, 102, 134), 3, 5)
    text = font.render("ゆうしゃ", True, white)
    screen.blit(text,(35, 35))
    text = font.render("H", True, white)
    screen.blit(text,(35, 65))
    text = font.render(f"{player_HP}", True, white)
    screen.blit(text,(85, 65))
    text = font.render("M", True, white)
    screen.blit(text,(35, 95))
    text = font.render(f"{player_MP}", True, white)
    screen.blit(text,(85, 95))
    text = font.render("ゆ：　", True, white)
    screen.blit(text,(35, 125))
    text = font.render(f"{Level}", True, white)
    screen.blit(text,(85, 125))

    # メッセージウィンドゥ
    if battle_message:
        # バトルメッセージの枠
        pygame.draw.rect(screen, white, Rect(20, 320, 600, 140), 3, 5)
        # バトルメッセージ
        draw_text(screen,message,(40,350),font)
    # コマンドウィンドゥ
    if command:
        # カーソル
        screen.blit(cursor, (cursor_x, cursor_y))
        cursor.set_alpha(alpha)
        alpha += delta
        if alpha <= 120 or alpha >= 255:
            delta = -delta
        # 白いヨコ線
        pygame.draw.line(screen, white, (20, 358),(236, 358))
        # コマンドウィンドゥの枠
        pygame.draw.rect(screen, white, (20, 320, 220, 140), 3, 5)
        text = font.render("ゆうしゃ", True, white)
        screen.blit(text,(80, 335))
        text = font.render("こうげき", True, white)
        screen.blit(text,(50, 370))
        # 魔物選択ウィンドゥ
        if select:
            # 魔物選択ウィンドゥの枠
            pygame.draw.rect(screen, white, (245, 320, 220, 140), 3, 5)
            text = font.render("モンスター", True, white)
            screen.blit(text,(290, 330))

    pygame.display.update()
    # キーハンドラー
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_z:
                # あらわれた！を消してコマンドウィンドゥをひらく
                if phase == 0:
                    battle_message = False # あらわれた！を消す
                    command = True
                    phase = 1
                # コマンドウィンドゥを開いたまま、魔物選択ウィンドゥをひらく
                elif phase == 1:
                    select = True
                    cursor_x = 270
                    cursor_y = 328
                    phase = 2
                # 魔物選択ウィンドゥを消して、メッセージの表示
                elif phase == 2:
                    message = "プレイヤーのこうげき"
                    command = False
                    select = False
                    battle_message = True
                    phase = 3
                # メッセージの表示(ただし次のphaseがキーハンドラーに必要)
                elif phase == 3:
                    message = "プレイヤーのこうげき\nモンスターに　～のダメージ"
                    phase = 4
                # コマンドウィンドゥに戻る
                elif phase == 4:
                    battle_message = False # ～のダメージを消す
                    command = True
                    phase = 1
                    cursor_x = 30
                    cursor_y = 368

```

1. `screen.blit(cursor, (cursor_x, cursor_y))`  
   - 画面 (`screen`) にカーソル (`cursor`) を描画します。カーソルの位置は `(cursor_x, cursor_y)` で指定されています。

2. `cursor.set_alpha(alpha)`  
   - カーソルの透明度（アルファ値）を `alpha` の値に設定します。`alpha` は 0 から 255 の範囲で、255 に近いほど不透明になります。

3. `alpha += delta`  
   - `alpha` の値を `delta` だけ増減させます。これによって透明度が変化します。

4. `if alpha <= 120 or alpha >= 255:`  
   - `alpha` が 120 以下または 255 以上になった場合、透明度の変化の方向を反転させます。

5. `delta = -delta`  
   - `delta` の符号を反転させることで、透明度の増減方向を変更します。例えば、`delta` が `5` なら `-5` に変わり、逆に `-5` なら `5` になります。



</details>

# コマンドのみ

<details><summary>ここにコードがあります</summary>

```python:

import pygame
from pygame import *
import sys


# # 2列×3行のテキストを描画する関数（コマンド）
def draw_text_grid(screen, text_list, start_x, start_y, spacing_x, spacing_y):
    for col_index, col in enumerate(text_list):  # 列ごとに処理
        for row_index, text in enumerate(col):  # 各行のテキストを描画
            text_surface = font.render(text, True, white)
            x = start_x + col_index * spacing_x  # 列ごとにX座標を調整
            y = start_y + row_index * spacing_y  # 行ごとにY座標を調整
            screen.blit(text_surface, (x, y))

# セットアップ
pygame.init()
width, height = 640, 480
screen=pygame.display.set_mode((width, height))
pygame.display.set_caption('コマンド')

# 色
white = (255,255,255)

# ここにフォントのパスを貼り付ける
font = pygame.font.Font(, 18)
# ここにカーソル画像のパスを貼り付ける
cursor = pygame.image.load()

alpha = 220 # 透明度
delta = 5   # 透明度の増減

command = True

# 2列×3行のテキストデータ
text_list = [
    ["攻撃", "魔法", "ガード"],  # 1列目
    ["アイテム", "装備", "逃げる"]  # 2列目
]
# コマンドウィンドゥのレクト情報
cmd_rect = pygame.Rect(20, 320, 220, 140)
cmd_rectx,cmd_recty = cmd_rect.topleft

cmd_index = 0
cmd_num = 0
cmd_num2 = 0

clock = pygame.time.Clock()
running = True

# ゲームのメインループ
while running:
    clock.tick(60)
    # 画面を黒色に塗りつぶし
    screen.fill((0, 0, 0))

    # コマンドウィンドゥ
    if command:
        # 白いヨコ線
        pygame.draw.line(screen, white, (20, 358),(236, 358))
        # コマンドウィンドゥの枠
        pygame.draw.rect(screen, white, cmd_rect, 3, 5)
        # ゆうしゃテキスト
        text = font.render("ゆうしゃ", True, white)
        screen.blit(text,((cmd_rectx + 14) + 60,(cmd_recty + 14)))
        # コマンドテキスト
        draw_text_grid(screen, text_list, start_x=(cmd_rectx + 35), start_y=(cmd_recty + 45), spacing_x=98, spacing_y=34)
        # カーソル描画
        screen.blit(cursor, ((cmd_rectx + 5) + 100 * cmd_num2, (cmd_recty + 40) + 34 * cmd_num))
        # カーソル点滅
        cursor.set_alpha(alpha)
        alpha += delta
        if alpha <= 120 or alpha >= 255:
            delta = -delta
        cmd_index = cmd_num + (cmd_num2 * 3)

    pygame.display.update()
    # キーハンドラー
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_DOWN:
                cmd_num = (cmd_num + 1) % 3  # 下へ移動
            if event.key == K_UP:
                cmd_num = (cmd_num - 1) % 3  # 上へ移動
            if event.key == K_RIGHT:
                cmd_num2 = (cmd_num2 + 1) % 2  # 右へ移動
            if event.key == K_LEFT:
                cmd_num2 = (cmd_num2 - 1) % 2  # 左へ移動


```
</details>