サマリ
p5.jsの環境でtoio™のプログラミングを簡単に楽しめるライブラリp5.toioの[α版(v0.5.0)をリリース] (https://tetunori.github.io/p5.toio/dist/0.5.0/p5.toio.min.js)いたしました。https://github.com/tetunori/p5.toio
ブラウザからアクセスするだけで、下記の様なサンプルをすぐに確認・制作できます。
toioのCubeと、p5.js及びp5.toioの多様なライブラリ群を利用することで、今まで画面内に閉じていたプログラミングの表現を簡単に現実世界へと拡張することが出来ます。
芸術作品だけでなく、プロトタイプ作成や、デーリーコーディング、ゲーム制作、小学生からのテキストプログラミングなど色々と使ってみてください。(α版なので、いろいろ制約事項有ります。)
P5 Editorでもすぐに始められますよ!(OpenProcessingは非対応)
P5 Editor: p5.toio basic sample
成果物
minifyした成果物はこちらですが、TypeScriptで書いた元のソースコード群もどうぞ。
※詳細は後述ですがAPI Referenceもあるよ。
いずれもMIT Licenseです。
開発モチベーション
課題
toio™Core Cubeを使って趣味で色々なものを作ってきて、下記の課題を感じています。
- 手軽に開発できない
- Node.jsはまだ導入が簡単な部類だが、とはいえ『
yarn
/npm install
実行したのに、なんか動かない』問題でどれだけの人類の心を折ってきただろうか。ほんとの初心者にはつらいと思う。
- Node.jsはまだ導入が簡単な部類だが、とはいえ『
- toio™Visual Programmingは手軽だけどスケールしない
- コピペできない、成果物をシェアしにくい、凝ったロジックを作ると膨大なブロック数になり、メンテは・・・
- 別途アプリ立ち上げが必要だったり、始めるまでにステップ数が最小ではない
- 個人的にはWebBluetoothを良く使うが、手続きが多くてしんどい
- 俺はただ、ランプをつけたいだけなのに、なぜこんなにコード行数必要なのだ?何回Promiseさせるんだい・・・と。
- ↑WebBluetoothは悪くなく、クラス化していない自分が悪い。
- toioの制御ライブラリがプリミティブなものしか存在しない。
- もう
Math.atan2
の計算したくない。
- もう
- 成果物をシェアするのに、毎回GitHubリポジトリ作るのは面倒だな
- JSの開発環境に関する知識が周回遅れになってしまっていて、話題についていけないので、モダンな開発手法に再チャレンジしたい
きっかけ
全然別の話題ですが、最近Daily Coding勢のツイートがよくタイムラインに表示されており、P5 EditorやOpenProcessingなどのオンラインツールを使って、気軽に楽しそうにプログラミングをし成果物をシェアされていました。
早速僕もp5.jsの勉強がてらOpenProcessingで色々作っては公開する日々を続けてみましたが、これは良い。
本当に気軽だし、p5.jsのライブラリも多いのでエンドレスなやりこみ要素もある。
任意の次数のベジエ曲線を描けるようになりました。より高次の表現は複雑だが美しい。
— Tetsunori NAKAYAMA | 中山 哲法 (@tetunori_lego) March 28, 2020
HigherBezierhttps://t.co/BroWbhMnDC#p5js #creativecoding #GenerativeArtWithMath pic.twitter.com/Qilk6nkgya
この手軽さでtoioもプログラミングできないか?と思い、P5 EditorでWebBluetoothを仮実装してみたところうまく動作したので、課題を解決するソリューションを作ってみようと奮起した次第であります。
課題解決の方針
下記を満たす、JSライブラリp5.toio
を作成する
- URLにアクセスするだけで、手軽に始められる、使える、創れる。 ⇒ toio™初心者歓迎
- P5 Editorで動作する ⇒ URLで作品シェアできる。
-
WebBluetooth
でスマホ・PC問わず、広く使える - 面倒な処理はぜーーーんぶラップしてAPI提供 ⇒ 『追いかけっこ』すら1行とか。
- JSのClass, ES6記法, TypeScript, ESLint, Prettier, TypeDoc, Jest, Docusaurus など自分にとって新しい技術領域にチャレンジする。
p5.toioのライブラリ構成
p5.toioは2つのクラスP5tCube
とP5tId
から構成されています。
P5tCube
クラスは、キューブを簡単にコントロールするためのたくさんのAPIやユーティリティを提供します。詳細はP5tCube Interfaceでご確認ください。
また、P5tId
クラスは、toio™のマットやカード、ステッカーなどに印刷されているtoio™IDについてのAPI・プロパティ群となっています。こちらも、P5tId Interfaceをご参照ください。
なお、今回説明した2クラスはp5.js
に特化する形でライブラリ化していますが、この2つのクラス以外は通常のWebBluetooth
でもほぼ同等の機能が使用可能なので、そちらもぜひご利用ください。
使い方
動作環境
toio™Core Cube
少なくとも1つは必要です。最近単売が始まったので、お手軽に導入できますね。Chargerも忘れずに!
また、本ライブラリを使う際は、スマホアプリから最新のFWへアップデートを御願いします。
PC環境
本ライブラリはWebBluetooth
へ依存しているため、下記の環境での動作となります。
- OS: Windows, MacOS, Android。iOS/iPadOSは非サポート。
- Browser: Google Chromeを強く推奨。
また、P5 Editorでは動作確認できていますが、OpenProcessingは残念ながら、動作出来ませんでした。(iFrameでSketchが動く都合、WebBluetooth
に必要なユーザーアクションが不正と判断されるため)
ライブラリのインポート
<head>
の中で、2つのp5.js
スクリプトp5.js
とp5.sound.min.js
の後に、1行読み込んでください。
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/addons/p5.sound.min.js"></script>
<!-- INSERT HERE -->
<script src="https://tetunori.github.io/p5.toio/dist/0.5.0/p5.toio.min.js"></script>
Minifyする前のライブラリも一応あるので、そちらでもOKです。
<script src="https://tetunori.github.io/p5.toio/dist/0.5.0/p5.toio.js"></script>
スケッチで使う
1. Cubeと接続しよう
API P5tCube.connectNewP5tCube()
をコールして、Promise
でresolve
された、P5tCube
インスタンスを受け取ってください。これだけで、すべてのAPIにアクセス可能です!簡単!
なお、このAPIはWebBluetooth
に依存しておりますので、接続の処理は必ず、ユーザーアクションの関数mouseClicked()
やkeyPressed()
などで実施してください。さもなくばエラーが出てしまいます。
const gCubes = [];
function mouseClicked() {
P5tCube.connectNewP5tCube().then( cube => {
// 'cube' is an instance of connected toio™Core Cube.
// Now you can call any API!
gCubes.push( cube );
} );
}
P5 Editor Sample 1: Turn Light On
2. APIを発行しよう
使用例 1: ランプを点灯する
P5tCube
インスタンスがあれば、API発行は簡単です。
得られたインスタンスがcube
だとして、ランプを白につけてみましょう。
// Turn the light on with white
cube?.turnLightOn( 'white' );
Done. これだけ。
P5 Editor Sample 1: Turn Light On
こんな感じで、全ての機能にアクセスできますので、詳しくは、下記のTypeDoc API Referenceを参照してください。後日、ちゃんとした説明のドキュメント作成します。 (2020/05/23更新済)
使用例 2: MIDI メロディーを再生する
// Play sequence C-D-E
cube?.playMelody( [
{ note: 0x3C, duration: 0x1E },
{ note: 0x3E, duration: 0x1E },
{ note: 0x40, duration: 0x1E }
] );
P5 Editor Sample 2: Play MIDI melody
使用例 3: マウスのX座標の方を向く
複数のキューブをtoioCollectionの土俵マットの右上においてください。複数のキューブがマウスのX座標の方を追いかけて回転します。
// Keep on gazing at mouse point
for( const cube of connectedCubeArray ){
const x = Math.floor(mouseX * 300 / windowWidth + 200);
const y = 144;
const speed = 115;
cube?.turnToXY( x, y, speed );
}
P5 Editor Sample 3: Keep on gazing at mouse point
使用例 4: 2つのキューブのインタラクション
2つのキューブをtoioCollectionの土俵マットの上においてください。
// Keep on gazing at the othre Cube
const speed = 115;
cubeP?.turnToCube( cubeQ, speed );
P5 Editor Sample 4-1: Keep on gazing at the other Cube
// Keep on chasing the othre Cube
const moveType = P5tCube.moveTypeId.withoutBack;
const speed = 80;
cubeP?.moveToCube( cubeQ, speed, moveType );
P5 Editor Sample 4-2: Keep on chasing the other Cube
使用例 5: カラータイルのマット
キューブをtoioCollectionのカラータイルマットの上においてください。
// Set background color with touched colored tile on mat
const color = P5tId.ColorTileMat.getTileColor(cube?.x, cube?.y);
background( color );
P5 Editor Sample 5: Change background color with touched mat color
3. Eventを受信しよう
本ライブラリでは、各種通知の取り扱い方法として、addEventListener
と、p5.js
っぽいコールバック関数の定義(mouseClicked()
やkeyPressed()
等と一緒)の両方をサポートしております。
使用例 6: addEventListner
// Button press event
const type = 'buttonpress';
cube?.addEventListener(type, ()=>{
console.log(type);
});
// Posture change event
const type = 'sensorposturechange';
cube?.addEventListener(type, (posture)=>{
console.log(type, posture);
});
P5 Editor Sample 6: addEventListner
使用例 7: コールバック関数定義
もしこれらの関数が定義されていたら、通知が発生次第コールバックされます。
const cubePositionIdChanged = (info) => {
console.log('cubePositionIdChanged!', info);
}
const cubeStandardIdChanged = (info) => {
console.log('cubeStandardIdChanged!', info);
}
P5 Editor Sample 7: Callback definition
以下に全てのコールバック関数定義をリストアップします。
const onButtonPressed()
const onButtonReleased()
const onBatteryLevelChanged(batteryLevel: number)
const onFlatChanged(flat: boolean)
const onCollisionOccurred()
const onDoubleTapped()
const onPostureChanged(posture: string)
const onPositionIdChanged(info: positionIdInfo)
const onStandardIdChanged(info: standardIdInfo)
Tips
パフォーマンスを上げるには
CubeのAPIコールにはasyncを使おう
もちろんPC環境にもよりますが、Cubeへのコマンドとp5.js
上の描画処理等をシーケンシャルに動かすと両方のパフォーマンスが落ちてしまうことが多いです。
そのため、それほど高いフレームレートを要求しないCubeのAPI発行はは下記の様に非同期関数としてもらえると、全体のパフォーマンスが向上します。
function draw() {
// Cube control command with async
asyncCubeControl();
// Then code your sketch...
ellipse( mouseX, mouseY, 20, 20 );
}
async function asyncCubeControl() {
// Cube control.
}
フレームレートあげる
このライブラリでは、僕のプアなPC環境でも満足に動くように、WebBluetooth
経由のAPI発行レートを15fpsに抑えています。(どんなに早く発行しても、15fpsを超えるものは破棄される)
そのため、位置情報の追従などは、若干精度に問題があるように感じるかたもいらっしゃると思います。そんなときはCubeのフレームレートを変更(上限30fps)してあげると、パフォーマンス向上する場合がありますので、お試しください。新しいMacBookなどではめっちゃ改善しますよ。
cube?.setFrameRate(30);
わかっている問題点
特定のWindows環境でのみですが、moveToMulti
APIが、3位置以上の指定をするとエラーが出てしまっています。Mac等では問題ない。
制約事項
p5.toio
はまだα版(0.5.0)のため、テストコードや詳細なAPIの説明資料、豊富なサンプル等が内包されていません。また、API仕様も改変する可能性もありますので、ご了承くださいませ。
次回のβ版(0.8.0)ではそのあたりも改善したものにする予定ですので、ご期待してお待ちください。
Enjoy!!!