スコープ
変数を定義する場所、方法によって変数の「有効範囲」が変化します。
スコープを知っているとより円滑にACSを作ることができます。
スコープとは、変数の有効範囲(scope)を意味します。
ACSには4種類のスコープが存在しています。
Script Scope
まずは例を見てみましょう。
#include "zcommon.acs"
Script 1 ENTER
{
int a = 1;
print(s:"a in script 1 is ",d:a);
//前置詞が間違っているのは許して下さい。
delay(35*2);
ACS_Execute(2,0,0,0,0);
//Script2を実行
delay(35*2);
print(s:"a in script 1 is ",d:a);
}
Script 2 (void)
{
int a = 2;
print(s:"a in script 2 is ",d:a);
}
これを実行すると、
![]() |
↓ |
![]() |
↓ |
![]() |
と表示されます。ACSが実行される順番は下図を参考にして下さい。
このACSではScript 1とScript 2の両方に変数aが存在していますが(例の赤い字の部分)、お互い影響し合っていないことがわかります。
このように、Script(または関数)の中(のいかなる所)で宣言された変数はそのScriptの中でのみ使用することができ、
この有効範囲(スコープ)をScript Scopeと呼びます。別のScript Scopeを持った変数と全く同じ名前を持っていても、互いに全く影響し合いません。
このScript(または関数)の外部からこの変数の使用したり、値を代入することはできません。
(これだけ聞くと不便そうに聞こえますが、ScriptScopeの変数を使うときは、宣言されたScript(または関数)のことをのみを考えれば良いので、
別のScript(または関数)で名前が同じ変数を宣言しても良いので、非常に便利です。)
Map Scope
先ほどの例を次の様に書き換えてみましょう。
#include "zcommon.acs"
int a = 4;
Script 1 ENTER
{
print(s:"a in script 1 is ",d:a);
delay(35*2);
a = 3;
//ここでaの値が3に変わる。
ACS_Execute(2,0,0,0,0);
delay(35*2);
print(s:"a in script 1 is ",d:a);
}
Script 2 (void)
{
print(s:"a in script 2 is ",d:a);
}
これを実行すると、
![]() |
↓ |
![]() |
↓ |
![]() |
と表示されます。ACSの実行される順番は先ほどの例と同じです。
変数aをScriptの外で宣言すると、どちらのScriptにも同じ変数が使用されていることがわかります。
このように、Script(または関数)の外で宣言された変数はそのACSファイルの中(の変数が宣言された場所より後の行)すべてで使用することができ、
この有効範囲(スコープ)をMap Scopeと呼びます。(ただし、Libraryで宣言されたMap Scopeを持った変数の有効範囲は、そのLibraryを利用したACSまで及びます。)
要するに、Script Scopeの有効範囲は変数が宣言されたScriptだけだったのに対し、Map Scopeは有効範囲がACS全体です。
※その5で紹介したように、配列はMap Scopeである必要があります。
World Scope
まず、次の例を見てみましょう。
一つのWADファイルに、MAP01とMAP02が存在し、MAPINFOによってこの二つのMAPがhubで繋がっていることが前提です。
MAP01のACSは次の様に記述します。
#include "zcommon.acs"
world int 1:this;
Script 1 ENTER
{
this = 2;
}
MAP02のACSは次の様に記述します。
#include "zcommon.acs"
world int 1:this;
Script 1 ENTER
{
print(d:this);
}
ゲームを@MAP01から始めてMAP02に移動すると(クリアすると)、画面に
と表示されます。
次に、AゲームをMAP02から開始すると、画面に
と表示されます。
一体どのようなことがおこっているのでしょうか。
赤い字の部分の変数thisの宣言を見てみましょう。
world int 1:this;
このように変数thisをScriptや関数の外で宣言したとき、変数thisの有効範囲はhubで繋がっているMAPとなり、この範囲をWorld Scopeと言います。
(複数のMAPをまたいで変数を扱うことができます。)
ただし、この変数を使用するMAPごと(のこの変数を使用する行より前の部分)にこの宣言を書く必要があります。
このように変数を宣言したとき、変数の値が定まっていないときは、変数の値は0に初期化されます。
(異なるhubに入るとWorld Scopeの変数は初期化されます。)
一般的なWorld Scope変数の宣言の仕方は、
world (変数の型) (番号):(変数の名前);
です。間に":"(コロン)があることに注意しましょう。(番号)によって、変数を特定するので、
MAP01で
world int 1:this;
と記述し、MAP02では
world int 2:this;
と記述すると、この二つの変数は別の物になります。
※番号が同じであれば、hubで繋がっているMAPでWorld Scopeの変数の名前が違っていても、同一の物と見なされます。
ただし、混乱のもとになるので同じ名前にしましょう。
先ほどの例を考えます。
@を実行すると、MAP01で変数thisの値が0から2に変わって、MAP02で変数thisの値2を出力しています。
Aを実行すると、いきなり変数thisの値を出力するので、0が画面に出力されます。
ちなみに、MAP01とMAP02がhubで繋がっていないようにすると、どちらのMAPからゲームを始めても、スコープが異なるので、変数thisは別物とみなされ、
となります。
Global Scope
さきほど、World Scopeの有効範囲は、hubで繋がったMAPのACSでしたが、
Global Scopeの有効範囲はすべてのACSになります。
先ほどのMAP01とMAP02の例を変更してみましょう。
今度は、この二つのhubを別の物にしてみましょう。
そして、それぞれのACSを次の様に変更します。
MAP01のACSは
#include "zcommon.acs"
global int 1:this;
Script 1 ENTER
{
this = 2;
}
MAP02のACSは
#include "zcommon.acs"
global int 1:this;
Script 1 ENTER
{
print(d:this);
}
ゲームを@MAP01から始めてMAP02に移動すると(クリアすると)、画面に
と表示されます。
次に、AゲームをMAP02から開始すると、画面に
と表示されます。
このように、変数をScriptや関数の外で
global (変数の型) (番号):(変数の名前);
と宣言すると(コロン":"に注意)、その変数の有効範囲はGlobal Scopeとなり、すべてのACSでこの変数を使用することができます。
つまり、World Scopeの有効範囲の「同じhub」という条件がなくなったということですね。
まとめ
スコープの種類 | 宣言の仕方 | 有効範囲 |
Script Scope | Scriptや関数の中で普通に宣言。 | 宣言されたScript |
Map Scope | Scriptや関数の外で普通に宣言。 | 宣言されたACS(とLibrary) |
World Scope | Scriptや関数の外で world (変数の型) (番号):(変数の名前); |
同じhubの関係にあるMAPのACS |
Global Scope | Scriptや関数の外で global (変数の型) (番号):(変数の名前); |
すべてのMAPのACS |
・World ScopeとGlobal Scopeを宣言するときには、コロン":"を使うことに注意。
・変数を使用するときは、その変数を使用する行より前の行で宣言されている必要がある。