Scripting/GML-Overview/Scope

Last-modified: 2018-12-26 (水) 12:01:25

変数と変数のスコープScope

 

他のプログラミング言語と同様に、GMLはほとんどのプログラミング操作の基本単位として変数を使用します。変数は、後で(または即時に)使用するためにデバイスのメモリに情報を格納するために使用され、関数やスクリプトで参照できるように名前が付けられています。GMLの変数には、実数(100、2.456575、-56など)、文字列( "Hello world!"など)、整数(1、556、-7など)など、さまざまなデータ型を格納できます。 )、またはブール値(trueまたはfalse)。

 

変数とは、1つ以上の操作または関数で使用するために値を格納するために使用するものです。たとえば、 "π"を考えてみてください。これは、3.14159265(など)の値を保持する実世界の変数です。どうして?ええと、「3.14159265…」と言うよりも、誰かに「π」と言う方がはるかに簡単です。それで、物に名前を付けることは人生をずっと簡単にします、そしてそれは、その変数の値が変わっても変数名がまだ同じであるので、我々はどこでも数を変える必要がないことを意味します。GMLでは、変数の名前は英字で始まる必要があり、英字、数字、およびアンダースコア記号「_」のみを最大64文字までの長さに含めることができます。したがって、有効な変数はfish、foo_bar、num1のようなもので、無効な変数は6fish、foo bar、または*numになります。

 

現在、多くのプログラミング言語では、使用する前に変数を「宣言」する必要があります。これは基本的に、あなたがその変数に保持することに決めたどんな値でも格納するために、メモリ内の場所を割り当てることができるようにあなたが使いたい名前をコンピュータに言うことを意味します。GMLでは、変数の範囲に依存するため、これは必ずしも必要ではありません。GameMaker Studio 2を使用してプログラムを作成するときには4つの主な変数カテゴリがあり、それぞれ独自のスコープを持ちます(これはその操作の範囲、または範囲と見なすことができます)。これらの変数とその範囲は以下の通りです。

 

インスタンス変数

インスタンス変数はオブジェクトのインスタンス内で作成され、そのインスタンスに固有のものと見なされます。つまり、同じオブジェクトの多くのインスタンスは同じ変数を持つことができますが、各変数はそれぞれのインスタンスに固有なので異なる値を持つことができます。しかし、インスタンス変数はどのように作成されますか?この小さな例に示すように、単純に変数に値を代入することで新しい変数を作成します。

potions = 12;
life = 100;
name = "Jock MacSweeney";
strength = 5.5;
armour = -2;

ご覧のとおり、名前を指定してから変数(数値または文字列)を設定し、コーディングしているオブジェクトのインスタンス内で使用できるようにするだけです。これらの変数は、インスタンス内からさまざまな方法で使用および変更できます。たとえば、次のコードは衝突イベントの中にあり、変数「life」の量を減らすのに使用できます。

life -= 5 + armour;

「life」が100であれば、97の値になります(100 - (5 + -2)= 97)。さて、これは簡単な例です。実際の値の-2を 「armor」に置き換えることもできますが、その値を複数の場所で使用してから変更するとどうなりますか?あなたはすべてのコードを見て、新しい値が何であれ、-2をすべて変更する必要があるでしょう。しかし、変数を使用する場合、それを新しい値に再割り当てするだけで、コードはそれ以降その新しい値を自動的に使用するようになり、問題が発生した場合の処理​​がはるかに柔軟になり、はるかに簡単になります。たとえ値が変わらないとしても、単に数値を見るよりも、「人生」と呼ばれる変数が何を意味するのか覚えておく方がはるかに簡単であることにも注意してください。

 

GameMaker Studio 2には「組み込み(built in)」のインスタンス変数のコレクションもありますので、自分のインスタンス変数の1つに同じ名前を付けたり、自分のグローバル変数に同じ名前を付けたいのであれば、それらを知っておく必要があります。エラーが発生しています。しかし、それらはコードエディタでは異なる色で表示され、下部のオートコンプリートバーに表示されるため、見つけやすいです。

 

インスタンス変数を扱うときに役立つように設計された2つの関数があります(主にインポートされたプロジェクトのための互換性スクリプトとドラッグアンドドロップアクションのためのコードですが、他の場所でも使用できます)。

 
  • variable_instance_exists
  • variable_instance_get
  • variable_instance_set
  • variable_instance_get_names
 

ローカル変数

ローカル変数は、特定のイベントに対してのみ作成し、イベントが終了したときに破棄する変数です(これに対する唯一の例外は、スクリプトリソースで、var宣言された変数はスクリプトに対してローカルであり、その後破棄されます)。なぜ必要なのでしょうか。変数はメモリ内のスペースを占有するため、1つの操作または関数にのみ使用することになる場合もあります。その場合は、使用されている短時間だけメモリ内に格納する必要があります。これはあなたのコードベースを清潔できちんとした状態に保ち、同時にそれを必要とするもののために最適化されたメモリ空間を保ちます。ローカル変数を宣言するには、次のように関数varを使用します。

var i, num, str;
i = 0;
num = 24.5;
str = "Hi there!";

上記で作成されたすべての変数は、それらが作成されたイベント(またはスクリプト)の終わりに「忘れられ」(つまり、メモリから削除され)ます。var宣言された変数に付ける名前が、コードを実行しているオブジェクト内の別のインスタンス変数と一致しないように注意する必要があります。また、イベントの外側でその変数に格納された値を使用する意図をもたないようにしなければなりません。これらの変数はプログラム、特に繰り返し回数を数えるためのループ、または1回の操作で複数回値を使用するときに繰り返し使用されることがない場合によく使用されます。これはまた別の、2つ目の例です。

var i = 0;
repeat (10)
   {
   inventory[i] = 0;
   i+=1;
   }

上記のコードは、 "i"というローカル変数を作成し、それを0に設定します。すべて同じ行にあります。以前のバージョンのGameMakerでは、最初にローカル変数を宣言してからそれらに値を割り当てる必要がありましたが、このバージョンでは同時に宣言して値を割り当てることができます。上記のコードは、この変数を使って配列を初期化します。これ以外のインスタンスでは、変数 "i"は他の関数に使用されないため、スコープ内でローカルにすることができます。もう1つ例を挙げましょう。

var xx,yy;
xx = x - 32 +irandom(64);
yy = y - 32 +irandom(64);
instance_create_layer(xx, yy, "Effects", obj_blood);

ここではローカル変数を使用してランダムな座標を格納し、それを使用してインスタンスを作成しました。この例では、これらの変数を使用することが厳密には必要ではないことがわかりますが、読みやすさと使いやすさのために行っています。下記のコードを使用した場合よりも、ここで行っていることがはるかに明確で明白になります。

instance_create_layer(x - 32 + irandom(64), y - 32 + irandom(64), "Effects", obj_guts);

var宣言された変数に関するもう1つのことに注意する必要があります。それらはそれらを実行するイベントに固有のものであるため、コードを介して他のインスタンスでも使用できます。つまり、これらの変数を使って他のインスタンスで "with()"構文を使って設定や変更を行うことができるということです(マニュアルのGML概要セクションにこれに関するセクションがあります)。実際のコード自体は次のようになります。

var num = instance_number(obj_Enemy);
with (obj_Enemy)
   {
   if num>10 instance_destroy();
   }

*(確認:obj_Enemyのインスタンス数が10より多い場合はインスタンスを破壊する?)
上記のコードは、var宣言された変数がインスタンスやゲームの世界ではなく、それが含まれるイベント(またはスクリプト)に対してローカルであり、同じコードブロック内である限り、どのオブジェクト内の、どの関数で使用できるため、機能します。

 

グローバル変数

グローバル変数の基本的な説明は、いったん宣言されると、特にインスタンスに属していなくても、誰でもアクセスできるというものです。ローカル変数と同じように、グローバル変数も宣言する必要がありますが、ローカル変数とは異なり、グローバル変数はゲームが終了するまでメモリに残ります。そのため、(たとえば)プレーヤーが持っている弾丸の数を追跡するためのグローバル変数を作成してから、ゲームのさまざまな時点でこの変数を更新することができます。グローバル変数は特定のインスタンスに属しておらず、いつでもすべてのインスタンスからアクセス、変更、および使用できますが、その変数を使用するすべてのインスタンスはその変更の影響を受けます。例を見てみましょう。

global.food = 5;

最初に "global"を書いてから "."を書き、"food"変数を宣言することで、この変数がグローバルスコープになったことをGameMaker Studio 2に伝えます。この変数にアクセスしたり変更したりする必要があるときはいつでも、このメソッドを使用する必要があります。そのように、私たちは "food"という新しい変数を作り、それをグローバル変数として宣言しました。これで、どのインスタンスもこの変数を任意の方法で使用および変更でき、他のすべてのインスタンスはこれを「見る」ことになります。たとえば、プレーヤーが別のfoodオブジェクトと衝突するとき、衝突イベントでは次のようになります。

global.food +=1;

このような値を描画する別のオブジェクトもあります。

draw_text(32, 32, "food = " + string(global.food));

グローバル変数を使用すると、値を変更して、この変数を参照しているオブジェクトのすべてのインスタンスにそれらの変更が反映されていることを確認できます。ローカル変数と同様に、グローバル変数をインスタンス変数と同じ名前にしないように注意してください。変数の重複により、バグがゲームに入り込むことがあります。これはデバッグが難しい場合があります。一般に、ゲームの開始時(たとえば、Room Startイベントなど)にすべてのグローバル変数を宣言する単一のスクリプトまたはオブジェクトを用意する必要があります。そうすれば、それらは初期化され、どのインスタンスでも使用できるようになります。変数名を確認する必要がある場合に、戻って参照するのに便利な場所を提供します。

 

GameMaker Studio 2にも "組み込み"グローバル変数のコレクションがあります。インスタンス変数の1つに同じ名前を付けたり、自分のグローバル変数に同じ名前を付けたいのであれば、それらを知っておく必要があります。エラーが発生します! しかし、それらはコードエディタでは異なる色で表示され、下部のオートコンプリートバーに表示されるため、見つけやすいです。組み込みグローバル変数の大部分は非常に特殊なもので、ごくまれにしか使用されません ── そしてマニュアルの適切なセクションに記載されています ── しかし、頻繁に使用され他には表示されない重要なものもあります。

 
  • async_load
 

注意が必要な3つの非推奨組み込みグローバル変数もあります(これらの変数は、以前のバージョンのGameMakerの古いプロジェクトをサポートするためだけに設計されているので、新しいプロジェクトでは使用しないでください)。

 
  • score
  • health
  • lives
 

次のメソッドはグローバル変数を宣言するためにも使用できますが、下位互換性のためにのみ含まれています。GameMakerStudio 2の将来のバージョンではサポートされない可能性があるため、このメソッドを新しいプロジェクトに使用することはお勧めできません。

 

グローバル変数を作成する2番目の方法は、var 宣言を使用してローカル変数を作成するのと同じように、globalvar 宣言を使用してそのように宣言することです。

 

重要!globalvar宣言は推奨されておらず、従来の目的のためにのみサポートされています。あなたはグローバル変数をマークするための識別子「global.」を常に使うべきです。

 

この(廃止予定の)宣言は次のように使用されます。

globalvar food;
food = 5;

このようにして宣言されると、その変数 "food"は今やグローバルと見なされ、接頭辞「global.」を必要としません。コード内のグローバル変数を識別するのははるかに困難です。また、異なるオブジェクトまたはインストールされた拡張機能で同じ変数名を使用するので、変数の重複を見つけるのもはるかに簡単です。このように宣言されると、グローバル変数は次のようにアクセスされます。

food += 2;

または、

draw_text(32, 32, "food = " + string(food));

お分かりのように、変数がスコープ内でグローバルであることを示すものは何もないので、あなたは潜在的に、あなたのゲームで発生する多くの微妙な問設定することになります。それでこの宣言は避けられるべきです。

 

グローバル変数を扱うときに役立つように設計された2つの関数があります(主にインポートされたプロジェクトのための互換性スクリプトとドラッグアンドドロップアクションのためのコードですが、他の場所でも使用できます)。

 
  • variable_global_exists
  • variable_global_get
  • variable_global_set
 

組み込み変数

組み込み変数は、ゲームの世界でオブジェクトや部屋に「組み込まれている」特別な変数であり、インスタンス内でもグローバルでもかまいません(ただしローカルではありません)。いくつかのグローバル変数は上のセクションにリストされています、そして、マニュアルのスプライト、ルーム、オブジェクトなどの異なったセクションで、利用可能な組み込み変数の概要を説明しています。そのような組み込みインスタンス変数の例は次のようになります。

 
  • sprite_index
  • path_scale
  • speed
 

組み込みグローバル変数の例は次のようになります。

  • view_xport
  • GM_version
  • room_speed
 

組み込み変数は他のほとんどの変数と同じように変更したり設定することができます。さらに配列にすることもできます。通常の変数のように設定してデフォルト値に初期化する必要はありません。

 

マクロ(定数)

厳密には変数ではありませんが、マクロはその使用方法が似ています。つまり、硬い値(hard values)を置き換えるためにコード全体で使用できる名前付きの値です。基本的に、マクロ(このように使用されるときは定数とも呼ばれます)は、定数の単一値(または文字列)を保持する名前付き変数です。スクリプトエディタを使用して独自の定数を定義し、それを通常の変数であるかのようにコードやDnDで使用することができますが、1つの違いはゲーム内で変更できないことです。たとえば、次のマクロを定数として定義したとします(前の "#"と末尾のコロン ";"に注意してください)。

#macro total_weapons 10

そのとき、あなたはこのようなコードでこれを呼び出すでしょう:

if ++pos == total_weapons
   {
   pos = 0;
   }

定数値を変更することはできないので、このようなコードを実行するとゲームがクラッシュします。

total_weapons = 11;

あなたのコードやスクリプトのどこにでもマクロを定義することができ、それは最初からそこにあったかのように事前にコンパイルされてあなたのゲームに含まれるでしょうが、私たちは専用のスクリプトリソースを作成しそこにあなたのすべてのマクロを定義することを勧めます。その方が、後で整理やデバッグが簡単です!

 

実行時にマクロの値を変更する必要がある場合は、マクロを関数に設定しない限り、ゲーム中にコードから変更できるため、おそらくグローバル変数にする必要があります。マクロを関数に設定することは、マクロを使用するたびにこの関数が呼び出されることを意味します。例えば:

#macro col make_colour_hsv(irandom(255), 255, 255)

このマクロを次のように呼びます。

image_blend = col;

このコードを使用すると、マクロが使用されるたびに画像が異なる色にブレンドされます。改行する場所を示すために、スラッシュ(\)を使用してマクロを複数の行に分割することもできます。例は次のようになります。

#macro hello show_debug_message("Hello" + \
string(player_name) + \
", how are you today?");

このようにマクロを分割しても最終的なマクロの結果には影響がありません。これは純粋に表面的なものであり、単に長いコード行を持つマクロで複数行のテキストをサポートするためのものです。

 

マクロの非常に重要な機能の1つは、特定の設定(config)で使用するために定義できることです。つまり、同じマクロ名を使用できますが、現在選択されている設定に基づいて異なる値を指定できます。たとえば、Android広告用とiOS広告用の別の設定があるとしたら、必要なアプリIDの値を保持するための単一のマクロを定義できます。

#macro ad_id "";
#macro Android:ad_id "com.yoyogames.googlegame"
#macro iOS:ad_id "com.yoyogames.appstoregame"

ご覧のとおり、最初に設定名、次にコロン:、そして次にマクロ名と値を指定します。コロン:と設定名またはマクロ名の間に空白を入れることはできません。そうしないとエラーが発生します。

 
 

Variables And Variable Scope

 

Like any programming language GML uses variables as the basic unit for most programming operations. Variables are used to store information in the devices memory for later (or instant) use, and they are given a name so that you can refer to them in functions and scripts. A variable in GML can store many different data types, like a real number (like 100, 2.456575, -56 etc...), a string (like "Hello world!"), an integer (like 1, 556, -7), or a boolean (true or false).

 

A variable is something that we use to store a value for use in one or more operations or functions. Think of "pi", for example... it is a real world variable that holds the value 3.14159265(etc...). Why? Well, it's much easier to say to someone "pi" than "three point one four one five nine two six five"! So, naming things makes life a lot simpler and it also means that should the value of that variable ever change, we don't have to change the number everywhere as the variable name is still the same. In GML a variable has a name that must start with a letter and can contain only letters, numbers, and the underscore symbol '_' with a maximum length of 64 symbols. So, valid variables are things like fish, foo_bar, num1, and invalid variables would be 6fish, foo bar, or *num.

 

Now, In many programming languages you need to "declare" a variable before you can use it. This basically means that you tell the computer the name you wish to use so that it can assign a place in memory to store whatever value you decide to hold in that variable. With GML, that is not always necessary as it depends on the scope of the variable. There are four main variable categories when you program with GameMaker Studio 2 and each has its own scope (which is can be considered as its area of operation, or reach). These variables and their scope are outlined below:

 

Instance Variables

An instance variable is created within an instance of an object and is considered unique to that instance - ie: many instances of the same object can have the same variable, but each variable can hold a different value as they are unique to each instance. But how is an instance variable created? Well, you create new variables simply by assigning a value to them as shown in this small example:

potions = 12;
life = 100;
name = "Jock MacSweeney";
strength = 5.5;
armour = -2;

As you can see you just have to give the name and then a value (either numeric or a string) to set that variable and have it ready for use within an instance of the object you are coding for. These variables can then be used and modified in a number of ways from within the instance, for example this code could be in a collision event and used to take an amount off of the variable "life":

life -= 5 + armour;

If "life" is at 100 it will now have a value of 97 (100 - (5 + -2) = 97). Now, that's a simple example, and you could replace "armour" for the actual value of -2, but what happens if you use that value in multiple places and then decide to change it? You would have to go through ALL your code and change every -2 to whatever the new value is, which is time consuming and very error prone! But if you use a variable, all you have to do is reassign it a new value and the code will automatically use that new value from then onwards, making things far more flexible and far easier to fix should there be a problem. It should also be noted that even if a value is not going to change it is far easier to remember what a variable called "life" means rather than just looking at a number.

 

GameMaker Studio 2 has a collection of "built in" instance variables too, so you should be aware of them as you may name one of your own instance variables the same or wish to have your own global variable with the same name and wonder why you are getting errors. They are easy to spot, however, as they are shown in a different colour in the code editor and also come up in the auto-complete bar at the bottom.

 

There are a couple of functions designed to help you when dealing with instance variables (primarily for use with Compatibility Scrpts for imported projects and the code for Drag and Drop actions, but they can be used elsewhere too):

 
  • variable_instance_exists
  • variable_instance_get
  • variable_instance_set
  • variable_instance_get_names
 

Local Variables

A local variable is one that we create for a specific event only and then discard when the event has finished (the only exception to this is in the script resources, where a var declared variable is local to the script and then discarded). Why would we need them? Well, variables take up space in memory and it may be that we are only going to use them for one operation or function in which case we only need to have it in memory for that short time that it's used. This keeps your code base clean and tidy as well as keeping memory space optimised for the things that really need it. To declare a local variable we use the function var like this:

var i, num, str;
i = 0;
num = 24.5;
str = "Hi there!";

All of the variables created above will be "forgotten" (ie: removed from memory) at the end of the event (or script) in which they were created. You must be careful that the name you give var declared variables does not coincide with another instance variable within the object running the code, and also make sure that you have no intention of using the value stored in that variable outside of the event declare it in. These variables are used a lot in programs, especially in loops for counting iterations, or when using a value several times in one operation that is not going to be repeated again. Here are another couple of examples:

var i = 0;
repeat (10)
   {
   inventory[i] = 0;
   i+=1;
   }

The above code creates a local variable called "i" and sets it to 0, all in the same line. Note that in previous versions of GameMaker you had to declare your local variables first and then assign them values, but in this version you can declare and assign them a value at the same time. The above code then uses this variable to initialize an array. As the variable "i" is not going to be used for any further functions in the instance other than this, it can be local in scope. Here is one more example:

var xx,yy;
xx = x - 32 +irandom(64);
yy = y - 32 +irandom(64);
instance_create_layer(xx, yy, "Effects", obj_blood);

Here we have used the local variables to store some random coordinates that we then use to create an instance. In this example you can see that it is not strictly necessary that we use these variables but for the sake of readability and ease of use, we do. It is MUCH clearer and obvious what we are doing there than if we used this code:

instance_create_layer(x - 32 + irandom(64), y - 32 + irandom(64), "Effects", obj_guts);

One other thing about var declared variables should be noted... As they are unique to the event that runs them, they can be used in any other instances through code too! This means that we can use these variables to set and change things in other instances using the "with()" construct (there is a section on this in the GML Overview section of the manual). The actual code itself would look something like this:

var num = instance_number(obj_Enemy);
with (obj_Enemy)
   {
   if num>10 instance_destroy();
   }

The above code works because the var declared variable is local to the event (or script) it is contained in, not the instance, nor the game world, and so can be used in any function in any object as long as it is in the same code block.

 

Global Variables

A basic description of a global variable is one that, once declared, belongs to no instance in particular and yet can be accessed by all. Just like local variables, global variables must be declared, but unlike a local variable, a global variable remains in memory until the end of the game. So, you can create a global variable to keep track of (for example) the number of bullets that the player has and then just update this variable at different points in the game. A global variable does not belong to any specific instance and can be accessed, changed and used by all instances at any time, but any change made to the variable are "global", in that all instances using the variable will be affected by the change. Let's have a look at an example:

global.food = 5;

We declare the "food" variable by first writing "global" and then a "." to tell GameMaker Studio 2 that this variable is now global scope. We will need to use this method from now on any time we are required to access or to change this variable in any way. So, we have created a new variable called "food" and we have declared it as global. Now, any instance can use and change this variable in any way and all other instances will "see" this. For example we could have a different food object that the player collides with and in the collision event we have:

global.food +=1;

We also have another object that draws this value like this:

draw_text(32, 32, "food = " + string(global.food));

With global variables we can change values and see those changes reflected in all instances of the objects that reference this variable. As with local variables you have to take care not to name your global variables the same as any instance variables as that will cause you problems and make bugs creep into your games due to variable overlap, which can be a difficult issue to debug sometimes. In general you should have a single script or object that declares all your global variables at the very start of the game (for example, in the Room Start Event), so that they are initialised and ready for any instance to use, and this also gives you a handy place to go back and reference should you need to check a variable name.

 

GameMaker Studio 2 has a collection of "built in" global variables too, so you should be aware of them as you may name one of your instance variables the same or wish to have your own global variable with the same name and wonder why you are getting errors! They are easy to spot, however, as they are shown in a different colour in the code editor and also come up in the auto-complete bar at the bottom. The majority of built in global variables are very specific and will only be used on rare occasions - and are listed in the appropriate sections of the manual - but there is one important one that is used frequently and isn't listed elsewhere:

 
  • async_load
 

There are also three deprecated built in global variables which you should be aware of (these variables are only designed to support legacy projects from previous versions of GameMaker and should not be used in new projects):

 
  • score
  • health
  • lives
 

The following method can also be used to declare global variables, but it is only included for backwards compatibility, and it is not recommended that you use this method for new projects as future versions of GameMaker Studio 2 may not support it.

 

The second method for creating global variables is to declare them as such using the globalvar declaration, much as you would a local variable using the var declaration.

 

IMPORTANT! The globalvar declaration is deprecated and only supported for legacy purposes. You should always use the global. identifier to mark global variables.

 

This (deprecated) declaration would be used as follows:

globalvar food;
food = 5;

Once declared in this way that variable "food" is now considered global and requires no global. prefix - which also means that it's a lot harder to identify global variables in your code and it's also much easier to get variable overlap as you use the same variable name in different objects or from extensions that you've installed. Once declared in this way the global variable is accessed as follows:

food += 2;

or:

draw_text(32, 32, "food = " + string(food));

As you can see, with nothing to show that the variable is global in scope you are potentially setting yourself up for many subtle problems to arise in your game, which is why this declaration should be avoided.

 

There are a couple of functions designed to help you when dealing with global variables (primarily for use with Compatibility Scripts for imported projects and the code for Drag and Drop actions, but they can be used elsewhere too):

 
  • variable_global_exists
  • variable_global_get
  • variable_global_set
 

Built In Variables

Built in variables are special variables that are "built into" the objects and the rooms in the game world and they can be either instance or global in scope (but never local). Some global variables are listed in the section above, and the different sections of the manual for sprites, rooms, objects etc... also outline the built-in variables available. Examples of such built-in instance variables would be:

 
  • sprite_index
  • path_scale
  • speed
 

And examples of built-in global variables would be:

  • view_xport
  • GM_version
  • room_speed
 

Built-in variables can be changed and set like most other variables, and some can even be arrays, only you don't have to set them to create them like you would a regular variable as they will already be initialised to a default value.

 

Macros (Constants)

While not exactly variables, macros are similar to them in how they are used, ie: they are named values that you can use throughout your code to replace hard values. Basically, a macro (also called a constant when used like this) is a named variable that holds a constant single value (or string). You can define your own constants using the Script Editor and then use them in your code and DnD as if they were regular variables, with the one difference being that they can't be changed in the game. For example say you define the following macro as a constant (note the preceding "#" and the lack of a colon ";" at the end):

#macro total_weapons 10

You would then call this in your code like this:

if ++pos == total_weapons
   {
   pos = 0;
   }

Note that you would not be able to change the constant value, so code like this will cause the game to crash:

total_weapons = 11;

You can define a macro anywhere in your code or scripts and it will be pre-compiled and included in your game as if it was there from the start, but we recommend that you create a dedicated script resource and define all your macros in there. It will be easier to organise and debug later!

 

If you need the value of a macro to change at run-time then you should probably make it a global variable, since these can be changed from code during a game, unless you set the macro to be a function. By setting the macro to a function it means that this function will be called every time you use the macro. For example:

#macro col make_colour_hsv(irandom(255), 255, 255)

You would then call this macro something like this:

image_blend = col;

Using this code will make the image blend a different colour every time the macro is used. It is worth noting that you can also split macros over multiple lines using the forward slash \ to show where the line breaks. An example would be something like:

#macro hello show_debug_message("Hello" + \
string(player_name) + \
", how are you today?");

This is purely cosmetic, in that splitting a macro like this will have no effect over the result of the final macro, and is simply to provide support for multiline text on macros that have longer lines of code.

 

One very important feature of macros is that they can be defined for use with specific Configurations (configs), meaning you can have the same macro name but give it different values based on the currently selected config. For example, say you have a configuration for Android Ads and another for iOS Ads, then you could define a single macro to hold the required app ID value:

#macro ad_id "";
#macro Android:ad_id "com.yoyogames.googlegame"
#macro iOS:ad_id "com.yoyogames.appstoregame"

As you can see, you give the config name first then a colon : and then the macro name and value. Note that you cannot have any whitespace between the colon : and either the config name nor the macro name otherwise you will get an error.

 
 

Back: GML Overview
Next: Addressing Variables in Other Instances