Pythonプログラミングでリヴァイ兵長のドット絵を作成!


完成品

縦204×横197

作り方概要

ざっくり言うと、Pythonでプログラミングしました。
環境構築及び設計図の下準備に2時間ほどかかったと思います。
そのあとはプログラムを実行して瞬作!
作成後の微調整を施して完成しました。

以下からは手順の概要を書いていきます。

元画像の取得

こちらから拝借しました。
https://bibi-star.jp/posts/6881

設計図作成

元画像を読み込ませると、Excelのドット絵ファイルを出力してくれるサイトです。
ドット絵ナニカ

カラー設定

出力されたExcelではマインクラフトのブロックコード等になっていないので、
対応する色を設定しなおしていきます。
これがちょっとだけ面倒です。

リヴァイの場合、以下のように設定しなおしました。

Excel出力されたカラー番号:ドット絵ナニカで出力されたExcelに設定されていたカラー番号
ブロック番号:マインクラフトのブロック番号(24:砂岩、35:羊毛)
ブロックのデータ番号:ブロック番号の枝番になる番号(ブロック番号の種類に該当)
※2は皮膚の近くだったのと、あまり数が無かったので1と同様に肌色想定で、「滑らかな砂岩」にしています。

ブロック番号
ブロックのデータ番号

Pythonのインストール

詳細は以下のサイトに譲ります。
https://www.python.jp/install/windows/install.html

Forge及びRaspberry Jam Modのインストール

Forge及びRaspberry Jam Modのインストールは、下記を参考にしました。
マインクラフトでpythonプログラミングをするための5つのステップ

私の場合、Minecraftのバージョンが1.16.4であったため、Forgeも1.16.4をインストールしましたが、「Raspberry Jam Mod」で使えるバージョンが異なるためかうまく読込ができなかったため、1.12.2(Raspberry Jam Modの最新Ver)に合わせております。
※本記事執筆時点(2020年12月31日)
Mincraft Forge 1.12.2

Raspberry Jam Modは以下から「mods.zip」をDLします。
https://github.com/arpruss/raspberryjammod/releases/tag/0.94

解凍したフォルダのうち、1.12.2に入っている「RaspberryJamMod.jar」を、
マインクラフトのmodsフォルダに置いて下さい。

カラーコードの変換

Excelでのカラーコードをマインクラフトのカラーコードに変換します。
先程の設定に対応した変換ツールを独自(VBA)に作りました。

マインクロフトのカラーコードは「ブロック番号ブロックデータ番号」と、
アンダーバー(
)で区切るようにしています。
これは後程のPython側で処理しやすくするためです。

module.bas
Sub main()
'// 高速化
Application.ScreenUpdating = False '描画停止
Application.EnableEvents = False 'イベント抑制
Application.Calculation = xlCalculationManual '手動計算

'// 取得元シート
Dim targetSt As Worksheet: Set targetSt = ThisWorkbook.Worksheets("dot-e-nanika")

'// 設定シート
Dim colorConfig As Worksheet: Set colorConfig = ThisWorkbook.Worksheets("カラー設定")
Dim configRange As Range: Set configRange = colorConfig.Range("A2:A16")

'// 最右端, 最下端の取得
Dim cols, rows As Long
cols = 197
rows = 204

'// 配列
Dim blockDataArray() As String
ReDim blockDataArray(rows - 1, cols - 1)

'// 縦のループ
For i = 1 To rows
    '// 横のル―プ
    For j = 1 To cols
        '// 値の取得
        targetVal = Cells(i, j)
        Set findRng = configRange.Find(What:=targetVal, LookIn:=xlValues, LookAt:=xlWhole)

        '// 変換
        blockData = "Nothing"
        If Not findRng Is Nothing Then
            blockNo = findRng.Offset(0, 1)
            blockDataNo = findRng.Offset(0, 2)
            blockData = "'" & blockNo & "_" & blockDataNo & "'"
        End If

        '// 配列に格納
        blockDataArray(i - 1, j - 1) = blockData
    Next j
Next i


'// 配列を別シートに出力
Worksheets.Add after:=Worksheets(Worksheets.Count)
For i = 0 To rows - 1
    colors_str = "["
    For j = 0 To cols - 1
        colors_str = colors_str & blockDataArray(i, j)
        If j < cols - 1 Then
            colors_str = colors_str & ","
        End If
    Next j
    colors_str = colors_str + "]"
    If i < rows - 1 Then
        colors_str = colors_str & ","
    End If
    ActiveSheet.Cells(i + 1, 1) = colors_str
Next i

'// 高速化解除
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic

End Sub

<出力結果>
['35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0','35_0'],
…(204行まで似たような行列が続く)

ソースコード(Python)

dot_levi.py
import mcpi.minecraft as minecraft
mc = minecraft.Minecraft()
x, y, z = mc.player.getPos()

rows = 204
cols = 197 

colors = [
# ここにVBAで出力したカラーコードが入る
]

for i in range(rows):
    row = colors[i]
    for j in range(cols):
        blockNo, blockDataNo = row[j].split('_')
        mc.setBlock(x + j, y + rows - i, z, int(blockNo), int(blockDataNo))

blockNo, blockDataNo = row[j].split('')
⇒ここで、アンダーバー()で区切ったブロック番号とブロックデータ番号を各変数に格納しています。
 1つのブロック番号に固定すると、そのブロック番号以外で使いたい色があった場合に対応できないので、このような形式で保持するようしました。
 これにより、肌色に近い「滑らかな砂岩(24_8])」と、羊毛(35_XX)を、
 同時に扱えるようにしています。

プログラムの実行

・マインクラフトを起動します。
・コマンドプロンプトで、dot_levi.pyがおいてあるフォルダに移動し、
 「python dot_levi.py」と入力してEnterとします。

まとめ

・大規模なドット絵はPythonでプログラミングできる。
・Pythonプログラミングするには、Python/Forge/Raspberry Jam Modのインストールが必要。
・ドット絵ナニカというサイトを利用すると、設計図がほぼ出来上がる。
・作成時のブロックの指定に柔軟性を持たせるため、「ブロック番号_ブロックデータ番号」という形式にするとよい。
・元画像、設計図、マイクラに対応したカラーコードがあれば何でもつくることができる!!