Python3でRPGを作る時に使えそうな技術の断片 -世界の中心はプレイヤー-

f:id:sakage24:20170714192724j:plain

RPGの魅力といえば、広大なワールドマップですよね。色々な村があって、ダンジョンがあってこそです。これらをバランス良く実装するには広大なマップが必要です。

しかし、従来のマップ表示の仕方には根本的に問題があります。10×10のマップならPythonは瞬時に表示出来ます。しかし100×100のマップならどうでしょうか?その内に開発が進み、1000×1000のマップが必要になるかもしれません。

その時、マップの描画に何秒かかるのでしょうか?サクサク進みたいのにマップを移動する度に描画処理で2秒も3秒も待たされては、興ざめですよね。私ならそんなクソゲーはすぐにゴミ箱にポイですw

何も、移動の度に全てのマップを描画する必要はないのです。本当に描画するべきなのはプレイヤーの座標とその周辺です。

今までのやり方

今まではマップを全て描画していました。手っ取り早くていいのですが、これだとマップの規模に比例して描画時間は伸びてしまいます。


width = 10
height = 10
maps = [[0 for x in range(width)] for y in range(height)]
for i in range(height):
for j in range(width):
print(maps[i][j], end='')
print()
>>> 結果
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

世界の中心はプレイヤー

これからはプレイヤーを中心に、世界が動くのです。この方式の良いところは

  • 軽い
  • 描画する場所はプレイヤーの周りだけ
  • 見やすい

いい事ずくめな描画方法ですね。それでは、実践してみましょう。

条件

  • 視界はプレイヤーの周囲5マス(player_pos[0] - 5 ... player_pos[0] + 5), (player_pos[1] - 5 ... player_pos[1] + 5)とします
  • playerの座標は(2, 2)とします
  • x(y)が負数を示していた場合、その座標は進入不可のとして扱います

ソースコード


ratio = 5
width = 10
height = 10
player_pos = (2, 2)
maps = [[0 for x in range(width)] for y in range(height)]
for i in range(player_pos[0] - ratio, player_pos[0] + ratio):
for j in range(player_pos[1] - ratio, player_pos[1] + ratio):
strings = ""
grid = (i, j)
try:
if grid == player_pos:
strings = "@"
elif grid[0] < 0 or grid[1] < 0:
strings = "壁"
elif maps[grid[0]][grid[1]] == 0:
strings = "ー"
elif maps[grid[0]][grid[1]] == 1:
strings = "村"
else:
strings = "壁"
except IndexError:
strings = "壁"
finally:
print(strings, end='')
print()
>>> 実行結果
壁壁壁壁壁壁壁壁壁壁
壁壁壁壁壁壁壁壁壁壁
壁壁壁壁壁壁壁壁壁壁
壁壁壁ーーーーーーー
壁壁壁ーーーーーーー
壁壁壁ーー@ーーーー
壁壁壁ーーーーーーー
壁壁壁ーーーーーーー
壁壁壁ーーーーーーー
壁壁壁ーーーーーーー

出来ました。プレイヤーの座標(2, 2)の左右上下 + 斜め5マスのみが出力されています。
今後、マップのサイズを変更することがあっても描画処理は重くなりません。Yatta!!

解説


for i in range(player_pos[0] - ratio, player_pos[0] + ratio):
for j in range(player_pos[1] - ratio, player_pos[1] + ratio):
....

range()が何やら複雑でかなりうるさくなっていますが、要するにplayerの座標から-5 ~ +5の範囲を切り取っているだけです。


player_pos = (2, 2)
ratio = 5
for i in range(player_pos[0] - ratio, player_pos[0] + ratio):
for j in range(player_pos[1] - ratio, player_pos[1] + ratio):
...         print((i, j), end='')
...     print()
...
(-3, -3)(-3, -2)(-3, -1)(-3, 0)(-3, 1)(-3, 2)(-3, 3)(-3, 4)(-3, 5)(-3, 6)
(-2, -3)(-2, -2)(-2, -1)(-2, 0)(-2, 1)(-2, 2)(-2, 3)(-2, 4)(-2, 5)(-2, 6)
(-1, -3)(-1, -2)(-1, -1)(-1, 0)(-1, 1)(-1, 2)(-1, 3)(-1, 4)(-1, 5)(-1, 6)
(0, -3)(0, -2)(0, -1)(0, 0)(0, 1)(0, 2)(0, 3)(0, 4)(0, 5)(0, 6)
(1, -3)(1, -2)(1, -1)(1, 0)(1, 1)(1, 2)(1, 3)(1, 4)(1, 5)(1, 6)
(2, -3)(2, -2)(2, -1)(2, 0)(2, 1)(2, 2)(2, 3)(2, 4)(2, 5)(2, 6)
(3, -3)(3, -2)(3, -1)(3, 0)(3, 1)(3, 2)(3, 3)(3, 4)(3, 5)(3, 6)
(4, -3)(4, -2)(4, -1)(4, 0)(4, 1)(4, 2)(4, 3)(4, 4)(4, 5)(4, 6)
(5, -3)(5, -2)(5, -1)(5, 0)(5, 1)(5, 2)(5, 3)(5, 4)(5, 5)(5, 6)
(6, -3)(6, -2)(6, -1)(6, 0)(6, 1)(6, 2)(6, 3)(6, 4)(6, 5)(6, 6)

分かりやすくprint()すると、上記の範囲を表示していますね。

終わり

次は何やろうか…考え中です。あ、正直これ組むのにめちゃ時間かかったけど、出来たから良かったですw

オススメの教科書類

指定教科書
入門 Python 3

入門 Python 3

これ無しでPython開発は無理です。私的にはあまり演習問題の類は説かずに知りたいことがあったら読む、辞書的な感じで使っています。

  • スライスって何?
  • リスト内包表記って何なんだよあれ?
  • リストとタプルはどう違うの?
  • そもそも集合って何に使うの?

少しでも上記に当てはまるなら購入しましょう。せっかくPythonを使っているんですから、有効に使えるようにしてみませんか?

副読本
Effective Python ―Pythonプログラムを改良する59項目

Effective Python ―Pythonプログラムを改良する59項目

  • 他言語を得意としているプログラマがPythonを書いた時にやりがちなこと…
  • ゲームの保存に使えるpickle
  • この機能はこう使うべきである
  • while, for文のelseを使うべきではない理由
  • Pythonでセッター, ゲッターを使うべきではない理由

みたいに、様々な事例とともにPythonのベストノウハウ、やってはいけないアンチパターンが紹介されています。pycon2016でも確か推されてましたw

初心者から上級者まで、手元に置いておくべき本です。

副読本2
退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング

退屈なことはPythonにやらせよう ―ノンプログラマーにもできる自動化処理プログラミング

ノンプログラマー向けとありますが、経験者の方も結構アイディアを貰える本でした。
序盤は文法の解説ですので、読み飛ばせます。後半は様々な局面で使えそうな自動化処理の書き方が載っていました。

ゲームの所持アイテムを辞書で表現しよう…みたいにゲームプログラマーに役立つ演習もありましたw

副読本3
ゲーム開発者のためのAI入門

ゲーム開発者のためのAI入門

  • 作者: David M. Bourg,Glenn Seemann,株式会社クイープ
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2005/01/12
  • メディア: 大型本
  • 購入: 24人 クリック: 395回
  • この商品を含むブログ (77件) を見る

C言語での解説が主ですが、しっかりとした説明があるので、だいたい分かりました。Pythonでも使える知識がほとんどです。ただ、ファジー理論など、数学的な要素は私にはどうともしがたい躓きポイントでしたw

ローグライクゲームに使える最短経路探索法やAIの作成法、確率の基本まで教えてもらえる良本でした!!

コメントを残す

メールアドレスが公開されることはありません。