# Arcade SceneControl ArcadeZeroにおけるSceneControlのチュートリアルです。 # はじめよう まず、Arcade0においてSceneControlがどのようにして動作するのかを知り、簡単なスクリプトを書いてみましょう。 SceneControlを動作させるには、譜面のプロジェクトフォルダ(譜面ファイルと楽曲ファイルが置かれている場所)に、「Scenecontrol」(大文字小文字全て一致すること)という名前のフォルダを作成します。これがSceneControlに関わる全てのものが入る場所になります。 ではここでSceneControlコマンドの構文を見てみましょう。 ```lua #aff file: scenecontrol(timing, scenecontrolType, parameter0, parameter1, parameter2, ...); ``` 全てのパラメータ(parameterX)がfloat型~(少数値)~でなければなりません(現時点ではこのようになっていますが、今後のバージョンでstring型~(文字列)~のパラメータにも対応するかもしれません)。どのようなパラメータやコマンドがどのような動作を及ぼすのかは「scenecontrolType」によって決まるので、そのタイプを決める必要があります。 ここでLuaスクリプトの登場です。それぞれのSceneControlタイプにおいて、Arcadeはそのタイプ名と同じ名前の.luaファイルをScenecontrolフォルダの中から呼び出すようになっています(例: 「redline」という名前のタイプであれば、「redline.lua」に対応します)。 特別なluaファイル「init.lua」も存在します。このスクリプトは譜面を読み込む度に毎回実行されます(init.luaが存在する場合)。例えば、あらゆるコマンドを実行するオブジェクトを生成する時などに便利です(arcahv debrisやarcahv distortなど)。 それではまずコツを掴むために簡単なものを作ってみましょう。実際のゲームシーンに画像を取り入れて、SceneControlコマンドでその画像を移動させます。 **注:ここではLuaの構文については解説しません。すでに任意の言語でプログラミングに慣れている方であればスムーズに読み進められると思われますが、初心者の方はこちらの公式Luaチュートリアルを参照することをおすすめします。 https://www.lua.org/pil/contents.html** ## 例1: 画像を移動させる SceneControlコマンドはこのようになっています。 ```lua #aff file: scenecontrol(timing, moveimage, newXposition, newYposition, newZposition); ``` コマンドが呼ばれる度に、コマンドで定義された通りに現在の位置から次の位置へと画像が移動します。タイプが「moveimage」なので、「Scenecontrol」フォルダの中に「moveimage.lua」というファイルを作成する必要があります。こうしたコマンドを動作させるためには、「onAffCommand」という関数を定義しなければなりません。 ```lua function onAffCommand(timing, parameter0, parameter1, parameter2...) end ``` それぞれのSceneControlコマンドのタイミングやパラメータはこの関数に渡されますが、このような書き方である必要はありません。意味ある名前を持つパラメータを渡してみましょう。「moveimage.lua」にこのように記述します: ```lua --moveimage.lua function onAffCommand(timing, newXposition, newYposition, newZposition) ``` このファイル内で必要なことはなんでしょうか?まずは操りたいオブジェクトを取り込む必要があります。ここに操りたい画像(「Sprite」といいます)を1つ用意したとしますが、まだシーンの中にはありません。なのでここで生成してみましょう。 ```lua --moveimage.lua function onAffCommand(timing, newXposition, newYposition, newZposition) Scene.createSprite("image", "image.png") end ``` 「SceneControl」フォルダ内に使用したい画像を置きます(名前はimage.pngでなくても構いません)。それでは.affファイルを開いてコマンドを記述して、Arcadeで開いてみましょう。 ```lua #aff file AudioOffset:0 - timing(0,100.00,4.00); scenecontrol(0, moveimage, 69, 420, 1337); ``` 譜面が読み込まれて画像もシーンの中に現れたと思います。素晴らしい! では、その他のコマンドも試してみましょう。 ```lua #aff file AudioOffset:0 - timing(0,100.00,4.00); scenecontrol(0, moveimage, 69, 420, 1337); scenecontrol(1000, moveimage, 69, 420, 1337); scenecontrol(2000, moveimage, 69, 420, 1337); ``` 譜面をもう一度開いてみましょう。うまくいっているように見えますがログを見るとそうでないことが分かるでしょう(ログは画面左にあるボタンから表示できます)。 追加しようとしているキーがすでに存在していると文句を言われると思います。 これはaffコマンドを実行する度に「image」という新しいSpriteを生成しようとしているためで、同じ名前のものを複数持つことはできないということです。一度Spriteを生成したら、その後はそれをコマンドで操作するだけという流れが理想です。なので、譜面を読み込む度に確実に1度だけ実行される「init.lua」(もちろん「Scenecontrol」フォルダ内に配置します)の中でSpriteを生成するのです。 ```lua --init.lua Scene.createSprite("image", "image.png") ``` これでシーン内に「image」というSpriteを作ることができました。「moveimage.lua」に戻って、ここに先ほどのSpriteを取り込みます。「Scene.getSprite」を使用します。このLuaスクリプトの中でそのSpriteを格納しておく場所を用意する必要があるので、「sprite」という名前の変数を宣言します。 ```lua --moveimage.lua function onAffCommand(timing, newXposition, newYposition, newZposition) sprite = Scene.getSprite("image") end ``` この変数は画像を自由に変化させる操作をすることができます。ここで譜面を開き直してログにエラーが書かれていないことを確認してください。 画像を置いておくだけではつまらないので、「SetTranslation(x, y, z)」というメソッドを使用してSpriteを動かしてみましょう。 ```lua --moveimage.lua function onAffCommand(timing, newXposition, newYposition, newZposition) sprite = Scene.getSprite("image") sprite.setTranslation(newXposition, newYposition, newZposition) end ``` それぞれのaffコマンドから渡された引数が、Spriteの位置を指定された通りに変更するよう定義したこの関数に渡されます。 4つの関数が次々に呼び出されるので、.affファイル内の最後のコマンドで書いた座標に画像があることがわかるはずです。色々試してみましょう。 これでもよくできていますが、理想的には時間をかけて移動してほしいものです。しかし、「onAffCommand」内では1つのコマンドにつき1度しか実行されないため、連続的な移動は実現できません。ここで、これを実現するための「register」という重要な関数があります。ここからはこの関数について解説します。 ## ちょっと回り道: Register() つまり、SceneControlが何をしているかというと、オブジェクトを操作しているのです。SceneControlとオブジェクトは1対1の関係ではなく、1つのSceneControlが複数のオブジェクトを操ることができ、複数のSceneControlが1つのオブジェクトを操ることもできます。 すなわち、各オブジェクトに対して、どのSceneControlイベントを実行するかを、いつでも指示できる方法が必要なのです。これはregister()という関数によって行うことができます。各オブジェクトのある時点の時間を読み出し、その間に関数を実行します。 構文: ```lua register(object, timing, duration, function_to_run) ``` これはそのオブジェクトにおいて、timing と timing+duration の間にある時点の時間をfunction_to_runに記述されている関数に渡しています。 ここで気をつけることとして、もしregister関数で登録した複数のイベントの継続時間が重複した場合(例えば、開始タイミング1000で継続時間1000のイベント1と、開始タイミング1500で継続時間1000のイベント2)、先に開始されたイベント1はその継続時間中に開始されるイベント2を実行する際に中止されます(この例の場合では1000〜1500の範囲がイベント1に割り当てられ、1500〜2500の範囲がイベント2に割り当てられます)。 しかし、あるイベントの継続時間が他のイベントの継続時間を囲んでいる場合(例えば、開始タイミング1500で継続時間5000のイベント1と、開始タイミング2000と継続時間100のイベント2)、イベント2の実行が終わった後にイベント1の実行が残りの継続時間内で再開されます。 イベント選択のアルゴリズムの詳細については今後のセクションの中で解説します。先ほどの例の実装に戻りましょう。 ## moveimageに戻ります これで、Spriteを関数に登録することが必要であることが分かりました。それでは自分で関数を作ってみましょう。この関数には同様にSceneControlコマンドのパラメータが渡されることになりますが、最初のパラメータ(timing)はそのコマンドのtimingではなく、楽曲の現在のtimingを表しています。 パラメータの名前は自由に決められますが、一貫した名付け方をしたほうががよいでしょう。関数名も同様で、意味のある名前に決めてください。 ```lua --moveimage.lua function MoveImage(charttiming, newXPosition, newYPosition, newZPosition) end ``` それでは「onAffCommand」にこの関数を追加登録しましょう。継続時間を1秒(1000ミリ秒)に設定します。 ```lua register(sprite, timing, 1000, "MoveImage") ``` 最後のパラメータの「"MoveImage"」は、先ほど自分で作成した関数の名前を意味します。もし関数の名前をHogeHoge(timing, parameters, parameters, ...)のように決めたのであれば、register関数の最後のパラメータには「"HogeHoge"」を入れます。 現時点ではまだこの関数は何もしていないので、Spriteが動き回るようにしてみましょう。以前と同様に「setTranslation(x, y, z)」を使用します。 ```lua function MoveImage(charttiming, newXPosition, newYPosition, newZPosition) local x = (charttiming - BaseTiming) / 1000 * newXPosition local y = (charttiming - BaseTiming) / 1000 * newYPosition local z = (charttiming - BaseTiming) / 1000 * newZPosition sprite.setTranslation(x, y, z) end ``` 「local」という単語に着目してください。localが付けられた変数は他の関数では使用できないようになります。できるだけこのlocalを使用するようにしてください。「BaseTiming」という変数にも着目してください。この変数は自動的にaffコマンド内のtimingの値が渡されていてどの関数でも使用することができます。 ここで一度今まで記述してきたスクリプトの全体を見てみましょう。 ```lua function onAffCommand(timing, newXposition, newYposition, newZposition) sprite = Scene.getSprite("image") register(sprite, timing, 1000, "MoveImage") end function MoveImage(charttiming, newXPosition, newYPosition, newZPosition) local x = (charttiming - BaseTiming) / 1000 * newXPosition local y = (charttiming - BaseTiming) / 1000 * newYPosition local z = (charttiming - BaseTiming) / 1000 * newZPosition sprite.setTranslation(x, y, z) end ``` 譜面を開き直すと画像が動くようになったと思います。素晴らしい! でもなんだかよろしくありません。この計算式だとただ画面中央に現れた後に目的の座標に移動しているだけに過ぎません。移動をする前の座標を取得して、その位置から徐々に次の座標に移動させる処理が必要になります。 移動前の座標を取得する処理は一度だけ実行すればいいので、「onAffCommand」の中に含めるといいということになります。 「getTranslationAt(timing)」を使用して移動前の位置を取得して、変数に代入します。 ```lua function onAffCommand(timing, newXposition, newYposition, newZposition) sprite = Scene.getSprite("image") Register(sprite, timing, 1000, "MoveImage") oldPos = sprite.getTranslationAt(timing - 1) end ``` 「oldPos」はx座標、y座標、z座標の3つの値を持ち、それぞれoldPos.x、oldPos.y、oldPos.zで取得できます。このように記述しましょう: ```lua function MoveImage(charttiming, newXPosition, newYPosition, newZPosition) local x = oldPos.x + (charttiming - BaseTiming) / 1000 * (newXPosition - oldPos.x) local y = oldPos.y + (charttiming - BaseTiming) / 1000 * (newYPosition - oldPos.y) local z = oldPos.z + (charttiming - BaseTiming) / 1000 * (newZPosition - oldPos.z) sprite.setTranslation(x, y, z) end ``` これで意図した通り、移動する直前の位置から目的の位置まで1秒間でオブジェクトが動くようになりました。 おそらく見苦しい計算式が出てきてうんざりしていることかと思います。ですが心配ありません。オブジェクトの移動を実現する度にこのような式を記述する必要はありません。オブジェクトのアニメーション作りを補助してくれる関数をご用意いたしました。 ```lua function MoveImage(charttiming, newX, newY, newZ) local percentage = (charttiming - BaseTiming) / 1000 sprite.setTranslation(Ease.Linear(oldPos.x, newX, percentage), Ease.Linear(oldPos.y, newY, percentage), Ease.Linear(oldPos.z, newZ, percentage)) end ``` もしイージング(曲線移動)に詳しいのであれば説明は不要でしょう。ですが、これがアニメーションを行う際の基本となります。すべてのイージング関数において下限、上限、パーセンテージの3つのパラメータを使用します。この関数は渡されたパーセンテージとイージングのタイプに対応する値を返します。同じように使用できるイージング関数のリストがこの後に掲載されています。 (また、上記のスクリプトでは変数名が長すぎるので短くしておきました。あなたも同じように変数名を短くできます。) 最終的に出来上がったスクリプトは以下の通りです。 ```lua function onAffCommand(timing, newXposition, newYposition, newZposition) sprite = Scene.getSprite("image") register(sprite, timing, 1000, "MoveImage") oldPos = sprite.getTranslationAt(timing - 1) end function MoveImage(charttiming, newX, newY, newZ) local percentage = (charttiming - BaseTiming) / 1000 sprite.setTranslation(Ease.Linear(oldPos.x, newX, percentage), Ease.Linear(oldPos.y, newY, percentage), Ease.Linear(oldPos.z, newZ, percentage)) end ``` これにて最初の例は終わりです! かなり基本的なことばかりで少々時間がかかったかもしれませんが、これを乗り越えられたならばあなたはほとんど理解できていると思います。 ## 例2: redlines 先ほど説明した、コマンドごとにオブジェクトを生成することについて覚えていますか?場合によってはそれがやりたいことにもなるので、名前を重複させずにそれを行う方法が必要です。その方法の一つとしてオブジェクトの名前に番号を付けるというものがあり、この番号はEventIDという変数で取得できます(BaseTimingと同様にどこでも使用できます)。 このテクニックを使ってArcahvの赤線エフェクトを再現してみましょう。まず赤線の画像を用意します(どの方法でも構いません。または練習のための適当な画像でもよいです)。「redlines.lua」を作成してSceneControlタイプを定義することで、affコマンドは以下のようになります。 ```lua scenecontrol(timing, redlines, duration); ``` 実際のArcahvの譜面ファイルにはこのような記述はされていませんがそんなの気にしません。とにかく、「redlines.lua」にはこのように記述します: ```lua --redlines.lua function onAffCommand(timing, duration) redline = Scene.createSprite("redline", "redline.png") register(redline, 0, 1, "Hide") register(redline, timing, 1, "Show") register(redline, timing+duration, 1, "Hide") end function Hide(timing, duration) end function Show(timing, duration) end ``` どの関数にも1ミリ秒しか登録していないことに注目してください。この場合はこれで十分なのです。 まだ名前の重複問題は解決していません。ここで「createSprite」の記述を変更してEventIDを渡してみましょう。 ```lua line = Scene.createSprite("redline"..EventID, "redline.png") ``` 「.\.」は、String型~(文字列)~の結合を表しています。奇妙だとは思いますがとても便利なものです。これで全ての線に独自の名前をつけることができました。 それでは「Hide」関数と「Show」関数も作っていきましょう。これには2つの方法があります:一つ目は透明度を設定する方法、もう一つはオブジェクトを無効化する方法です。 ```lua --set color method: function Hide(timing, duration) redline.setColor(255,255,255,0) end function Show(timing, duration) redline.setColor(255,255,255,255) end --enable/disable method: function Hide(timing, duration) redline.setActive(false) end function Show(timing, duration) redline.setActive(true) end ``` 後者の方法のほうがやや効率がいいのでおすすめです。もし多量のオブジェクトがあるならなおさら、不要になった時に無効化する方法をおすすめします。 加えて赤線の位置をランダムにしてスケールも適当に設定します。それぞれのSpriteで1度だけ行う必要があります。 ```lua function onAffCommand(timing, duration) redline = Scene.createSprite("redline", "redline.png") redline.setScale(1000, 1, 1) redline.setTranslation(0, math.random(-700, 700), 0) register(redline, 0, 1, "Hide") register(redline, timing, 1, "Show") register(redline, timing+duration, 1, "Hide") end ``` これでできましたね! ## 例3: テキスト 画像だけでなくその他のものも扱うことができます。この例では文字列をランダムに生成して左から右に流れるaffコマンドを定義します。 構文: ```lua scenecontrol(timing, livechat); ``` 現行のバージョンでは引数として文字列を渡すことはできないことに気をつけてください。 では、どのようにしてテキストを生成するのかというと... ```lua function onAffCommand(timing) text = Scene.createText("text"..EventID, "kusa", other parameters) y = math.random(250,450) offsetUntilStart = math.random(0,500) duration = math.random(2500,3500) register(text, 0, 1, "Hide") register(text, timing + offsetUntilStart, duration, "MoveAcross") register(text, timing + offsetUntilStart + duration, 1, "Hide") end function Hide(timing) text.setActive(false) end function MoveAcross(timing) text.setActive(true) text.setTranslation(Ease.Linear(-3000, 3000), y, 0) end ``` ここで新しく登場したのは「math.random」関数と「CreateText」関数です。 また、必ずしもaffコマンドのタイミングで更新する必要はなく、ここではイベントをランダムな時間で間を開けることで、変化をつけています。 文字列もランダムにしてみましょう。 ```lua textList = {"kusa", "lol", "ww", "haha"} text = Scene.createText("text"..EventID, textList[math.random(1, #textList)], other parameters) ``` これはLua構文の一部なので、この書き方についてもっと知りたい場合はLuaチュートリアルを参照するとよいでしょう。念の為ここでも少しだけ説明します: - Luaでは、最初の番号が一般的な言語とは異なり、0ではなく1である - 「#textList」はそのリストの要素数を返す ## 例4: スパチャ ここでは、オブジェクトをヒエラルキーにセットすることでどれだけ時間を節約できるか紹介したいと思います。さあ、さっきの例をコピーして背景にイカしたスパチャを表示するよう変更していきましょう! ```lua function onAffCommand(timing) text = Scene.createText("text"..EventID, "kusa", other parameters) y = math.random(250,450) offsetUntilStart = math.random(0,500) duration = math.random(2500,3500) superchat = Scene.createSprite("superchat"..EventID, "superchat.png") superchat.setParent(text) superchat.setTranslation( --tinker around with this-- ) register(text, 0, 1, "Hide") register(text, timing + offsetUntilStart, duration, "MoveAcross") register(text, timing + offsetUntilStart + duration, 1, "Hide") end function Hide(timing) text.setActive(false) end function MoveAcross(timing) text.setActive(true) text.setTranslation(Ease.Linear(-3000, 3000), y, 0) end ``` テキストをスーパーチャットの親に設定することで、スーパーチャットの更新を丸ごとスキップすることができます。スーパーチャットの位置はテキストに従い、テキストを無効化することでスーパーチャットも無効になります。 しかしここで問題が発生します。スーパーチャットにテキストが隠れてしまう可能性があるのです。これを解決するには、setLayerOrder() と setLayerName() を使ってレイヤーを設定してあげる必要があります。 ではArcadeで使われるレイヤーについて解説します。フロアより後ろに位置する「Background」、フロアの前に位置する「Foreground」、そしてSkyinputラインを含む全てのオブジェクトより前に位置する「Topmost」の3つから選ぶことができます。 ポーズボタンとスコアボードよりも手前に画像を配置することは、現状のArcadeZeroのバージョンではできません。 また、同一レイヤー内でもレイヤーオーダーを設定することでどのオブジェクトを前面に表示するか設定することができます。レイヤーオーダーの高いものが前に表示されます。これを使ってみましょう。 ```lua superchat.setLayerOrder(EventID*2) text.setLayerOrder(EventID*2+1) ``` 古いイベントの手前に新しいイベントを確実に出現させるためにここでもEventIDを使用しました。例えばトラックの上にオブジェクトを出現させたい場合、同様に「superchat.setLayerName("Foreground")」や、「text.setLayerName("Foreground")」のように記述します。 ## ゲーム内部品を操作する 例えば、トラックを隠したり、Sky Inputの線を移動させたり、UIをピンクに染めたり...といったことをやりたいとしましょう。 実はこれらは全てSpriteと同じで特に新しく学ぶ必要はないんです。これらのものにアクセスするために何かを生成する必要はありません。以下がゲーム内部品を取得する関数と要素のリストです: #### Scene.getSprite(~[以下の名前をここに記述]~) - "Track" - "CriticalLine" - "DivideLine01" - "DivideLine12" - "DivideLine23" - "SingleLineL" - "SingleLineR" - "SkyInputLine" - "SkyInputLabel" - "Background" #### Scene.getUIPause() #### Scene.getUIInfo() #### Scene.getUICanvas() ※Scene.getUICanvas()はArcadeZero v3.1以降で使用可能 ## ん? これはPhigrosですか?? おっしゃる通りです。これを使えばそれぞれのノーツを回したり動かしたりできるんです。しかし、これを扱うのはとても難しいので、簡潔にまとめておいて、頭の良い人に解決してもらおうと思います(私は含まれませんが)。 基本的には、同じようにしてノーツそれぞれを操ることができます。「getNoteGroup()」関数を使用することで、そのSceneControlイベントが置かれているTiming Groupの中にある全てのノーツを取得することができます。 できることの詳細は下記のリストにあります。ここで、ノーツを移動させたとしても判定位置は移動しないことに配慮してください。ノーツの判定位置がズレている状態にしたくないなら移動させたノーツを元の位置に戻すようにしましょう。 ## おまけのヒント もしSceneControlが全く作動していないようであれば、エラーログを確認してみてください(Arcade内の画面左のパネルにあるボタンから表示できます)。 加えて、自身のスクリプトからログを出力することもできます。出力したいものを返り値(return)として記述してください。 ```lua function onAffCommand(timing, params0, params1): return "Hello world" end ``` Arcadeで譜面を読み込むとaffファイル内のそれぞれのSceneControlコマンドごとに「Hello world」が出力されます。 ここで、出力するものはString型~(文字列)~でなければなりません。もし数値を出力したいのであれば、「tostring(number)」を使用するか他の文字列と結合するなどしてString型に変換してください。 # 全てのオブジェクトと関数 ## 組み込み済みの関数と変数 これらは全て自身のスクリプトでどこでも直接呼び出すことができます。 変数: |変数名|概要| |-|-| |EventID|そのSceneControlイベントのID。スクリプト内のそれぞれのイベントに上から順にIDが昇順で付与されている。IDはSceneControlタイプ別で数えられる。| |BaseTiming|affファイル内のscenecontrolコマンドに最初に渡されている値(timingの値のこと)| 関数: |関数名|概要|返り値| |-|-|-| |getNoteGroup()|そのSceneControlイベントと同じTiming Groupにあるノーツの情報を取得する。|NoteGroupController |register(ControllerBase object, number timing, number duration, string function)|「register()」の解説を参照|Nil| ## 組み込み済みのクラス #### XYZ 3軸の座標の値をまとめて持っているデータ型。他の関数やクラスメソッドは、座標を返す時やパラメータとして座標を取得する時にこのクラスを使用する。 属性(クラスの構成要素) |変数|概要| |-|-| |x|X座標の値| |y|Y座標の値| |z|Z座標の値| 使用例: ```lua xcoord = object.getTranslationAt(t).x --XYZ型の座標を返すgetTranslation関数 object2.setTranslation(x, 0, 0) --別のオブジェクトのX座標を合わせる ``` #### RGBA 色のRGB値と不透明度の値をまとめて持っているデータ型。他の関数やクラスメソッドは、色を返す時やパラメータとして色を取得する時にこのクラスを使用する。 属性 |変数|概要| |-|-| |r|赤色の濃さの値、0〜255の範囲で指定| |g|緑色の濃さの値、0〜255の範囲で指定| |b|青色の濃さの値、0〜255の範囲で指定| |a|アルファの値(不透明度)、0〜255の範囲で指定| 使用例: ```lua sprite = Scene.getSprite("examplesprite") color = sprite.getColorAt(t) --この変数はRGBA型になる return color.r..color.g..color.b..color.a --色の構成要素を出力する ``` #### HSVA RGBAとは違って色の色相、彩度、明度の値をまとめて持っているデータ型。主に色の作業をする際に便利。 属性 |変数|概要| |-|-| |h|色相の値、0〜360の範囲で指定| |s|彩度の値、0〜1の範囲で指定| |v|明度の値、0〜1の範囲で指定| |a|アルファの値(不透明度)、0〜1の範囲で指定| 使用例: ```lua sprite = Scene.getSprite("examplesprite") color = sprite.getColorAt(t) -- RGBA型 hsvcolor = Color.RGBAToHSVA(color) -- RGBA型からHSVA型に変換 hsvcolor.h = (hsvcolor.h + 180) % 360 -- 色相を逆転させる sprite.setColor(Color.HSVAToRGBA(hsvcolor)) -- 色をRGBA型に戻してセットする ``` #### Ease さまざまなイージングタイプ(曲線移動)を提供する静的クラス。全てのイージングのグラフはこちらで見られます: https://easings.net メソッド 全てのメソッドは*start*、*end*、*percentage*をパラメータとして取得し、*start*から*end*の間の値を返す。*percentage*は0〜1の範囲でなければならない。 メソッド名: - Linear - InSine - OutSine - InOutSine - InQuad - OutQuad - InOutQuad - InCubic - OutCubic - InOutCubic - InQuart - OutQuart - InOutQuart - InQuit - OutQuit - InOutQuit - InExpo - OutExpo - InOutExpo - InCirc - OutCirc - InOutCirc - InBack - OutBack - InOutBack - InElastic - OutElastic - InOutElastic - InBounce - OutBounce - InOutBounce 使用例: ```lua x = Ease.OutSine(-1000, 1000, (timing - BaseTiming) / duration) y = Ease.OutBounce(-300, 300, (timing - BaseTiming) / duration) object.setTranslation(x, y, 0) ``` #### Color HSVA、RGBA、カラーコード(#1f1e33など)の3つのカラータイプを簡単に変換できる機能を提供する静的クラス。 メソッド: |関数名|概要|返り値| |-|-|-| |RGBAToHex(RGBA rgbacolor)|RGBAからカラーコードに変換|string| |RGBAToHex(number r,number g,number b, number a)|R、G、B、Aの0〜255の範囲で指定された値の色をカラーコードに変換|string| |HSVAToHex(HSVA hsvacolor)|HSVAからカラーコードに変換|string| |HSVAToHex(number h, number s, number v, number a)|H(0〜360)、S、V、A(0〜1)で指定された値の色をカラーコードに変換|string| |HexToRGBA(string hex)|カラーコードをRGBAに変換。不正な文字列が渡された場合は黒を出力|RGBA| |HexToHSVA(string hex)|カラーコードをHSVAに変換。不正な文字列が渡された場合は黒を出力|HSVA| |RGBAToHSVA(RGBA rgbacolor)|RGBAをHSVAに変換|HSVA| |RGBAToHSVA(number r, number g, number b, number a)|R、G、B、Aの0〜255の範囲で指定された値の色をHSVAに変換|HSVA| |HSVAToRGBA(HSVA hsvacolor)|HSVAをRGBAに変数|RGBA| |HSVAToRGBA(number h, number s, number v, number a)|H(0〜360)、S、V、A(0〜1)で指定された値の色をRGBAに変換|RGBA| 使用例: ```lua hex = HSVAToHex(Ease.Linear(0, 360, timing), 1, 1) text = "<color="..hex..">gaming moment</color>" textObject.setText(text) ``` #### Scene オブジェクトを生成したり、名前からオブジェクトを取り出す機能を提供する静的クラス。 メソッド: |関数名|概要|返り値| |-|-|-| |createSprite(string name, string imagePath[, string blendMode])|「imagePath」から読み込まれた画像であるSpriteをシーン内に生成し、「name」に渡された文字列を名前にして「blendMode」を適用する。(次のいずれかひとつを指定可能:"Add"、"Multiply"、"Darken"、"Lighten"、"Screen"・指定しなければ標準設定となる)|SpriteController| |getSprite(string name)|「name」と一致する名前のSpriteを取得する。|SpriteController| |createText(string name, number width, number height, number lineSpacing, string alignment, bool overflow[, string font])|シーン内にテキストオブジェクトを生成し、「name」に渡された文字列を名前にする。テキストボックスは、「width」(幅) × 「height」(高さ)のサイズとなる。「lineSpacing」は行間の幅を指定する。「alignment」はテキストを寄せる位置を指定する(次のいずれかひとつを指定可能:"UpperLeft"、"UpperCenter"、"UpperRight"、"MiddleLeft"、"MiddleCenter"、"MiddleRight"、"LowerLeft"、"LowerCenter"、"LowerRight")。「overflow」がfalseの場合はテキストボックスからはみ出たテキストが切り取られる。「font」はOSにインストール済みのフォントの名前を指定するとテキストにそのフォントが適用される。|TextController| |getText(name)|「name」と一致する名前のテキストを取得する。|TextController| ## コントローラ コントローラは、Unity内の実際のオブジェクトを参照するサンドボックスです。各コントローラを通して、参照しているオブジェクトを変化させることができます。 複数の種類のコントローラがありますが、それらは全て「ControllerBase」を継承しているため、全てのコントローラで以下のメソッドを使用できます。 #### ControllerBase 全てのコントローラで以下のメソッドを使用できます: |関数名|概要|返り値| |-|-|-| |setTranslation(XYZ xyzcoord)|XYZ型の値の通りにオブジェクトの位置をセットする。|Nil| |setTranslation(number x, number y, number z)|3軸の座標を指定してオブジェクトの位置をセットする。|Nil| |getTranslationAt(number t)|Timing「t」の時点でのオブジェクトの位置を取得する。なお、現在のSceneControlイベントより後に発生したイベントは考慮されない(以降の「get」関数も同様)。|XYZ| |setRotation(XYZ xyzcoord)|XYZ型の値の通りにオブジェクトの回転角をセットする。|Nil| |setRotation(number x, number y, number z)|以下略|Nil| |getRotationAt(number t)||XYZ| |setScale(XYZ xyzcoord)||Nil| |setScale(number x, number y, number z)||Nil| |getScaleAt(number t)||XYZ| |setActive(bool state)|「state」がfalseの場合はオブジェクトが無効になる(見えなくなる)。|Nil| |getActiveAt(number t)||bool| |setParent(controller other[, bool worldTransformStays])|そのオブジェクトの親をセットする。「worldTransformStays」がtrueの場合はこの操作後に自身の座標系を親の座標に変更しない(デフォルトではfalse)。|Nil| #### SpriteController SpriteControllerはControllerBaseの全てのメソッドに合わせて以下のメソッドも使用できます。 |関数名|概要|返り値| |-|-|-| |setColor(RGBA rgbacolor)|画像の色合いをセットする|Nil| |setColor(HSVA hsvacolor)||Nil| |setColor(number r, number g, number b, number a)||Nil| |getColorAt(number t)|Timing「t」におけるオブジェクトの色をRGBA型の値で取得する|RGBA| |setLayerName(string layer)|Spriteのレイヤーをセットする。レイヤーは次の3つ値をとる:"Background"、"Foreground"、"Topmost"(技術的にさらに他のプログラム内部のレイヤー名も使用できますが乱用しないようにしてください)|Nil |getLayerNameAt(number t)||string| |setLayerOrder(number order)|1つのレイヤー内でのSpriteの表示順をセットする|Nil| |getLayerOrderAt(number t)||number| #### TextController TextControllerはControllerBaseの全てのメソッドに合わせて以下のメソッドも使用できます。 |関数名|概要|返り値| |-|-|-| |setText(string text)|リッチテキストに対応。詳細はこちらをご覧ください: https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/StyledText.html|Nil| |getTextAt(number t)||string| |setAlpha(number a)|テキストボックスの不透明度をセットする|Nil| |getAlphaAt(number t)||number| |setLayerName(string layer)|テキストのレイヤーをセットする。レイヤーは次の3つ値をとる:"Background"、"Foreground"、"Topmost" (技術的にさらに他のプログラム内部のレイヤー名も使用できますが乱用しないようにしてください)|Nil |getLayerNameAt(number t)||string| |setLayerOrder(number order)|1つのレイヤー内でのテキストの表示順をセットする|Nil| |getLayerOrderAt(number t)||number| #### NoteGroupController Timing Group内のノーツのグループのコントローラ。NoteGroupControllerはControllerBaseの全てのメソッドに合わせて以下のメソッドも使用できます。 |関数名|概要|返り値| |-|-|-| |setRotationIndividual(XYZ xyzcoord)|それぞれのノーツの軸における個々のノーツの回転角をセットする|Nil| |setRotationIndividual(number x, number y, number z)||Nil| |getRotationIndividualAt(number t)||XYZ| |setScaleIndividual(XYZ xyzcoord)|個々のノーツのスケールをセットする|Nil| |setScaleIndividual(number x, number y, number z)||Nil| #### UIPauseController・UIInfoController ポーズボタンとスコアボードをそれぞれ操作するコントローラ。どちらもControllerBaseの全てのメソッドに合わせて以下のメソッドも使用できます。 |関数名|概要|返り値| |-|-|-| |setColor(RGBA rgbacolor)|UIの色合いをセットする|Nil| |setColor(HSVA hsvacolor)||Nil| |setColor(number r, number g, number b, number a)||Nil| |getColorAt(number t)|Timing「t」におけるUIの色合いをRGBA型の値で取得する|RGBA| #### UICanvasController 上記のUIが設置されているキャンバス(UI用の平面)のコントローラ。ControllerBaseクラスのメソッドと、Sceneクラスの`Scene.getUICanvas()`のみ使用可能。 ※ArcadeZero v3.1以降に対応