6-4 保存するデータ3 マップ
同人誌について
この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで288ページの本になります。ぜひ、こちらもご購入ください(2024-03-10:ver1.0.3 に更新)。
説明と全体コード
「src/mymod/data/map.py」の説明です。マップのデータ用のモジュールです。
from random import seed, randrange
from dataclasses import dataclass
SEED = None # ランダムのシード値(None or int)
PLAIN = 0
FOLEST = 1
MOUNTAIN = 2
WATER = 3
TOWN = 4
CASTLE = 5
COLS = [ # ミニ マップ用色配列
(152, 232, 0), # 平地
( 56, 104, 0), # 森
(192, 112, 0), # 山
( 80, 128, 255), # 水
(232, 208, 32), # 街
(144, 64, 240) # 魔王城
]
@dataclass
class Map:
w: int
h: int
map:list[int]
towns: list[list[int]]
# 初期化
@classmethod
def from_wh(cls, w: int, h: int) -> "Map":
res = Map(w, h, [], [])
res.map = [PLAIN] * h * w
return res
# マップ生成
def gen(self, start_x: int, start_y: int):
seed(SEED)
w, h, m = self.w, self.h, self.map
# 水
for i in range(int(w * 1.5)):
x = randrange(w)
y = randrange(h)
for j in range(3):
r = (j % 2) + 1
x2 = x + randrange(-r, r, 1)
y2 = y + randrange(-r, r, 1)
x2 = (x2 + w) % w
y2 = (y2 + h) % h
m[x2 + y2 * w] = WATER
# 開始位置(周囲の水を消す)
for i in range(9):
x = start_x - 1 + i % 3
y = start_y - 1 + i // 3
m[x + y * w] = PLAIN
# 山と森
for i in range(w):
x = randrange(w)
y = randrange(h)
for j in range(24):
r = (j % 3) + 1
x2 = x + randrange(-r, r, 1)
y2 = y + randrange(-r, r, 1)
x2 = (x2 + w) % w
y2 = (y2 + h) % h
if j < 16:
m[x2 + y2 * w] = FOLEST
else:
m[x2 + y2 * w] = MOUNTAIN
# 街と城
step = 5
area_w = w // (step * 3)
area_h = h // (step * 3)
for i in range(9):
x = i % 3
y = i // 3
x2 = (x * step + 1) * area_w + randrange(area_w * 3)
y2 = (y * step + 1) * area_h + randrange(area_h * 3)
if i == 4:
m[x2 + y2 * w] = CASTLE
else:
m[x2 + y2 * w] = TOWN
self.towns.append([x2, y2])
インポート部分
インポート部分を示します。
from random import seed, randrange
from dataclasses import dataclass
マップ生成にランダムを使うので`random`モジュールの`seed`と`randrange`を読み込みます。また、`dataclass`を使うので読み込みます。
定数
冒頭では、ゲームで利用する定数を用意します。
SEED = None # ランダムのシード値(None or int)
PLAIN = 0
FOLEST = 1
MOUNTAIN = 2
WATER = 3
TOWN = 4
CASTLE = 5
`SEED`の値を数値にすると、マップの配置を固定化できます。通常は`None`にして、毎回異なるマップにしています。
次は、ミニマップの色の配列です。ミニマップは、マップ画面の右上に表示する、小さなマップです。このミニマップの色を用意します。
COLS = [ # ミニ マップ用色配列
(152, 232, 0), # 平地
( 56, 104, 0), # 森
(192, 112, 0), # 山
( 80, 128, 255), # 水
(232, 208, 32), # 街
(144, 64, 240) # 魔王城
]
Mapクラス1
マップを表す`Map`クラスです。クラス メソッド`from_wh()`を持ちます。このメソッドは、横幅と高さの引数から、自身のオブジェクトを作成します。
@dataclass
class Map:
w: int
h: int
map:list[int]
towns: list[list[int]]
# 初期化
@classmethod
def from_wh(cls, w: int, h: int) -> "Map":
res = Map(w, h, [], [])
res.map = [PLAIN] * h * w
return res
Mapクラス2 マップ生成
マップ生成のアルゴリズムです。`random`の`randrange()`関数を利用して、一定の範囲に地形を散布していきます。
# マップ生成
def gen(self, start_x: int, start_y: int):
seed(SEED)
w, h, m = self.w, self.h, self.map
# 水
for i in range(int(w * 1.5)):
x = randrange(w)
y = randrange(h)
for j in range(3):
r = (j % 2) + 1
x2 = x + randrange(-r, r, 1)
y2 = y + randrange(-r, r, 1)
x2 = (x2 + w) % w
y2 = (y2 + h) % h
m[x2 + y2 * w] = WATER
# 開始位置(周囲の水を消す)
for i in range(9):
x = start_x - 1 + i % 3
y = start_y - 1 + i // 3
m[x + y * w] = PLAIN
# 山と森
for i in range(w):
x = randrange(w)
y = randrange(h)
for j in range(24):
r = (j % 3) + 1
x2 = x + randrange(-r, r, 1)
y2 = y + randrange(-r, r, 1)
x2 = (x2 + w) % w
y2 = (y2 + h) % h
if j < 16:
m[x2 + y2 * w] = FOLEST
else:
m[x2 + y2 * w] = MOUNTAIN
# 街と城
step = 5
area_w = w // (step * 3)
area_h = h // (step * 3)
for i in range(9):
x = i % 3
y = i // 3
x2 = (x * step + 1) * area_w + randrange(area_w * 3)
y2 = (y * step + 1) * area_h + randrange(area_h * 3)
if i == 4:
m[x2 + y2 * w] = CASTLE
else:
m[x2 + y2 * w] = TOWN
self.towns.append([x2, y2])
広大なマップを作ることを想定していないので、簡単なランダムで済ませています。ある程度以上大きなマップを作るなら、もっと構造化された作り方をした方がよいです。
また、きちんとマップを作るのなら、移動不能な場所を排除する必要があります。今回のゲームでは、そうしたマップが生成される可能性は低いので割愛しています。
`random`モジュールの`randrange()`関数の説明を書きます。いくつかの引数を指定できます。
randrange()
次の内容については省略します。こちらは同人誌をご覧ください。
6-5 保存するデータ4 マップ イベント
同人誌について
この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで288ページの本になります。ぜひ、こちらもご購入ください(2024-03-10:ver1.0.3 に更新)。
このnoteの記事と、Webページに一部抜粋版を掲載しています。
技術系同人誌など まとめページ
この記事が気に入ったらサポートをしてみませんか?