ここではRigidChipsにおける制御の前段階として、大まかですがLuaの導入と基本について解説します。
Lua
Lua
とは、リオデジャネイロ・カトリカ大学の情報工学科コンピュータグラフィックステクノロジーグループ TeCGraf によって設計開発されたスクリプト言語である。(byWikipedia)
RigidChips Version1.5.B4で実装されました。
Luaブロック
Luaを使用するにはモデルデータに
Luaブロック
を用意する必要があります。
Luaブロックは、VelブロックやBodyブロックのように"Lua{" から "}"で囲まれた部分で、そのブロック内にLuaを記述します。
Scriptとの違い
モデルを制御する手段として
Script
がRigidChips Version1.0(つまり最初から)導入されていましたが、Luaはこれとはまた違うものです。
Scriptにできることは全てLuaで再現可能で、Luaにしかできないことが多数あります。
具体的には、
ifの入れ子
else
ループ文
関数
外部スクリプトの読み込み
etc...
Luaの方がScriptより拡張性にも優れており、もしどちらも知らないでどちらかを学ぼうとするのなら間違いなくLuaをお勧めします。
Luaの導入
LuaはScriptとは違い何もしないプログラムでも一定のことを書いておくことが必要です。
Luaの基本形はこんな感じです。
Lua{
function main()
end
}
この
function main
とは
main関数
ということで、この「()」から「end」で囲われた部分がmain関数の中身です。
今は深く考えず、
おまじない
だと思って書いておいてください。
はじめてのLua
表示
Scriptでは数値を画面に表示するのにPRINTを使いますが、Luaでは
out関数
を使います。
Lua{
function main()
out(0,"RigidChips")
end
}
表示結果
RigidChips
基本的にLuaの内容はこの"()" から "end"の間に記述します。
「out(」の次の「0」が表示行数で0から24までが指定できます。
「"RigidChips"」の部分が表示する内容で「"」(ダブルクオーテーション)で囲うことで
文字列
になります。
代入
Val変数をとりあえず用意して、BodyでVal変数をAngleか何かに設定します。
Val{
ANGLE()
}
Key{
}
Body{
Core(){
N:Chip(Angle=ANGLE){}
}
}
LuaでVal変数Angleに適当な数値を
代入
してみましょう。
ANGLE = 30
この文での「=」は代入を意味し、変数ANGLEを30にすることを示します。
Luaで変数に代入するときはValブロックでの表記にかかわらず全て大文字で表記します。
ANGLE = ANGLE + 1
もし「=」がイコールという意味であればあり得ない式ですが代入式なので大有りです。
変数ANGLEに変数ANGLEより一つ大きい数を代入する ということでANGLEが毎フレーム(Luaが実行されるたびに)1づつ増えていきます。
_KEY()
KeyブロックではなくLuaブロックで変数を操作してみましょう。
Keyの状態を調べるには
_KEY()関数
を使います。
「_KEY()」の括弧の中に0~16の数値を入れることで数字に対応するキーの状態を取得できます。
画像はデフォルト設定の時のものです。設定でこの対応を変更することが出来ます。
_KEY関数は指定したキーが押されているときに1を、押されていないときに0を
返し
、これを
返り値
と言います。
では、Zキー(デフォルトでは4)の状態を表示してみましょう。
また、キーを押した瞬間だけ1を返す
_KEYDOWN関数
とキーを離した瞬間だけ1を返す
_KEYUP関数
があります。
使い方は_KEY関数と同じなので並べて書いてみましょう。
out(1,_KEY(4))
out(2,_KEYDOWN(4))
out(3,_KEYUP(4))
何もしていないときの表示結果
0.00
0.00
0.00
キーを押したときのそれぞれの動作はこの表の通り。
フレーム | 状態 | _KEY | _KEYDOWN | _KEYUP |
1 | - | 0 | 0 | 0 |
2 | - | 0 | 0 | 0 |
3 | 押 | 1 | 1 | 0 |
4 | 押 | 1 | 0 | 0 |
5 | 押 | 1 | 0 | 0 |
6 | 押 | 1 | 0 | 0 |
7 | - | 0 | 0 | 1 |
8 | - | 0 | 0 | 0 |
9 | - | 0 | 0 | 0 |
このようにキーを押した
最初の1フレームだけ
_KEYDOWNが1になり、キーを離した
次のフレームだけ
_KEYUPが1になります。
これを踏まえて、先ほどのANGLEのモデルでキーを使って変数を操作してみましょう。
ANGLE = ANGLE + _KEY(0) - _KEY(1)
_KEY関数は押されたときに1を返し、そうでないときは0を返すので、
(デフォルトで)↑キーを押したときの動作
ANGLE = ANGLE + 1 - 0
↓キーを押したときの動作
ANGLE = ANGLE + 0 - 1
両方押してる時の動作
ANGLE = ANGLE + 1 - 1
なんとなくわかったでしょうか。ちなみに、_KEY関数に係数をつけてやれば動作速度を変えることも出来ます。
ANGLE = ANGLE + _KEY(0)*5 - _KEY(1)*5
コメントアウト
function main()--ここから行末までコメント
--[[
これで挟まれてもコメント
out(0,"RigidChips")
コメントだからコードも動作しない
]]
end
表示結果なし
このように「--」「--[[]]」によってLuaの動作には関係しないコメントを挟むことができます。
プログラムを分かりやすくする時とかに使えます。
Luaでいろいろやる
if
if、もし
Luaに条件を判断させて動作を変える
構文
です。
以下の説明に都合のいいモデルをご用意ください。
Val{
ARMPOWER()
}
Key{}
Body{
Core(){
N:Jet(Angle=-90,Power=-ARMPOWER){
E:Arm(Angle=90,Power=ARMPOWER,Option=200000,Name=ARMCHIP){}
W:Arm(Angle=90,Power=ARMPOWER,Option=200000){}
}
}
}
コアの前方のJetにArmが2つ前を向いて接続してあります。
変数ARMPOWERはJetとArmのPowerに共通して設定されています。
さて、Armの射撃条件は皆さんご存知だとは思いますが、PowerがOptionと同じか上回る数値になった時にOptionに比例する威力のArm弾が発射されます。
Armの反動はOptionに比例し、チャージ時間もまたOptionに比例し増大します。
Arm発射の瞬間はOptionと同じPowerのJetを噴射したのと同じ力が加わるので、Jetで逆方向にふかしてやれば反動はきれいに消えるはずです。
そのためにはArmがチャージできているか判断する必要があります。
Chipの状態を知るための関数はいろいろありますが、今回はチャージ状況を知る
_E関数
を使います。その他の関数については簡易リファレンスをどうぞ。
_E関数を表示させてみましょう。括弧内にChipの名前(番号)を入れることでChipのチャージ状況が
返り
ます。
out(0,_E(ARMCHIP))
表示結果
200000.00
数字はもりもり増加して200000、ArmのOptionと同じ数字をさすはずです。
ARMCHIPとはBodyブロックでName=ARMCHIPと指定した
変数
です。Chipには全て番号が振ってありますが、Nameを指定することで番号ではなく名前で使うことが出来ます。
ちなみに、「ARMCHIP」という名前は数字に張ったラベルなので、表示しようとすると何番のChipなのか知ることが出来ます。
out(1,ARMCHIP)
表示結果
2.00
ARMCHIPと名前のついたChipは
2番
のようです。コアは0番なので0,1,2と番号が振られた
3枚目
のChipです。
ではいよいよif文の登場です。if文に
判断
させるには、各種条件式を使います。
a==b | 等しい |
a~=b | 等しくない |
a>b | aがbより大きい |
a<b | aがbより小さい |
a>=b | 等しいかaがbより大きい |
a<=b | 等しいかaがbより小さい |
チャージ出来ているときは_E(ARMCHIP)が200000の時ですから、このように書けるはずです。
if _E(ARMCHIP)==200000 then
ARMPOWER = 400000
end
「ARMPOWER = 400000」の部分は、見ての通りArmが2つあるため200000の2倍の出力でJetをふかします。
しかしこれではチャージが出来たら無条件で発砲してしまいます。そこで
and
の登場です。
if _E(ARMCHIP)==200000 and _KEY(4)==1 then
ARMPOWER = 400000
end
名前からして大体わかると思いますが、andを使って条件式を並べることで2つどちらも満たされたときだけ式が実行されます。
これで4番キー(デフォルトならZ)を押したとき、
尚且つ
チャージが完了したときにARMPOWERが400000になります。
これで全てが解決かというともう一つ問題があり、この変数ARMPOWERにはstepもmaxも設定してありません。
そこで自分で変数を元に戻しておく必要があります。そこで今度は
else
が登場します。
elseとは
さもないと
とかいう意味で、「Hand it over, or else!」(それをこっちに渡せ、さもないと)みたいな脅しにも使えるようです。
この脅し文句はifと対になるendの手前に記述します。
if _E(ARMCHIP)==200000 and _KEY(4)==1 then
ARMPOWER = 400000
else
ARMPOWER = 0
end
これで、「ArmをチャージしてZキーを押せ、さもなくばARMPOWERは0だ!」ということになり、発射時以外はARMPOWERが0に落ち着きます。
_E関数の値はOptionまで上昇するので、このOptionも関数で取得してしまえば汎用性が生まれます。
if _E(ARMCHIP)==_OPTION(ARMCHIP) and _KEY(4)==1 then
ARMPOWER = _OPTION(ARMCHIP) * 2
else
ARMPOWER = 0
end
こんな具合。