フューチャー技術ブログ

p5.jsで好きなプログラミング言語発表ドラゴンを作ろうとした

はじめに

春の入門連載2024の11日目です。

SAIGの小橋です。JavaScriptライブラリの1つであるp5.jsに入門します。

日本語版公式ページによれば、p5.jsとは…

クリエイティブなコーディングのためのJavaScriptライブラリで、 アーティスト、デザイナー、教育者、初心者、その他誰にとっても、コーディングを身近で包括的なものにすることに焦点を当てています。

…です。もともとProcessingという言語がグラフィックスやアニメーションに強いもので、それをJavaScriptから使えるようにしたのがp5.jsというライブラリです。

Webエディタがあるので、最初はここの上で色々試してみるのも良いでしょう。

今回は、公式ページの「はじめに」で説明されている通り、CDNの上にあるp5.jsライブラリを読み込むことにします。後述の通り、ローカルでWebサーバーを立てて表示しています。

作ったもの

今回は、ネット上で最近急によく見かけるようになった「好きな惣菜発表ドラゴン」を真似て、流行りに乗っかって「好きなプログラミング言語発表ドラゴン」の簡易版を作ります。

画像の表示、線分や四角形の描画、テキストの表示、といった感じで、基本的な機能を使っています。

Animation.gif

JavaScriptのファイルは以下の通りです。

prev_unit = -1;
random_lang_list = ["Python", "C", "C++", "Java", "C#", "JavaScript", "Go", "Visual Basic", "アセンブリ言語"];
random_lang = "";

// Load the image.
function preload() {
img = loadImage('fantasy_dragon_white_flipped.png');
}

function setup() {
createCanvas(1280, 720);
}

function draw() {
ms = millis();

// 背景を白に設定。前フレームの描画を上書きして消す
background(255);

// ドラゴンを表示
base_offset = 300;
if (ms <= 500) {
right_offset = 2 * base_offset;
} else if (500 < ms && ms <= 1000) {
right_offset = base_offset;
} else {
right_offset = 0;
}
image(img, width/2 + right_offset, (height-width/2)/2, width/2, width/2);

// 吹き出しの線を表示
// 塗りつぶしをオフにして長方形を表示
noFill();
strokeWeight(5);
rect(50, 50, 450, 300);
fill(0);
// 長方形で右側の一部の線を消す
erase();
dx=5;
rect(50+450-dx, 300/4, dx*2, 300/4);
noErase();
// 残りの2本の線を表示
line(50+450, 300/4, 600, 200);
line(50+450, 300/2, 600, 200);

// 言語名を1秒に1回、ランダムに選択する
unit_ms = 1000
now_unit = Math.floor(ms / unit_ms)
if (ms >= 3000 && now_unit != prev_unit) {
random_lang = random_lang_list[(Math.floor(Math.random() * random_lang_list.length))];
}

textSize(40);
textStyle(BOLD);
textAlign(CENTER, CENTER);
text(random_lang, 50+450/2, 50+300/2);

prev_unit = now_unit
}

HTMLファイルは上記のJavaScriptを読み込むだけの単純なものなので、省略します。

はまったポイント

シンプルなプログラムですが、いくつか詰まった点があったのでメモに残しておきます。

ちなみに、「p5.js 機能名」で検索したときに、Stack Overflowなどに加えて、先述したWebエディタで書かれたコードが見つかることもあります。Webエディタでは書いたコードをWeb上に公開できるので、検索時にヒットする可能性があります。公式ドキュメントでは無いので品質には注意する必要がありますが、参考にするのには良いのではないでしょうか。

画像を表示するためには、ローカルでWebサーバーを立てる必要がある

単純な四角形や円を描くだけならば、HTMLファイルをブラウザで開くだけでも動きます。

しかし、PCの内部にある画像を表示しようとすると、この方法ではうまく動かなくなります。ブラウザは Loading... と表示されたまま止まって見えます。これは、画像を読み込もうとしているpreload()関数が終了せずにエラーになっているせいです。デベロッパーツールを見ると下記のようなエラーが表示されていました。

Access to fetch at 'file:///C:/path/to/file/filename.png' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.

公式のこのページにも記載のある通り、この”cross-origin” エラーを回避するためにはローカルでWebサーバーを立てる必要があります。公式ページでは「Web Server for Chrome」のChrome拡張機能を使うように案内していましたが、現在は使えないようです。後継と思われる「Simple Web Server」を使用しました。ダウンロードしてインストールするだけなので、導入は簡単です。

draw() は1/60秒に1回実行される関数

公式ページにも明記されていますが、draw()は自動的に一定頻度で呼び出されて実行される関数です(フレームレートは変更可能です)。

ドラゴンを段階的に左に移動させつつ表示しようとしたときに、最初はsleep()関数のようなもので一時的に更新を停止するのかと思いましたが、sleep()関数はありませんでした。考えてみれば、draw()が一定頻度で実行されるので、表示を一時的に止めることはできないのでした。

millis()を使うと、プログラム実行開始からの時間を取得できるので、それを使って条件分岐させることにしました。

画像の左右反転

今回素材で使った いらすとやのドラゴンの絵はもともと右を向いていました。今回の用途では、左向きで表示させたいところです。

調べてみると、画像を左右反転させるためには、scale()を使う方法やtranslate()を使う方法がありそうでしたが、なかなか複雑そうだったので、諦めて手元の画像編集で左右反転しました。

ただし、つい最近の2024年3月に新しい機能がライブラリに追加され、それを使うと簡単に左右反転できるようになったようです。こちらを参照ください。

おわりに

JavaScriptのライブラリp5.jsを触ってみました。

実はp5.jsには p5.sound という音声を扱うライブラリがあり、本格的な音声信号処理ができる機能を備えています。例えば簡単に周波数スペクトルを表示することができるようです。音の処理もやってみたかったのですが、次の機会に譲ることにします。

p5.jsには例もかなり充実しているので、眺めているだけでも楽しいですね。