CODE Python RPG

独学でPythonでRPGを作成する(第42回)フィールドマップ

更新日:

こんにちは。
「Pythonでつくる ゲーム開発 入門講座」の
Chapter11,12(本格RPGを作ろう!全編・後編)を基にRPGを作っていきます。

前回は補助呪文の修正や戦闘時にモンスターが攻撃以外の行動を取れるようにしました。

今回はモンスターの特技をもう少し修正します。
他に、久しぶりにマップに手を加えました。

目次

  1. モンスターシート
  2. フィールドマップ
  3. 最後に

モンスターシート

前回、戦闘時にモンスターが攻撃以外の
行動を取れるようにしました。

ただ、前回追加した攻撃以外の行動は
「その他」でそれは何もしないでした。
※「どうしていいのか わからない!」

なので今回はもう一つ特技として
「痛恨の一撃」を追加します。

 

今までも「痛恨の一撃」はありましたが
プレイヤーの「会心の一撃」と
同様に一定の確率で発生するように
していました。

chara.py

class Monster(Chara):
(省略)

    def attack(self, obj):
        message = []
        # 痛恨の一撃、通常攻撃の会心では、敵の守備力に関わらず、攻撃力と同程度のダメージを与える(ダメージ幅は±5%)。
        if random.random() < 1/32:
            base_dmg = self.atk
            min_dmg = int(self.atk - 0.05*self.atk)
            max_dmg = int(self.atk + 0.05*self.atk)
            dmg = random.randint(min_dmg, max_dmg)
            message.append("つうこんの いちげき!")
            message.append(obj.name + "は " + str(dmg) + "ポイントの ダメージを うけた!")
            return dmg, message
if random.random() < 1/32:

1/32の確率で「痛恨の一撃」です。

でもこれですと、
どんなに弱いモンスターでも発生するので
「痛恨の一撃」は特技にして、
特定のモンスターのみに発生するようにします。

 

モンスターシートのM列に
痛恨の一撃を追加します。
※特技=戦闘中の行動の為、
 攻撃も記載します。

 

もう一つ、呪文シートにも追加します。

ここに追加した目的は
ターゲットを使う為です。
(今のところ)

 

 

charaの変更

chara.pyを変更します。

痛恨の一撃はモンスタークラスの
attackメソッドから外して、
別のメソッドにします。

class Monster(Chara):
(省略)

    def attack(self, obj):
        message = []
        message.append(self.name + " のこうげき!")

        # 痛恨の一撃、通常攻撃の会心では、敵の守備力に関わらず、攻撃力と同程度のダメージを与える(ダメージ幅は±5%)。
        # if random.random() < 1/32:
        #     base_dmg = self.atk
        #     min_dmg = int(self.atk - 0.05*self.atk)
        #     max_dmg = int(self.atk + 0.05*self.atk)
        #     dmg = random.randint(min_dmg, max_dmg)
        #     message.append("つうこんの いちげき!")
        #     message.append(obj.name + "は " + str(dmg) + "ポイントの ダメージを うけた!")
        #     return dmg, message

        if self.flag_manusa: # 攻撃者がマヌーサにかかっている
            if random.random() > 3/8: # 命中率が37.5%
                message.append("ミス!" + obj.name + " は ダメージを うけない!")
                return 0, message
(省略)

    def grief(self, obj):
        message = []
        message.append(self.name + " のこうげき!")
        min_dmg = int(self.atk - 0.05*self.atk)
        max_dmg = int(self.atk + 0.05*self.atk)
        dmg = random.randint(min_dmg, max_dmg)
        message.append("つうこんの いちげき!")
        message.append(obj.name + "は " + str(dmg) + "ポイントの ダメージを うけた!")
        return dmg, message

「○○のこうげき!」はbattle.pyから
こちらに持ってきました。
何となくです。

痛恨の一撃はgriefメソッドにしました。

 

あとモンスターの行動を決める
set_monster_comを変えます。
※前回追加したメソッドです。

変更前

class Monster(Chara):
(省略)

    def set_monster_com(self): # モンスターの戦闘コマンド
        if self.flag_sleep:
            self.act = 28 # 眠っている
        else:
            skill_no = random.randint(0, len(self.skill)-1) 
            if self.skill[skill_no] == "攻撃":
                self.act = 13 # 攻撃
            else:
                self.act = 29 # 特技

変更後

class Monster(Chara):
    def __init__(self, num):
(省略)

        self.skill = mon_skill[num].split(",")
        self.skill_no = 0 # skillの添字
(省略)

    def set_monster_com(self): # モンスターの戦闘コマンド
        if self.flag_sleep:
            self.act = 28 # 眠っている
        else:
            self.skill_no = random.randint(0, len(self.skill)-1) 
            if get_spell_target(self.skill[self.skill_no]) == 1: # 単体攻撃
                self.act = 13 # 攻撃
            else:
                self.act = 29 # 特技

まず、変数skill_noを
インスタンス変数にしています。

後述しますが、battle.pyでも
使う為です。

そして、特技のターゲットが
単体攻撃の場合は
行動を13(モンスターの攻撃)に
しました。

if get_spell_target(self.skill[self.skill_no]) == 1: # 単体攻撃
    self.act = 13 # 攻撃

 

charaの変更は以上です。

 

 

battleの変更

モンスターの攻撃であるidx13を変更します。

 

変更前

def main(screen, clock, font, fontS, player, area):
(省略)

        elif idx == 13: # 敵のターン、敵の攻撃
            draw_battle(screen, fontS, turn_obj, player)
            if tmr == 5:
                set_message(turn_obj.name + " のこうげき!")
                emy_step = 30
            if tmr == 9:
                dmg, get_message = turn_obj.attack(player)
                for mes in get_message:
                    set_message(mes)
                if dmg > 0:
                    dmg_eff = 5
                else:
                    dmg_eff = 0
                emy_step = 0
(省略)

変更後

def main(screen, clock, font, fontS, player, area):
(省略)

        elif idx == 13: # 敵のターン、敵の攻撃
            draw_battle(screen, fontS, turn_obj, player)
            if tmr == 1:
                if turn_obj.skill[turn_obj.skill_no] == "攻撃":
                    dmg, message = turn_obj.attack(player)
                elif turn_obj.skill[turn_obj.skill_no] == "痛恨の一撃":
                    dmg, message = turn_obj.grief(player)
                set_message(message[0]) # 〜のこうげき!
                emy_step = 30
            if tmr == 9:
                for i, mes in enumerate(message):
                    if i == 0:
                        continue
                    set_message(mes)
                if dmg > 0:
                    dmg_eff = 5
                else:
                    dmg_eff = 0
                emy_step = 0
(省略)

 

if turn_obj.skill[turn_obj.skill_no] == "攻撃":
    dmg, message = turn_obj.attack(player)
elif turn_obj.skill[turn_obj.skill_no] == "痛恨の一撃":
    dmg, message = turn_obj.grief(player)

特技が「攻撃」の場合はattack、
特技が「痛恨の一撃」の場合はgrief
を使います。
※ここでskill_noを使う為、
 先ほどchara.pyで
 インスタンス変数にしました。

 

今後、やり方を変えるかもしれませんが
ひとまず以上で「痛恨の一撃」を
特技として使えるようになりました。

 

 

フィールドマップ

久しぶりにマップを更新します。

少しずつ作っていましたが
どうにか1マップできました。

まず、こちらと同じ方法で
画像を作ります。

今回も緑\('ω')/箱さんのを
利用させて頂きます。

これを129個の画像にしました。
たくさんあるので以下です。

 

129あるので、マップ情報は3桁にします。
以前は2桁でした。

変更前(抜粋)

class Maps():
    def get_map(self, num, player):
        if num == 0:
            maps = [
                ["6116", "6116", "6116", "6116", "6116", "6116", "6116", "6116", "6116", 

変更後(抜粋)

class Maps():
    def get_map(self, num, player):
        if num == 0:
            maps = [
                ["61101", "61101", "61101", "61101", "61101", "61101", "61101", 

ちなみに「61101」の後半3桁が
マップの情報です。
前半の2桁はモンスターエリアです。

61:モンスターエリア
101:マップ情報(画像のファイル名)

それぞれの値は
以下のように取得しています。

ex_list = ["1234"]の場合、
ex_list[:2] = "12"
ex_list[2:] = "34"

ex_list = ["12345"]の場合、
ex_list[:2] = "12"
ex_list[2:] = "345"

list[start:end]
※start と end はインデックス。

startを省略すると最初から、
endを省略すると最後まで
スライスします。
※詳細はこちら

なので、後半が2桁でも3桁でも
プログラムは変わりません。
※前半の桁数が変わると
 手を加える必要がありますね。

 

なお、モンスターエリアは
出現するモンスターを決める為の値です。
※マップの場所によって
 出現するモンスターを変えます。
※詳しくはこちら

また、マップ情報は画像のファイル名と
一致させます。
※101は101.pngの画像を使います。

 

というわけで、129の画像を読み込みます。
move.pyです。

変更前

imgmap = [
    pygame.image.load("map/0.png"),
    pygame.image.load("map/1.png"),
    pygame.image.load("map/2.png"),
    pygame.image.load("map/3.png"),
    pygame.image.load("map/4.png"),
    pygame.image.load("map/5.png"),
...
    pygame.image.load("map/30.png")
]

変更後

imgmap = []
for i in range(129):
    imgmap.append(pygame.image.load("map/" + str(i) + ".png"))

129個あるのでfor文を使いました。
というか、31個の時から
使っておくべきでした(^_^;)

 

あとはmaps.pyです。

 

こんな感じです。

こちらは全体を歩く様子の動画です。

 

という感じで、今回は以上です!(`・ω・´)

 

 

最後に

今回は痛恨の一撃をモンスターの特技にしました。
また、フィールドマップを更新しました。

次回は違うマップ(町)へ移動できるようにしようと思います。

まとめサイトへ

 

 

【ご注意】
プログラムやデータなどは著作権法により保護されています。
著作者の許諾を得ずに、プログラムおよびデータそのものまたは改変したものを
配布したり販売したりすることはできません。
また、これらを利用して発生した損害などに関して、著作者は一切責任を負いません。

 

 

-CODE, Python, RPG
-, , , , , , , , ,

Copyright© kerublog , 2022 All Rights Reserved Powered by STINGER.