こんにちは。
「Pythonでつくる ゲーム開発 入門講座」の
Chapter11,12(本格RPGを作ろう!全編・後編)を基にRPGを作っていきます。
前回はマップ(エリア)ごとに出現するモンスターを変えました。
今回はマップの場所によって移動できない制限をつけます。
あと、その他にもモンスターエリアを複数追加したり、
先制攻撃の時は逃げられるように変更します。
目次
移動の制限
マップによって移動できたり、できなかったりと
制限をつけます。
例えば、今までは海を歩けたりしましたが
歩けないようにします。
今は以下のようなマップチップを
利用させて頂いています。
※緑\('ω')/箱さんの画像です。
※当ブログ(第29回)

このマップチップをリストimgmapに格納しています。
imgmap = []
for i in range(31):
imgmap.append(pygame.image.load("map/" + str(i) + ".png"))
なので、
imgmap[0]は「0.png」
imgmap[1]は「1.png」
になります。
そして、移動できないようにするのは
16.png〜30.png
にしますので、
imgmapのインデックスが16以上の時は
移動できないようにします。
imgmapは以下のようにして使っていますので
インデックスはリストn_mapの値のうち
後ろの2文字([2:]です。
※詳細は前回
bg.blit(imgmap[int(n_map[dy+y_range][dx+x_range][2:])], [X, Y])
リストn_mapはmaps.pyの
リストmapsです。
maps = [["0000", "0101",......]]
ということで、n_mapの後ろ2文字が
16以上の場合は移動できないようにします。
move.py
変更前
(省略)
def move_player(key, player): # 主人公の移動
(省略)
if key[K_UP] == 1:
player.d = 0
if n_map[player.y-1][player.x] != 9:
player.y = player.y - 1
if key[K_DOWN] == 1:
player.d = 1
if n_map[player.y+1][player.x] != 9:
player.y = player.y + 1
if key[K_LEFT] == 1:
player.d = 2
if n_map[player.y][player.x-1] != 9:
player.x = player.x - 1
if key[K_RIGHT] == 1:
player.d = 3
if n_map[player.y][player.x+1] != 9:
player.x = player.x + 1
変更後
(省略)
def move_player(key, player): # 主人公の移動
(省略)
if key[K_UP] == 1:
player.d = 0
if player.y > 0:
if int(n_map[player.y-1][player.x][2:]) < 16:
player.y = player.y - 1
if key[K_DOWN] == 1:
player.d = 1
if player.y < map_h-1: # map_hになるとout of rangeになる
if int(n_map[player.y+1][player.x][2:]) < 16: # player.y+1なので、player.y=map_h-1の時out of rangeになる
player.y = player.y + 1
if key[K_LEFT] == 1:
player.d = 2
if player.x > 0:
if int(n_map[player.y][player.x-1][2:]) < 16:
player.x = player.x - 1
if key[K_RIGHT] == 1:
player.d = 3
if player.x < map_w-1:
if int(n_map[player.y][player.x+1][2:]) < 16:
player.x = player.x + 1
n_mapの後ろ2文字が16以上は移動できないので
16未満(<16)で移動できるようにしています。
また、今回のマップは海で囲まれるので、
端には移動できないですが、
マップから出ないように制限を追加しました。
※端に行ったら逆の端から出るようにしたいですが
なんかおかしくなったので、制限つけます(^_^;)
いずれ、修正したいと思います。
if player.y > 0:
if player.x > 0:
などのことです。
これで海には移動不可にできました。

モンスターエリアを複数に
前回、モンスターエリアを追加しましたが
1モンスターに付与できるのは1つのエリアのみでした。

出現するマップは1つに限らせたくないので
1モンスターにいくつもエリアを追加できるようにします。
エリアを複数にする場合は以下のように
「,」で区切ります。
※「0,2,3」はエリアが0か2か3のいずれかの場合に
出現する可能性がある。

そしてbattle.pyでfindを使います。
※前回、変更した箇所です。
変更前
list_land = [i for i, tmp in enumerate(list_mon_area) if tmp == str(mon_area)]
変更後
list_land = [i for i, tmp in enumerate(list_mon_area) if tmp.find(str(mon_area)) != -1]
findは指定した引数の文字列(mon_area)が
元の文字列(tmp)に含まれているかを
検索してくれます。
※詳細はこちら。
あれば最初の位置、無ければ-1を返しますので
-1でなければ(!=-1)、
そのモンスターの出現エリアとなります。
これで、1モンスターが複数のエリアに
出現できるようになりました。
尚、findは該当の文字列が含まれているか確認するので
エリアで区切るのは「,」である必要はなく、
「/」でも「-」でも何でも同じ結果となります。
先制攻撃
戦闘についてです。
先制攻撃では100%逃げられるように
変更します。
※テストしていて気が付いたのですが、
先制攻撃なのに逃げられないのは
何となく違和感があり。。
battle.py
(省略)
ESCAPE_RATE = 60 # 逃げられる確率(100は100%逃げる)
(省略)
def main(screen, clock, font, fontS, player, area):
(省略)
btl_start = 0 # 0:通常、1:先制攻撃、2:不意打ち
(省略)
elif idx == 14: # 逃げられる?
draw_battle(screen, fontS, turn_obj, player)
if tmr == 1:
set_message(player.name + " は逃げ出した!")
if tmr == 5:
if btl_start == 1 or random.randint(0, 99) < ESCAPE_RATE: # 変更
btl_exp = 0 # 逃げたら0
idx = 22 # 戦闘終了
else:
set_message("しかし、まわりこまれてしまった!")
先制攻撃はbtl_startが1の時なので
逃げられる条件を以下に変更しました。
※btl_start == 1を追加
if btl_start == 1 or random.randint(0, 99) < ESCAPE_RATE:
これで先制攻撃の時は逃げられるようになりました(^_^)
あと、逃げられる確率を定数にしました。
ESCAPE_RATE = 60
プレイヤーのレベルやモンスター側の条件によって
逃げられる確率を変更できたらな、と思っています。
いずれ・・
ついでに、モンスターの出現確率も定数にしました。
APPEAR_RATE = 20
こちらもエリアによって、出現確率を変更できたらな、
と思っています。
いずれ・・
(省略)
APPEAR_RATE = 20 # モンスターの出現確率(0は0%)
(省略)
def move_player(key, player): # 主人公の移動
global tmr, food, potion, blazegem, treasure
if random.randint(0, 99) < APPEAR_RATE: # 敵出現
という感じで、今回は以上です!(`・ω・´)
最後に
今回はマップの場所によって
移動できない制限をつけました。
ただ、変えた後に気が付いたのですが、
5.pngの山も歩けなくするつもりでした。
※赤枠
プレイヤーがいる場所も5.pngの山

が、今回はこのままにしました(^_^;)
そのうち、また町のマップとかも作りますが、
その時に移動の制限とかも
まとめて変えようかと思っています(^_^)
次回はまた戦闘に戻って呪文を変更しようと思います。
今は攻撃呪文の対象がモンスター1匹のみですが
グループもしくは全体に攻撃できるようにしたいと思います。
【ご注意】
プログラムやデータなどは著作権法により保護されています。
著作者の許諾を得ずに、プログラムおよびデータそのものまたは改変したものを
配布したり販売したりすることはできません。
また、これらを利用して発生した損害などに関して、著作者は一切責任を負いません。