参考にしたサイト
頭が痛くならない「ダメージ計算式」の基本の話
ダメージ計算
ここにコードがあります
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回キー操作が増えるので、分岐させてます)