0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

pygameでRPG(まほう)

Posted at

テスト中

新RPGの目次

まほう

ここにコードがあります

import pygame
from pygame import *
import sys
import time
import random

# 部分一致で値を取得する関数
def get_value_by_partial_key(dictionary, partial_key):
    for key in dictionary:
        if key in partial_key:
            return dictionary[key]
    return None

# 改行してテキストを描画する関数(バトルメッセージ)
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() * 2

# 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))

# ここのpathはそのままにしておく(パスを貼り付けるところではない)
def bgm(path):
    pygame.mixer.music.load(path)
    pygame.mixer.music.play(-1)

pygame.init()
width, height = 640, 480
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('まほう')

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

# SE
# ここにボタン音のパスを貼り付ける
sound = pygame.mixer.Sound()
# ここにダメージ音のパスを貼り付ける
sound2 = pygame.mixer.Sound()

# BGM
# ここに戦闘のBGMのパスを貼り付ける
battle_bgm = 
# ここに勝ったときのBGMのパスを貼り付ける
win_bgm = 
# ここに負けたときのBGMのパスを貼り付ける
lose_bgm = 

bgm(battle_bgm)    

# モンスター
nameA = ""
nameB = ""
nameC = ""
# モンスターのグループ
# 全角スペースで区切ります
# ex) "スライム ウルフ"
# ひとグループ5体までです
groupA = ""
groupB = ""
groupC = ""
monster_list = [groupA,groupB,groupC]

# 色
white = (255, 255, 255)

# カーソル
alpha = 220
delta = 5

message = "モンスターが あらわれた!"

battle_message = True
command = False
select = False
masic_select = False
defeat = False

actor_index = 0
select_index = 0
masic_index = 0
chara_index = 0
cmd_index = 0
cmd_num1 = 0
cmd_num2 = 0

phase = 0
masic_phase = 0

# 枠点滅
status_flash = 0
status_visible = 0
mon_flash = 0
mon_visible = 0
player_damage = 0
mon_damage = 0

# まほうエフェクト
masic_effect = 0
# まほうフレーム
masic_frame = 0
# まほうサーフェイス
damera_surface = pygame.Surface((width,height),SRCALPHA)
damera_surface.fill((255,201,14,128))
hoimun_surface = pygame.Surface((width,height),SRCALPHA)
hoimun_surface.fill((255,255,255,128))
# まほうリスト
damera = {"masic_name":"ダメラ","MP":2,"数値":10,"masic_effect":1,"masic_type":"攻撃まほう","surface":damera_surface}
hoimun = {"masic_name":"ホイムン","MP":3,"数値":30,"masic_effect":2,"masic_type":"補助まほう","surface":hoimun_surface}
masic_list = [damera,hoimun]
cmd_cursor = False
# キャラリスト
chara_list = ["ゆうしゃ","せんし"]

# レクト
select_rect = pygame.Rect(width * 0.4,height * 0.67,220,140)
select_rectx,select_recty = select_rect.topleft
cmd_rect = pygame.Rect(20, height * 0.67, 220, 140)
cmd_rectx,cmd_recty = cmd_rect.topleft
message_rect = pygame.Rect(20, height * 0.67, 600, 140)
message_rectx,message_recty = message_rect.topleft


# 2列×3行のテキストデータ
text_list = [
    ["攻撃", "魔法", "ガード"],  # 1列目
    ["アイテム", "装備", "逃げる"]  # 2列目
]

status_data = []

# 勇者の初期ステータス
player_name = "ゆうしゃ"
player_Max_HP = 53
player_HP = 53
player_Max_MP = 5
player_MP = 5
player_power = 23
player_quick = 6
player_deffence = 0
player_level = 1

# 2列×3行のテキストデータ
text_list2 = [
    ["H", "M", ""],  # 1列目
    [f"{player_HP}", f"{player_MP}", f"{player_level}"]  # 2列目
]

# モンスターの初期ステータス
mon_images_dict = {nameA: monsterA_image,
                   nameB: monsterB_image,
                   nameC: monsterC_image}
mon_HP_dict = {nameA: 4,nameB: 6,nameC: 8}
mon_power_dict = {nameA: 3,nameB: 25,nameC: 6}
mon_deffence_dict = {nameA: 4,nameB: 4,nameC: 8}
mon_quickness_dict = {nameA:3,nameB:4,nameC:8}
mon = random.choice(monster_list)
mon_group_list = mon.split()

for i in range(len(mon_group_list)):  
    status_data.append({
        "name": f"{mon_group_list[i]}",
        "HP": get_value_by_partial_key(mon_HP_dict,mon_group_list[i]),
        "power": get_value_by_partial_key(mon_power_dict,mon_group_list[i]),
        "deffence": get_value_by_partial_key(mon_deffence_dict,mon_group_list[i]),
        "quickness": get_value_by_partial_key(mon_quickness_dict,mon_group_list[i]),
        "image": get_value_by_partial_key(mon_images_dict,mon_group_list[i]),
        "attack_on": 0
    })

status_data.append({"name": f"{player_name}","HP":player_HP,"MP":player_MP,"power":player_power,"deffence":player_deffence,"quickness": player_quick,})


# モンスターの位置を定義(奇数・偶数で異なる)
monster_positions = {
    1: [0.5],  # 1体
    2: [0.4, 0.6],  # 2体
    3: [0.3, 0.5, 0.7],  # 3体
    4: [0.2, 0.4, 0.6, 0.8],  # 4体
    5: [0.1, 0.3, 0.5, 0.7, 0.9]  # 5体
}

# モンスターの位置を設定
monster_rects = [
    get_value_by_partial_key(mon_images_dict,mon_group_list[i]).get_rect(center=(width * monster_positions[len(mon_group_list)][i], height * 0.5))
    for i in range(len(mon_group_list))
]


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

while running:
    clock.tick(60)
    # 画面を黒色に塗りつぶし
    screen.fill((0, 0, 0))
    # ステータスウィンドゥ
    if status_visible == 0:
        pygame.draw.line(screen, white, (20, 58),(118, 58))
        pygame.draw.rect(screen, white, (20, 20, 102, 134), 3)
        text = font.render("ゆうしゃ", True, white)
        screen.blit(text,(35, 35))
        draw_text_grid(screen, text_list2, start_x=32, start_y=65, spacing_x=40, spacing_y=30)  # テキスト描画
        text_list2 = [["H", "M", ""],[f"{player_HP}", f"{player_MP}", f"{player_level}"]]
    # モンスターの画像表示
    if mon_group_list:
        for i in range(len(mon_group_list)):
            if select_index == i and mon_visible == 0:
                screen.blit(get_value_by_partial_key(mon_images_dict,mon_group_list[i]), (monster_rects[i].topleft))
            if select_index != i:
                screen.blit(get_value_by_partial_key(mon_images_dict,mon_group_list[i]), (monster_rects[i].topleft))
    # コマンドウィンドゥ
    if command:
        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, 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=51, start_y=365, spacing_x=98, spacing_y=34)  # テキスト描画
        if cmd_cursor:
            screen.blit(cursor, ((cmd_rectx + 5) + 100 * cmd_num2, (cmd_recty + 40) + 34 * cmd_num1))  # カーソル描画
            cmd_index = cmd_num1 + (cmd_num2 * 3)
        # 魔物選択ウィンドゥ
        if select or masic_phase == 2 and masic_list[masic_index]["masic_type"] == "攻撃まほう":
            pygame.draw.rect(screen,white,select_rect,3,5)
            # モンスター名の描画
            if mon_group_list:
                for i, mon in enumerate(mon_group_list):
                    text = font.render(mon, True, white)
                    screen.blit(text, ((select_rectx + 14) + 30, (select_recty + 14) + 24 * i))
                screen.blit(cursor, ((select_rectx + 14), (select_recty + 11) + 24 * select_index))  # カーソル描画
        if masic_phase == 2 and masic_list[masic_index]["masic_type"] == "補助まほう":
            pygame.draw.rect(screen,white,select_rect,3,5)
            # キャラ選択
            # カーソル
            for i, chara in enumerate(chara_list):
                text = font.render(chara, True, white)
                screen.blit(text, ((select_rectx + 14) + 30, (select_recty + 14) + 24 * i))
            screen.blit(cursor, ((select_rectx + 14), (select_recty + 11) + 24 * chara_index))  # カーソル描画
        if masic_select and masic_phase == 1:
            # まほうがある場合のみ描画
            pygame.draw.rect(screen,white,select_rect,3,5)
            if masic_list:
                for i, masic in enumerate([masic_list[i]["masic_name"] for i in range(len(masic_list))]):
                    text = font.render(masic, True, white)
                    screen.blit(text, ((select_rectx + 14) + 30, (select_recty + 14) + 24 * i))
                screen.blit(cursor, ((select_rectx + 14), (select_recty + 11) + 24 * masic_index))  # カーソル描画
    # メッセージウィンドゥ
    if battle_message:
        pygame.draw.rect(screen, white, message_rect, 3,5)
        # バトルメッセージ
        draw_text(screen,message,((message_rectx + 24),(message_recty + 24)),font)

    # プレイヤーのダメージエフェクト
    if status_flash > 0:
        status_visible = pygame.time.get_ticks() // 90 % 2
        status_flash -= 1
        if status_flash == 19:
            sound2.play()
    if status_flash == 1:
        status_flash = 0
        status_visible = 0
        if player_HP <= 0:
            bgm(lose_bgm)
            message = "そのあと\nゆうしゃのすがたをみたものはいない"
            phase = 4
        else:
            phase = 2
    # モンスターのダメージエフェクト
    if mon_flash > 0:
        mon_visible = pygame.time.get_ticks() // 90 % 2
        mon_flash -= 1
        if mon_flash == 19:
            sound2.play()
    if mon_flash == 1:
        mon_flash = 0
        mon_visible = 0
        if status_data[select_index]["HP"] <= 0: 
            defeat = True
        else:
            phase = 2
                
    # まほう(色付き半透明レクト)
    if player_MP >= masic_list[masic_index]["MP"]:
        if masic_frame > 0:
            screen.blit(masic_list[masic_index]["surface"],(0,0))
            masic_frame -= 1

    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 and mon_flash == 0 and status_flash == 0:
                # あらわれた!を消してコマンドウィンドゥをひらく
                if phase == 0:
                    sound.play()                        
                    battle_message = False # あらわれた!を消す
                    command = True
                    cmd_cursor = True
                    phase = 1
                # コマンドウィンドゥを開いたまま、魔物選択ウィンドゥをひらく
                # 「たたかう」
                elif phase == 1 and cmd_index == 0:
                    sound.play()                        
                    select = True
                    cmd_cursor = False
                    phase = 2
                # 「まほう」
                elif phase == 1 and cmd_index == 1:
                    sound.play()                        
                    masic_select = True
                    cmd_cursor = False
                    masic_phase += 1
                    if masic_phase == 2:
                        phase = 2
                # 魔物選択ウィンドゥを消して、メッセージの表示
                elif phase == 2:
                    command = False
                    select = False
                    masic_phase = 3
                    battle_message = True
                    status_data2 = sorted(status_data, key=lambda dictionary: dictionary["quickness"], reverse=True)
                    if actor_index < len(status_data2):
                        current_actor = status_data2[actor_index]
                        sound.play()
                        if cmd_index == 0:
                            message = f'{current_actor["name"]}の こうげき!'
                        if cmd_index == 1:
                            if current_actor["name"] == "ゆうしゃ":
                                message = f'{player_name}は {masic_list[masic_index]["masic_name"]}を となえた!'
                                masic_effect = masic_list[masic_index]["masic_effect"]
                                masic_frame = 10
                            else:
                                message = f'{current_actor["name"]}の こうげき!'

                        phase = 3
                    # ターン終了したら、コマンドウィンドゥをひらく
                    elif actor_index == len(status_data):
                        actor_index = 0
                        select_index = 0
                        masic_index = 0
                        masic_phase = 0
                        cmd_index, cmd_num1,cmd_num2 = 0, 0, 0
                        sound.play()
                        battle_message, command, masic_select, cmd_cursor = False, True, False, True
                        phase = 1
                        for i in range(len(mon_group_list)):
                            status_data[i]["attack_on"] = 0
                # プレイヤーの攻撃(モンスターに与えるダメージ)
                elif phase == 3 and current_actor["name"] == "ゆうしゃ" and not defeat:
                    if cmd_index == 1 and player_MP < masic_list[masic_index]["MP"]:
                        message = "MPが足りない…"
                        phase = 2
                    elif cmd_index == 0 or masic_list[masic_index]["masic_type"] == "攻撃まほう":
                        if cmd_index == 0:
                            mon_damage = player_power // 2 - status_data[select_index]["deffence"] // 4
                        elif cmd_index == 1:
                            mon_damage = masic_list[masic_index]["数値"]
                            player_MP -= masic_list[masic_index]["MP"]
                        mon_damage = random.randint(mon_damage,int(mon_damage * 1.5))
                        if mon_damage <= 0:
                            mon_damage = 1
                        status_data[select_index]["HP"] -= mon_damage
                        message = f'{player_name}の こうげき!\n{status_data[select_index]["name"]}に {mon_damage}の ダメージ!' 
                        mon_flash = 20
                        if status_data[select_index]["attack_on"] == 1:
                            actor_index -= 1
                    elif masic_list[masic_index]["masic_type"] == "補助まほう":
                        # まほう(回復)
                        if masic_effect == 2:
                            if player_MP >= masic_list[masic_index]["MP"]:
                                recovery  = random.randint(masic_list[masic_index]["数値"],int(masic_list[masic_index]["数値"] * 1.5))
                                player_HP = min(player_Max_HP,player_HP + recovery)
                                message = f'{player_name}は {masic_list[masic_index]["masic_name"]}を となえた!\n{chara_list[chara_index]}の きずが かいふくした!' 
                        player_MP -= masic_list[masic_index]["MP"]
                        phase = 2
                    actor_index += 1
                elif defeat:
                    message = f'{player_name}の こうげき!\n{status_data[select_index]["name"]}に {mon_damage}の ダメージ!\n{status_data[select_index]["name"]}をたおした!'
                    del mon_group_list[select_index]
                    del monster_rects[select_index]
                    del status_data[select_index]
                    defeat = False
                    phase = 2
                    # モンスターをすべてたおした時の処理
                    if len(mon_group_list) == 0:
                        bgm(win_bgm)
                        message = "モンスターたちをやっつけた!"
                        phase = 4
                # モンスターの攻撃(プレイヤーに与えるダメージ)
                elif phase == 3:
                    sound.play()
                    for i in range(len(mon_group_list)):
                        if current_actor["name"] == status_data[i]["name"]:
                            player_damage = status_data[i]["power"] // 2 - player_deffence // 4
                            player_damage = random.randint(player_damage,int(player_damage * 1.5))
                            if player_damage <= 0:
                                player_damage = 1
                            player_HP -= player_damage
                            message = f'{current_actor["name"]}の こうげき!\n{player_name}に {player_damage}のダメージ!'
                            status_flash = 20
                            if player_HP <= 0:
                                player_HP = 0
                    current_actor["attack_on"] = 1
                    actor_index += 1
                # ワンテンポ置く
                elif phase == 4:
                    sound.play()
                    phase = 5
                elif phase == 5:
                    sound.play()
                    pygame.quit()
                    sys.exit()
                        
            #方向キー
            if event.type == KEYDOWN:
                if command and not select and not masic_select:
                    if event.key == K_DOWN:
                        cmd_num1 = (cmd_num1 + 1) % 3  # 下へ移動
                    if event.key == K_UP:
                        cmd_num1 = (cmd_num1 - 1) % 3  # 上へ移動
                    if event.key == K_RIGHT:
                        cmd_num2 = (cmd_num2 + 1) % 2  # 下へ移動
                    if event.key == K_LEFT:
                        cmd_num2 = (cmd_num2 - 1) % 2  # 下へ移動
                if select or masic_phase == 2 and masic_list[masic_index]["masic_type"] == "攻撃まほう":
                    if event.key == K_DOWN:
                        select_index = (select_index + 1) % len(mon_group_list)  # 下へ移動
                    if event.key == K_UP:
                        select_index = (select_index - 1) % len(mon_group_list)  # 上へ移動
                if masic_phase == 2 and masic_list[masic_index]["masic_type"] == "補助まほう":
                    if event.key == K_DOWN:
                        chara_index = (chara_index + 1) % len(chara_list)  # 下へ移動
                    if event.key == K_UP:
                        chara_index = (chara_index - 1) % len(chara_list)  # 上へ移動
                if masic_select and masic_phase <= 1:
                    if event.key == K_DOWN:
                        masic_index = (masic_index + 1) % len(masic_list)  # 下へ移動
                    if event.key == K_UP:
                        masic_index = (masic_index - 1) % len(masic_list)  # 上へ移動
                                       

ここにコードの概要があります

コードの概要

1.インポート:star:

 import pygame
 from pygame import *
 import sys
 import time
 import random
 

2.関数:hammer_pick:

 部分一致で値を取得する関数 改行してテキストを描画する関数
 2列×3行のテキストを描画する関数
 BGMの関数

3.セットアップ:gear:

 パス 各種変数(まほう) レクト コマンドテキスト 勇者のステータス
 ステータステキスト モンスター関連

4.描画:art:

 ステータスウィンドウ モンスター画像 コマンドウィンドゥ
 魔物選択ウィンドゥ キャラの選択ウィンドゥ まほうの選択ウィンドゥ 
 バトルメッセージウィンドゥ

 プレイヤーのダメージエフェクト + 敗北判定
 モンスターのダメージエフェクト + 倒したかどうかの判定

 まほう(色付き半透明レクト)

5.キーハンドラー:keyboard:

 Zキー:
(あらわれた! たたかうコマンド まほうコマンド こうげきメッセージ
まほうメッセージ ターン終了  MP判定
モンスターへ与えるこうげきダメージ計算 モンスターへ与えるまほうダメージ計算 まほう回復 倒した時の処理 プレイヤーに与えるダメージ計算
ワンテンポ置く 画面を閉じる) 
 方向キー:
(コマンドの方向キー、魔物選択の方向キー 
 キャラ選択の方向キー まほう選択の方向キー)


ここに変数の説明があります

変数の説明


🔢 インデックス

masic_index = 0
chara_index = 0

🧙‍♂️ 説明: まほう(魔法)とキャラの選択に使用するインデックス変数。カーソルの位置にも利用している。
🎯 データ取得:

  • 🌀 まほうmasic_list から値を取得
  • 🧑‍🎤 キャラchara_list から要素を取得

🔄 まほう選択の段階

masic_phase = 0

説明: まほうの選択を 2段階 に分ける。

  • 🔥 攻撃まほうmasic_phase = 1まほう選択masic_phase = 2モンスター選択
  • ❤️ 回復まほうmasic_phase = 1まほう選択masic_phase = 2キャラ選択

💥 まほうエフェクト

masic_effect = 0

🌟 説明: まほうの効果を管理するフラグ。

  • 🔥 攻撃まほう1
  • ❤️ 回復まほう2

⏳ まほうフレーム

masic_frame = 0

説明: まほうのエフェクトの持続時間を管理する変数。
🕰️ まほうメッセージの表示時に設定され、10 から 1 ずつ減少。(正確な秒数は不明)


🎨 まほうサーフェイス(半透明)

damera_surface = pygame.Surface((width, height), SRCALPHA)
damera_surface.fill((255, 201, 14, 128))

hoimun_surface = pygame.Surface((width, height), SRCALPHA)
hoimun_surface.fill((255, 255, 255, 128))

🖌️ 説明: まほうの視覚的なエフェクトを表す半透明のサーフェイス。

  • 🔥 攻撃まほうオレンジ (damera_surface)
  • ❤️ 回復まほう (hoimun_surface)

📖 まほう辞書

damera = {
    "masic_name": "ダメラ",
    "MP": 2,
    "数値": 10,
    "masic_effect": 1,
    "masic_type": "攻撃まほう",
    "surface": damera_surface
}

hoimun = {
    "masic_name": "ホイムン",
    "MP": 3,
    "数値": 30,
    "masic_effect": 2,
    "masic_type": "補助まほう",
    "surface": hoimun_surface
}

📜 説明: まほうのデータを辞書として管理。
📌 各まほうの特性:

  • 🌀 MP → 消費MP
  • 🔥 masic_effect1(攻撃まほう) / 2(回復まほう)
  • 📊 数値 → 攻撃まほうは ダメージ、回復まほうは 回復量
  • 🎭 masic_type:
    • "攻撃まほう"魔物選択ウィンドウ を開く
    • "補助まほう"キャラ選択ウィンドウ を開く

📋 まほうのリスト

masic_list = [damera, hoimun]

🗂️ 説明: まほうのデータをまとめたリスト。


🖱️ コマンドカーソル

cmd_cursor = False

👀 説明: コマンド選択中にコマンドカーソルを 表示 するフラグ。


👥 キャラリスト

chara_list = ["ゆうしゃ", "せんし"]

🧑‍🎤 説明: 回復まほう使用時に選択する キャラリスト
⚠️ "せんし" はカーソルのテスト用。(実際には使用しない


ここにコードの説明があります
# まほう(回復)
if masic_effect == 2:
    if player_MP >= masic_list[masic_index]["MP"]:
        recovery  = random.randint(masic_list[masic_index]["数値"],int(masic_list[masic_index]["数値"] * 1.5))
        player_HP = min(player_Max_HP,player_HP + recovery)
        message = f'{player_name}は {masic_list[masic_index]["masic_name"]}を となえた!\n{chara_list[chara_index]}の きずが かいふくした!' 

min(player_Max_HP,player_HP + recovery)
player_Max_HPを超えないようにする。

例:
player_Max_HPを超える場合
player_Max_HP 53
player_HP 50
recovery 30
min(53,80)
最小値が選ばれ、53

player_Max_HPを超えない場合
player_HP 13
recovery 30
min(53,43)
最小値が選ばれ、43

まほうフローチャート:point_down:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?