事始め
訳あってScratchの自主練をしていたところ、楽しそうな記事を見つけました。
そんなことができるのですね!
そしたら、Realtime Database のブロックとかつくって、ネットワークゲームも制作できるようになる......!!!
これはやるしかないでしょ、ということで。
やってみたいぃぃい✨
— kami_teru (@kami_teru) February 22, 2021
Scratch 3.0 で Web API 呼び出しの拡張ブロックを作る、の手始め - https://t.co/oJ6pjzKviS
やってみた事とその結果をまとめます。
なおNode.jsは今回初めて触りましたので、変な事していたらそこは温かい目で見守っていただければ幸いです。
環境構築
Windows上で行います。作業ディレクトリは次の場所にしました。
mkdir C:\Users\kami_teru\source\repos\scratch\
cd C:\Users\kami_teru\source\repos\scratch\
以下の記事を参考に、Node.jsをインストールし、scratch-gui をlocalhostで起動できるようにしました。
一つだけ注意点。私のWindows環境では npm run deploy
を実行したとき、次のエラーが出ました。
PS C:\Users\kami_teru\source\repos\scratch\scratch-gui> npm run deploy
> scratch-gui@0.1.0 deploy C:\Users\kami_teru\source\repos\scratch\scratch-gui
> touch build/.nojekyll && gh-pages -t -d build -m "Build for $(git log --pretty=format:%H -n1) [skip ci]"
'touch' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
touch
コマンドは、Git for Windowsをインストールしている方なら、次のようにすれば利用可能になります。
$ENV:Path+=";c:\Program Files\Git\usr\bin"
さてさてこれで、Scratchを試せるようになりました。
次は、Realtime Database の準備を行います。
Realtime Database のセットアップ
1) Firebase プロジェクトの作成
Firebaseコンソールにアクセスし、プロジェクトを追加します。
設定項目 | 値 |
---|---|
名前 | (任意の名前) |
Google アナリティクス | 無効にする |
アナリティクスは有効にすると、これから作る拡張ブロックの利用頻度などが取得できるようになるのでお勧めですが、本記事に関係のない情報なので無効にします。
2) Firebase プロジェクトに Webアプリ を追加
Scratch 3.0はNode.jsで動作するクライアントサイドのWebアプリなので、次のようにします。
設定項目 | 値 |
---|---|
アプリのニックネーム | (任意の名前) |
Firebase Hosting | 設定しない |
LLK/scratch-gui は、Github Pages にデプロイする仕組みを備えており、本記事もそれを利用します。よって Firebase Hosting は設定しません。
Webアプリを登録すると、 Firebase SDK の追加
のページで「この作業は Firebase サービスを使用する前に行ってください。」という情報が表示されますが、あとで拡張ブロックからやるので、ここではスキップしました。
3) Firebase プロジェクトに Realtime Database を追加
Firebase コンソールの構築メニューから Realtime Database を選択。「データベースを作成」をクリックします。
設定項目 | 値 |
---|---|
Realtime Databaseのロケーション | 米国 (us-central1) |
セキュリティルール | テストモードで開始 |
拡張ブロックの動作確認までがとりあえずの目的なので、セキュリティルールはテストモードにしました。
4) Realtime Database への接続情報の確認
「プロジェクトの設定」ページを開くと、全般タブの「マイアプリ」セクションに作成した Webアプリ があります。それを選択すると、 Firebase SDK snippet 欄に次のような接続情報が表示されます。
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/8.2.9/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/8.2.9/firebase-analytics.js"></script>
<script>
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
var firebaseConfig = {
apiKey: "AI***********************************WQ",
authDomain: "************.firebaseapp.com",
databaseURL: "https://************-default-rtdb.firebaseio.com"
projectId: "************",
storageBucket: "************.appspot.com",
messagingSenderId: "************",
appId: "1:************:web:**********************",
measurementId: "G-**********",
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
</script>
※***
の部分が、作成したFirebaseプロジェクト固有の部分。
以上で準備完了!では Realtime Database 拡張ブロック づくりへ。
Realtime Database 拡張ブロックの作成
Scratch に Realtime Database 拡張機能 を追加
Scratch で Realtime Database 拡張ブロックを表示できるようにするための機能情報を記述するために、C:\Users\kami_teru\source\repos\scratch\scratch-gui
のソースを編集します。
機能名は realtimedb
とします。
src/lib/libraries/extensions/index.jsx
に以下を追加。
...(中略)...
import realtimedbIconURL from './realtimedb/realtimedb.png';
import realtimedbInsetIconURL from './realtimedb/realtimedb-small.png';
export default [
...(中略)...
{
name: 'Realtime Database',
extensionId: 'realtimedb',
iconURL: realtimedbIconURL,
insetIconURL: realtimedbInsetIconURL,
description: (
<FormattedMessage
defaultMessage="Connect to Realtime Database."
description="Realtime Database"
id="gui.extension.realtimedb.description"
/>
),
featured: true,
internetConnectionRequired: true
}
]
src/lib/libraries/extensions/realtimedb/
配下に、画像ファイルを配置。
Firebaseブランドガイドライン から適当なものをピックアップ&サイズを調整。
Realtime Database 拡張機能 の最低限の実装
いよいよ拡張ブロックの実装です。C:\Users\kami_teru\source\repos\scratch\scratch-vm
のソースを編集。
まずは SDKの組み込み。Node.js から Realtime Database を利用する場合、Firebase SDK が便利です。
次のようにして、Firebase SDK をインストール。
cd C:\Users\kami_teru\source\repos\scratch\scratch-vm
npm install firebase --save
次に、Webサイトの Firebase認証 を済ませるための最低限の実装を行います。
こんなブロックを実装していきます。
const ArgumentType = require('../../extension-support/argument-type');
const BlockType = require('../../extension-support/block-type');
const Cast = require('../../util/cast');
const log = require('../../util/log');
const firebase = require('firebase/app');
//require('firebase/analytics');
require('firebase/database');
const firebaseConfig = {};
class Scratch3Realtimedb {
constructor (runtime) {
this.runtime = runtime;
this._firebaseApp = undefined;
this._realtimedb = undefined;
}
get firebaseApp () {
if (this._firebaseApp == undefined)
{
this._firebaseApp = firebase.default.initializeApp(firebaseConfig);
//firebase.default.analytics();
}
return this._firebaseApp;
}
get realtimeDb () {
if (this._realtimedb == undefined)
{
this._realtimedb = this.firebaseApp.database();
}
return this._realtimedb;
}
getInfo () {
return {
id: 'realtimedb',
name: 'Realtime Database',
blocks: [
{
opcode: 'setApiKey',
blockType: BlockType.COMMAND,
text: '【設定1】apiKey は [TEXT] を使う',
arguments: {
TEXT: {
type: ArgumentType.STRING,
defaultValue: "Firebase SDK snippetから貼り付けてね"
}
}
},
{
opcode: 'setAuthDomain',
blockType: BlockType.COMMAND,
text: '【設定2】authDomain は [TEXT] を使う',
arguments: {
TEXT: {
type: ArgumentType.STRING,
defaultValue: "Firebase SDK snippetから貼り付けてね"
}
}
},
{
opcode: 'setDatabaseURL',
blockType: BlockType.COMMAND,
text: '【設定3】databaseURL は [TEXT] を使う',
arguments: {
TEXT: {
type: ArgumentType.STRING,
defaultValue: "Firebase SDK snippetから貼り付けてね"
}
}
},
{
opcode: 'setProjectId',
blockType: BlockType.COMMAND,
text: '【設定4】projectId は [TEXT] を使う',
arguments: {
TEXT: {
type: ArgumentType.STRING,
defaultValue: "Firebase SDK snippetから貼り付けてね"
}
}
},
{
opcode: 'setStorageBucket',
blockType: BlockType.COMMAND,
text: '【設定5】storageBucket は [TEXT] を使う',
arguments: {
TEXT: {
type: ArgumentType.STRING,
defaultValue: "Firebase SDK snippetから貼り付けてね"
}
}
},
{
opcode: 'setMessagingSenderId',
blockType: BlockType.COMMAND,
text: '【設定6】messagingSenderId は [TEXT] を使う',
arguments: {
TEXT: {
type: ArgumentType.STRING,
defaultValue: "Firebase SDK snippetから貼り付けてね"
}
}
},
{
opcode: 'setAppId',
blockType: BlockType.COMMAND,
text: '【設定7】appId は [TEXT] を使う',
arguments: {
TEXT: {
type: ArgumentType.STRING,
defaultValue: "Firebase SDK snippetから貼り付けてね"
}
}
},
{
opcode: 'setMeasurementId',
blockType: BlockType.COMMAND,
text: '【設定8】measurementId は [TEXT] を使う',
arguments: {
TEXT: {
type: ArgumentType.STRING,
defaultValue: "Firebase SDK snippetから貼り付けてね"
}
}
},
{
opcode: 'setText',
blockType: BlockType.COMMAND,
text: '[PATH] の [VALUENAME] に [TEXT] をセット',
arguments: {
PATH: {
type: ArgumentType.STRING,
defaultValue: "データパス"
},
VALUENAME: {
type: ArgumentType.STRING,
defaultValue: "データ項目名"
},
TEXT: {
type: ArgumentType.STRING,
defaultValue: "データ値"
}
}
}
],
menus: {
}
};
}
setApiKey(args)
{
firebaseConfig.apiKey = Cast.toString(args.TEXT);
}
setAuthDomain(args)
{
firebaseConfig.authDomain = Cast.toString(args.TEXT);
}
setDatabaseURL(args)
{
firebaseConfig.databaseURL = Cast.toString(args.TEXT);
}
setProjectId(args)
{
firebaseConfig.projectId = Cast.toString(args.TEXT);
}
setStorageBucket(args)
{
firebaseConfig.storageBucket = Cast.toString(args.TEXT);
}
setMessagingSenderId(args)
{
firebaseConfig.messagingSenderId = Cast.toString(args.TEXT);
}
setAppId(args)
{
firebaseConfig.appId = Cast.toString(args.TEXT);
}
setMeasurementId(args)
{
firebaseConfig.measurementId = Cast.toString(args.TEXT);
}
setText(args) {
const path = Scratch3Realtimedb.parsePathInput(args.PATH);
const valueName = Cast.toString(args.VALUENAME);
const text = Cast.toString(args.TEXT);
var data = {};
data[valueName] = text;
this.realtimeDb.ref(path).set(data);
}
}
module.exports = Scratch3Realtimedb;
※アナリティクスを利用する場合はコメントアウトの箇所を有効にします。
最低限の実装ができたら、それを機能の一覧に登録するために記述を追加。
const builtinExtensions = {
...(中略)...
realtimedb: () => require('../extensions/scratch3_realtimedb')
};
では、ローカルで動作確認してみます。ビルドしてスタート。
cd C:\Users\kami_teru\source\repos\scratch\scratch-vm
yarn install; yarn link
cd C:\Users\kami_teru\source\repos\scratch\scratch-gui
yarn link scratch-vm; yarn install
yarn start
一度目はFirebase認証を通すだけになるので、Realtime Databaseへの書き込みは失敗するようです。
でもこれでWebサイトとしての認証が通りました。
これと同じ手順を、Github Pagesでも行います。デプロイ。
yarn run build
yarn run deploy
同じように、Github Pagesに公開した Scratch からも Realtime Database に書き込めることが確認できました。
Realtime Database 拡張機能 の本実装
以下の技術情報を参考に、さらに機能を付け加えていきます。
- https://firebase.google.com/docs/web/setup?hl=ja#node.js-apps
- https://firebase.google.com/docs/database/web/start?hl=ja
- https://firebase.google.com/docs/database/web/read-and-write?hl=ja
以下、実装コードは、github のリンクから併読ください。
機能 | ブロックイメージ | ブロック情報 | 実装 |
---|---|---|---|
データ階層の表現 | ![]() |
getInfo | concatPath |
文字データの送信 | ![]() |
getInfo | setText |
データ変更の監視 | ![]() |
getInfo | listen |
データ追加の監視 | ![]() |
getInfo | listenChildAdd |
データ受信の判定 | ![]() |
getInfo | whenReceived |
文字データの取得 | ![]() |
getInfo | receiveText |
追加された子階層名の取得 | ![]() |
getInfo | receiveChildKey |
ではいよいよ、これを使い方を示すものとなる参照実装を行います。
Realtime Database 拡張ブロック の参照実装
あいさつをほかのユーザーと共有してみた
まずは指定したパスの「データ変更の監視」と「データ受信の判定」と「文字データの取得」を中心に確認。
こんなプログラムにしてみました。
動かしてみましょう。
動作を確認するために、簡単なページを作りました。
※Github-Pagesのscratch-guiをiframeで呼び出してちょっと小細工したものです。
(2)で表示されたあいさつが、(1)のほうにも表示されましたね😄
どんどんいきましょう。
ユーザーが部屋に入ったらキャラクターを表示するようにしてみた
つぎは指定したパスへの「データ追加の監視」と「追加された子階層名の取得」を中心に確認。
プログラムはこんな感じ。
ねこ | おともだち |
---|---|
![]() |
![]() |
動かしてみましょう。
おぉぉ!お友達が部屋を訪れましたね!!😆
じろうさんの部屋にも、たろうさんがちゃんといます。
どんどん動かしてみた/つぶやけるようにしてみた
今度は Realtime Database拡張ブロックは使っていませんが・・・つぶやく機能を追加。
ねこ(追加分) | おともだち |
---|---|
![]() |
変更なし |
おぉぉぉ、なかなかそうだいな画になってきましたね🤣
さらに20人追加してみましょう。性能テストですね。
ともだちがいっぱいでも大丈夫!🤣🤣🤣
これで好きな部屋に入って、会話を楽しみむことが出来ますね!!
でも・・・
あれっ?
こんなアプリ、どこかで見たような・・・
🦀🦀🦀 - 完 - 🦀🦀🦀
おわりに
例のパロディ作品のパクリでした(汗
なお今回作ったものは、以下の場所で公開しています。