Web AR開発用のJSライブラリ AR.js

これまでARアプリを作るときはARKitを使うことがほとんどだったが、マルチプラットフォームで動くライトウェイトなARアプリを作る機会があり、Web ARを試すことになった。Web ARを実現するためのライブラリは多数存在するが、2024年現在もっとも多く使われているライブラリは調べる限りAR.jsのようだ。サポートしているブラウザの種類や資料の数をみても、今の所AR.jsを使わない理由はなかったのでAR.jsを試してみることにした。

“Web AR開発用のJSライブラリ AR.js” の続きを読む

Google Slideのスライドをスクリプトで生成する

Google Apps Scriptに用意されているSlidesサービスを使うと、プログラムでスライドを新しく生成することができる。

https://developers.google.com/apps-script/reference/slides/slides-app

SlideAppクラスのcreate メソッドを使うと全く新しいスライドを新規で生成できるが、まっさらなスライドに要素を追加していく処理を全てスクリプトで書くのは結構大変なので、ベースとなるスライドをコピーするアプローチをとった方が何かと楽だ。

// srcFileId: コピー元のスライドのID
// filename: コピーして作られたファイルにつけるファイル名

const copy = DriveApp.getFileById(srcFileId).makeCopy(filename);

// 特定のフォルダに配置したければmoveToを呼び出す
// copy.moveTo(DriveApp.getFolderById(targetFolderId));


const newSlideId = copy.getId();

ファイルのコピーはSlidesサービスではなくDriveサービスのmakeCopyで行う。

const slide = SlidesApp.openById(newSlideId);

コピーしたスライドのIDをSlidesAppのopenByIdの引数に渡す形で、スライドを開き編集していくことができる。

const firstSlide = slide.getSlides()[0]
firstSlide.insertTextBox('Hello');

Google Apps ScriptのBigQuery Serviceのメソッドの引数の調べ方

Google Apps ScriptからBigQueryの機能を利用するにはAdvanced ServiceであるBigQuery Serviceを利用する。

https://developers.google.com/apps-script/reference#advanced_services

このAdvanced Serviceのメソッドを調べるには少し知識が必要になる。

“Google Apps ScriptのBigQuery Serviceのメソッドの引数の調べ方” の続きを読む

Google Apps Scriptでスプレッドシートの内容をオブジェクトの配列として取得する

Apps Scriptでスプレッドシートをテーブル的に使いたい時に、シートの内容をオブジェクトの配列として取得したいケースがよくある。

シート全体のセルの値はgetValues()もしくはgetDisplayValues()メソッドを使って取得することができる。

取得した値のうち、一行目をヘッダー行(keyの配列)として取り出し、残りの行を値として取り出すことで、オブジェクトの配列を作る。

function getRowsAsObjects(sheet) {
  var data = sheet.getDataRange().getDisplayValues();
  
  const header = data.shift();
  
  var rows = data.map(function(row) {
    var dic = {}
    header.forEach((h, idx) => {
      dic[h] = row[idx];
    });
    return dic;
  });

  return rows;
}

すると、このような結果が得られる。

[{name=Apple, date=2024/01/01}, {date=2024-03-13, name=Orange}]

よく書くコードなので、GASのライブラリとしてまとめた。

https://script.google.com/home/projects/1igMdPkdNu4Yg7u_rnBrXYTh7x15KotD0IpikNvrP52fCLV67ClXJ81ut

スクリプトID: 1igMdPkdNu4Yg7u_rnBrXYTh7x15KotD0IpikNvrP52fCLV67ClXJ81ut

使い方

var objects = SheetValues.getRowsAsObjects(SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TestSheet"))

Godot 4でtresファイルのダイナミックロードがやりにくくなった問題

Godot 4で、フォルダ内にあるtresファイルを動的に読み込むプログラムを書いたところうまく動作しなかった。

for file in dir_contents(folder_path):
	if file.get_extension() == "tres":
		tres_files.append(file)

上のコードは、特定のフォルダにあるtresファイルを全てリストアップするためのコードだ。Godot Editor上でこのコードを実行すると、フォルダ内のtresファイルがリストアップされるが、iOS上ではファイルが一つもリストアップされない。調べてみると、.tresファイルは見つからないが代わりに.tres.remapというファイルが存在していることがわかった。

https://github.com/godotengine/godot/issues/66014

Godot 3では動作していたのだが、どうやら仕様が変わりtresファイルもRemapされるようになったらしい。Remapされたファイルはload()やpreload()でres://プロトコルでファイルを指定して呼び出す際には内部的に自動でRemap後のデータが参照されるため、プログラム内で参照先をハードコーディングしているような場合は特にファイルの実態を意識する必要がないが、今回のように「フォルダからファイルを探して動的に読み込む」というような実装では「フォルダ上に見つかるファイル(remapファイル)」と「res://プロトコルで参照する際のURL」に差異が生まれてしまうのでそのままでは動かなくなってしまう。

for file in dir_contents(folder_path):
	if file.get_extension() == "tres":
		tres_files.append(file)
	if '.tres.remap' in file: # 追加
		image_files.append(file.trim_suffix(".remap"))

Godot 4でそのようなことをやりたい場合は、フォルダ内から.tres.remap ファイルを探し、読み込む際には.remapを取り除いたURLでload() するように実装する。ただし、Godot Editor上で作業している際にはRemapが行われていない元ファイルを参照しに行くことになるので、上のコードのように.tresファイルと.tres.remapファイルの両方に対応できるようなコードを書く必要がある。

https://github.com/godotengine/godot/issues/25672

最初にはったIssueと、上に貼ったもう一つのIssueでも指摘されているが、なかなかわかりにくい仕様だと思う。

M1 iMacへの買い換え

2020年末に購入したM1チップ搭載のMacBook Proが快適だ。Xcodeを使ったアプリ開発やPremiereでの動画編集はもちろん、最近少しずつ増えてきたニューラルネットワークが内部的に使われているようなAIアプリのパフォーマンスにおいて、Intel搭載のiMacとは顕著な差があることを実感している。

早くiMacもApple Silicon搭載の27インチモデルが発売されないかとずっと待ってきたが、待ち続けているうちに2年が経過してしまった。2023年中には発売されるのではないかという噂もあったが、昨今のApple製品の値段設定を見ていると発売されてもかなり高価になりそうなこと、それを待つ間の作業今のiMacの作業効率で失う生産性のバランスを考えて、24インチモデルの現行iMacに買い換えることにした。

Apple Siliconが出た当初はDockerや音源プラグインなどで色々問題があったが、最近ではほとんど解消され、さらにはプログラムの最適化も進んでおり環境構築もかなりスムーズに終わった。環境が綺麗な状態で、パフォーマンスをテストしておこうと思う。

“M1 iMacへの買い換え” の続きを読む

年末年始なのでGodotでゲームでも作ってみる 6日目

今日の目標

  • 音をつける
  • パーティクルシステムを使って軌跡を描く

音をつける

GodotではAudioStreamPlayerというNodeを使うと簡単にサウンドを再生させることができる。GameStageシーンにAudioStreamPlayerを追加する。

Nodeの名前はHitSoundにした。

FinderからFileSystem dockに適当なサウンドファイルを読み込む。

HitSoundのInspectorで、Streamプロパティのところに先ほど読み込んだサウンドファイルを指定する。

func _input(event):
	if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed:
		for enemy in get_tree().get_nodes_in_group("enemies"):
			var distance = event.position.distance_to(enemy.position)
			if distance <= ENEMY_RADIUS:
				enemy.position = Vector2(rng.randf_range(-STAGE_MARGIN, get_viewport().size.x + STAGE_MARGIN), -STAGE_MARGIN)
				score += 1
				get_node("HitSound").play(0)

サウンドを再生したいタイミングで、play(0)を呼ぶとそのサウンドが冒頭から再生される。今回のコードでは、標的が叩かれたタイミングでplay(0)を呼び出して効果音が鳴るようにした。

標的の軌跡を描く

パーティクルシステムを使って、標的の軌跡を描いてみる。

各標的から軌跡のパーティクルが放出されるようにしたいので、Hae.tscnにパーティクルシステムを導入する。Godotのパーティクルシステムには2種類のパーティクルシステムが用意されているが、Open GL ES 3系のプロジェクトでは、より高度でGPUで処理可能なParticles2Dノードを使うことができるので、今回はParticle2Dを追加。

Particles2Dノードが追加されたが、動作に必要なMaterialがセットされていないので警告マークが付いている。

ParticleのProcess Material(描画される一つ一つのパーティクルの表現を決めるもの)がemptyになっているので、New ParticlesMaterialを選択して新しいMaterialを作る。Inspectorの下の方にCanvas ItemのMaterialを設定する項目があるが、こちらではないので注意。

次にTexture(パーティクルの描画に使われる画像)を指定する。適当な画像をFileSystemに読み込んで、そこからドラッグで指定できる。

エディタ上でパーティクルシステムの動きが既に確認できるようになっている。現在は縦方向にパーティクルが放出されるだけであまりかっこよくないので、放射状に広がるようにパラメータを調整したい。

このパーティクルの動きは先ほど作ったMaterialの設定から行う。現在パーティクルが放出されると下に落ちていくのはGravityの影響なので、一旦Gravitiyを全て0にセットする。こうすることでパーティクルは生成されても下に落ちて行かなくなる。次にInitial Velocityに適当な値をセットする。この値はパーティクルが放出されるときの初速となり、大きくすれば大きくするほど勢いよくパーティクルが放出されるようになる。奇跡として描く場合はあまり大きくしすぎないほうが良いだろう。最後にDirectionで放出される方向を設定する。今回は特定の方向ではなく全方位に放出されて欲しいので、xyzはそれぞれ0をセットし、放出の範囲を決めるSpreadに180をセットした。

若干面倒ではあるが、Color Rampのところでグラデーションを指定することで、フェードインやフェードアウトも表現することができる。

設定の変更はすぐにエディタ上にも反映され動作を確認することができる。必要に応じて、その他のパラメータを調整して良い感じになるようにする。

最後に、Particles2DノードのDrawing / Local CoordsプロパティをOffにする。これをOnにしていると、放出されたパーティクルは親のNodeの移動に合わせて一緒に移動してしまう。今回は軌跡として表示をしたいので、標的(親ノード)が移動したとしても放出されたパーティクルは放出された場所にとどまって欲しいので、Offにする。

まとめ

一週間あるからある程度形になるだろうと思ってGodotを始めてみたが、前半油断してゆっくりやりすぎたこと、そしてそもそも実は休みが六日間しかなかったことなどもあって後半かなり駆け足になってしまった。とりあえずGodotを使ってゲームを作っていく上での基礎的なことは分かってきた感じがある。Godotはかなりサクサク動くし、Pythonライクな文法のGDScriptもコーディング量が少なく、気軽に遊びには良いゲームエンジンだなと思った。

Godotはクロスプラットフォームであるという点が魅力の一つなので、もうちょっとゲームとして形になったらiOS / Androidでそれぞれ動かしてみるというのを試してみたいと思う。

年末年始なのでGodotでゲームでも作ってみる 1日目

特に深い理由はないものの、今年の年末年始は久しぶりにゲームでも作ってみようかという気分になった。Godot Engineというフリーのゲームエンジンが気になっていたので、今回は休みの間気力が続く限りGodot Engineを試してみようと思う。

Godot Engineとは

Godot EngineはiOS / Android / Windows / macOS / HTML5…など様々な環境に対応したゲームを作ることができるゲーム開発環境で、無料で利用することができる。2D/3Dの両方に対応している。登場する概念や設計・思想はUnityやCocos2d、SpriteKitなどといった近年のゲームエンジン/フレームワークのそれに近しく、ドキュメントも充実しているので学習の材料として良さそうだったので、今回これを勉強していくことにした。

今日の目標

  • Godotをインストールする
  • Godotでサンプルプロジェクトを開いて実行してみる

新しいことを始めるときに、全容が見えないうちに高すぎる目標を掲げることは避けたい。初日は環境を構築してサンプルが無事に動いたら上出来ぐらいのテンションで行きたい。

Godotのインストール

公式サイトからGodotの最新版をインストールする。2021年12月29日現在の最新版は3.4.2。

DownloadページからGodotをダウンロードする。独自言語であるGDScriptが使えるStandard版とC#が使えるMono版がある。せっかくなので独自言語であるGDScriptを使うStandard版をインストールした。なおbrew caskを使ってもインストールできるようだ。Zipファイルを解凍して出てきたGodot.appをApplicationsディレクトリに移動するだけでインストールは完了。

起動してみたところ。「プロジェクトが一つもないけど、Asset Libraryにある公式のサンプルでもみてみる?」とのことなので「Open Asset Library」を開いて公式サンプルを見てみようと思う。

Asset LibraryのDemoのリストを見ていると、Skeleton2D DemoというシンプルそうなDemoがあったので、こちらを試してみよう。

詳細画面で「Download」を押すと、Asset Libraryからローカルにプロジェクトがダウンロードされる。

ダウンロードしたデモをインストールする場所を指定する。Project Pathには実在する空のフォルダのパスを指定する。

「Install & Edit」を選ぶと、指定した場所にプロジェクトがインストールされエディタが起動する。

エディタの右上にある「Play」を押すと、プロジェクトを実行して動作を試すことができる。

ゲームが起動した。矢印キーでキャラクターを操作できる。

ゲームを終了してエディタに戻ったら、「Quit to Project List」でプロジェクトを閉じてプロジェクト一覧画面に戻ろう。

プロジェクト一覧画面(Project Manager)に行くと、今開いていたSkeleton2D Demoプロジェクトがリストアップされている。別のデモを試したいときは画面上部のタブを「Asset Library Projects」に切り替えると、そこから先ほどのようにデモを検索してインストールすることができる。

まとめ

インストールはバイナリをzipからコピーするだけ、パスの設定なども不要で躓く点はなかった。サンプルプロジェクトも動いたことだし、今日はここまでにしておいてあとは体調を整えることにでも時間を使いたい。プログラマーはやはり体が資本。少し寒いがランニングにでも行こうと思う。アスファルトの上を走ると膝が痛くなるのが悩みだ。ずっと昔スポーツで膝の半月板を痛めたことの後遺症だと思っていたが、少し前にCTをとってみたらそれが原因ではなく姿勢の悪さ(骨盤の歪み)が原因だと言われた。実際、その後足を組むのをやめて、ストレッチの時間を増やしてから膝の痛みはかなり軽減した。そんなことを思い出した。明日は公式ドキュメントを読みながらプロジェクトを作ってみよう。

PythonとGolangのCSVの処理速度の違いを調べる

大量のデータをバッチ処理するようなプログラムを用意するときに、PythonとGolangのどちらを使うべきかいつも悩む。処理速度は悩むポイントの一つだ。近々大量のCSVを扱うプログラムを書く予定があったので、PythonとGolangでどの程度CSVの処理速度に違いがあるのか実験してみた。

実験は手元のiMac (Intel Core i5 3.4GHz / 40GB 2400MHz DDR4 RAM / Fusion Drive) で行った。

“PythonとGolangのCSVの処理速度の違いを調べる” の続きを読む