俺に解るように説明する "Godot Engine 3.x" 入門+

ゲームエンジン Godot Engine に関すること。入門とか使い方とかチュートリアルとか、あれとかこれとか。日本語解説。

Alicia in Godot Land #09「外部ファイルを扱うぞ! 1/2(CSVとPNG)」

f:id:ore2wakaru:20190902191112p:plain

日本語しか表示できないと顧客が限定されてしまうので、ガッポガッポ儲けられない。そこで、言語化が必要なんだけど、何ケ国語にも自力で翻訳出来るわけではないので、ユーザーが勝手に翻訳ファイルを作成出来るシステムを作ったぜ。


YouTube

出来ることは、こんな感じのものだ。

CSV形式のファイルを外部に用意して、KEYVALUEを書き入れて、それが辞書機能になって翻訳されるもの。CSVの外部ファイルなのでユーザーが編集可能! すごいね

だが、今気付いたけど、KEYが日本語なので、日本語と欧米諸国の文字しか対応できないな~。しまったな。Fontも外部から持ってきたものを指定できるのかな? まーいいや、後で考えよう。

さらに今気付いたけど、これだと、ゲームの話の内容がダダ洩れだな。あっはっはー。 ま、それはいいや。


外部テキストファイルの扱い方

今出来ててもどうせ、すぐに忘れるので書いておく。今回、生まれて初めて辞書型の変数を使ったが、考えようによっちゃ、配列よりも扱いが簡単かも。

f:id:ore2wakaru:20190902170017p:plain

・L10 まずは空の辞書(つまりDictionary型の変数)を用意する。空の配列と辞書の用意は、

var my_array = []        #配列
var my_dictionary = {}   #辞書

のように中に何にも入れない「[]」と「{}」で表して作る。

・L23 外部・内部どっちでもファイルを扱うには、まず、入れ物(箱)が必要なのでFileクラスとして準備する。なんで入れ物が必要? だって読み書きすんだから、データを一旦しまっておく場所が必要だろ? ってことでOK?

var file = File.new()

とは、"file"という変数をFileクラスと同じ内部構造の(箱の)形にして新しく作るってこと。だから、今後はfile.~~~みたいにドットの後にFileクラスの変数・関数が使えるようになる。

どんな時、このnew()すればいいのか分からん! って思う人がいるかもしれないけど、俺もよくは分からん。

・L24 さっそくドットの後にopen()関数を持ってきた。大事なのは、open()関数はただファイルをオープンするだけじゃなくて、エラー値を吐き出すってこと。で、「0」と比べてるのは、エラー番号が「0」、つまりエラーが無ければ次の処理に行けってしたいから。

エラー番号「0」はエラーが無いことを表す「番号」で、エラーの数が0個とかの意味じゃないからな。詳しくは、以下リンク。

https://docs.godotengine.org/en/3.1/classes/class_@globalscope.html#enum-globalscope-error

(一番上のOKが「0」ってことね。)

読み込むファイルの指定を"user://"で始めて書いている。これで外部ファイルを扱える。"res://"だと扱えるのは内部ファイルだけみたい。で、場所がどこになるかは動画でも示したけど、

"C:/Users/ユーザー名/AppData/Roaming/Godot/app_userdata/プロジェクト名"

のフォルダになる。だが、OSの違いやGodotのバージョンによっても違うみたいだなココの場所は。

L25 whileステートメントeof_reached()関数で最終行までまわす。

・L26 ファイルの中身はCSV形式なので、get_csv_line()関数で1行ずつ読み込むことが可能。その1行が変数"csv"に入るんがだ、カンマで区切られてる部分が配列の要素になって入るんだな。だから、変数"csv"は配列型(array型)になるってことに注意。

・L27 コメントにも書いたけど、配列の要素が2個以上あるときのみ、次行く。これを書くとこで、ファイル中カンマで区切らなかった文字列(配列の要素が1個しかない場合って事ね)はコメントとかカテゴリとか見た目上の体裁を整えるために使えるのだ。(動画でもそういう風に"---"を使ってるからね。)また、単なる無駄な改行があっても(配列の要素が0でも)エラーにならない。

・L28 ここがちょっと自分でも混乱する箇所。辞書の扱いの特徴で、新しく何かを辞書に登録する時、配列型みたいにappend()みたいな関数を使わなくてイイってことなんだ。つまり、

my_dictionary[KEY] = VALUE

ってやれば、KEYにVALUEが登録される。まー例えば、動画の具体例で行けば、ファイル中で

レモンティー,lemon tea

ってあるだろ。これは、変数"csv"にget_csv_line()で読み込むと、「csv[0]に"レモンティー"」、「csv[1]に"lemon tea"」が入るってことだよ。だよな。で、"G"は辞書型で宣言したろ、だから、

G[KEY] = VALUE

で登録できる。つまり、

G[csv[0]] = csv[1]

は、

G["レモンティー"] = "lemon tea"

って事だよ。これで、「KEY:"レモンティー"、VALUE:"lemon tea"」の辞書登録が出来ましたよってこと。あとはうまい事スクリプトを組めば、「レモンティー」の翻訳を「lemon tea」にすることが可能って事だ。(「レモンティー」っていう文字列があったら、「lemon tea」にせよってやればいいダケね。)

・L29 で最後、他の人(人?)が使えるように閉じておく。(多分、あけっぱだとエラーを吐いて開けない。とは言ってもGodotを閉じてしまえば関係ないから心配すんな。)

まー、今回は最低でもどんな関数が使えるのか、FileDictionaryAPIは見ておこうぜ。

Filehttps://docs.godotengine.org/en/3.1/classes/class_file.html

Dictionaryhttps://docs.godotengine.org/en/3.1/classes/class_dictionary.html


PNGは次にしよう

これでもう外部CSVは扱えるようになっただろ? で、外部画像ファイルの扱い方だが、次にするわ。

以上。


いちおう該当箇所コピペ

extends Node

var G = {}      #翻訳用の言語辞書

func _ready():
    #辞書準備
    var file = File.new()
    if file.open("user://ENG.txt", File.READ) == 0:     #エラーが無い時だけ読み込み
        while !file.eof_reached():
            var csv = file.get_csv_line()
            if csv.size() >= 2:          #2個(以上)ある時だけ有効
                G[csv[0]] = csv[1]
        file.close()

要らなかったかな?