スコープ

変数を定義する場所、方法によって変数の「有効範囲」が変化します。
スコープを知っているとより円滑に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を宣言するときには、コロン":"を使うことに注意。
・変数を使用するときは、その変数を使用する行より前の行で宣言されている必要がある。


Home Back Next