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-28

新RPGの目次 

モンスターの描画

ここにコードがあります

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

pygame.init()
width, height = 640, 480
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("モンスター描画")

# ロード
# ここにモンスター画像のパスを貼り付ける
monsterA_image = pygame.image.load()
# ここにモンスター画像のパスを貼り付ける
monsterB_image = pygame.image.load()
# ここにモンスター画像のパスを貼り付ける
monsterC_image = pygame.image.load()


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

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

# モンスターの位置を定義
monster_positions = {
    1: [0.5],  # 1体
    2: [0.4, 0.6],  # 2体
    3: [0.3, 0.5, 0.7],  # 3体
}

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

# 色
black = (0, 0, 0)

clock = pygame.time.Clock()
while True:
    clock.tick(60)
    screen.fill(black)
    for i in range(len(mon_group_list)):
        screen.blit(monster_images_dict[mon_group_list[i]], (monster_rects[i].topleft))

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

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

コードの説明です。

🎮 Pythonでモンスターを配置するコード! 🐺🦅

🦾 モンスターの位置を設定

monster_rects = [
    monster_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))
]

X座標を変更しつつ、モンスターの数だけレクトを作成する処理です! 🔥


📌 リスト内包表記とは?

リストを簡潔に作成できるPythonの便利な構文!
基本形はこちら👇

新しいリスト = [ for 要素 in イテラブル]

短い処理ならスッキリ記述可能
⚠️ 長くなりすぎる場合は for ループに切り替え


🛠 実際の処理

mon_group_list = ["ウルフ", "ウルフ", "バード"]
monster_positions = {
    1: [0.5],  
    2: [0.4, 0.6],  
    3: [0.3, 0.5, 0.7],  
}

monster_images_dict[mon_group_list[i]].get_rect(center=(width * monster_positions[len(mon_group_list)][i], height * 0.5))

💡 例:

  • mon_group_list[0]"ウルフ" → monster_images_dictから"ウルフ"をキーとして、ウルフの画像を取得

    • モンスター数が 3 なので、monster_positions[3] = [0.3, 0.5, 0.7]
  • 一回目の処理は、iが0なので、monster_positions[3][0] = 0.3

  • 結果: ウルフの画像を center=(width * 0.3, height * 0.5) に配置するレクトを取得!
    ウルフのレクト []

    for i in range(len(mon_group_list)):
    screen.blit(monster_images_dict[mon_group_list[i]], (monster_rects[i].topleft))

monster_images_dict {'スライム': , 'ウルフ': , 'バード': }

mon_group_list ['ウルフ', 'スライム', 'バード']

moster_rects [, , ]
monster_rects[0].topleft (142, 192)
monster_rects[1].topleft (273, 188)
monster_rects[2].topleft (395, 187)


モンスターを消す

上下キーで選択
Zキーで消す

ここにコードがあります

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

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

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

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

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

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

clock = pygame.time.Clock()
while True:
    clock.tick(60)
    screen.fill(black)
    pygame.draw.rect(screen,white,window_rect,3,5)
    # モンスター画像の描画
    for i in range(len(mon_group_list)):
        screen.blit(monster_images_dict[mon_group_list[i]], (monster_rects[i].topleft))
    # モンスター名の描画
    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:
                del mon_group_list[arrow_index]
                del monster_rects[arrow_index]
                if mon_group_list:
                    arrow_index = min(arrow_index, len(mon_group_list) - 1)  # 削除後のカーソル位置調整
                else:
                    arrow_index = 0  # リストが空ならカーソルをリセット


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

🎮 Pygameでモンスター選択ウィンドウを作成!

🛠 ウィンドウの座標と描画

window_rect = pygame.Rect(width * 0.4, height * 0.65, 220, 140)
rectx, recty = window_rect.topleft

width * 0.4, height * 0.65 の計算結果は int に変換
(Rect) を作成し、その座標 (topleft) を取得
枠内にモンスター名を描画するための基準座標


📌 モンスター名の描画処理

if mon_group_list:
    for i, mon in enumerate(mon_group_list):
        text = font.render(mon, True, (255, 255, 255))
        screen.blit(text, ((rectx + 14) + 30, (recty + 14) + 34 * i))
    screen.blit(cursor_img, ((rectx + 14), (recty + 14) + 34 * arrow_index))  # カーソル描画

💡 enumerate() を使うと…

  • iインデックス
  • monモンスター名

🔹 例:

インデックス: 0, モンスター名: ウルフ
インデックス: 1, モンスター名: ウルフ
インデックス: 2, モンスター名: バード

🔹 描画位置の計算

  • rectx, recty枠の描画座標
  • 14枠の端からの距離
  • 30カーソル分、横にずらす
  • 34フォントサイズ + 行間 (モンスター名が重ならないよう調整)
  • arrow_indexカーソルの縦位置を変更

🎯 カーソル移動処理 (↑↓キー)

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)  # 下へ移動

カーソルを上下に移動
リストをループさせる (% len(mon_group_list))

📌 負の数の % 計算例

方向キー 
割られる数 -3 -2 -1 0 1 2 3
割る数 3 3 3 3 3 3 3
余り 0 1 2 0 1 2 0

✨ まとめ

🐍 Python + Pygame でモンスター選択画面を作成!
ウィンドウを描画し、モンスター名を枠内に表示
カーソル移動機能 (↑↓キー) を実装
選択式 UI を簡潔なコードで実現!


elif event.key == K_z and mon_group_list:
    del mon_group_list[arrow_index]
    del monster_rects[arrow_index]

    for i in range(len(mon_group_list)):
        screen.blit(monster_images_dict[mon_group_list[i]], (monster_rects[i].topleft))

mon_group_list ['ウルフ', 'スライム', 'バード']
moster_rects [<rect(142, 192, 101, 97)>, <rect(273, 188, 95, 105)>, <rect(395, 187, 106, 107)>]
monster_rects[0].topleft (142, 192)
monster_rects[1].topleft (273, 188)
monster_rects[2].topleft (395, 187)
      ↓
arrow_index[1]でZキーを押すと
      ↓
mon_group_list ['ウルフ','バード']
moster_rects [<rect(142, 192, 101, 97)>, <rect(395, 187, 106, 107)>]
monster_rects[0].topleft (142, 192)
monster_rects[1].topleft (395, 187)

真ん中の画像が消えます。


min() 関数の活用例:カーソルの範囲調整

arrow_index = min(arrow_index, len(mon_group_list) - 1)

このコードは、リスト mon_group_list から要素が削除された際に、カーソル (arrow_index) がリストの範囲外に出ないように調整するためのものです。


min() 関数について

min() は Python の組み込み関数で、与えられた値の中から最小値を返します。

基本的な使い方:

x = min(5, 2, 8)
print(x)  # 出力: 2

この場合、min()5, 2, 8 の中から最も小さい 2 を返します。


カーソル位置の調整(例)

モンスターが 3 体いる場面

モンスターが 3 体いる状態で、1 体倒したときの arrow_index の変化を説明します。

  • 上から 2 番目のモンスターを選んでいた場合

    • arrow_index = 1
    • len(mon_group_list) は 3 体から 2 体になり、len(mon_group_list) - 1 = 1
    • min(1,1) = 1 となるので、カーソル位置の変化なし。
  • 上から 3 番目のモンスターを選んでいた場合

    • arrow_index = 2
    • len(mon_group_list) は 3 体から 2 体になり、len(mon_group_list) - 1 = 1
    • min(2,1) = 1 となるので、arrow_index2 から 1 に変化あり。

この処理により、カーソルのタテ座標が 2 から 1 に減り、描画位置が上に移動します。
このコードを使うことで、カーソルがリストの範囲外に飛び出すのを防げます。

変化なし
スクリーンショット (1412) - コピー.png

変化あり
スクリーンショット (1414) - コピー.png


ダメージエフェクト

上下キーで選択
Zキーでダメージエフェクト

ここにコードがあります

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


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()
# ここにダメージ音のパスを貼り付ける
sound2 = pygame.mixer.Sound()
# ここにカーソル画像のパスを貼り付ける
cursor_img = pygame.image.load()
# ここに背景のパスを貼り付ける
bg = pygame.image.load()


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

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

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

# モンスターの位置を設定
monster_rects = [
    monster_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.66,220,140)
rectx,recty,_,_ = window_rect

# 黒い画像(ダメージエフェクトのため)
m_width, m_height = 110,110
black_image = pygame.Surface((m_width, m_height))

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

effect = 0
flash = 0
visible = 0

clock = pygame.time.Clock()
while True:
    clock.tick(60)
    screen.fill(black)
    screen.blit(bg,(0,0))
    pygame.draw.rect(screen,white,window_rect,3,5)
    for i in range(len(mon_group_list)):
        if arrow_index == i and visible == 0:
            screen.blit(monster_images_dict[mon_group_list[i]], (monster_rects[i].topleft))
        if arrow_index != i:
            screen.blit(monster_images_dict[mon_group_list[i]], (monster_rects[i].topleft))
    # モンスターがいる場合のみ描画
    if mon_group_list:
        for i, mon in enumerate(mon_group_list):
            text = font.render(mon, True, (255, 255, 255))
            screen.blit(text, ((rectx + 14) + 30, (recty + 14) + 34 * i))
        screen.blit(cursor_img, ((rectx + 14), (recty + 14) + 34 * arrow_index))  # カーソル描画

    pygame.display.update()
    if effect == 1:
        if flash > 0:
            visible = pygame.time.get_ticks() // 90 % 2
            flash -= 1
            if flash == 19:
                sound2.play()
            if flash == 1:
                if mon_group_list:
                    del mon_group_list[arrow_index]
                    del monster_rects[arrow_index]
                    arrow_index = min(arrow_index, len(mon_group_list) - 1)  # 削除後のカーソル位置調整
                else:
                    arrow_index = 0  # リストが空ならカーソルをリセット
                effect = 0
                visible = 0
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        elif effect != 1:
            if 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:  # 決定
                    effect = 1
                    flash = 20
                elif event.key == K_x:
                    print(monster_rects,monster_images_dict,mon_group_list)



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

モンスター画像の点滅処理

モンスターの画像を 90ミリ秒ごと に点滅させる処理を pygame.time.get_ticks() を使って実装。

処理の概要

  • pygame.time.get_ticks() は、プログラム開始からの経過時間をミリ秒単位で取得
  • pygame.time.get_ticks() // 90 % 2 を使い、偶数のときは表示(visible = 0)、奇数のときは非表示(visible = 1
  • 90 の数値を大きくすると点滅速度がゆっくりになるが、flash = 20 に対して大きすぎるとあまり変化がない

コードの動作

for i in range(len(mon_group_list)):
    if arrow_index == i and visible == 0:
        screen.blit(monster_images_dict[mon_group_list[i]], (monster_rects[i].topleft))
    if arrow_index != i:
        screen.blit(monster_images_dict[mon_group_list[i]], (monster_rects[i].topleft))

if effect == 1:
    if flash > 0:
        visible = pygame.time.get_ticks() // 90 % 2
  • flash を減少させながら、点滅を制御
  • flash == 19 のタイミングで sound2.play() を再生
  • flash == 20 だと音が再生されないので注意

キー操作制限

elif effect != 1:
    if event.type == KEYDOWN:
  • 点滅中にキー操作ができないよう制限

モンスター選択時の処理

elif event.key == K_z and mon_group_list:
    effect = 1
    flash = 20  # 点滅時間を設定
  • flash の値が大きいほど点滅時間が長くなる

あまり正確ではない数値ですが、参考までに…

flashが1回につき0.015秒
20回だと0.3秒
// 90だと0.06秒間隔


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?