見出し画像

Processing でマイクラ④ 村を自動生成する

マイクラの魅力の一つは、「自動生成される世界」です。マイクラで新規ワールドを作成するたびに、異なったバイオーム(海、山、砂漠、平地など)が現れます。ところどころに村があり、地下迷宮や寺院、海底神殿など、魅惑的なスポットがランダムに存在しています。私はマイニングしていてダンジョンに出くわすと、テンションがバク上がり↑です。
さて今回は、マイクラ風の村の自動生成に挑戦してみました。20軒の家と道路、岩地だけの簡単な世界ですが、マイクラが世界を作る仕組みが感じられることと思います。

ランダムな家を作成する

def minecraftic_house(w, d, h, x=0, z=0):
    # heights = [0, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 0]
    heights = [0]
    for i in range(w):
        if i < w / 2:
            if w % 2 == 0:
                heights.append(h - (w / 2) + i + 1)
            else:
                heights.append(h - (w / 2) + i)
        else:
            heights.append(h + (w / 2) - i)
    heights.append(0)
    # print(heights)
    wood_id = 35
    roof_color = randint(0, 15)
    body_id = 5
    pillar_id = 12
    for i in range(w + 2):
        for j in range(d):
            roof_height = heights[i]
            if (i == 1 and j == 0) or (i == 1 and j == d - 1) or (i == w and j == 0) or (i == w and j == d - 1):
                block_id = pillar_id
            else:
                block_id = body_id
            if roof_height > 0:
                for k in range(roof_height):
                    block_positions.append((i + x, k, j + z, block_id))
                else:
                    block_positions.append((i + x, k + 1, j + z, wood_id, roof_color))
            else:
                block_positions.append((i + x, heights[1] - 1, j + z, wood_id, roof_color))

# クラフトデータを作成
for i in range(2):
    for j in range(10):
        minecraftic_house(
            randint(5, 11),
            randint(5, 11),
            randint(8, 11),
            j * 15,
            i * 30,
        )
house

マイクラ編の第一回で作った家のプログラムを改造しました。同じ家が並んでいてもつまらないので、縦横高さ、屋根の色がランダムに作成されるように変更しています。屋根の色は羊毛で表しており、16種類の色を表現できます。
for文を二重にすることで、10 x 2 軒のマイクラ風の家が建築されます。Processingのスケッチを実行するたびに、違った家の並びが現れます。そしてその並びは2度と現れないのです。(厳密にいうと、何度も何度もやっていたら同じ並びが現れます。)

道路を建築する

def road():
    for i in range(150):
        for j in range(9):
            if 0 < i % 10 < 5 and j == 4:
                block_id = 12
            else:
                block_id = 1
            block_positions.append((i, -1, j + 15, block_id))

road()
house and road

家の並びと平行に道路を建築しました。単に石ブロックを並べるだけではつまらないので、中央線(砂で表現)を描いています。こだわるのならば、縁石や歩行者用の道を作るのもよいでしょう。いくらでも細部を作りこんでいくことができます。

街路樹を植える

def tree(x, z):
    tree_height = randint(7, 8)
    for i in range(tree_height):
        wood_id = 35
        branch_color = 12
        leaf_color = 13
        if i < 3:
            block_positions.append((x, i, z, wood_id, branch_color))
        elif i == tree_height - 1:
            block_positions.append((x, i, z, wood_id, leaf_color))
        else:
            for j in range(3):
                for k in range(3):
                    block_positions.append((x - 1 + j, i, z - 1 + k, wood_id, leaf_color))

# クラフトデータを作成
for i in range(2):
    for j in range(10):
        minecraftic_house(
            randint(5, 11),
            randint(5, 11),
            randint(8, 11),
            j * 15,
            i * 30,
        )
        tree(j * 15, 13)  # 追記
        tree(j * 15, 25)  # 追記
house and road and tree

家と道路の間に、街路樹を植えました。これでぐっとリアルさが増したように思います。街路樹は羊毛の茶色と緑で作りました。高さはランダムに 7 か 8 を選ぶようにしてあります。

バイオームを作成する

地形作成編①で紹介させていただいた、Webサイトをまた利用させていただきます。
地形自動生成
150x150サイズの地形を作成し、「minecraftic_village.csv」の名前で保存します。csv を読み込んで、地形を作成するコードは以下のようになります。

import csv
import codecs

sketch_name = 'minecraftic village'

def land():
    with open(csv_file, 'r') as f:
        reader = csv.reader(codecs.EncodedFile(f, 'utf-8', 'utf-8-sig'), delimiter=",")
        land_data = [row for row in reader]
        row_num = len(land_data)
        column_num = len(land_data[0])
        max_height = int(max([max(l) for l in land_data]))
        print(max_height)

        for i in range(row_num):
            for j in range(column_num):
                land_height = int(land_data[i][j])
                if j < 45 or 90 < j:
                    for k in range(land_height):
                        block_positions.append((i, k, j - 50, 1))
                elif j == 45 or j == 90:
                    for k in range(int(land_height / 2)):
                        block_positions.append((i, k, j - 50, 1))

land()
house and road and tree and biome

地形作成編①のコードを少し修正しています。
地形の配置を Z方向に50移動させています。家並みが存在する場所はバイオームを設置しないようにしました。バイオームと家並みの境界線は段差が少なくなるように調整してあります。
これで、マイクラ風の村の建築は完了です。マイクラ(本物)の内部で動くプログラムは、今回紹介したもの(もどき)より、もっともっと複雑です。しかしやっていることはランダムに地形を生成することですから、今回のプログラムと本質は同じということができます。

村をマイクラの世界にコピーする

copy village to minecraft

マイクラの世界にコピーしてみました。なかなかいい感じです。スライムが遊んでいるのが楽しいです。改造するとしたら、バイオームと家並みの境界が段差が大きいので、もっとなだらかにしたいです。バイオームがすべて石なのも不自然ですね。細かい修正は読者の皆様にお願いします。
Processing x Minecraft = Processincraft の世界にようこそ!


前の記事
Processing でマイクラ③ Processingからマイクラにデータを送信
次の記事
MagicaVoxel① はじめてのボクセルアート

その他のタイトルはこちら


この記事が気に入ったらサポートをしてみませんか?