⚔️

『RPGツクールMZ』[スクリプト]の使い方基礎

2021/12/27に公開

『RPGツクールMZ』関連記事 目次

『RPGツクールMZ』は JavaScript というプログラミング言語で作られています。
普通はその辺は気にせずに、エディタに用意された[イベントコマンド]を使っていればゲームは作れます。
ただ、ちょっとかゆいところに手が届かないし、そこらを解消してくれるプラグイン(機能拡張)もみつからない。
そんな時に[スクリプト]イベントコマンドを使って、ちょっと JavaScript を書けば解決することもたくさんあります。
あと…[移動ルートの設定]の中に[プラグイン]コマンドがないので、しょうがなく[スクリプト]コマンドを使うこともあります。とほほー。

公式ヘルプの機能説明には「テキストをJavaScriptとして評価します。」とだけ書いてあります。
いや、こんなんでわかるわけねぇ!!!

というわけで今回は[スクリプト]を使う際の基礎知識的なものを書いていきます。
JavaScript を書くんだから JavaScript の勉強すればいいんですけど、そこまではちょっと…別にプログラマになりたいわけじゃないので。
という感じの方を対象に、JavaScript入門に書かれているようなことはすっ飛ばして、「コピペしてそれっぽい数字とかいじる」というところまでいければと思います。

JavaScriptそのものを勉強したい方は、次のオンライン講座をどーぞ!

ちなみに、スクリプトってプとリを逆にしてスプリクトって発音する人多いんで気をつけてください。スクですスク、両面宿儺のスク!強そう(呪並感)

参考になるスクリプト集

すでにあちこちに便利なスクリプト例が公開されているので、スクリプトはサンプル集からいただいてきましょう。
この記事は『RPGツクールMZ』向けですが、一応『RPGツクールMV』の方のスクリプトを書いてあるページへのリンクも用意しました。

敬称略

著作権について

人が書いたプログラムをコピーして使っていいのか?ということ気になりませんか。
そこ気になった人!ナイス着眼点!その気持ちを大切に、人の作品を勝手に使うことを許すな!

で、スクリプトです。
俳句に著作権が認められるので不安になるかもしれませんが、数行程度のプログラムで著作権を主張できた例は、今の所聞いたことがありません。
一般的に「単なる情報であり、思想心情の表現といった創作物ではない」と判断されているようです。

とくに先ほどのリンク先のページは「コピーして使うことを前提に公開されている」ものなので安心してコピペしまくってください。
ゲームを公開する時の著作権表示もなくて構いませんが、スペシャルサンクスにスクリプト集の作者名を入れておくと、なんかハクがついた感じがしていいと思います。一人で開発しているとエンディングのスタッフロールが寂しいですしね(笑)

ちなみに、サンプル集であってもページ丸ごとコピーして公開とかすると、流石にアウトです。
あとプラグインのようにスクリプトを公開する場合、質問があったときに答えられなくて汗かくので、人のコードを参考にするときも、ちゃんと理解してからやろう!
なお、自分でスクリプト書いたのに質問に答えられないことも、割と良くあります (笑)

スクリプト集の使い方

スクリプトをコピーして貼り付けて改造。
まず最初は、意味はわからんが「動けばよかろうなのだッ」という感じで使えばいいんじゃあないかな。
スクリプトを貼り付けられる箇所は意外とたくさんあって、大きく値を戻すタイプと戻さないタイプに分けられます。
そういう値を返り値(かえりち)とか戻り値(もどりち)とか言います。結果、って書く場合もあります。

では、その辺を前提にスクリプトを書いていける場所を紹介します。

イベントコマンド

まずマップ[イベント]もしくは[コモンイベント]の[実行内容]、あるいは[データベース]-[敵グループ]-[バトルイベント]から開ける[イベントコマンド]ウィンドウの中に、その名もずばり[スクリプト]というボタンがあります。


[3]-[上級]-[スクリプト]


[スクリプト]ボタンを押すと出現するウィンドウです。ここに JavaScript を書いて…というか貼り付けて行きます。
なお alert( "Hello World" ); とあるのは適当に書いた JavaScript で、中央にあるのはコンテキストメニューです。

以後、[スクリプト]イベントコマンド、と書きます。
返り値はありません。

移動ルートの設定

次にマップ[イベント]もしくは[コモンイベント]の[移動ルートの設定]の中に[スクリプト]があります。


[2]-[移動]-[移動ルートの設定]


[移動コマンド]-[スクリプト]


だいぶ小さいですが、機能は[スクリプト]イベントコマンドとほぼ同じでコンテキストメニューも開きます。

以後、[スクリプト]移動コマンド、と書きます。
返り値はありません。

自律移動カスタムのルート

次にマップ[イベント]の[自律移動]のところに[スクリプト]があります。


[自律移動]-[タイプ]-[カスタム]を選択した際に下に出る[ルート]


[移動ルートの設定]イベントコマンドにある[スクリプト]とほぼ同じですが、左上の対象のキャラクターを指定できないのが大きな違いです。
以後、[スクリプト]移動コマンド、と書きます。
あれ?前のやつと一緒じゃない?と思ったかもしれません。だいたい一緒です。
必要なときだけ、自律移動の[スクリプト]、と書きます。
返り値はありません。

変数の操作

次にマップ[イベント]もしくは[コモンイベント]、[バトルイベント]で開ける[イベントコマンド]ウィンドウの[変数の操作]中に[スクリプト]があります。


[1]-[ゲーム進行]-[変数の操作]


[オペランド]-[スクリプト]

以後、変数の[スクリプト]、と書きます。
返り値があり、指定した変数に設定されます。

条件分岐

最後にマップ[イベント]もしくは[コモンイベント]、[バトルイベント]で開ける[イベントコマンド]ウィンドウの[条件分岐]中に[スクリプト]があります。


[1]-[フロー制御]-[条件分岐]


[4]-[スクリプト]です。
以後、条件の[スクリプト]、と書きます。
返り値があり、それに従って分岐が行われます。

計算式

最後と言いましたがもう1つ!
実は[データベース]-[スキル]-[ダメージ]にある[計算式]、あれ JavaScript です。
あらかじめ値の入った ab が使えます。JavaScript の機能ではない[計算式]特有の機能として v[n] を変数として使えます。
返り値があり、ダメージの数値として使われます。

ということで、終了!
紹介したサイトを巡って、面白そうなスクリプトをコピペして遊んでみましょう!

と、ここで終わってもいいんですが、今回はここからが本番です。


今後のさらなる利用範囲拡大の布石としてRPGツクールMZ 非公式 JavaScriptリファレンスに適宜リンクをしておきますが、いちいち見る必要はありません。
このページをひと通り読んで、ある程度[スクリプト]作りに慣れた後に参照すると良いと思います。

あと、ある程度慣れないと意味わからない部分も多いと思うので、すっ飛ばして読めばいいです。

スクリプトの書き方で気になる細かい部分

あちこちのスクリプトを見ていると、同じような説明だけど微妙に書き方が違うことがあります。
この辺がはっきりしないと、不安になる人もいると思うので、代表的なところを説明します。

アルファベットの大文字小文字

JavaScript はアルファベットの大文字と小文字を厳密に区別します!
なので aA は別物です。
識別子の大文字と小文字の違いで機能的な差はないのですが、 JavaScript 界では作法として次のようなものがあります。

識別子の例 説明 使われるもの
SampleValue 頭が大文字で大文字で単語区切り クラス
sampleValue 頭が小文字で大文字で単語区切り 変数、関数、プロパティ、メソッド、可変値が代入される定数
SAMPLE_VALUE 全体が大文字で _ で単語区切り 固定値(リテラル)が代入される定数

使われるものの意味はわからなくていいですが、要するに全部違うものなので大文字小文字の打ち間違いに気をつけるようにしてください。
やっぱり安心なのは「コピー&ペースト」です!

なお JavaScript 的にはとくにパターンというわけではないですが『RPGツクールMZ』では次のようなパターンがあります。

識別子の例 説明 使われるもの
Sample_Value 頭が大文字で _ で単語区切り コアスクリプトのクラス
_sampleValue _ に続けて頭が小文字で大文字で単語区切り クラス内部で使うプロパティ
$sampleValue $ に続けて頭が小文字で大文字で単語区切り 大域変数

これらの詳細は別に解説します。

スクリプトの最後の ; について

あちこちで紹介してあるスクリプトを見ると、最後に ; があったりなかったりします。
これ「必要なの?なくてもいいの?」と不安になるかと思いますが、基本的には必要ありません!

; が何かというと「スクリプトを区切るもの」なんです。
で[スクリプト]に書くJavaScriptは短いので、大体は区切りなくても成立するんです。

逆に[移動ルート]や[条件分岐]、[計算式]のように、通常1行しか書けない場合も ; をつけることで複数行を「畳んで」書けるようになります。
返り値がある場合、最後の区切りの結果が返ります。

たとえば[変数の操作]の[スクリプト]に次のように書くと、 ; の区切り毎に順次実行されて、最後の区切りの結果である 20 が返ってきます。

const a = 4;a * a + a;

個人的には長いスクリプトを書くことが多いので、そこでは ; をいつもつけています。
短いスクリプトを書くときも癖でつけるので、このページでは基本 ; 付きで書きます!

結論: つけてたら プロっぽいです ;(セミコロン)

クォーテーションについて

まずクォーテーションってなんだよ!って話ですが、引用符のことですね。セリフとかくくる記号です。
JavaScript では囲った部分がプログラム部分とは別の、文字列データとして解釈されます。
で[スクリプト]の中で出てくる引用符って3種類あるんですよ。

値と操作 機能
'シングルクォート' 文字を囲みます
"ダブルクォート" 文字を囲みます
`バッククォート` 文字を囲みます

…機能一緒やんけ!まぁ落ち着いてください。

"文章の中に'シングルクォート'を使いたい"
'逆に"ダブルクォート"を使いたい'

というように、同じクォートが出てくるまでは囲っている状態だと判断されるので、もう一方のクォートが書けるんですね。
…これのために二種類存在させるのってバカっぽくない?って思いますけど、JavaScriptというのは、そういう作りなので!!
プログラム的にもプログラムコードを文字列として書きたい時ってそこそこあるんですよ、そういう時便利なのです。

さて『RPGツクールMZ』のゲーム本体のスクリプトのことをコアスクリプトと言います。
コアスクリプトでは基本的に " が使われるので、ここでも " を使います。
極力書式をコアスクリプトに揃えておくと、コアスクリプトを読むときに違和感を持たずに読めます(大事)

ところでバッククォートは?ですって!
えらい、よく覚えてました。これは JavaScript 的にはあとで導入された方式で、文字列の途中に JavaScript の処理を埋め込めたり、改行が可能だったり、ちょっと高性能なクォートです。

`こういう感じで番号${id}を埋め込んだり
改行をそのまま書いたりできます。`

なので、バッククォートをダブルやシングルに変更すると動かなくなる可能性があるので気をつけてください。
逆に言えばダブルやシングルでは改行を入れることはできず、\nという特殊な記号を使って改行を表す必要があります。

ちなみに true とか false とか数字とかクォートで囲ってないけどいいの?という疑問がわくかもしれません。
これらは文字列とは別の種類の値なので、そのまま書きます。そういうもんです。
逆に "true" みたいに囲ってしまうと、文字列と判断されて動かなく…なるならまだいいんですが、しばらく正常動作しているように見せて、突然不具合が出るみたいなことになりがちなので、裸のものはそのままにして絶対囲わないように!良かれと思って囲わないように!!

コメントについて

JavaScript では // の後に続く文字は行末まで無視されます。
この部分に注釈をいろいろ書くわけで、これをコメントといいます。
/* と */ で挟むパターンのコメントもありますが、スクリプトのサンプルではあんまり使われてないと思います。

let a = 0;// この部分がコメント
console.log( a );/* この部分もコメント
こっちは改行もできます! */

コメントは実行されるときに無視されるわけですから、コピーしないかコピーした後に削除して構いません。
もちろん無視されるわけなので、そのままにしておいてもいいし、自分の好きなように文字を書き換えてもいいです。

スクリプトの空白(スペース)について

スクリプトには、各所にスペース(空白)が入っていますが、法則があるように見えて各スクリプトで微妙に異なっています。
実は法則はなくて各人の好みで入っています!
プログラムって厳密に書かないといけないイメージありますから、びっくりですね。
ただし単語(識別子と言われます)の途中に空白を入れることはできません。

func ( 12 + 1 , "文字" ) ;

これから空白を抜いて次のように書いても意味は同じです。

func(12+1,"文字");

なお、全角の空白はスクリプトには使えません。文字列データの中やコメントには使えます。

余談

個人的には「単語の前後、コンマなどの区切り記号の後ろ、カッコの内側、数学記号の前後に空白」あと「関数、メソッド、制御文と ( の間に空白は入れない」感じです。

func( 12 + 1, "文字" );

しょーじき、この辺どーでもいいところなんですけど、決めておかないと書くたびに「どうしようかなー」って無駄に悩んでマジで無駄です。
プログラマはしっかり決めて書くのが普通ですし、複数人で仕事するときは全体(場合によっては会社単位)で決めてます。
最近の開発環境だと、大抵は設定に細かく空白の入れ方が指定できて、自動でフォーマットを整えてくれます。便利!

JavaScript の意味がわからなくても、プラグインの中身を見て空白の使い方に一貫性がない場合、ほぼ間違いなく JavaScript の書き方もいい加減です。
プラグインの品質の判定にどーぞ。僕のは「開発環境が自動で整えているので綺麗です!」(笑)

メソッドとプロパティと配列とオブジェクト

…ナニそれ、って感じですよね。
スクリプトを使っていると、似たようなことしているのに書き方が微妙に違うものに出くわすことがあります。

$gameMessage._positionType = 2;
$gameMessage.setPositionType( 2 );

どちらも positionType に 2 を設定しようとしている感じなんですが、この使い分けなんなんでしょう。
他にもカッコも [] だったり () だったりするし…意味わかんないですよね。

これは説明が非常に面倒くさくて、その理由には主に2つあります。

  • ユーザが使うことを想定してない部分を無理に使ってる。
  • 元から、とくに理由なく異なる記法を使って書かれている。

『RPGツクールMZ』は割と使い分けに脈絡がない方だと思います(個人の感想です)
プログラムって、この辺を統一しなくても動くんで!動いちゃうんで!!
細かいこと言うと、どーしてもそう書かざるを得ない、といった場面もあったりしますが、説明しても細かい上に長いし意味わかんないと思います。
なので、ここでの結論は「そういうもんだと思ってあんまり気にすんな!」とゆーことで、ひとつ!!

メソッドとプロパティと配列とオブジェクトという仕組みがあってそれぞれ記法が違います。
これら単語については、そーゆーのがあるんだ程度の理解で、とりあえずいいと思います。
JavaScriptを本格的にやりたくなってから調べてください。

thisについて

スクリプトに頻繁に現れる this という単語ですが、これが何かを説明するのはなかなかややこしいです。
ややこしいのばっかりですね。
『RPGツクールMZ』のスクリプト上に限って言えば、スクリプトを書いた位置によって中身が変わる変数です。

スクリプト位置 this
イベントコマンド Game_Interpreter
移動コマンド Game_PlayerGame_Event
変数の操作 Game_Interpreter
条件分岐 Game_Interpreter

Game_Interpreter はイベントコマンドを処理する仕組みです。
Game_Player は[プレイヤー]キャラです。
Game_Event は名前の通り[イベント]です。
なので、同じthisであっても全然違う性質を持っています。

リファレンス: Game_Interpreter
リファレンス: Game_Player
リファレンス: Game_Event

RPGツクールMZによく現れるパターン

JavaScript としては別にそんな意味はないけど、『RPGツクールMZ』特有の知ってると理解が進む情報を紹介します。

テンキー対応

『RPGツクールMZ』でキャラの向きや移動方向などで方向を指定する場合、数字が使用されます。

テンキー | 向き

7 8 9 ↖︎ ↗️
4 5 6
1 2 3 ↙︎ ↘︎

という対応になっていて、たとえば 4 なら ← 向きというわけです。ちなみに 5 はだいたい無視されます。
これ知ってると割とわかりやすいですが、知らないと「なんで 4 で左?」という疑問を解消するのは難しいと思います。

$が頭についている識別子

スクリプトを見ていると、頭に $ がついている識別子にちょいちょい出くわします。
これは JavaScript 的にはとくに意味はなくコアスクリプト特有の決まり事で、大域(グローバル)変数であることを示す記号です。
大域変数は[スクリプト]イベントコマンド、ルートの設定の[スクリプト]、変数の[スクリプト]、条件の[スクリプト]いずれの場所であっても同じように使える変数です。
またテストプレイ中に[F8]キーで呼び出せる[デベロッパーツール]の[コンソール]からも使えます。

リファレンス: 大域(グローバル)変数の一覧

大文字から始まる識別子

$ が頭についている識別子の他に、大域で使えるものが大文字で始まっている識別子です。
これは JavaScript 的にはとくに意味はないんですが、ほぼみんなが守っているので事実上の標準です。
『RPGツクールMZ』で主なものは次の通り。

識別子 説明
AudioManager 音環境の管理
BattleManager 戦闘の管理
ColorManager 色データの管理
ConfigManager 設定の管理
DataManager データ入力の管理
EffectManager エフェクトの管理
FontManager フォントの管理
ImageManager 画像データの管理
PluginManager プラグインの管理
SceneManager シーンの管理
SoundManager 音声データの管理
StorageManager 保存データの管理
TextManager 文字の管理
Graphics 画像の処理
Input ゲームパッド・キーボード入力の処理
TouchInput マウス・タッチ入力の処理
Utils その他の処理
Video 動画の処理

_が頭についている識別子

スクリプトを見ていると、頭に _ がついている識別子にちょいちょい出くわします。
これはJavaScript 的にはとくに意味はなくコアスクリプト特有の決まり事で、局所(ローカル)的な値であることを示す記号です。
局所といっても、実際は局所でしか使えないわけではなく「_ が付いているのはできるだけ使わないようにしましょうね」ぐらいのゆるいお願い程度の意味しかありません。
(ちなみに $ のついた大域変数はちゃんと大域で使えますが $ がついているから大域で使えるわけではなく、コアスクリプトが大域変数に $ つけるルールを採用しているだけです)
JavaScript は局所に隠蔽する方法にバリエーションがないので、お願いするしかないという悲しい理由です。
実際のところ、あんまり気にせずに使われまくっています(笑)

ですが一応 _namename() があって同じ値が取れるようになっているなら後者のname()を使う方が正当な方法で、動きが異なることもあります。
たとえば受け取る値が整数化されているとか、そういう違いです。
逆にそういう動作が必要ない場合、あえて _name を使っていることがあったりします。
また_name があってもname() がコアスクリプトに用意されていない場合もあり、そういう場合は _name を使うしかありません。
ややこしいですね。

結論としては、コピペで使えば気にすることはないし、書き写すときは _ を抜かさないように気をつけて!
ちなみに、識別子末尾に複数形の s がついている場合も書き写す時に見落としがちなので、こちらも気をつけて。
というか…識別子はとにかくコピペを心がけましょう![⌘C]アンド[⌘V]です!

JavaScriptコンソール

テストプレイ中に[F8](または[F12])キーを押すと[デベロッパーツール]のウィンドウが開かれます。
これを使うことで、さまざまな開発用の調査が可能です。
とくに重要なのは JavaScriptコンソールです。

コンソールを開く

[ヘルプ]-[補助ツールの使い方]-[テストプレイ]には「デベロッパーツールは Google Chrome に搭載されたものと同じ機能です。」と Chrome のヘルプに丸投げです!

Google公式サイトのヘルプを見ればいいんで、問題ないといえばないん…ワオ!ディスイズエイゴ!
とゆーことで、JAVASICIPT.INFO 開発者コンソール をオススメしておきます。
なお実際ブラウザの Chrome で[⌥⌘I]でデベロッパーツールを開けます。[⌥⌘J]だと直接 JavaScript コンソールが開けます。

[デベロッパーツール]はかなり高機能で JavaScript での開発を本格的に行う場合は避けて通れませんし、使えばすごく便利です!
ただできることが多すぎるので、とりあえずここでは[スクリプト]を記述するにあたって知ってると便利、という部分を抜粋してお届けします。

[F8]で開いた[デベロッパーツール]の中で[Console]と書いてあるタブが JavaScriptコンソールです。

DevTools failed to load SourceMap: Could not load content for chrome-extension://njgcanhfjdabfmnlmpmdedalocpafnhl/js/libs/pixi.js.map: System error: net::ERR_FILE_NOT_FOUND

って表示が出てますね。
これ環境(OSとかNW.jsのバージョン)によって多少表示に違いがあるでしょうが、要するに"pixi.js.map" ってファイルがないよ、って表示なんですよ。
<Bad!>このファイルが必要かというと不要なんですけど、ちゃんと動くからってこういう表示をそのままにしておくのは製品としてどうかなって思います。

豆知識

"pixi.js.map" が何かというと、リリース時は不要だけど開発時には必要な情報を結びつける情報が入ったファイルです。
"pixi.js"という JavaScriptのライブラリ(プログラムから使う機能を集めたプログラム)を『RPGツクールMZ』は使っているんですが、ツクールでゲームの開発をする場合にコアスクリプトまでは見ますが、さらにその基盤である pixi.jsライブラリそのものの開発は必要ないので "pixi.js.map" は入ってないのです。

"pixi.js.map" ってファイルに次のような内容を書いておいて、"js/libs/"フォルダに置いておけば、上記エラーは出なくなります。

{
    "sources": []
}

これは見ての通り、これといった内容のないダミーファイルです。

もしくは、"js/libs/"フォルダにある"pixi.js"ファイル末尾のコメントを削除するとエラーが出なくなります。

//# sourceMappingURL=pixi.js.map

なお、この変更を行ったことによる不具合などの保証はしません。
というか、記事全般そうです。変なことになっても知りませんよっ!自己責任でプリーズ!

JavaScript を動かす

コンソールの > が表示されているところをクリックして、 JavaScript を入力・実行できます。
試しに、ごく基本的な計算を行ってみます。

1+1

入力に対し、リアルタイムに結果が表示されます。おおっハイテク!
計算のように答えがわかればいいものではなく、何か他に動作させる必要がある場合は[↩]キーで実行します。
画像などはゲームウィンドウを選択しないと表示が更新されないので注意してください。

コンソールでの this は(ブラウザの) Window が入っています。ざっくりいうと「一番外側」という位置です。
[スクリプト]でこの状態はないので、this を含んだスクリプトのテストはできません。

これじゃあスクリプトのテストはできないような気がしますが、$のついた大域変数などはどこででも使えたことを思い出してください。
そう、大域変数ならコンソールで実行できるのです。
いちいち[スクリプト]イベントコマンドに書いてテストプレイして[実行内容]を動かさなくてもイイ!
サンプルが $ から始まっていたら、まず間違いなく[コンソール]で実行可能なので、活用してどんどん試しましょう。

$gamePlayer.setDirection(6);

マップ上にプレイヤーが表示されている時に、試しにこのスクリプトをコピペして[↩]キーで実行してください。
先ほど書いた通り、ゲームウィンドウを選択するのを忘れずに!
どうですか?かなり JavaScript を身近に感じられたのではないでしょうか。

一度打ち込んだスクリプトは[↑]キーで表示できたり、 JavaScript が持っている識別子や、『RPGツクールMZ』で定義された識別子は補完されます。[↑]と[↓]キーで選んで[tab]キーで決定です。マウス操作でも選べます。
<Nice!>めちゃめちゃ便利!!

もう自分でスクリプトを量産できそうですね!
…そこまではいかないでしょうが(笑) 改造ぐらいだとかなり楽にできると思います。

デベロッパーツールにはエラーが発生した時の対処用の機能も色々用意してあるんですが…説明してると今回の記事の量どころではないので、解説しているサイトを検索してどうぞっ!
正直に言いますと、僕も機能をちゃんと把握してませんっ!!
あと『RPGツクールMV』ではデベロッパーツールがちゃんと動作していないので、ここに書いた手順が実行できないかもしれませんが、このページはあくまでも『RPGツクールMZ』の解説なので悪しからず。

最後に

割とこの「イベントコマンドから スクリプト(JavaScript)」への橋渡しの部分は、ツクールから入った人に対してはほとんどまったくフォローされてなくて、相当な断崖絶壁に感じます。
非常に近くにあるように見えて、実はいったんプラグインをじっくりやった方が近道なのではないか、と思ってしまうぐらいです。

とはいえ、せっかく近くにあるのですから、直接登りたいものです。
この記事でエレベーター設置…とまではいかないものの、階段…まではいかないかな、崖にハーケン打ち込んだぐらいにはなったんじゃないでしょうか?なってない?ロープかけたらハーケンが抜けた?

まぁ…そういうこともあるかもしれません。

レッツエンジョイ!ツクールライフ!(強引に締め)

スクリプトのコピペになれたら、続きの『RPGツクールMZ』[スクリプト]の応用をどうぞ!

Discussion