Luaのざっくり解説は実践制御0だけで終わらせようと思ったけどなんか長くなったのでLua解説2ページ目です。
変数
Val変数
Val変数とは普段モデルを動かすのに使う変数で、Bodyブロック内で指定できるのはVal変数だけです。RC変数とも呼ばれます。
Val変数はみなさんご存知の通り
default
と
max
と
min
と
step
が指定できます。
しかしdefault以外の動作は
全て
Luaで再現できるので、Luaで上限や下限の動作を指定するときはこんな具合に書きます。
Val{
HENSU(min=-999999) }
maxは指定しないと無限(floatの上限=3.4*10^38ぐらい?)、minは指定しないと0になるようです。なんでこんな仕様にした・・・
グローバル変数
Luaで作る変数の一つです。Bodyブロックでモデルを操ることはできませんが、いろいろな情報や状態を記憶しておくのに使えます。
作り方はいたって簡単、こんな具合に書いておくことでグローバル変数が生まれ出ます。
main関数内でも外でも
GlobalVal1 = 10
function main()
out(0,GlobalVal1)
out(1,GlobalVal2)
GlobalVal2 = 20
end
表示結果
10.00
20.00
ちなみに変数名は大文字小文字が区別されるようなので注意。
ローカル変数
グローバル変数に対するのがローカル変数で、かなり一時的な変数です。
グローバル変数と違って
フレームを跨ぐと
電子の海の藻屑と消えます。
フレームの他にもdo-end間(後述)だけで働いたりして、do-end間で作られたローカル変数はendに達すると同じく藻屑です。
作り方はグローバル変数の時の変数名の前に
local
とつけるだけ。
function main()
local Val1 = 30
out(0,Val1)
out(1,Val2)
local Val2 = 40
end
表示結果
30.00
nil
Val2の方は
nil
と表示されています。プログラムは上から下へ順番に処理されるので、Val2は作成された直後に表示もされず電子の海に消えています。
次のフレームでVal2をoutで表示しようとしても、「Val2?そんな奴知らないね」か、「Val2か・・・あいつはもう・・・」と言われます。
ちなみにこのnilとは「この変数はからっぽだよ、役に立たないよ」という意味です。
nilに対して足したり引いたり計算しようとするとエラーです。if文の==だか>だかで比較しようとしてもエラーです。
Val変数に代入すると0になるらしいです。
テーブル型変数
正確にはローカル変数とグローバル変数と対になるような変数ではなく、変数がとりうる形の一つであって、ローカルのテーブル型変数とかグローバルのテーブル型変数とかできます。
テーブル型変数の作り方はこんな感じ。
Table = {6,7,8}
function main()
out(0,Table[0])
out(1,Table[1])
out(2,Table[2])
out(3,Table[3])
end
表示結果
nil
6.00
7.00
8.00
このように{}の中に数字を連ねることでTableというテーブル型変数の中に順番に数字が入っていきます。
中に書き連ねるだけだと1,2,3番目のテーブルに入るようで、0番目のテーブルはnilです。
ちなみに、この「Table[2]」とかの「[2]」部分を忘れてout関数で表示しようとするとRCが
即死
するので注意してください。
こんな感じにテーブル型変数の番号を指定することでテーブルに中身を入れることが出来ます。
Table = {}
Table[0] = 10
Table[-3] = 30
Table[3.1415] = 33
Table["ABC"] = 66
function main()
out(0,Table[0])
out(1,Table[-3])
out(2,Table[3.1415])
out(3,Table["ABC"])
end
表示結果
10.00
30.00
33.00
66.00
[]の中身は相当フリーダムで、0、マイナス、小数、果ては文字列も受け付けます。
それどころかテーブルの中身もなかなかフリーダムで、テーブルの中にテーブルとか文字列とか突っ込めます。
Table = {}
Table[3] = {7,6,5}
function main()
out(0,Table[3][1])
out(1,Table[3][2])
out(1,Table[3][3])
end
表示結果
7.00
6.00
5.00
テーブルの事を
一次元配列
と呼んだりしますが、テーブルインテーブルだと
二次元配列
とか呼んだりします。
このテーブル型変数はこのままではあまりメリットを感じませんが、後述の繰り返し文と組み合わせることで大きな威力を発揮します。
論理型
論理型とは変数の取りうる形の一つで、やたら難しそうな名前ですがプログラミングでは良くあることです。
他の変数のように数字や文字列ではなく、true(真)かfalse(偽)の2つの状態が存在します。
やや抽象的で説明しにくいですが、解説のためにif文に使う条件式をoutしてみましょう。
a = 2
out(0,a==2)
out(1,a==3)
表示結果
true
false
trueとfalseが出てきました。
これをif構文に突っ込んでみましょう。
if true then
out(0,"test1")
end
if false then
out(1,"test2")
end
表示結果
test1
この通り、if trueの方だけが実行されました。if構文の条件式が何であれ、if構文が必要とするのはtrueかfalseだけなのです。
そして、論理型を変数に代入して表示してみましょう。
a = true
b = false
out(0,a)
out(1,b)
if a then
out(0,"test3")
end
if b then
out(1,"test4")
end
表示結果
true
false
test3
こちらも、条件式ではなく変数に代入された論理型でif構文が実行されました。
そしてこの論理型は、いろいろな操作をすることが出来ます。
a = true
b = false
c = a and b
d = a or b
e = not a out(0,c)
out(1,d)
out(2,e)
表示結果
false
true
false
a and b
はaとbの論理積といい、a
と(and)
bがtrueの時にだけtrueになります。
a or b
はaとbの論理和といい、a
か(or)
bがtrueの時にだけtrueになります。
not a
はaの論理否定といい、aがtrueならfalse、aがfalseならtrueになります。aの
逆
ということです。
全体的に抽象的なのでうまく具体的な説明が出来ませんが、 ベン図 とかでぐぐると分かりやすい図が出てくると思います。(丸投げ)
繰り返し文
単純な繰り返し作業はLuaにやらせてしまいましょう。繰り返し文を使いこなせばぐっとプログラムが楽に、強力になります。
for
作り方はいたって簡単、次の通りに書けばループが回り始めます。
for i = 1 , 20 do
out(i,i)
end
表示結果
1.00
2.00
3.00
中略
19.00
20.00
for
の後の「i」がループをまわすために必要な変数名、別に何でもいいんだけど大抵iを使っている。Luaリファレンスでも使ってたし、何かの頭文字なのかな。
次の「1」が「i」の初期値、「20」が終点。
outされた結果を見ればわかるように、1から2,3,4と増えて20になるまでの20回ループしています。
また、outの一つ目の数字(行数指定)にも変数が使えます。タツジン!
for i = 1 , 20 , 2 do
out(i,i)
end
表示結果
1.00
3.00
5.00
中略
17.00
19.00
先ほどの「i = 1 , 20」の後に「2」がつきました。見ればわかるように2づつ増えながら動作します。
while
このループはforと違ってループ回数を指定せず、条件が満たされる限りループを続けます。
if文のように条件式を仕込んで動作させます。
local Val = 55
while Val > 20 do
Val = Val - 10
end
out(0,Val)
表示結果
15.00
「Val > 20」は「Valが20より大きければ」ということで、初期値は55なので条件式が
成立、真、true
を取り、whileループが実行されます。
ループ内でValは10づつ減り、いずれは「Val > 20」が成立しなくなり、ループから脱出します。
フレーム | Val | Val>20 |
0 | 55 | true |
1 | 45 | true |
2 | 35 | true |
3 | 25 | true |
4 | 15 | false |
という具合にValは15まで減ります。
whileはループ条件が満たされている限りずっと回るので、絶対に
false
(条件式が成立しない)にならない式を入れるとまずいことになります。
while true do end
とか書くなよ!絶対だぞ!
_G
これもテーブル型変数なのですが、forと組み合わせるとすごいことになるので最後に紹介します。
_GというテーブルにはVal変数が全て収まっていて、_Gを通して書き換えることが出来ます。
Val{
VAL1()
VAL2()
VAL3()
中略
VAL79()
VAL80()
VAL81()
}
ここに81個のVal変数があります。これをごく簡単なループで動かしてみましょう。
for i = 1 , 81 do
_G["VAL"..i] = 10
end
このループだけで81個の変数が全て書き換わります。
この「"VAL"」と「i」を結んでいる「..」は
文字列結合
する演算子です。
とにかくVAL1、VAL2、VAL3などは「"VAL"..i」と表現でき、数字の両側に文字がある場合も
VAL1ANG、VAL2ANG などを「"VAL"..i.."ANG"」と表現できます。
関数
関数とは
関数、functionとは・・・ 一言で説明するのが難しいので
入力と出力がある便利なもの
ということにしてください。
今までにも
out関数
、
_KEY関数
などがここに登場しています。
基本的な使い方
関数名の後ろには決まって括弧が登場し、そこに何か入力したり入力しなかったりしました。
括弧の中身を
引数
と言います。ひきすうです。いんすうじゃないんだぜ。
そして関数は何かしらの反応を示します。何かしらの数値、文字列その他を返す場合、それを
返り値
と言います。
返り値の利用方法は前述の_KEY関数の項あたりを参照。
_FPS関数、_TICKS関数などは引数を必要とせず、返り値を持ちます。
out関数などは返り値はありませんが画面表示という出力を持ちます。
便利な関数
math.max関数は引数をいくつか取れて、その引数の中で最大の物を返します。
out(0,math.max(2,8,6,5))
表示結果
8.00
同様に最小を返すmath.minや切り上げ、切捨て、三角関数、乱数などいろいろあるので簡易リファレンスを眺めてみてください。
自作関数
これら関数は自作することも出来ます。
書き方は簡単、main関数のように
function 関数名()
~中身~
end
と
他の関数の外
に記述するだけ。
では、Valで記述するmax、minの動作を再現した関数を作ってみましょう。
使うのは
math.max関数
と
math.min関数
です。
HENSU = math.max(MIN,math,min(MAX,HENSU))
これがどう動作するのか見てみましょう。
HENSU
が60、
MIN
が20、
MAX
が40だとする時、
このプログラムは次のようになります。
HENSU = math.max(20,math,min(40,60))
このmin部分だけ見ると
math.min(40,60)
なので最小の値、40になり、その後
math.max(20,40)
で最大の値、40が残ります。
これを使いやすいように関数にまとめてみましょう。
function limit(val,min,max)
return math.max(min,math,min(max,val))
end
これを使うには
HENSU = limit(HENSU,20,40)
この時、使う側の
HENSU,20,40
部分、関数側の
val,min,max
部分が引数にあたります。
引数として「HENSU,20,40」、つまり「60,20,40」が渡され、「val,min,max」に順に代入されます。
それぞれ代入されて「math.max(min,math,min(max,val))」はしめやかに処理され、40が残ります。
最後重要なのが
return
、これで値を
返す
わけです。
ちょっとしたこと
引数が複数指定できるように、返り値も複数指定できます。
返す側は
return 10,20,30
と、カンマで区切ってreturnすればよく、
受け取る側は
a,b,c = 関数()
と、返り値の数だけ変数を用意しておけばよいわけです。