【Scratch拡張機能をJavascriptで自作】svg画像からRPG風のマップを生成する拡張機能を作る〜マップ作成編②
※ 当ページには【広告/PR】を含む場合があります。
2021/02/02
前回に引き続き、タイル画像からRPG風マップを構成するためのテクニックを解説していきます。
この記事ではsvgマップの種となるcsvファイルを使って、Base64化したタイルの画像を所定の座標に張り合わせていくようなプログラムを作ります。
タイル画像を張り合わせるスクリプト
SVG画像の利点は、ラスター系のバイナリデータ画像と違って、テキストエディタ等で自在に変形できることが挙げられます。
ですので、タイル画像をテキストとして予め読み込んでおいて、正しい座標に上手く張り合わせることで、全体のマップ画像を生成することが容易にできます。
そこで今回の内容ではチョチョイと適当なスクリプト言語でタイル画像を張り合わせることを念頭においているのですが、世の中のスクリプト言語といえばpython/perl/php...様々な選択肢があり、人によってはそれぞれ得意不得意があると思います。
とはいえ今回のようなスクリプトは座標の計算と文字列を張り合わせる程度ですので、この程度ならばシェルスクリプトの能力で十分作成可能です。
以降ではどのような開発環境でも使えることを考慮して、汎用性の高いシェルスクリプト(bash)を用いたスクリプトを例に説明していきます。
タイル張り合わせ用スクリプトの作成
まず

簡単な例として全体の画像を4x4マスとしておいて、以下のようなcsvファイル(
sample.csv
1,1,2,1
2,1,2,1
2,2,2,1
1,1,2,2
この中身の数値に応じて、各マスに1の時に草原のタイルをセットし、2の時には壁のタイルをセットするようにします。
このcsvファイル(
sample.csv
sample.svg
#!/bin/bash
CANVAS_WIDTH=96
CANVAS_HEIGHT=96
TILE_SIZE=24
cat << EOF > ./sample.svg
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${CANVAS_WIDTH}" height="${CANVAS_HEIGHT}" version="1.1" viewBox="0 0 ${CANVAS_WIDTH} ${CANVAS_HEIGHT}">
<defs>
<image id="tile1" x="0" y="0" width="${TILE_SIZE}" height="${TILE_SIZE}" preserveAspectRatio="none" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOxAAADsQBlSsOGwAABbJJREFUSEs1lllTG1cUhFUplzFgNuPECZtAIFYvyY912YA24MEBYmkkjUYsyXtikBBg5yll0DZaqPyGk6+vnIfLaGbunKVPd18iXrho+faiBa2YFepRy3a47y9ZqT1vQXuWa9QO736y4/6GZR+2rNRds8L9vJU7y+5doTFjZ/2YFZuzbhXaC5a+GXXXYhi1SLG7YkF/1VLVETvhdzZcst9aUQvCBSu1Zuy0t2x+L26/tuN21FmzbH3Rznpr5rcopD7LdcGSlSH2UyRLgcv9ZUtdj1iRYiMeH777NDyohpfvK2NW6m+STB29sJ1Pjyx1M27ewys77m6Y11yxcrhi+zxT8HOS7f41RCFxl7TYXrICRWYbdNMlQbG7bn5n1cpsKLSWLH37g+VbcUt8GrI/ejHLVIfNp7OjZtwOW+uWup02P1wGjqiDKXnxxM66q3Qbs1x9wTI3E25/PuS+EyMBf9R2sjZtXmMN3OJW6gAbyQJmotl4jSXLd7es0HtpuRYwsr/cWwV/YGwu2H5tFLjmbe92kg5WzGut2Uet9qZFNGB1sH3xjJcvLXE1bnmqU+AzNpfpJlWZAL5VMN203atnDHrDdbt3PerIMFhADEQ5ikl/fm4lilGSiNr1mjFLXj+3XJOqCKp2/XrMDqoTdlCZslIDSMA25wJsMbNpS14RPBwwx2vOkBTmaQGr15q37cpjoFqyiLIWwCvfXred6hTTH7QZMMy9yzE7D4ENqPY+j1FAlI9es3fLJQw6c44MYoy61jMPBvrdZTdooRMphvPugar3GGKyNsHGGNhSDavcgJYMMQW78i0+ZLAeRfkUVSLg7sWQ7V9P0DWdh+uWqNLd9QvLtV8x5NeDBNuVJ3B9w3JsyBJUlToq1saZAwG/wvcmMEGABAMtP6xYqvbU0fKU5O5dY8WKFJhvEqNBopsZ+3C3CkSNOTv4MmXHd7NkhAEduM5wEtUxKDhsp8xDjCpReYKgmpdjFTj7CMlrRKHnIgx6xpDpkL1F9gp2MTRS7oAbdJOYCp24eb1Ne8twFUhduOBNAhGw1OOeAjQjibLUHTBHlM1iHxliqBCvOecKEDp0MOMsIne/QoXP7Rg7OCZRgWv+fhGhDaAoYhlHdKngPjBqqLvVoW+Bos5/svdzTnwqrMjsAuClA6YvdiCyQvjSDmGNTG23NunaFmUDCnhfY8hUmrkas3RlxGGfwL9UZb7FjIBL+7b/fGzn/XVLV8ctefmUIZNJLnqO/3y8X7ZDJn/UfWNvL/Ef8M2Au3D9cIc7Pmy6hCd0oG+kIbFJMKlLvVP1rsP7BVdERA8PbiYtcfnE4Z7rv7ZfW5tOF+nr8YHnULnu312M2wnwaSbqRAmEuZIkqqMwaww6I8BvidKI0QlNw/lfJB7Xotp3lqHqllwgdVfCj1LoRF6lYNqfZ9haQZ+5kSjJd9KR4rnzQIpzgVnieOb2KXYw64KXezitrASofv/3F8fznQrv6UpiK+HAYpZ0JAOUR/kdtABd5c7vL74DIn7oA1WVFx2h2MHfE7ZzyanERgUvYYa7l5Pm1QmIGHW//wXvwqN2oXQGiy+0tmDRmiVRcr6B+ChMBw9K5nQia7I66R6KDdn6DIzgOcoNunGcdsRSV9N22n9DEpKykrUpillFZBhka4OkP/MbEmARQWfLiU9UjmTvkDmtp9GAFCqXdKxA/pkrDg8YIYYd/8Mz/F2J/PYGBUHhcJOk2PJXdKIkIWcGVuHe0aVQieihRxXa4LfXYI7YwbDgcMBxGvBbSRRYH5/0XhGQIbLfzeRymKIQI91m75kjZ4fEKOZp2JFic5Agj9CEr/islUbB0ogOEiUpsieAvlK8kmh/5np6YNdXj/hmYN3aqyW6itKRfJ12K9+79tSBBKT/DlS1NiqBbNnnTA5clxsElzVvOaa50yz80Z0NfpuDh/3F5rxLkKqM2n+9RwQjDz4j0AAAAABJRU5ErkJggg=="/>
<image id="tile2" x="0" y="0" width="${TILE_SIZE}" height="${TILE_SIZE}" preserveAspectRatio="none" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAABPSURBVEhLYzx8+PB/BhoCxvr6eqItcHFxYdizZw+URxiA1DNB2TQDoxYQBAOTishJLbjUj0YyQTBMUxEuMFoW0QQM01Q0WhYhg6FuAQMDAMbWKtE8sR+/AAAAAElFTkSuQmCC"/>
</defs>
EOF
cat ./sample.csv | awk -F"," '
BEGIN {
OFS=",";
row_count=1;
}
{
for(i=1;i<=NF;i++) {
print i, row_count, $i;
}
row_count++;
}
' | awk -F"," -v tile_size=${TILE_SIZE} '
BEGIN {
row_count=0;
}
{
y_pos = tile_size*($2 - 1);
x_pos = tile_size*($1 - 1);
use_arr[row_count] = "<use xlink:href=\\\"#tile" $3 "\\\" x=\\\"" x_pos "\\\" y=\\\"" y_pos "\\\"/>";
row_count++;
}
END {
bundle="";
for (i=0;i<row_count;i++) {
bundle = bundle use_arr[i] "\\\n";
#print use_arr[i];
}
bundle = bundle "</svg>";
print bundle;
}
' | xargs echo >> ./sample.svg
という内容で最低限のスクリプトの名前を
csv2map.sh
では早速これを現在のフォルダ上でターミナルを開き、実行させてみますと、
$ chmod +x csv2map.sh
$ ./csv2map.sh
$ cat sample.svg
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="96" height="96" version="1.1" viewBox="0 0 96 96">
<defs>
<image id="tile1" x="0" y="0" width="24" height="24" preserveAspectRatio="none" xlink:href="data:image/png;base64,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"/>
<image id="tile2" x="0" y="0" width="24" height="24" preserveAspectRatio="none" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAABPSURBVEhLYzx8+PB/BhoCxvr6eqItcHFxYdizZw+URxiA1DNB2TQDoxYQBAOTishJLbjUj0YyQTBMUxEuMFoW0QQM01Q0WhYhg6FuAQMDAMbWKtE8sR+/AAAAAElFTkSuQmCC"/>
</defs>
<use xlink:href="#tile1" x="0" y="0"/>
<use xlink:href="#tile1" x="0" y="24"/>
<use xlink:href="#tile2" x="0" y="48"/>
<use xlink:href="#tile1" x="0" y="72"/>
<use xlink:href="#tile2" x="24" y="0"/>
<use xlink:href="#tile1" x="24" y="24"/>
<use xlink:href="#tile2" x="24" y="48"/>
<use xlink:href="#tile1" x="24" y="72"/>
<use xlink:href="#tile2" x="48" y="0"/>
<use xlink:href="#tile2" x="48" y="24"/>
<use xlink:href="#tile2" x="48" y="48"/>
<use xlink:href="#tile1" x="48" y="72"/>
<use xlink:href="#tile1" x="72" y="0"/>
<use xlink:href="#tile1" x="72" y="24"/>
<use xlink:href="#tile2" x="72" y="48"/>
<use xlink:href="#tile2" x="72" y="72"/>
</svg>
というsvg画像が生成されていたら成功です。
なお、タイルの画像の扱いに関しては
defs
ここではあくまで簡単な例を挙げるために2つの画像(
id="tile1"
id="tile2"
タイルの画像の種類を増やす場合は、
defs
Scratchのレンダラーに描画
現時点では拡張機能のプログラミングが出来ていないので、スクリプトで組み上げたSVG画像を読み込めるか否かの確認はレンダラーだけを使うという選択肢があります。
ということで先程のスクリプトで吐き出したマップがスクラッチアプリ上で正しく表示されるかは、スクラッチ3のコアライブラリの一つである
なお、scratch-renderの立ち上げ・ビルド方法などは以前の記事で特集していますので、お手元で動作確認する場合にはご参考ください。
今回のsvg画像を手っ取り早く試すのであれば、前回のscratch-renderで試したプロジェクトの

ハードコードするのが嫌でファイルとしてインポートしたい場合には、webpack側に
まとめ
今回はタイルマップのシードファイル(csvファイル)とそこから生成済みのタイルマップ(svgファイル)の2つの構築方法を解説してみました。
この時点でも、この2つのファイルを使って、タイルマップを背景画像に、シードファイルをリストにセットするなどしてもRPG風なゲームが作れそうな気がします。
ここで満足されても良いのですが、よりスクラッチプログラミングの高みを目指すのが当初の目的でもあるので、次回以降では、このファイルを使って拡張機能化を図りたいと思います。