PythonとPygameで作る レトロ風RPG 全コード

同人誌について

 この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。

 同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。

(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)


6-4 保存するデータ3 マップ

公開:2024-03-21

説明と全体コード

 「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モジュールのseedrandrangeを読み込みます。また、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 マップ生成

 マップ生成のアルゴリズムです。randomrandrange()関数を利用して、一定の範囲に地形を散布していきます。

# マップ生成
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()

関数 説明
random.randrange(stop) 0から始めて、1ずつ違う値を、stop未満で作成する
random.randrange(start, stop) startから始めて、1ずつ違う値を、stop未満で作成する
random.randrange(start, stop, step) startから始めて、stepずつ違う値を、stop未満で作成する

 次の内容については省略します。こちらは同人誌をご覧ください。


同人誌について

 この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。

 同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。

(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)

 技術系同人誌など まとめページ


トップページに戻る
Cronus Crown(クロノス・クラウン)のトップページに戻る
(c)2002-2024 Cronus Crown (c)1997-2024 Masakazu Yanai
ご意見・お問い合わせはサイト情報 弊社への連絡までお願いします
個人情報の取り扱い、利用者情報の外部送信について