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(ダメージ計算)

Last updated at Posted at 2025-05-30

新RPGの目次

参考にしたサイト
頭が痛くならない「ダメージ計算式」の基本の話

ダメージ計算

ここにコードがあります

import pygame
import sys
from pygame.locals import *
import random

# テキストを改行して描画する関数
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

pygame.init()
width, height = 640, 480
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("ダメージ計算")

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


# 勇者の初期ステータス
player_name = "ゆうしゃ"
player_power = 13

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

mon_images_dict = {nameA:monsterA_image,
                   nameB:monsterB_image,
                   nameC:monsterC_image}

mon_HP_dict = {nameA: 4,nameB: 6,nameC: 8}
mon_deffence_dict = {nameA: 4,nameB: 4,nameC: 8}

status_data = []

for i in range(len(mon_group_list)):  
    status_data.append({
        "name": f"{mon_group_list[i]}",
        "HP": mon_HP_dict[mon_group_list[i]],
        "deffence": mon_deffence_dict[mon_group_list[i]],
        "image": mon_images_dict[mon_group_list[i]],
    })

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

# モンスターの位置を設定
monster_rects = [
    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))
]

arrow_index = 0  # 選択カーソルの位置
window_rect = pygame.Rect(width * 0.4,height * 0.65,220,140)
rectx,recty = window_rect.topleft


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

battle_message = False
select = True
message = ""
phase = 0
damage = 0

clock = pygame.time.Clock()
running = True
while running:
    clock.tick(60)
    screen.fill(black)
    # メッセージウィンドゥ
    if battle_message:
        pygame.draw.rect(screen, white, Rect(20, 320, 600, 140), 3)
        # バトルメッセージ
        draw_text(screen,message,(40,350),font)
    # モンスター画像の描画
    for i in range(len(mon_group_list)):
        screen.blit(mon_images_dict[mon_group_list[i]], (monster_rects[i].topleft))

    # 魔物選択ウィンドゥ
    if select:
        pygame.draw.rect(screen,white,window_rect,3,5)
        # モンスター名の描画
        if mon_group_list:
            for i, mon in enumerate(mon_group_list):
                text = font.render(mon, True, white)
                screen.blit(text, ((rectx + 14) + 30, (recty + 14) + 34 * i))
            screen.blit(cursor_img, ((rectx + 14), (recty + 14) + 34 * arrow_index))  # カーソル描画

    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        elif event.type == KEYDOWN:
            if event.key == K_UP and mon_group_list:
                arrow_index = (arrow_index - 1) % len(mon_group_list)  # 上へ移動

            elif event.key == K_DOWN and mon_group_list:
                arrow_index = (arrow_index + 1) % len(mon_group_list)  # 下へ移動

            elif event.key == K_z and mon_group_list:
                if phase == 0:  
                    select = False
                    battle_message = True
                    message = f"{player_name}のこうげき!"
                    phase = 1
                elif phase == 1:  
                    damage = player_power // 2 - status_data[arrow_index]["deffence"] // 4
                    damage = random.randint(damage,int(damage * 1.5))
                    if damage <= 0:
                        damage = 1
                    status_data[arrow_index]["HP"] -= damage
                    message = f'{player_name}のこうげき!\n{status_data[arrow_index]["name"]}に {damage}の ダメージ!'
                    if status_data[arrow_index]["HP"] <= 0: 
                        phase = 2
                    else:
                        phase = 3
                elif phase == 2:
                    message = f'{player_name}のこうげき!\n{status_data[arrow_index]["name"]}に {damage}の ダメージ!\n{status_data[arrow_index]["name"]}をたおした!'
                    del mon_group_list[arrow_index]
                    del monster_rects[arrow_index]
                    del status_data[arrow_index]
                    if mon_group_list:
                        arrow_index = min(arrow_index, len(mon_group_list) - 1)  # 削除後のカーソル位置調整
                    else:
                        arrow_index = 0  # リストが空ならカーソルをリセット
                    phase = 3
                elif phase == 3:
                    select = True
                    battle_message = False
                    phase = 0
                    
            elif event.key == K_x:
                print(arrow_index,mon_group_list,monster_rects,status_data)

                    
ここにコードの説明があります

damage = player_power // 2 - mon_deffence // 4

ダメージ計算です。


damage = random.randint(damage,int(damage * 1.5))

ダメージに幅を持たせています。同じ数値だと、飽きてしまうからです。


    if damage <= 0:
        damage = 1

ダメージが 0 以下にならないように調整
ダメージが0やマイナスだと違和感があるので最低値を1に設定


    mon_HP -= damage

モンスターのHPを減少


    message = f"{player_name}のこうげき!\n{mon_name}に {damage}の ダメージ!"

    return mon_HP,message,damage

メッセージの更新


elif phase == 1:  
    status_data[arrow_index]["HP"],message,damage = mon_damage(player_name,player_power,status_data[arrow_index]["name"],status_data[arrow_index]["HP"],status_data[arrow_index]["deffence"],damage,message)

mon_damage関数を実行し、値を更新


    if status_data[arrow_index]["HP"] <= 0: 
        phase = 2
    else:
        phase = 3

モンスターを倒したかどうかでフェーズを分岐。
(単純にphase = 2 にすると、倒せなかった場合、
無駄に1回キー操作が増えるので、分岐させてます)


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?