コマンド/Press to code/発展編

Last-modified: 2025-11-19 (水) 18:20:32

このページでは他のシステムとの連携などを行う発展的なPress to codeを紹介する。
注意:ここでの内容はBloxd外のシステムやプログラミング言語(ex:地理情報システム,Pythonなど)を用います。
そのためそれぞれのシステムについてのある程度の知識が必要となります。理解できない場合はまずは基礎から始めましょう。

各ページはサイドバーから

目次

地理情報システム(GSI)からBloxdへの受け渡し

ここでは、国土地理院が提供する地理情報システムである基盤地図情報をBloxdに渡して現実の地形をBloxdに再現する方法を解説する。

必要となるもの

基盤地図情報(推奨10A/10Bメッシュ)
基盤地図情報ビューア
Python (Python3以降)
(Power Automate / 業務効率上昇用)

使用言語

Python
(JavaScript)

手順

1.基盤地図情報をダウンロードする

基盤地図情報サイト/国土地理院にアクセスし、ダウンロードのための会員登録(無料)を済ませる。
基盤地図情報のダウンロードをクリックし、次のページでは「数値標高モデル」のボタンをクリックする。
あとは好きな地域とメッシュを選択してダウンロードするだけ。
Bloxdに起こす領域にもよるが大体の場合は10A/10Bメッシュで十分。
狭い範囲ならば5ABC以下を考えても良いかもしれない。

2.基盤地図情報ビューアをダウンロードする

先ほどのリンクから今度は基盤地図情報ビューアをダウンロードする。
この時取扱説明書も提供されているので一緒にダウンロードすることを勧める。

3.標高メッシュからシェーブデータ(.xyz)を制作する

まずファイル>新規プロジェクト作成の後読み込むファイルに先ほどダウンロードした数値標高モデルを追加する。
奥行きはブロック配置の観点から430の倍数を推奨
スクリーンショット 2025-07-07 183148.png
その後エクスポート>矩形領域選択で出力したい領域を設定し エクスポート>標高メッシュをシェーブファイルに出力をクリックし表示に従う。
.xyzファイルが出力されたら拡張子をxyzからcsvに変更する。(.xyzはカンマ区切り形式でこれはcsvファイルと同じ)
.xyzは各行にそれぞれ[インデックス,直交座標系のx(緯度方向)座標,直交座標系のy(経度方向),z(高さ)]の順でデータが入っている。
(座標系はBlenderと同じでzが高さになっている)

4.Bloxd内で用いることができる形へと変形していく

無論、このままではとてもBloxd内では用いることができない。よってここから

1.標高のみを起こした二次元配列を作る
2.標高のデータを圧縮する
3-1.Bloxd側でデータが入ったアイテムを作成する
3-2.チェストを用意しデータを入れる

の順でBloxdで読み出せる形式へと変換していく。なお、ここからはPythonを用いていく。

  1. 標高のみを起こした二次元配列を作る
    今回は標高さえわかれば後は適当にBloxd側で成形できるので二次元配列を作っていく。
    まずはPythonのコードを掲載する。
    import csv
    import math
    result = [[]]
    FILE_ADRESS = r"ファイルアドレス"
    
    with open(FILE_ADRESS,encoding='utf8',newline="")as f:
        csv_read = csv.reader(f)
        csv_read = [row for row in csv_read]
        write_y = 0
        last = float(csv_read[0][2])
        for i in csv_read:
            if float(i[2]) - last < 0:
                write_y += 1
                result.append([])
            result[write_y].append(math.floor(float(i[3])/10)) #メッシュの縮尺
            last = float(i[2])
    #ここまでcsv読み込み
    minlen = len(result[0])
    for i in result:
        if len(i) < minlen:
            minlen = len(i)
    
    for i in range(len(result)):
        result[i] = result[i][:minlen]
    #ここで二次元配列を成形する(一部だけ大きい可能性がある)
    コードの内容はそこまで拙いものでもないので理解し難くはないとは思うが一応解説を掲載する。
    ファイルを読み込んでそれぞれの3つ目の要素(高さ)を10(メッシュの縮尺 5Aなどを使用した場合は5になる)割って二次元配列に追加し
    y座標が逆行しているなら改行を加えている。コードについての詳細な質問はコメントまで。
  2. データを圧縮する
    この二次元配列はそのままではデータ量は膨大である。
    しかし最初の標高とそれからの増減を1文字で表せればデータ量は最初のxyzファイルから実に60分の1程度にまで減らすことができる。
    データ形式としては

    [参照チェスト,[開始標高,差分文字列],[...],...(計36個)...,[開始標高,差分文字列]]

    といった形式となる。
    以下に先ほどに続くPythonのコードを掲載する。
    注意:実行前にファイルとおなじアドレスに「Results」フォルダを作成すること
    bring_to_next = 0 #4ブロック以上上昇した場合の繰り上がり なお自然な地形なら崖でも出力しない限りはめったに使われない
    #また繰り下がりは実装していないためその場合は既存のコードを参考に追加してほしいがめったなことがない限り繰り上がり含め不要である。
    #繰り下がりを実装する場合は5を引いた値を比較して0以下になった値に5を足して繰り上がりと同時に足せばよい。
    #P
    for i in range(len(result)*minlen//15480): #1回で処理する合計チェスト量を計算する
        result_t = f"data=[{i}," #チェストの番号
        for j in range(36):#チェストのインデックス数
            nowResult="resultの参照 参照位置はマップの広さによって変わるので自分でコードを組んでください。"
            #iとjから読み込み位置は割り出せるので//と%を用いれば簡単に読み込み位置は指定できます
            last_h = result[12*i+j//3][j%3*430]
            result_t+=f"[{last_h},\""#初期の高さ
            if j%3==0:
                bring_to_next == 0
            heightResult = ""
    
            #
            for k in range(430):#customAttributesに書き込める限界付近の数
                nowResult="resultの参照"
                inc = (nowResult+bring_to_next) - last_h + 5 #5なら変化なし6なら1上昇4なら1下降といったように圧縮
                if(inc > 9):
                    bring_to_next = inc-9
                    inc = 9
                else:
                    bring_to_next = 0
                heightResult+=str(inc) #結果を追加
                last_h = nowResult #高低差比較用の一時変数
            result_t+=heightResult
            result_t+="\"],"#実質的な配列の形式の文字列とする
        result_t+="];api.log()"#データ追加時のチャット流れ防止
        with open(fr"Results\{i}.txt",encoding='utf-8',mode="w") as f:
            f.write(result_t)#結果はチェストごとにResultsフォルダへ"チェスト番号.txt"の形式で出力される
            print(f"wrote {i}.txt")
    なおこのコードおよびその後の処理では性質上出力が途中で途切れマップの終端の形が変形する可能性が高い。(15480ブロックを最少単位として構成しているため)
    また15480ブロック以下の場合はこのコードはうまく動作しない。
    その場合は中身だけを取り出して終端に達した際にbreakするコードを書きその結果を直にCodeBlockに入れてTickを使わずに設置する方が効率が良い。
  3. データの入ったアイテムの作成/チェストへの保存
    まずは保存用のチェストを用意すべきである。
    用意が必要なチェストの数は出力された最後のファイル名の数字+1個なのでWorldBuilderなどで出力する。
    この時一直線にするとコードが簡略化でき非常に楽。
    変数dataは(チェスト番号).txtの中身をそのままCodeBlockに入れる。
    この時PowerAutomateを使って例えば
    powerAutomate.png
    のようにするとキーを押すだけでデータがコピーでき非常に楽である。
    以下はチェストへの登録用のコード
    dataを設定してから実行する。
    function cspz(i){
    	return [x,y,z] //座標と増加方向を自分で追加する
    }
    for(i=0;i<36;i++){
    datas = {
    	he:data[i+1][0],
    	ic:data[i+1][1]
    }
    api.setStandardChestItemSlot(cspz(data[0]),i,"Ice",1,myId,{
    	customAttributes:datas});
    }#氷にデータを設定する。なお設定するものは何でもよい。
    api.log("End",data[0])

5.Tickを用いてブロックを配置する

先ずはコード

Bx=100;//開始位置設定
Bz=100;
nx=Bx;
nz=Bz-1;
read=0;
nh=0;
rC=0;
rB=0;
function cspz(i){
	return [x,y,z]//4番の関数と同じもの
}
tick = () => {
    for(i=0;i<50;i++){#50回/tick , 1000回/s(理論値)
        if(read%15480==0){#チェストの読み替え
            rD = api.getStandardChestItems(cspz(rC));
            rB=0;
            rC++;
        }
        if(read%430==0){#本の読み替え
            nh = rD[rB]["attributes"]["customAttributes"]["he"]+75;
            rB++;
        }
        if(read%/*マップの奥行*/)==0){//設置位置を変更
            nx++;//ここは設置方向によって遂次変更
            nz=Bz;
        }
        inc=rD[rB-1]["attributes"]["customAttributes"]["ic"][read%430];
        nh+=(inc-5);
        if(inc>6||inc<4){
            api.setBlockRect([nx,nh,nz],[nx,nh-(inc-5),nz],"Stone");
        }else{
            api.setBlock(nx,nh,nz,"Stone");//ブロックを設定
        }
        if(api.getBlock(nx,nh,nz)!="Air"||read%430==0){//前のブロックが置かれているもしくは読んでいる本が変わるタイミングなら進める

            nz++;#設置方向によって遂次変更
            read++;
        }else{//でなければ描画するy座標を修正して再び繰り返す(エラー対策)
			nh-=(inc-5);
		}
    }
}

コードの内容としては本の内容を読んで行って高低差を元にブロックを配置していくだけ。
なお生成後に穴が開いているように見える箇所が見られることがある。
これは生成のシステムからなる仕様で(z方向に進めるなら)z方向への大きな標高の変化はブロックを多数配置して
対処できるもののその場合x方向の穴を埋めることはデータ読み込みの観点からも難しいため。
ただし急斜面でもない限りほとんど起きないので生成後は斜面のみを見ればよい。

以上が生成までのコードである。質問等あればコメントへ。


コメント

  • 取扱説明書ダウンロード、、されたかな? -- 2025-07-07 (月) 18:20:23
  • 3がよくわからない。 -- 2025-07-07 (月) 18:21:35
  • PythonとJavaScriptって違うもんじゃないん? -- aaa_ 2025-07-10 (木) 19:37:55
  • 違うもんだね -- 2025-07-10 (木) 20:10:47
  • やべえ全然わかんねえw -- Sora 2025-11-07 (金) 06:49:19
  • すげええ -- SushiPal 2025-11-19 (水) 18:20:32