diff --git a/Manual/contents/Additional_Information/Additional_Information.htm b/Manual/contents/Additional_Information/Additional_Information.htm index e718f4569..b682744e2 100644 --- a/Manual/contents/Additional_Information/Additional_Information.htm +++ b/Manual/contents/Additional_Information/Additional_Information.htm @@ -1,6 +1,7 @@ +
このセクションでは、プログラミングとGameMaker Language の動作に関連する雑多な記事を集めています。以下の記事は、GameMaker の仕組みと、さまざまな言語機能を最大限に活用する方法について、理解を深めるための関連記事として作成されています。
+このセクションでは、プログラミングとGameMaker Language の動作に関連する雑多な記事を集めています。以下の記事は、GameMaker の仕組みと、さまざまな言語機能を最大限に活用する方法について、理解を深めるための関連記事として作成されています。
このページでは、ゲームをプログラミングする際の「ベストプラクティス」をいくつか紹介し、同時にGameMakerの内部動作についても少し説明します。ただし、その前に2つの重要なポイントを押さえておきましょう。
+このページでは、ゲームをプログラミングする際の「ベストプラクティス」をいくつか紹介し、同時にGameMakerの内部動作についても少し説明します。ただし、その前に2つの重要なポイントを押さえておきましょう。
ということで、次に、いつでも適用できる、良いGML コードを書くための一般的なヒントをいくつか見てみましょう...
コードを書くとなると、誰にでもスタイルがあります。そのスタイルとは、括弧の付け方、行のインデントの仕方、変数の宣言や名前の付け方などであり、あなたのコードを他の人に(そして、他のことに時間をかけた後にこのプロジェクトに戻ってくることになった将来の自分にも)明確で読みやすいものにするために不可欠なものです。
-プログラミングのスタイルはたくさんあり、自分のスタイルがベストだと主張する人もいますが、実際には、一貫性を持って 使用し、すべてのものが何であり、何をしているかが明確 であれば、ほぼすべてのスタイルで問題ありません。
-上の画像は、上記の点を説明するためのscript の関数宣言の例です。JSDoc スタイルのコメントを使って、何をするのかが明確に説明されていることがわかります。また、4 スペースでのインデント、ローカル変数に使用するアンダースコア、ログ出力など、コーディングスタイルが一貫していることもわかります。
また、script エディターでは、開閉ブラケットごとにコードを折りたたむことができますが、 #region と #endregion タグを使ってコードの一部を区切り、特に複数の関数を含む大きなscripts を処理するときに、可読性を大幅に高めることができることに注意してください。リージョンはコメントも可能です。マニュアルのこのページの編集のセクションを参照してください)。
-コードを書くときに注意しなければならないのは、GameMakerはコンパイル時にコメントを削除し、不要な改行や空白を取り除き、定数/マクロ/enum値を代入し、一般的にコードを圧縮していることです。つまり、コードの周りに必要なだけ空白を追加することができ、コメントを短くしたり、控えめにしたりすることを気にする必要がないのです。
+ コードを書くとなると、誰にでもスタイルがあります。そのスタイルとは、括弧の付け方、行のインデントの仕方、変数の宣言や名前の付け方などであり、あなたのコードを他の人に(そして、他のことに時間をかけた後にこのプロジェクトに戻ってくることになった将来の自分にも)明確で読みやすいものにするために不可欠なものです。 +
+プログラミングのスタイルはたくさんあり、自分のスタイルがベストだと主張する人もいますが、実際には、一貫性を持って + 使用し、すべてのものが何であり、何をしているかが明確 であれば、ほぼすべてのスタイルで問題ありません。
+上の画像は、上記の点を説明するためのscript の関数宣言の例です。JSDoc
+ スタイルのコメントを使って、何をするのかが明確に説明されていることがわかります。また、4 スペースでのインデント、ローカル変数に使用するアンダースコア、ログ出力など、コーディングスタイルが一貫していることもわかります。
また、script エディタでは、開閉ブラケットごとにコードを折りたたむことができますが、 #region と #endregion タグを使ってコードの一部を区切り、特に複数の関数を含む大きなscripts + を処理するときに、可読性を大幅に高めることができることに注意してください。リージョンはコメントも可能です。マニュアルのこのページの編集のセクションを参照してください)。
+コードを書くときに注意しなければならないのは、GameMakerはコンパイル時にコメントを削除し、不要な改行や空白を取り除き、定数/マクロ/enum値を代入し、一般的にコードを圧縮していることです。つまり、コードの周りに必要なだけ空白を追加することができ、コメントを短くしたり、控えめにしたりすることを気にする必要がないのです。
+
続けて、プログラミングのスタイルについてですが、多くの初心者がやってしまうことの一つに、1行のコードにできるだけ多くのことを詰め込むということがあります。例えば
-draw_sprite(sprite_index, image_index, x + lengthdir_x(100, point_direction(x, y, mouse_x, mouse_y)), y + lengthdir_y(100, point_direction(x, y, mouse_x, mouse_y)));
-全く読めないわけではありませんが、非効率的であり(例えば point_direction() 関数が2回呼び出されています)、見た目もゴチャゴチャしていますし、厄介です。次のように表現した方がはるかに良いだろう。
+draw_sprite(sprite_index, image_index, x + lengthdir_x(100, point_direction(x, y, mouse_x, + mouse_y)), y + lengthdir_y(100, point_direction(x, y, mouse_x, mouse_y)));
+全く読めないわけではありませんが、非効率的であり(例えば point_direction() + 関数が2回呼び出されています)、見た目もゴチャゴチャしていますし、厄介です。次のように表現した方がはるかに良いだろう。
var p_dir = point_direction(x, y, mouse_x, mouse_y);
var local_x = x + lengthdir_x(100, p_dir);
var local_y = y + lengthdir_y(100, p_dir);
draw_sprite(sprite_index, image_index, local_x, local_y);
ローカル変数を作成するために必要なメモリやリソースはごくわずかであり、その明快さによってあなた(あるいは後でコードを読む人)が即座に得られる利益よりもはるかに大きいのです。関数でも同じことが言えます。入力変数に適切な名前を付け、必要な箇所には明確な書式設定と局所変数を使用して、可能な限り読みやすいコードにする必要があります。
-ローカル変数はゲーム内の処理が速いので、有効に活用しましょう。また、コードブロックやscript 、ある式が2回以上登場する場合は、その式のローカル変数を作成することを考えましょう。YoYo Compiler (YYC)ターゲットを使用する場合、関数やコードブロックの中で global やインスタンス変数を何度も参照する場合は、コードの先頭でローカル変数に代入し、そのローカル変数を参照すると、特にパフォーマンスが良くなります。
++ ローカル変数を作成するために必要なメモリやリソースはごくわずかであり、その明快さによってあなた(あるいは後でコードを読む人)が即座に得られる利益よりもはるかに大きいのです。関数でも同じことが言えます。入力変数に適切な名前を付け、必要な箇所には明確な書式設定と局所変数を使用して、可能な限り読みやすいコードにする必要があります。 +
+ローカル変数はゲーム内の処理が速いので、有効に活用しましょう。また、コードブロックやscript + 、ある式が2回以上登場する場合は、その式のローカル変数を作成することを考えましょう。YoYo + Compiler (YYC)ターゲットを使用する場合、関数やコードブロックの中で global + やインスタンス変数を何度も参照する場合は、コードの先頭でローカル変数に代入し、そのローカル変数を参照すると、特にパフォーマンスが良くなります。
配列はデータ構造よりも高速で、必要なメモリ量も少なくて済みますが、さらに最適化することも可能です。配列を作成すると、そのサイズに応じてメモリが割り当てられます。したがって、たとえ後で値を入れる予定がなくても、まずは最大サイズまで配列を初期化するようにしましょう。たとえば、最大 100 個の値を格納する配列が必要だとわかっている場合は、すぐに 100 スロットに初期化します。 array_create()関数で初期化します。
+配列はデータ構造よりも高速で、必要なメモリ量も少なくて済みますが、さらに最適化することも可能です。配列を作成すると、そのサイズに応じてメモリが割り当てられます。したがって、たとえ後で値を入れる予定がなくても、まずは最大サイズまで配列を初期化するようにしましょう。たとえば、最大 + 100 個の値を格納する配列が必要だとわかっている場合は、すぐに 100 スロットに初期化します。 array_create()関数で初期化します。
array = array_create(100, 0);
そうしないと、配列に新しい値を追加するたびに、メモリ全体を再割り当てしなければならないからです。
-注意HTML5ターゲットでは、このような配列の代入は適用されず、配列は0から初期化される必要があります。例えば、os_browser変数をチェックすることで、簡単に処理することができます。
+注意HTML5ターゲットでは、このような配列の代入は適用されず、配列は0から初期化される必要があります。例えば、os_browser変数をチェックすることで、簡単に処理することができます。 +
if (os_browser == browser_not_a_browser)
{
array_create(100, 0);
@@ -62,8 +91,11 @@ プログラミングのベストプラクティス
}
また、配列に関連するメモリを解放するには、使用する変数に0を設定します。したがって、上記のコード例で配列をクリアするには、単に
array = 0;
-また、配列は参照渡しですが、変更があったときに全体をコピーすることに注意してください(この動作をcopy on write と呼びます)。つまり、配列を関数に渡す場合は元の配列への参照を 渡すことになり、そこから読み込まれる値はすべて元の配列から取得されることになります。しかし、配列の値を変更する必要がある場合は、 書き込みの時点で配列が複製されてしまうので、関数から値を返さなければ変更した内容が失われてしまいます。そのため、関数内での配列の使用には注意が必要です。
-しかし、特殊な配列アクセッサ @ を使用することで、書き込み時のコピー動作を回避することができます。例えば
+また、配列は参照渡しですが、変更があったときに全体をコピーすることに注意してください(この動作をcopy on write + と呼びます)。つまり、配列を関数に渡す場合は元の配列への参照を 渡すことになり、そこから読み込まれる値はすべて元の配列から取得されることになります。しかし、配列の値を変更する必要がある場合は、 + 書き込みの時点で配列が複製されてしまうので、関数から値を返さなければ変更した内容が失われてしまいます。そのため、関数内での配列の使用には注意が必要です。
+しかし、特殊な配列アクセッサ @ を使用することで、書き込み時のコピー動作を回避することができます。例えば
// Call a function, passing our array
my_function(my_array);
// The function looks like this:
@@ -83,30 +115,68 @@
GameMakerの データ構造は、以前のバージョン(GameMaker )よりもずっと高速になるように最適化されています。しかし、データ構造の使いやすさと、データを扱うための追加機能は、最小限の速度差に勝ることが多いので、恐れずにゲームに使ってください。
+GameMakerの データ構造は、以前のバージョン(GameMaker + )よりもずっと高速になるように最適化されています。しかし、データ構造の使いやすさと、データを扱うための追加機能は、最小限の速度差に勝ることが多いので、恐れずにゲームに使ってください。
すべてのデータ構造の中で、特にDS Mapsは読み込みも書き込みも高速で、あらゆるタイプのタスクに最適な選択肢となることに注目すべきだろう。
-前回は配列に対するアクセサを紹介しましたが、データ構造に対しても利用可能で、コードをすっきりさせて読みやすくすることができます。
+前回は配列に対するアクセサを紹介しましたが、データ構造に対しても利用可能で、コードをすっきりさせて読みやすくすることができます。 +
GameMaker には衝突を処理する方法が複数ありますが、そのほとんどは CPU のオー バーヘッドを少し余分に必要とします。 collision_ と point_ 関数、 place_ 関数、 instance_ 関数はすべて、room 内の与えられたタイプのすべてのインスタンスとのバウンディングボックスチェックに依存しています。これらのチェックを制限するために、エンジンにいくつかの最適化が組み込まれていますが、衝突は決して最も効率的に処理されるものではあり ません。正確なコリジョンを使用し始めると、パフォーマンスが著しく悪化します。バウンディングボックスチェックだけでなく、ピクセル単位のチェックも行うことになり、これは実に遅いのです。
+GameMaker には衝突を処理する方法が複数ありますが、そのほとんどは + CPU のオー バーヘッドを少し余分に必要とします。 collision_ と point_ 関数、 place_ 関数、 instance_ 関数はすべて、room 内の与えられたタイプのすべてのインスタンスとのバウンディングボックスチェックに依存しています。これらのチェックを制限するために、エンジンにいくつかの最適化が組み込まれていますが、衝突は決して最も効率的に処理されるものではあり + ません。正確なコリジョンを使用し始めると、パフォーマンスが著しく悪化します。バウンディングボックスチェックだけでなく、ピクセル単位のチェックも行うことになり、これは実に遅いのです。
これらの機能はとても便利なので、使ってはいけないというわけではありません。しかし、どの関数をいつ使うかは知っておく必要があります。というのも、これらの関数はそれぞれ微妙に動作が異なり、速度も異なるからです。大まかな目安としては、 place_ 関数は instance_ 関数より速く、 collision_ および point_ 関数より速くなります。マニュアルのそれぞれのタイプの関数のページを読み、あらゆる状況に最も適したものを選択するようにしてください。
-タイル ベースのコリジョンシステムは、タイルマップ関数やカスタム2D配列、DSグリッドを使用して作成することも可能です。これらは非常に高速で、ゲームの速度を向上させるのに役立ちます。ただし、不規則な地形や壁、objects を使用していて、グリッドに整列していない場合は、適切でない可能性があります。タイルマップの衝突に関する非常に簡単なチュートリアルは、次のビデオリンクから参照できます。
++ これらの関数はとても便利なので、使ってはいけないというわけではありません。しかし、どの関数をいつ使うかは知っておく必要があります。というのも、これらの関数はそれぞれ微妙に動作が異なり、速度も異なるからです。大まかな目安としては、 + place_ 関数は instance_ 関数より速く、 collision_ および point_ + 関数より速くなります。マニュアルのそれぞれのタイプの関数のページを読み、あらゆる状況に最も適したものを選択するようにしてください。 +
+タイル ベースのコリジョンシステムは、タイルマップ関数やカスタム2D配列、DSグリッドを使用して作成することも可能です。これらは非常に高速で、ゲームの速度を向上させるのに役立ちます。ただし、不規則な地形や壁、objects + を使用していて、グリッドに整列していない場合は、適切でない可能性があります。タイルマップの衝突に関する非常に簡単なチュートリアルは、次のビデオリンクから参照できます。
をswitch 。 デバッグオーバーレイをクリックすると、テスト時に画面の上部に括弧で囲まれた2つの数値が表示されるのがわかると思います。1 つは実行中のテクスチャスワップの 数で、もう 1 つは頂点バッチの数です。これらの数値にはさまざまな要因が影響し、エンジンはすべてのステップでそれぞれ1つか2つを必要とするので、これらを (0) (0) にすることはできませんが、これらの値をできる限り低くすることを目指す必要があります。
- texture のスワップでは、 と背景が ページに保存される方法を最適化するのが、最も効率的な方法です。これはsprites texture スプライトプロパティから行います。また、テクスチャグループエディタで texture ページを作成することができます。例えば、メインメニューにしか使わない画像が多数ある場合、それらを別のテクスチャページにまとめます。レベル固有の画像や、プレイヤーと敵などの画像がある場合も同じです。基本的には用途別にまとめて、なるべくスワップを減らしたいところです。さらに、VRAM を最適化するために、異なるプリフェッチとフラッシュ機能 を使って、必要に応じてメモリから をロードしたり、 削除したりすることができます。textures
注意このページの冒頭で述べたように、ゲームが適切な FPS で問題なく動作するのであれば、texture の交換についてあまり気にする必要はありません... 特にデスクトップターゲットでプロジェクトを作成する場合は。これらの最適化は、大規模なゲームやローエンドモバイルデバイスで使用する場合に最適で、間違った使い方をすると、実際にパフォーマンスに悪影響を与える可能性があります。
-頂点情報は描画のために GPU に「バッチ」で送られ、一般にバッチは大き い方が良い。したがって、描画時にバッチを「壊す」ことは避けるべきで、そうす ると GPU に送られる頂点のバッチの数が増えるからです。バッチを壊すものはいくつかあり、主なものは、ブレンドモード、シェー ダの変更、何かを描く前にshader のユニフォームを変更する、内蔵のシェイプ とプリミティブを使用して描く、などです。
-ですから、例えば、 bm_add のブレンドモードを使って描画する弾丸インスタンスが多数ある場合、それぞれの弾丸に対して新しいvertex batch を作成することになり、これは間違いなく悪いことです!代わりに、ゲーム内で、すべての弾丸を描画するコントローラobject を、次のように用意します。
+をswitch 。 デバッグオーバーレイをクリックすると、テスト時に画面の上部に括弧で囲まれた2つの数値が表示されるのがわかると思います。1 + つは実行中のテクスチャスワップの 数で、もう 1 + つは頂点バッチの数です。これらの数値にはさまざまな要因が影響し、エンジンはすべてのステップでそれぞれ1つか2つを必要とするので、これらを (0) (0) + にすることはできませんが、これらの値をできる限り低くすることを目指す必要があります。
+ texture のスワップでは、 と背景が
+ ページに保存される方法を最適化するのが、最も効率的な方法です。これはsprites texture スプライトプロパティから行います。また、テクスチャグループエディタで texture
+ ページを作成することができます。例えば、メインメニューにしか使わない画像が多数ある場合、それらを別のテクスチャページにまとめます。レベル固有の画像や、プレイヤーと敵などの画像がある場合も同じです。基本的には用途別にまとめて、なるべくスワップを減らしたいところです。さらに、VRAM を最適化するために、異なるプリフェッチとフラッシュ機能 を使って、必要に応じてメモリから
+ をロードしたり、 削除したりすることができます。textures
注意このページの冒頭で述べたように、ゲームが適切な FPS で問題なく動作するのであれば、texture の交換についてあまり気にする必要はありません... + 特にデスクトップターゲットでプロジェクトを作成する場合は。これらの最適化は、大規模なゲームやローエンドモバイルデバイスで使用する場合に最適で、間違った使い方をすると、実際にパフォーマンスに悪影響を与える可能性があります。
+頂点情報は描画のために GPU に「バッチ」で送られ、一般にバッチは大き い方が良い。したがって、描画時にバッチを「壊す」ことは避けるべきで、そうす ると GPU + に送られる頂点のバッチの数が増えるからです。バッチを壊すものはいくつかあり、主なものは、ブレンドモード、シェー ダの変更、何かを描く前にshader のユニフォームを変更する、内蔵のシェイプ とプリミティブを使用して描く、などです。
+ですから、例えば、 bm_add のブレンドモードを使って描画する弾丸インスタンスが多数ある場合、それぞれの弾丸に対して新しいvertex batch を作成することになり、これは間違いなく悪いことです!代わりに、ゲーム内で、すべての弾丸を描画するコントローラobject を、次のように用意します。
gpu_set_blendmode(bm_add);
with (obj_BULLET)
@@ -116,25 +186,60 @@
注:これはbm_addを使用する場合にのみ適用されるわけではありません - ブレンドを変更するとバッチが壊れ、パフォーマンスが低下します。
-こうすることで、すべての弾が一括で描画されるようになります。関数をうまく使う gpu_set_blendenable(), gpu_set_alphatestref()と gpu_set_alphatestenable()をうまく使えば、パフォーマンスが大幅に向上し、プロジェクトコード全体で必要に応じて有効/無効を切り替えることができます。ただし、すべての種類のグラフィックスやプロジェクトに適しているわけではありません。
-注意この方法でコントローラを使用する際に、インスタンス自体の描画を必要としない場合は、単に描画イベントにコメントを追加してデフォルトの描画を抑制するか、インスタンスを不可視にします (ただし、これによりすべての描画イベントでインスタンスに対して実行されるすべてのコードが無効になります)。
-これらの数を減らすもう一つの方法は、絶対に必要でない限り、Texture の「Separatesprites Page」オプションを無効にすることです。この方法で保存された各画像は独自のtexture ページに送られ、異なるバッチ処理が行われるため、これらの画像を通常のtexture ページに置く方がよいのです。次に、UVS 座標を sprite_get_uvs()関数を使って UVS 座標を取得し、変数に保存して後で使用することができます。わずかな追加コードかもしれませんが、得られるブーストはそれに見合うものです。この方法はtexture の繰り返しを許可しないことに注意してください!
+注:これはbm_addを使用する場合にのみ適用されるわけではありません - ブレンドを変更するとバッチが壊れ、パフォーマンスが低下します。
+こうすることで、すべての弾が一括で描画されるようになります。関数をうまく使う gpu_set_blendenable(), gpu_set_alphatestref()と gpu_set_alphatestenable()をうまく使えば、パフォーマンスが大幅に向上し、プロジェクトコード全体で必要に応じて有効/無効を切り替えることができます。ただし、すべての種類のグラフィックスやプロジェクトに適しているわけではありません。 +
+注意この方法でコントローラを使用する際に、インスタンス自体の描画を必要としない場合は、単に描画イベントにコメントを追加してデフォルトの描画を抑制するか、インスタンスを不可視にします + (ただし、これによりすべての描画イベントでインスタンスに対して実行されるすべてのコードが無効になります)。
+これらの数を減らすもう一つの方法は、絶対に必要でない限り、Texture の「Separatesprites Page」オプションを無効にすることです。この方法で保存された各画像は独自のtexture ページに送られ、異なるバッチ処理が行われるため、これらの画像を通常のtexture + ページに置く方がよいのです。次に、UVS 座標を sprite_get_uvs()関数を使って UVS + 座標を取得し、変数に保存して後で使用することができます。わずかな追加コードかもしれませんが、得られるブーストはそれに見合うものです。この方法はtexture + の繰り返しを許可しないことに注意してください!
これらのヒントと同様に、変更することで生活が苦しくなり、ゲームが正常に動作するのであれば、あまり気にする必要はありません...。
パーティクルは、ゲーム内でダイナミックなエフェクトを作成するための非常に迅速かつ効率的な方法を提供し、一般的に良好なパフォーマンスを発揮します。しかし、パーティクル上で加算ブレンディング、アルファブレンディング、カラーブレンディングを使用すると、特にモバイルターゲットではパフォーマンスが低下することがあるので、必要ない場合は使用しないでください。特に、アディティブブレンディングは、頂点バッチを大幅に増加させる可能性があるので、注意して使用する必要があります。
-非 WebGL の HTML5 ターゲットでは、マルチカラーでフェードするパーティクルを使用すると、多くの画像キャッシュが必要となり、非常に遅くなることに注意してください。しかし、パーティクルsprites はアニメーションさせることができるので、色が変化するサブ画像を持つアニメーションsprite を作成し、それをパーティクルに使用することができます。この場合でも、色が徐々に変化するように見えますが、cache の画像を常に作成する必要はありません。
-パーティクルについては、Guide To Using Particlesのページで詳しく説明されています。
+パーティクルは、ゲーム内でダイナミックなエフェクトを作成するための非常に迅速かつ効率的な方法を提供し、一般的に良好なパフォーマンスを発揮します。しかし、パーティクル上で加算ブレンディング、アルファブレンディング、カラーブレンディングを使用すると、特にモバイルターゲットではパフォーマンスが低下することがあるので、必要ない場合は使用しないでください。特に、アディティブブレンディングは、頂点バッチを大幅に増加させる可能性があるので、注意して使用する必要があります。 +
+非 WebGL の HTML5 + ターゲットでは、マルチカラーでフェードするパーティクルを使用すると、多くの画像キャッシュが必要となり、非常に遅くなることに注意してください。しかし、パーティクルsprites はアニメーションさせることができるので、色が変化するサブ画像を持つアニメーションsprite を作成し、それをパーティクルに使用することができます。この場合でも、色が徐々に変化するように見えますが、cache の画像を常に作成する必要はありません。
+パーティクルについては、Guide To Using Particlesのページで詳しく説明されています。 +
最後に、サーフェスの使用について簡単に触れます。GameMakerでは、サーフェスをゲームに使用する際にかなり重要な最適化が行われています。switch 深度バッファのオンとオフが可能です。
-サーフェスを普通に使うと、GameMakerはサーフェスとそれに付随する深度buffer を実際に作成し、3D で何かを描くときに適切な深度ソートを確保します。しかし、ほとんどの2Dゲームでは、この余分な深度buffer は必要ないため、他のことに使えるはずのメモリスペースと処理時間を余計に消費しています。そこで、この関数 surface_depth_disable()が登場するのです...
-この関数は、サーフェスを作成する前に呼び出すと、深度buffer の生成を無効にすることができ、その後に作成されたすべてのサーフェスには、深度buffer が作成されません。この関数は必要に応じて有効/無効にでき、ゲームの開始時に一度だけ呼び出して、それ以降のすべてのサーフェス呼び出しで深度buffers を無効にすることもできます(そしてほとんどの2Dゲームではこれで問題ありません)。この機能によってパフォーマンスが大幅に向上することはありませんが、サーフェスを多用するゲームでは覚えておくとよいでしょう。また、低スペックのデバイスでゲームがメモリ不足になるのを防ぐことができるかもしれません。
+最後に、サーフェスの使用について簡単に触れます。GameMakerでは、サーフェスをゲームに使用する際にかなり重要な最適化が行われています。switch 深度バッファのオンとオフが可能です。
+サーフェスを普通に使うと、GameMakerはサーフェスとそれに付随する深度buffer を実際に作成し、3D で何かを描くときに適切な深度ソートを確保します。しかし、ほとんどの2Dゲームでは、この余分な深度buffer は必要ないため、他のことに使えるはずのメモリスペースと処理時間を余計に消費しています。そこで、この関数 surface_depth_disable()が登場するのです...
+この関数は、サーフェスを作成する前に呼び出すと、深度buffer + の生成を無効にすることができ、その後に作成されたすべてのサーフェスには、深度buffer + が作成されません。この関数は必要に応じて有効/無効にでき、ゲームの開始時に一度だけ呼び出して、それ以降のすべてのサーフェス呼び出しで深度buffers + を無効にすることもできます(そしてほとんどの2Dゲームではこれで問題ありません)。この機能によってパフォーマンスが大幅に向上することはありませんが、サーフェスを多用するゲームでは覚えておくとよいでしょう。また、低スペックのデバイスでゲームがメモリ不足になるのを防ぐことができるかもしれません。 +
上記の主なものとは別に、パフォーマンスを向上させる、より一般的なものもあり、それも「グッドプラクティス」とされています。
@@ -143,18 +248,20 @@しかし、このページの冒頭で述べたように、これらの最適化はすべてオプションであり、もしあなたのゲームが60頂点バッチ、80texture スワップ、加算ブレンディングなどでうまく動くなら、あまり気にする必要はありません!次のゲームをプログラミングするときに、これらのことを心に留めておいてください...
+しかし、このページの冒頭で述べたように、これらの最適化はすべてオプションであり、もしあなたのゲームが60頂点バッチ、80texture + スワップ、加算ブレンディングなどでうまく動くなら、あまり気にする必要はありません!次のゲームをプログラミングするときに、これらのことを心に留めておいてください...
+ \ No newline at end of file diff --git a/Manual/contents/Additional_Information/Bitwise_Operators.htm b/Manual/contents/Additional_Information/Bitwise_Operators.htm index 3fb650158..3300e57ac 100644 --- a/Manual/contents/Additional_Information/Bitwise_Operators.htm +++ b/Manual/contents/Additional_Information/Bitwise_Operators.htm @@ -1,6 +1,7 @@ +
コンピュータ時代の初期には、2進数や 16進数(hexadecimal)が主流であった。おそらく、高レベル言語(BASICなど)の実行速度が単に遅かったからであろう。例えば、32×32の掛け算は、BASICではCPUサイクルを何回もかけて実現していたかもしれないが、2進数では1CPUサイクルで1つの演算として行われる。
-なぜなら、マシンのスピードと、より複雑なCPU構造が、このアプローチの欠点を補ってくれるからです。もちろん、これはあなたが書くコードのすべての行を最適化する必要がないことを意味するので、素晴らしいニュースですが、これが事実であれば - あなたは本当に全くバイナリについて気にする必要がありますか?
-答えは間違いなく「イエス、そうすべき」です。バイナリやヘックスを使うことで、CPUがどのように動作しているかをより深く理解することができ、より良いコードを書いたり、データをうまくパックしたり、いくつかの作業をよりシンプルにしたりすることができます。このページでは、バイナリとは何か、そしてゲームを作るときにどのように使うことができるのかについて、少し説明します。
+コンピュータ時代の初期には、2進数や + 16進数(hexadecimal)が主流であった。おそらく、高レベル言語(BASICなど)の実行速度が単に遅かったからであろう。例えば、32×32の掛け算は、BASICではCPUサイクルを何回もかけて実現していたかもしれないが、2進数では1CPUサイクルで1つの演算として行われる。 +
+なぜなら、マシンのスピードと、より複雑なCPU構造が、このアプローチの欠点を補ってくれるからです。もちろん、これはあなたが書くコードのすべての行を最適化する必要がないことを意味するので、素晴らしいニュースですが、これが事実であれば + - あなたは本当に全くバイナリについて気にする必要がありますか?
++ 答えは間違いなく「イエス、そうすべき」です。バイナリやヘックスを使うことで、CPUがどのように動作しているかをより深く理解することができ、より良いコードを書いたり、データをうまくパックしたり、いくつかの作業をよりシンプルにしたりすることができます。このページでは、バイナリとは何か、そしてゲームを作るときにどのように使うことができるのかについて、少し説明します。 +
そこで、まず最も基本的な二進法の理論、つまり数字がどのように作られるかを見てみましょう。この表を見てください。
000 = 0
001 = 1
010 = 2
100 = 4
それぞれの1または0はデータの1ビットを表し、これはご覧の通り、2進数では10が2に相当することを意味します!(※1)。つまり、ビット2=2、ビット3=4、ビット4=8といった具合です(このバイト表は下図に示すとおり)。
+それぞれの1または0はデータの1ビットを表し、これはご覧の通り、2進数では10が2に相当することを意味します!(※1)。つまり、ビット2=2、ビット3=4、ビット4=8といった具合です(このバイト表は下図に示すとおり)。
00000001 = 1
00000010 = 2
00000100 = 4
@@ -32,18 +41,34 @@
2の累乗の数字ならそれでもいいが、もっと複雑な数字を作るにはどうしたらいいのだろう。2進数には0か1しか格納できないので、より複雑な数を作るには、ビットを足し合わせる必要があります。例えば6を作りたい場合、4と2を足すとこうなります。
++ 2の累乗の数字ならそれでもいいが、もっと複雑な数字を作るにはどうしたらいいのだろう。2進数には0か1しか格納できないので、より複雑な数を作るには、ビットを足し合わせる必要があります。例えば6を作りたい場合、4と2を足すとこうなります。 +
00000010 = 2
00000100 = 4
00000110 = 6
これは、すべての 2進数について言えることで、コンピュータが内部でどのように数字を構成しているかということである。もう少し複雑な数字、23を例にとってみよう。23という数字は、実際には、 1+2+4+16 または 00010111 で構成されています。もっと複雑な例として、196はどうでしょうか?これは、 128+64+4 または 11000100 で構成されています。
-しかし、1バイトの範囲外の値(0から255までの数値を格納可能)を扱うようになると、追跡が少し難しくなってきます。例えば、217,361は2進数で 110101000100010001 。あるいは、 1+16+256+etc... どのような値を表現する場合でもルールは同じで、各数値は複数のビットを加算して作られます。
-さて、これらの値に対して、どのように数学的な演算を行うのでしょうか。例えば、 true または false を値として格納したいとします。通常、コンパイラは INT ( INT は通常符号付き 32 ビット数として定義されます。符号付きとは正負の値を取れるということで、符号なしとは正しか取れないということです) を使って、単純に 0 または 1 に代入します。2つの状態しか持たない true / false の値はビットに格納するのに最適です。そうすれば INT それぞれに対して 1 ビットだけではなく 32 true / false ビットを格納できます。これは、1 INT が 32 ビットからできていることと同じです。
+これは、すべての 2進数について言えることで、コンピュータが内部でどのように数字を構成しているかということである。もう少し複雑な数字、23を例にとってみよう。23という数字は、実際には、 + 1+2+4+16 または 00010111 で構成されています。もっと複雑な例として、196はどうでしょうか?これは、 + 128+64+4 または 11000100 で構成されています。 +
+しかし、1バイトの範囲外の値(0から255までの数値を格納可能)を扱うようになると、追跡が少し難しくなってきます。例えば、217,361は2進数で 110101000100010001 。あるいは、 1+16+256+etc... + どのような値を表現する場合でもルールは同じで、各数値は複数のビットを加算して作られます。
+さて、これらの値に対して、どのように数学的な演算を行うのでしょうか。例えば、 true または false + を値として格納したいとします。通常、コンパイラは INT ( INT は通常符号付き 32 + ビット数として定義されます。符号付きとは正負の値を取れるということで、符号なしとは正しか取れないということです) を使って、単純に 0 または 1 に代入します。2つの状態しか持たない true / false + の値はビットに格納するのに最適です。そうすれば INT それぞれに対して 1 ビットだけではなく 32 true / + false ビットを格納できます。これは、1 INT が 32 ビットからできていることと同じです。 +
どうすればいいのか?それは、とても簡単なことです。
flags = flags | 1;
-|" 演算子はビット演算です。 OR 、これは上記の命令 ORs 1 を変数 flags に保持されている値に変換することを意味します。先ほどから覚えているように、1を使うと最初のビットが設定されます。もし2番目のビットを設定したい場合は、次のようにします。
+|" 演算子はビット演算です。 OR 、これは上記の命令 ORs 1 を変数 flags + に保持されている値に変換することを意味します。先ほどから覚えているように、1を使うと最初のビットが設定されます。もし2番目のビットを設定したい場合は、次のようにします。
flags = flags | 2;
-ビットパターン 00000010 は 2 に等しいので、2 で OR となります。では、二項演算子 OR はいったい何をするのでしょうか?このように、すべてのビットを1つの値に統合するのです。
+ビットパターン 00000010 は 2 に等しいので、2 で OR となります。では、二項演算子 OR はいったい何をするのでしょうか?このように、すべてのビットを1つの値に統合するのです。
010110100 // Value 1
110011001 // value 2
110111101 // Value 1 OR Value 2
つまり、ゼロが2つある値では、ゼロのままです。このようなビットを true/false の状態として使用する利点は、一度の操作で複数のビットを「フラグ」として設定できることです。例えば、ビット1が「active」flag で、ビット3が「visible」flag であるとする。このようにすることで、両方を設定することができます。
+つまり、ゼロが2つある値では、ゼロのままです。このようなビットを true/false + の状態として使用する利点は、一度の操作で複数のビットを「フラグ」として設定できることです。例えば、ビット1が「active」flag + で、ビット3が「visible」flag であるとする。このようにすることで、両方を設定することができます。
flags = flags | 5;
-これは、5が2進数で 00000101 、上記のルールに従って、変数 "flags "はこれら2つのビットを自分のものと統合されるからです。したがって、ビット1がすでにセットされていたとしても、この操作は有効で、ビット3もセットされることになる。
-flags をクリアするのは?ここで、ビット単位の "&"AND オペレーションが登場するわけです。 AND の場合、マスクで設定されたビットは保持され、マスクでクリアされたビットは削除されます - このように。
+これは、5が2進数で 00000101 、上記のルールに従って、変数 "flags + "はこれら2つのビットを自分のものと統合されるからです。したがって、ビット1がすでにセットされていたとしても、この操作は有効で、ビット3もセットされることになる。
+flags をクリアするのは?ここで、ビット単位の "&"AND オペレーションが登場するわけです。 AND + の場合、マスクで設定されたビットは保持され、マスクでクリアされたビットは削除されます - このように。
01110010101 // Value 1
00110000100 // Value 2
00110000100 // Value 1 AND value 2
だから、それぞれの場所にビットがあるときだけ、キープされる。これはどういうことかというと、複数のflags を一度に設定できるのと同じように、複数のflags を一度にクリアすることもできるのです。例えば、上のようなケースで、今度はクリアしてみましょう。ビット1と3をクリア(値5を与える)したいのですが、上の真理値表を思い出すと、やりたいことは、他のビットを全部残して、ビット1と3をクリアすることです。これは1111111111111111111111010(32ビット)のバイナリ「マスク」になります。このマスクは、現在設定されているすべてのビットを保持し、実際にクリアしたい2つのビットをクリアします。つまり、1000111011という値があって、上記のマスクを使ってビット1と3をクリアしたい場合、以下のようになります。
+だから、それぞれの場所にビットがあるときだけ、キープされる。これはどういうことかというと、複数のflags を一度に設定できるのと同じように、複数のflags + を一度にクリアすることもできるのです。例えば、上のようなケースで、今度はクリアしてみましょう。ビット1と3をクリア(値5を与える)したいのですが、上の真理値表を思い出すと、やりたいことは、他のビットを全部残して、ビット1と3をクリアすることです。これは1111111111111111111111010(32ビット)のバイナリ「マスク」になります。このマスクは、現在設定されているすべてのビットを保持し、実際にクリアしたい2つのビットをクリアします。つまり、1000111011という値があって、上記のマスクを使ってビット1と3をクリアしたい場合、以下のようになります。 +
00000000000000000000001000111011 // Value
11111111111111111111111111111010 // Mask
00000000000000000000001000111010 // Value AND Mask
これは素晴らしいことですが、flags をクリアする必要があるたびにこの作業をしなければならないとしたら、うんざりしてしまうでしょう。必要なのは、ビットを簡単に(できればCPUコストをかけずに)反転させる方法です。幸いなことに、" ~" NOT 演算子を使えば、簡単にこれを行う方法がある。
-NOT 演算子はその名の通り、これらのビットではありません。以下は、 NOT の真理値表です。
+これは素晴らしいことですが、flags + をクリアする必要があるたびにこの作業をしなければならないとしたら、うんざりしてしまうでしょう。必要なのは、ビットを簡単に(できればCPUコストをかけずに)反転させる方法です。幸いなことに、" ~" NOT 演算子を使えば、簡単にこれを行う方法がある。
+NOT 演算子はその名の通り、これらのビットではありません。以下は、 NOT の真理値表です。 +
~00 = 11
~01 = 10
~10 = 01
~11 = 00
この演算子を使うと、flags の削除が非常に簡単になります。さらに、通常はコンパイル時の最適化で、定数(つまり変数ではない)を使っている場合は、コンパイラが自動的にビットを反転させるようになっているのです。この例では、ビット1と3を再びクリアします。
+この演算子を使うと、flags + の削除が非常に簡単になります。さらに、通常はコンパイル時の最適化で、定数(つまり変数ではない)を使っている場合は、コンパイラが自動的にビットを反転させるようになっているのです。この例では、ビット1と3を再びクリアします。
a = a & ~5;
-この場合、実際には"a & 11111111111111111111111111111010"だけにコンパイルされます。これによって、flags をクリアするという点では、かなりシンプルになります。
-最後に見ておきたい演算子は "^" EOR (Exclusive OR, 時には XOR) です。この演算子は両方の値に設定されているビットを反転させます。以下は、 EOR の真理値表です。
+この場合、実際には"a & 11111111111111111111111111111010"だけにコンパイルされます。これによって、flags をクリアするという点では、かなりシンプルになります。
+最後に見ておきたい演算子は "^" EOR (Exclusive OR, 時には XOR) です。この演算子は両方の値に設定されているビットを反転させます。以下は、 + EOR の真理値表です。 +
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
これは不思議なことですが、信じられないほど便利です。例えば、単純に0から1にカウントして0に戻る(0と1の間をトグルする)カウンターが欲しいとします。1つ追加して、 IF 、2になったかどうかを確認し、リセットして1に戻すということができます。あるいは...1個追加して、1個で AND ( 01+01 = 10, and 10 & 01 = 0 以降)、あるいはこうすることもできますね。
+これは不思議なことですが、信じられないほど便利です。例えば、単純に0から1にカウントして0に戻る(0と1の間をトグルする)カウンターが欲しいとします。1つ追加して、 IF + 、2になったかどうかを確認し、リセットして1に戻すということができます。あるいは...1個追加して、1個で AND ( 01+01 = + 10, and 10 & 01 = 0 以降)、あるいはこうすることもできますね。
a = a ^ 1;
-これは、1回目の実行時に 0 ^ 1 = 1 、2回目に 1 ^ 1 = 0 、それによって0から1へトグルで切り替わります。
-OR (|)、 AND(&)、 NOT(~)、 EOR(^) では、比較的簡単にビットを操作でき、最も単純なレベルでは、複数のビットを一度に制御することが可能です。sprites のマスク、 MOD の整数演算( AND を使用)、ループカウンタなど、ゲームを開発する際にこれらの演算を使用できることは明らかです。
-では、単純なビット演算はできるのですが、もっと複雑なものを見てみましょう。まず、「コンピュータの足し算はどうなっているのか」という疑問からです。非常に簡単な例を見てみましょう。 1+1.
+これは、1回目の実行時に 0 ^ 1 = 1 、2回目に 1 ^ 1 = 0 + 、それによって0から1へトグルで切り替わります。
+OR (|)、 AND(&)、 NOT(~)、 EOR(^) では、比較的簡単にビットを操作でき、最も単純なレベルでは、複数のビットを一度に制御することが可能です。sprites のマスク、 MOD の整数演算( AND + を使用)、ループカウンタなど、ゲームを開発する際にこれらの演算を使用できることは明らかです。
+では、単純なビット演算はできるのですが、もっと複雑なものを見てみましょう。まず、「コンピュータの足し算はどうなっているのか」という疑問からです。非常に簡単な例を見てみましょう。 1+1.
00000001
00000001
00000010
普通の足し算と同じように、数字を足し合わせて、次の列にオーバーフローさせるのですが、普通の10進数の足し算と違って、0から1までしかできず、0から9まではできないのです。つまり、 1+1 を足すと、オーバーフローして 10 になります。では、もっと複雑な例を見てみましょう。
+普通の足し算と同じように、数字を足し合わせて、次の列にオーバーフローさせるのですが、普通の10進数の足し算と違って、0から1までしかできず、0から9まではできないのです。つまり、 1+1 を足すと、オーバーフローして 10 になります。では、もっと複雑な例を見てみましょう。
01011011 = 91
00101101 = 45
10001000 = 136
ここでは明らかに見づらいですが、オーバーフローは列の中に1がなくなるまで波及します。注目すべきは、コンピュータは一度に2つの数しか加算(または減算、乗算、除算)できないことです。例えば 19 + 19 + 19 。人間であれば、9を全部足して、2を足し、さらに続けることができます。しかし、コンピュータにはそれができません。コンピュータにできるのは、次のようなことです: (19 + 19) + 19.だから、コンピュータは2つのブロックに分かれて計算をするのです。
-プログラマーとして最も関心のある2進数の計算は、掛け算と割り算です。コンピュータは2進数の掛け算しかしませんし、それ以上のことをするには、数字をバラバラにして、その結果をすべて足し算します。まず、非常に簡単な例を挙げてみよう。 4 * 2 = 8.さて、2進数で2を掛けるには、すべてのビットを1つ左にシフト します。こんな感じです。
+ここでは明らかに見づらいですが、オーバーフローは列の中に1がなくなるまで波及します。注目すべきは、コンピュータは一度に2つの数しか加算(または減算、乗算、除算)できないことです。例えば 19 + 19 + 19 + 。人間であれば、9を全部足して、2を足し、さらに続けることができます。しかし、コンピュータにはそれができません。コンピュータにできるのは、次のようなことです: (19 + 19) + + 19.だから、コンピュータは2つのブロックに分かれて計算をするのです。
+プログラマーとして最も関心のある2進数の計算は、掛け算と割り算です。コンピュータは2進数の掛け算しかしませんし、それ以上のことをするには、数字をバラバラにして、その結果をすべて足し算します。まず、非常に簡単な例を挙げてみよう。 + 4 * 2 = 8.さて、2進数で2を掛けるには、すべてのビットを1つ左にシフト します。こんな感じです。 +
00000100 * 2 = 00001000 = 8
この場合、すべてのビットが1つ左に移動し、3ビット目から4ビット目に移動し、値が4から8に変化しているのです。もっと大きな数字ではどうでしょう?
101 = 01100101 * 2 = 11001010 = 202
-ここでも、すべてのビットが1つずつ移動し、2の倍数になります。では、4の倍数はどうでしょうか。簡単です。すべてのビットを1つずつではなく、2つずつ左に移動させるのです。では、16倍、つまり128倍はどうでしょう?この場合、それぞれ4ビット、7ビットの左シフトが必要です。これは非常に便利なことで、ビットを移動させるだけで簡単な乗算ができるようになります。これを実現するために、左シフト演算子 << を使用します。以下はその例です。
++ ここでも、すべてのビットが1つずつ移動し、2の倍数になります。では、4の倍数はどうでしょうか。簡単です。すべてのビットを1つずつではなく、2つずつ左に移動させるのです。では、16倍、つまり128倍はどうでしょう?この場合、それぞれ4ビット、7ビットの左シフトが必要です。これは非常に便利なことで、ビットを移動させるだけで簡単な乗算ができるようになります。これを実現するために、左シフト演算子 + << を使用します。以下はその例です。 +
00000001 << 1 = 000000010 = 2
00000001 << 2 = 000000100 = 4
00000001 << 3 = 000001000 = 8
@@ -108,10 +166,15 @@
さて、高速・単純な乗算に非常に便利なのはもちろんですが、ビット値を把握することなく、特定のビットを設定するのにも非常に便利です。例えば、ビット27を設定したい場合、それは何番でしょうか?(ちなみに67108864です!)。上の構文を使って、flags を簡単に設定することができます。
++ さて、高速・単純な乗算に非常に便利なのはもちろんですが、ビット値を把握することなく、特定のビットを設定するのにも非常に便利です。例えば、ビット27を設定したい場合、それは何番でしょうか?(ちなみに67108864です!)。上の構文を使って、flags を簡単に設定することができます。
a = a | (1 << 27)
-なるほど...今までの説明では(ビットが1から始まっているので)これはビット26になりますが、実は...ビットはビット1からではなく、ビット0から始まり、上に向かっていきます。つまり、INTEGERには32ビットがありますが、ビットの範囲は0から31までで、1から32までではありません。これは、ビット数に対する定数を設定することができるため、実際にはかなり便利です。
-そこで、Bit27がactiveflag 、bit0がexplodingflag だとします。どうすれば両方を設定できるのでしょうか?
++ なるほど...今までの説明では(ビットが1から始まっているので)これはビット26になりますが、実は...ビットはビット1からではなく、ビット0から始まり、上に向かっていきます。つまり、INTEGERには32ビットがありますが、ビットの範囲は0から31までで、1から32までではありません。これは、ビット数に対する定数を設定することができるため、実際にはかなり便利です。 +
+そこで、Bit27がactiveflag 、bit0がexplodingflag + だとします。どうすれば両方を設定できるのでしょうか?
ACTIVE = 27;
BOOM = 0;
A = A | (1 << ACTIVE) | (1 << BOOM);
A = A | 13421772;
これらのビットをクリアするには(上で見たように)、次のようにNOT修飾子を使えばよいのです。
A = A & ~((1 << ACTIVE) | (1 << BOOM));
-このように、ビットの設定やクリアを自由に行えるので、データ構造を大幅に圧縮することができます。データ構造を圧縮することは良いことです。なぜなら、使用するメモリが少なければ、cache のミスが減り、コードの実行速度が速くなるからです。32MBのデータをコピーするのと、4MBのデータをコピーするのと、どちらが速いでしょうか?明らかに4MBの方が速いですよね。ですから、もしあなたがflags をすべて1回のメモリアクセスにまとめることができれば、これは良いことです!
-では、除算をどのように行うのか、なぜ除算が便利になるのか、簡単に説明しましょう。除算は、右シフト演算子( >> )を使ってビットを右にシフトすることで行われます。64という単純な数を32で割ってみましょう。
+このように、ビットの設定やクリアを自由に行えるので、データ構造を大幅に圧縮することができます。データ構造を圧縮することは良いことです。なぜなら、使用するメモリが少なければ、cache + のミスが減り、コードの実行速度が速くなるからです。32MBのデータをコピーするのと、4MBのデータをコピーするのと、どちらが速いでしょうか?明らかに4MBの方が速いですよね。ですから、もしあなたがflags をすべて1回のメモリアクセスにまとめることができれば、これは良いことです!
+では、除算をどのように行うのか、なぜ除算が便利になるのか、簡単に説明しましょう。除算は、右シフト演算子( >> + )を使ってビットを右にシフトすることで行われます。64という単純な数を32で割ってみましょう。
64 / 32 = 01000000 >> 5 = 00000010
そこで、1ビットを5だけシフトダウンして(これは32に必要なシフト数です - 上記を参照)、2を得ます。しかし、そこに他のビットがあるとどうなるでしょうか?さて、見てみましょう。
68 / 32 = 01000100 >> 5 = 00000010
-そうそう...。まったく同じです。シフトダウンしたビットは単に失われるだけです。これは実に便利なことです。なぜなら、割り算をするときに余りが必要なら、もっと簡単に余りを求める方法があるからです。その前に、実際の例を見てみましょう。XとYの位置があり、これが32x32の大きさのグリッドのどのセルに入るかを取得したい。この方法によって、objects 、衝突、flags など、あらゆるものを保存し、素早くアクセスすることができます。それでは、ご覧ください。
++ そうそう...。まったく同じです。シフトダウンしたビットは単に失われるだけです。これは実に便利なことです。なぜなら、割り算をするときに余りが必要なら、もっと簡単に余りを求める方法があるからです。その前に、実際の例を見てみましょう。XとYの位置があり、これが32x32の大きさのグリッドのどのセルに入るかを取得したい。この方法によって、objects 、衝突、flags + など、あらゆるものを保存し、素早くアクセスすることができます。それでは、ご覧ください。
var X_index = x >> 5;
var Y_index = y >> 5;
cell_data = mygrid[# X_index,Y_index];
では、余りを求めるとしたらどうだろう。もしかしたら、この余りは、ある種のオーダーflag として使われるのかもしれない。どんな理由であれ、余りを得るのは AND を実行するのと同じくらい簡単です。
+では、余りを求めるとしたらどうだろう。もしかしたら、この余りは、ある種のオーダーflag として使われるのかもしれない。どんな理由であれ、余りを得るのは AND を実行するのと同じくらい簡単です。
var remainder = x & 31
var X_Index = x >> 5;
さて、ここで何行ものコードを使ったことにお気づきかもしれませんが(よくあることです)、これはまだ非常に高速な命令を2つ並べただけなのです。しかし、なぜ31なのでしょうか?ビット5が32なので、その下のビットはすべて31になり、これが最大の余りなので、 AND 。( (1 << 5) - 1 も使えるので、 32 - 1 = 31 になります)。さて、もし私が2進法を理解せずにこれをやるとしたら、次のようになります。
++ さて、ここで何行ものコードを使ったことにお気づきかもしれませんが(よくあることです)、これはまだ非常に高速な命令を2つ並べただけなのです。しかし、なぜ31なのでしょうか?ビット5が32なので、その下のビットはすべて31になり、これが最大の余りなので、 + AND 。( (1 << 5) - 1 も使えるので、 32 - + 1 = 31 になります)。さて、もし私が2進法を理解せずにこれをやるとしたら、次のようになります。 +
var r = x mod 32;
var X_Index = floor(x / 32);
では、なぜこれほどまでに悪いのだろうか。32で割るためには、浮動小数点数の除算を実行しなければなりません。これは明らかに時間がかかりますが、 mod 32 を実行するために、実際にはもう1回実行しなければならないのですアセンブラでこれを行う場合、実際には1回の除算で2つの値が得られますが、高級言語ではこれができないので(まあ、あまりないことですが)、すべての作業を2回行わなければならないのです。特に、このような計算がたくさんあるタイトなloop を行っている場合は、これが積み重なります。上記のようなビットシフトを使った整数の割り算は、ゲームの最適化にとても役立ちます。
-この概念は、実際のプログラミングに適用するにはかなり複雑なため、以下にGameMakerで作成したゲームに適用できる短い例をいくつか示します。
+では、なぜこれほどまでに悪いのだろうか。32で割るためには、浮動小数点数の除算を実行しなければなりません。これは明らかに時間がかかりますが、 mod 32 + を実行するために、実際にはもう1回実行しなければならないのですアセンブラでこれを行う場合、実際には1回の除算で2つの値が得られますが、高級言語ではこれができないので(まあ、あまりないことですが)、すべての作業を2回行わなければならないのです。特に、このような計算がたくさんあるタイトなloop を行っている場合は、これが積み重なります。上記のようなビットシフトを使った整数の割り算は、ゲームの最適化にとても役立ちます。
+この概念は、実際のプログラミングに適用するにはかなり複雑なため、以下にGameMakerで作成したゲームに適用できる短い例をいくつか示します。 +
GameMakerの開発者は、よく関数 place_free() を使い、衝突が見つかったら、その関数を実行し続けながら x や y の位置をループするか、関数 move_outside_all() を使ってobject をゆっくりと移動させようとします。
-では、より高速に行うにはどうしたらよいのでしょうか。さて、適切なpower-of-2tiles を使えば、非常にシンプルな方法で、しかも電光石火の速さで処理することができます。右方向に動いていて、衝突ブロックに移動した場合、ご存知のようにすべてが 32 に整列されているので、sprite も 32 ピクセルの境界線(できれば左側の境界線)に整列する必要があり、sprite は衝突の外に移動します。これは本当に簡単で、上で余りを求めるのに使ったルールと、ビットの逆数を求める方法を知っていれば、単にこうすればいいのです。
+GameMakerの開発者は、よく関数 place_free() を使い、衝突が見つかったら、その関数を実行し続けながら x や y の位置をループするか、関数 move_outside_all() を使ってobject をゆっくりと移動させようとします。
+では、より高速に行うにはどうしたらよいのでしょうか。さて、適切なpower-of-2tiles + を使えば、非常にシンプルな方法で、しかも電光石火の速さで処理することができます。右方向に動いていて、衝突ブロックに移動した場合、ご存知のようにすべてが 32 に整列されているので、sprite も 32 ピクセルの境界線(できれば左側の境界線)に整列する必要があり、sprite + は衝突の外に移動します。これは本当に簡単で、上で余りを求めるのに使ったルールと、ビットの逆数を求める方法を知っていれば、単にこうすればいいのです。
x = x & ~31;
-そうです、これだけで、32ピクセルの境界線にアライメントすることができるのです。31を変更することで、2の累乗であれば、どのような位置にも合わせることができます(これは、32で割ってから32を掛けることで、下位ビットを削除することに相当します)。
-もし、右寄せにしたいのであれば、上記のようにしますが、次のtile に移動するために32を追加します。簡単ですね。このようにすることで、コリジョンコード全体が非常に速くなり、CPU時間を本当に必要なところに使うことができるようになります。
++ そうです、これだけで、32ピクセルの境界線にアライメントすることができるのです。31を変更することで、2の累乗であれば、どのような位置にも合わせることができます(これは、32で割ってから32を掛けることで、下位ビットを削除することに相当します)。 +
+もし、右寄せにしたいのであれば、上記のようにしますが、次のtile + に移動するために32を追加します。簡単ですね。このようにすることで、コリジョンコード全体が非常に速くなり、CPU時間を本当に必要なところに使うことができるようになります。
例えば、いくつかのドアがあり、それぞれに鍵があるレベルがあるとします。特定のドアのためのキーを簡単にマークするにはどうしたらいいでしょうか?通常、キーとドアにIDを割り当てるでしょう。では、1つのキーで2つ、3つのドアを開けたい場合はどうすればいいでしょうか?簡単です。MASKを使えばいいのです。ドアには、このように1ビットを割り当てます。
-
+ 例えば、いくつかのドアがあり、それぞれに鍵があるレベルがあるとします。特定のドアのためのキーを簡単にマークするにはどうしたらいいでしょうか?通常、キーとドアにIDを割り当てるでしょう。では、1つのキーで2つ、3つのドアを開けたい場合はどうすればいいでしょうか?簡単です。MASKを使えばいいのです。ドアには、このように1ビットを割り当てます。
+
door_id = 1; // 0001
他はこんな感じでしょうか。
-
door_id=2; // 0010
door_id=4; // 0100
door_id=8; // 1000
etc...
1と3の扉を開ける鍵にしたい場合、鍵のMASK値は5(2進数で101)です。これを AND 、「0でない」と出れば、その鍵はドアを開けられることが分かります。MASKが0であれば、何も開かない鍵もあります。実際のチェックは以下のコードを見てください。
+1と3の扉を開ける鍵にしたい場合、鍵のMASK値は5(2進数で101)です。これを AND + 、「0でない」と出れば、その鍵はドアを開けられることが分かります。MASKが0であれば、何も開かない鍵もあります。実際のチェックは以下のコードを見てください。
if ((key_id & door_id) ! = 0)
{
opendoor();
@@ -165,24 +254,34 @@
例えば、0から15までの単純なアニメーションカウンターを作りたいとします(16フレームのアニメーションがあるため)。通常は、インクリメントを行い、 if チェックを行い、数値を折り返しますが、この例では、 AND(&) 演算子を使用してみましょう。
+例えば、0から15までの単純なアニメーションカウンターを作りたいとします(16フレームのアニメーションがあるため)。通常は、インクリメントを行い、 if チェックを行い、数値を折り返しますが、この例では、 AND(&) 演算子を使用してみましょう。
counter = (counter + 1) & 15;
-16は2の累乗なので、その数を1減らしてマスクとし、それを使ってカウンタ値をラップすることができるのです。カウンタが15から16に上がると、ビットパターン 10000 、それを15(ビットパターン 01111 )で AND 、 00000 (単に0)で終わります。つまり、上記のコードは2のべき乗の範囲内で値をラップするのに有効です。
+16は2の累乗なので、その数を1減らしてマスクとし、それを使ってカウンタ値をラップすることができるのです。カウンタが15から16に上がると、ビットパターン 10000 、それを15(ビットパターン 01111 )で AND + 、 00000 (単に0)で終わります。つまり、上記のコードは2のべき乗の範囲内で値をラップするのに有効です。
何かが2のべき乗であるかどうかを確認したい場合はどうすればよいのでしょうか。ここでちょっとしたトリックを紹介しよう。これは、与えられた値が2のべき乗であれば、 true を返します。
+何かが2のべき乗であるかどうかを確認したい場合はどうすればよいのでしょうか。ここでちょっとしたトリックを紹介しよう。これは、与えられた値が2のべき乗であれば、 true を返します。
function is_pow2(_val)
{
return _val & (_val - 1)) == 0;
}
では、51という数字があったとしたら(110011 )、これはどうなるのでしょうか。さて、こうなります。 110011 & 110010これは明らかに、 AND の後にたくさんのビットが残っているので、 false となります。 64 (1000000) なら、こうなります... 1000000 & 0111111 これは0を残しているので、 true となります。
+では、51という数字があったとしたら(110011 )、これはどうなるのでしょうか。さて、こうなります。 110011 & 110010これは明らかに、 AND の後にたくさんのビットが残っているので、 false となります。 64 (1000000) なら、こうなります... 1000000 & 0111111 これは0を残しているので、 true となります。
2の累乗に揃えるための簡単なコードを紹介します。(1,2,4,8,16など)です。これは、メモリの割り当てや、データを適切な境界に書き込むことを確認するのに非常に便利です。この例では、 _val1 は _val2 バイトにアラインする必要があり、 _val2 は 2 の累乗の数字です。この小さな関数は、希望する数値の次の境界に丸めるのです。
+2の累乗に揃えるための簡単なコードを紹介します。(1,2,4,8,16など)です。これは、メモリの割り当てや、データを適切な境界に書き込むことを確認するのに非常に便利です。この例では、 + _val1 は _val2 バイトにアラインする必要があり、 _val2 は 2 の累乗の数字です。この小さな関数は、希望する数値の次の境界に丸めるのです。 +
function align_pow2(_val1, _val2)
{
return _val1 + (_val2 - 1)) & ~(_val2 - 1);
@@ -196,11 +295,12 @@
GameMaker の以前のバージョンからプロジェクトをインポートする際、プロジェクトに互換性のあるスクリプトが追加されているのを見かけることがあります。一般に、これらのscripts は、更新されたGameMaker Language (GML) 関数を使用します。 - は、古い機能を新しい方法に変換するもので、GameMakerでどのように物事を行うべきかを学ぶには最適な方法です。しかし、いくつかの関数は互換性のために使われているもので、決して使ってはいけないものです。 - また、あなた自身のプロジェクトにも使用しないでください。これらの互換性関数を識別するために、ここにリストアップされていますが、互換性スクリプト以外では決して使用しないようにしなければならないことを強調しておきます。
+GameMaker の以前のバージョンからプロジェクトをインポートする際、プロジェクトに互換性のあるスクリプトが追加されているのを見かけることがあります。一般に、これらのscripts は、更新されたGameMaker Language (GML) 関数を使用します。 + は、古い関数を新しい方法に変換するもので、GameMakerでどのように物事を行うべきかを学ぶには最適な方法です。しかし、いくつかの関数は互換性のために使われているもので、決して使ってはいけないものです。 + また、あなた自身のプロジェクトにも使用しないでください。これらの互換性関数を識別するために、ここにリストアップされていますが、互換性スクリプト以外では決して使用しないようにしなければならないことを強調しておきます。 +
旧バージョンのGameMaker からGameMakerをご利用の方は、プロジェクトassets 、編集、コーディングの方法がいくつか変更されているため、最初は少し戸惑うかもしれません。これらの変更により - IDEやGameMaker 言語(GML)では、以下の項目はサポートされていません。ただし、以下の項目がサポートされないというわけではありません。 - 以前のバージョンで作られたゲームをGameMakerにインポートすることはできませんので、インポートすることは可能です。GameMakerはすべての古い関数を自動的に互換スクリプトに変換します。互換スクリプトとは、scripts 。 - を更新することができます。
-GameMakerはあなたのプロジェクトを解析して、あなたが使っていた古い関数や変数をすべて見つけ出し、それらの関数名を使って一連のscripts を作成します。これらのscripts には、新しい同等の関数が含まれています。 - ランタイム関数、または廃止された関数と同じ動作をする短いスクリプト関数です。
+旧バージョンのGameMaker からGameMakerをご利用の方は、プロジェクトassets + 、編集、コーディングの方法がいくつか変更されているため、最初は少し戸惑うかもしれません。これらの変更により + IDEやGameMaker 言語(GML)では、以下の項目はサポートされていません。ただし、以下の項目がサポートされないというわけではありません。 + 以前のバージョンで作られたゲームをGameMakerにインポートすることはできませんので、インポートすることは可能です。GameMakerはすべての古い関数を自動的に互換スクリプトに変換します。互換スクリプトとは、scripts 。 + を更新することができます。 +
+GameMakerはあなたのプロジェクトを解析して、あなたが使っていた古い関数や変数をすべて見つけ出し、それらの関数名を使って一連のscripts を作成します。これらのscripts には、新しい同等の関数が含まれています。 + ランタイム関数、または廃止された関数と同じ動作をする短いスクリプト関数です。 +
GameMakerのプロジェクトを初めてインポートするとき、このような互換性レポートが表示されます。
-レポートの本文には、どのobjects とscripts がどこで影響を受けたかが示され、末尾には
- には、プロジェクトで作成されたscripts のリストが表示されます。レポートに記載されているscripts のいずれかをマウスの中ボタン
でクリックするか、
を押して開くと、何が行われたかを確認することができます。
もし、名前の前に二重のアンダーバーが付いたscripts が作成された場合(例: __global_object_depths )、これらは互換性を保つためにscripts によって作成されたIDE であり、スクリプトではないことに注意してください。 - 他の互換機能(scripts )を動作させるために必要なものなので、いじらないようにしてください。
-互換性レポートの修正が完了したら、workspace を閉じますが、レポート内の何かを修正する必要がある場合は、「ノート」セクションの - アセットブラウザ
-これらの互換性scripts は、レガシーバージョンGameMaker で使用していた関数と同じように使い続けることができますが、その動作方法によって、パフォーマンスに影響があることに注意してください。私たちは、以下のことをお勧めします。 - 新しいメソッドを直接使用するようにプロジェクトを更新し、互換性scripts を削除することができれば、パフォーマンスが向上し、また、GameMakerとGameMaker Language が従来の製品と比較してどのように動作するかを理解することができます。
-また、古いプロジェクトとの互換性を確保するためにGameMaker Language に導入された関数があり、これらの互換性scripts に表示されることに注意してください。しかし、これらの関数はあなた自身のプロジェクトでは決して使ってはいけません。 +
レポートの本文には、どのobjects とscripts
+ がどこで影響を受けたかが示され、末尾には
+ には、プロジェクトで作成されたscripts のリストが表示されます。レポートに記載されているscripts のいずれかをマウスの中ボタン
でクリックするか、
を押して開くと、何が行われたかを確認することができます。
もし、名前の前に二重のアンダーバーが付いたscripts が作成された場合(例: __global_object_depths )、これらは互換性を保つためにscripts + によって作成されたIDE であり、スクリプトではないことに注意してください。 + 他の互換関数(scripts )を動作させるために必要なものなので、いじらないようにしてください。
+互換性レポートの修正が完了したら、workspace を閉じますが、レポート内の何かを修正する必要がある場合は、「ノート」セクションの + アセットブラウザ +
+これらの互換性scripts は、レガシーバージョンGameMaker + で使用していた関数と同じように使い続けることができますが、その動作方法によって、パフォーマンスに影響があることに注意してください。私たちは、以下のことをお勧めします。 + 新しいメソッドを直接使用するようにプロジェクトを更新し、互換性scripts を削除することができれば、パフォーマンスが向上し、また、GameMakerとGameMaker Language + が従来の製品と比較してどのように動作するかを理解することができます。
+また、古いプロジェクトとの互換性を確保するためにGameMaker Language に導入された関数があり、これらの互換性scripts に表示されることに注意してください。しかし、これらの関数はあなた自身のプロジェクトでは決して使ってはいけません。 これらの関数の一覧は、マニュアルの次のセクションで見ることができます。
-また、廃止された関数のうち、同等の互換性(scripts )が作成されている関数の一覧は、以下のページで確認できます。
+また、廃止された機能のうち、同等の互換性(scripts )が作成されている機能の一覧は、以下のページで確認できます。
@@ -44,11 +67,12 @@エラー報告の最初の形式はシンタックスエラーです。これはコンパイルする前にGameMakerがキャッチしたコードのエラーで、IDE 、コードエディタかシンタックスエラー出力ウインドウに表示されます。
-次のレベルのエラーレポートは、コンパイラーエラーです。このタイプのエラーはランナーエラーよりも一般的で、ゲームコード内の微妙なエラーが原因で、実行する前にコンパイル中にクラッシュすることがあります。これらのエラーも、コンパイラーエラー出力ウィンドウに報告されます。
エラー報告の最初の形式はシンタックスエラーです。これはコンパイルする前にGameMakerがキャッチしたコードのエラーで、IDE 、コードエディタかシンタックスエラー出力ウインドウに表示されます。
+次のレベルのエラーレポートは、コンパイラーエラーです。このタイプのエラーはランナーエラーよりも一般的で、ゲームコード内の微妙なエラーが原因で、実行する前にコンパイル中にクラッシュすることがあります。これらのエラーも、コンパイラーエラー出力ウィンドウに報告されます。
ゲームがコンパイルされ、エラーが発生した場合、Runner Errorが表示されます。このタイプのエラーは、以下のようなメッセージが画面に表示されます。
ほとんどのランナーエラーメッセージは、エラーの種類、エラーが発生したインスタンスとイベント、そしてエラーの詳細を説明する一連のランナー詳細、最後にその時点でゲーム内で宣言されているすべてのグローバル変数、インスタンス変数、ローカル変数のリストという、同じアウトラインに従っています。一番下には、ゲームを中断するAbort ボタンと、エラーをクリップボードにコピーするCopy ボタン、そしてエラーメッセージをウィンドウから消去するClear ボタンがあります。このエラーレポートによって提供される情報は、完成したゲームをクラッシュさせるような大規模な構文関連のバグを検出して報告するため、非常に重要です。
+ ほとんどのランナーエラーメッセージは、エラーの種類、エラーが発生したインスタンスとイベント、そしてエラーの詳細を説明する一連のランナー詳細、最後にその時点でゲーム内で宣言されているすべてのグローバル変数、インスタンス変数、ローカル変数のリストという、同じアウトラインに従っています。一番下には、ゲームを中断するAbort
+ ボタンと、エラーをクリップボードにコピーするCopy ボタン、そしてエラーメッセージをウィンドウから消去するClear
+ ボタンがあります。このエラーレポートによって提供される情報は、完成したゲームをクラッシュさせるような大規模な構文関連のバグを検出して報告するため、非常に重要です。
+
次のページでは、Syntax、Runner、Compilerの各エラーについて、その意味を説明します。
ゲームに報告されるエラーの2つ目のタイプは、コンパイラエラーです。コンパイラエラーは、シンタックスチェッカーが検出できないようなエラーが発生したときに起こります。例えば、変数の宣言を忘れたり、string を real と間違えて入力したりすることはよくあります。また、ターゲットプラットフォーム用にPlatform Preferencesから設定したコンパイルツールに関連するエラーが発生した場合にも起こります。これらのエラーは、ゲームがコンパイルされる際にGameMakerによって検出され、以下のようにCompiler Error Output にその情報が表示されます。
-
注これらのエラーは通常、ウィンドウをポップアップせず、コンパイラの出力に「Build Failed」と表示されるだけです。もし、ウィンドウが表示される場合は、通常ランナーエラーです。
++ ゲームに報告されるエラーの2つ目のタイプは、コンパイラエラーです。コンパイラエラーは、シンタックスチェッカーが検出できないようなエラーが発生したときに起こります。例えば、変数の宣言を忘れたり、string を real と間違えて入力したりすることはよくあります。また、ターゲットプラットフォーム用にPlatform + Preferencesから設定したコンパイルツールに関連するエラーが発生した場合にも起こります。これらのエラーは、ゲームがコンパイルされる際にGameMakerによって検出され、以下のようにCompiler Error Output にその情報が表示されます。
+
注これらのエラーは通常、ウィンドウをポップアップせず、コンパイラの出力に「Build Failed」と表示されるだけです。もし、ウィンドウが表示される場合は、通常ランナーエラーです。
コンパイラのエラーメッセージは、すべて同じフォーマットで表示されます。
[object] - [event] - [Line Number]: [error string]
もし、script でエラーが見つかった場合は、単純にそうなります。
[script] - [Line Number]: [error string]
- そして、コンパイラーエラーエントリーのどれかをダブルクリックすると、エラーが発生したとフラグが立った位置のasset が表示され、メッセージに含まれる情報を使ってobject またはscript のどこでエラーが発生したかを正確に特定できます。しかし、これらのエラーは少し不可解に見えることがあるので、以下にすべてのエラーの完全なリストとその意味の簡単な説明を掲載します。
そして、コンパイラーエラーエントリーのどれかをダブルクリックすると、エラーが発生したとフラグが立った位置のasset
+ が表示され、メッセージに含まれる情報を使ってobject またはscript
+ のどこでエラーが発生したかを正確に特定できます。しかし、これらのエラーは少し不可解に見えることがあるので、以下にすべてのエラーの完全なリストとその意味の簡単な説明を掲載します。
| エラー | -商品説明 | +説明 | |
|---|---|---|---|
| + |
その他 |
||
| Fatal Error while compiling[name]- bailing details below. | -このメッセージは、単に何らかのエラーが発見されたが、コンパイラが何を、どこで、どうしたのか特定できないことを意味します(このような現象が何度も起こる場合は、サポートに連絡して、コンパイラの出力ウィンドウが示す詳細を提供するとよいでしょう)。 | +このメッセージは、単に何らかのエラーが発見されたが、コンパイラが何を、どこで、どうしたのか特定できないことを意味します(このような現象が何度も起こる場合は、サポートに連絡して、コンパイラの出力ウィンドウが示す詳細を提供するとよいでしょう)。 | |
| 再帰的なマクロ展開には対応していません | @@ -53,7 +69,9 @@|||
| TextureGroupが見つからない [group] | -このエラーは通常、不正なプロジェクトファイルを実行しようとした場合にのみ発生します(このような現象が頻繁に発生する場合は、サポートに連絡して、コンパイラの出力ウィンドウに表示される詳細を提供するとよいでしょう)。 | +このエラーは通常、不正なプロジェクトファイルを実行しようとした場合にのみ発生します(このような現象が頻繁に発生する場合は、サポートに連絡して、コンパイラの出力ウィンドウに表示される詳細を提供するとよいでしょう)。 | |
| [value] を数値に変換するのが間違っている | @@ -87,7 +105,8 @@ファイル機能使用中に予期せずファイルの末尾に到達した場合 | ||
| + |
ストリングス |
||
| + |
スクリプトです。 関数 と引数 |
||
| action_execute_script() のパースに失敗しました - 受け取った引数の数が正しくありません。 | -GML Visual アクションの実行Script は、呼び出される指定されたscript に対して引数が多すぎるか、少なすぎる。 | +GML Visual アクションの実行Script + は、呼び出される指定されたscript に対して引数が多すぎるか、少なすぎる。 | |
| 不明な関数 [function] script が空かどうかのチェック | -コンパイラが認識できないscript または関数が呼び出された (このエラーは通常、空のscript asset 参照で発生します。コンパイラはコンパイル時にこれらのassets を削除します)。 | +コンパイラが認識できないscript または関数が呼び出された (このエラーは通常、空のscript asset 参照で発生します。コンパイラはコンパイル時にこれらのassets を削除します)。 | |
| 関数 [function] は n の引数を期待し、 a は提供される。 | -nある関数が、ある数の引数を想定していたのに、間違った数の引数を与えてしまった (a) | +関数 [function] は n の引数を期待し、 a は提供される。 | +nある関数が、ある数の引数を想定していたのに、間違った数の引数を与えてしまった (a) |
| 空値の代入(関数が何も返さない?) | @@ -136,11 +161,16 @@|||
| 他の関数が必要で、他の関数が利用できない関数の呼び出し | -コリジョンイベントの外、または with の文の外で、キーワード other を使っていますね。 | +コリジョンイベントの外、または with の文の外で、キーワード other を使っていますね。 + | |
| Argument naming error, n arguments but no reference found to the a | -script にいくつかの引数を与えたが、そのうちの1つをscript で参照していない。例えば、script は3つの引数を取るが、引数 n と しか使っていない。 a | +Argument naming error, n arguments but no reference found to the a | +script にいくつかの引数を与えたが、そのうちの1つをscript + で参照していない。例えば、script は3つの引数を取るが、引数 n と しか使っていない。 + a + |
| 引数の比較ができない | @@ -178,7 +208,8 @@評価される式の引数の型が間違っています。 | ||
| + |
変数 |
読み取り専用に設定された変数を使用しようとしました。 | |
| + |
定数 |
名前付き定数に新しい値を代入しようとしました。 | |
| + |
アレイ(配列 |
負の配列インデックスを使用して配列値にアクセス、作成、または設定しようとしました。 | |
| + |
不正な... |
||
| グローバルな gml_pragma の不具合 | -を使用する際に、間違ったグローバルstring を作成しています。 gml_pragma | +を使用する際に、間違ったグローバルstring を作成しています。 gml_pragma + | |
| 不正な PNGCrush gml_pragma | -PNGCrushを使用する際に、誤ったstring コマンドを作成しています。 gml_pragma | +PNGCrushを使用する際に、誤ったstring コマンドを作成しています。 gml_pragma | |
| Texgroup.Scale の gml_pragma が不正。 | -を使用する場合、間違ったグローバルstring を作成しています。 gml_pragma | +を使用する場合、間違ったグローバルstring を作成しています。 gml_pragma + | |
| + |
スイッチ/ケース |
||
| 句式タイプの不一致(句式はすべて同じタイプであるべきです。) | -あなたのswitch では、2つの異なる定数ケースタイプをチェックしています。例えば、あるケースではstring を、別のケースでは整数をチェックします。 | +あなたのswitch では、2つの異なる定数ケースタイプをチェックしています。例えば、あるケースではstring を、別のケースでは整数をチェックします。 | |
| ケース引数は定数であるべき | @@ -304,14 +343,17 @@|||
| switch のステートメントは、case または default の後に表示されなければならない(MUST)。 | -case: または default: のどちらかの呼び出しの外側で、switch にステートメントを追加しています。 | +case: または default: のどちらかの呼び出しの外側で、switch にステートメントを追加しています。 | |
| 重複する事例を発見/オリジナルはこちら | -switch 内の2か所で同じ case 定数を使用しています (「元のここ」というコメントが別の行に表示され、クリックすると元の case が表示されることに注意してください)。 | +switch 内の2か所で同じ case 定数を使用しています (「元のここ」というコメントが別の行に表示され、クリックすると元の case + が表示されることに注意してください)。 | |
| + |
エクスプレッション |
この式では、許可された式のシンボルセットに含まれていないシンボルを使用しています - 問題のシンボルは表示されます。 | |
| + |
未知のオペレーター |
||
| 不明 プリオペレーター | -例えば、 **[var] や >>[var] のように、使用できない記号をプリ・オペレーターとして使用しようとした場合、 ++ と -- だけが許容されます。 | +例えば、 **[var] や >>[var] + のように、使用できない記号をプリ・オペレーターとして使用しようとした場合、 ++ と -- + だけが許容されます。 | |
| 不明 ポストオペレーター | -例えば、 [var]** や [var]>> のように、使用できない記号をポストオペレータとして使用しようとした場合、 ++ と -- のみが許容されます。 | +例えば、 [var]** や [var]>> + のように、使用できない記号をポストオペレータとして使用しようとした場合、 ++ と -- + のみが許容されます。 | |
| 不明なプラグマ [gml_pragma string]。 | @@ -357,13 +404,15 @@未知の記号を演算子として使用しようとしました(記号はエラーに表示されます)。 | ||
| + |
ブレーク/コンティニュー |
||
| 文脈を無視して使用されるブレーク | -switch またはloop またはその他の許可された構造内で break を使用していないこと。 | +switch またはloop またはその他の許可された構造内で break + を使用していないこと。 | |
| 文脈を無視して使用し続ける | @@ -374,7 +423,8 @@コードの一部でcontinueが許可されていない箇所でcontinueを使用している。 | ||
| + |
エンムス |
その列挙型に定義されていないキーを使用して、列挙型項目を参照しようとしました。 | |
| + |
期待される記号・値 |
演算子を必要とする代入を作成したが、演算子が指定されていない場合 | |
| + |
Android専用 |
||
| AndroidARM ToolChain ディレクトリ [dir] が存在しない。 | -Android Preferences で指定されたARM toolchain のリンクは正しくなく、存在しません。 | +Android Preferences で指定されたARM toolchain + のリンクは正しくなく、存在しません。 | |
| Android MIPS ToolChain ディレクトリ [dir] が存在しない。 | @@ -460,7 +513,8 @@|||
| Android NDK ディレクトリ [dir] が存在しない。 | -Android Preferences に記載されているAndroid NDK へのリンクは正しくなく、存在しません。 | +Android Preferences に記載されているAndroid NDK + へのリンクは正しくなく、存在しません。 | |
@@ -468,8 +522,11 @@ コンパイルエラー |
|||
| 設定上の問題 :Windows Visual Studio Path がVisual Studio (.bat) バッチファイルを指すように設定する必要があります。 | -Windows Preferences にあるVisual Studio (.bat) バッチファイルのリンクが正しくなく、存在しない。 | +設定上の問題 :Windows Visual Studio Path がVisual Studio (.bat) + バッチファイルを指すように設定する必要があります。 | +Windows Preferences にあるVisual Studio + (.bat) バッチファイルのリンクが正しくなく、存在しない。 |
コードエディターで構文チェックを行い、コンパイラーでコンパイラーエラーをチェックした後でも、何か問題が発生する場合があります。ほとんどの場合、次のような仮想マシン(VM)ランナーエラー(実行時例外とも呼ばれる)が投げられます。
-ランナーエラーは一般的にコンパイルエラーよりも深刻で、コードエディターやコンパイラーが検出できない何か深刻な問題がコードにあることを意味します。エラーが発生したら、ポップアップのコピーボタンを使って、そのエラーをクリップボードにコピーし、テキストファイルなどに貼り付けて参照することができます。
コードエディタで構文チェックを行い、コンパイラーでコンパイラーエラーをチェックした後でも、何か問題が発生する場合があります。ほとんどの場合、次のような仮想マシン(VM)ランナーエラー(実行時例外とも呼ばれる)が投げられます。 +
+
+ ランナーエラーは一般的にコンパイルエラーよりも深刻で、コードエディタやコンパイラーが検出できない何か深刻な問題がコードにあることを意味します。エラーが発生したら、ポップアップのコピーボタンを使って、そのエラーをクリップボードにコピーし、テキストファイルなどに貼り付けて参照することができます。
+
このエラーの構造は以下の通りです。
上記のように、ある種のエラーメッセージは、インスタンスIDの値ではなく、負の 値によってスコープを識別します。これらの値は、エラーの正確な性質と、それが何を指しているかを特定するために、以下のような値が考えられます。
+上記のように、ある種のエラーメッセージは、インスタンスIDの値ではなく、負の + 値によってスコープを識別します。これらの値は、エラーの正確な性質と、それが何を指しているかを特定するために、以下のような値が考えられます。
| エラー | メッセージ | 操作方法 | -商品説明 | +説明 | |||
|---|---|---|---|---|---|---|---|
| DoSet | -無効な比較タイプ | +DoSet | ++ 無効な比較タイプ | データの種類 | -これは、ランナーが実数とstring のような、互換性のない2つのデータ型を比較しようとしたことを表します。 | +これは、ランナーが実数とstring のような、互換性のない2つのデータ型を比較しようとしたことを表します。 | |
| DoConv | -実行エラー | +DoConv | ++ 実行エラー | データの種類 | -これは、あるデータ型から別のデータ型への変換にエラーがあることを意味します。 | ++ これは、あるデータ型から別のデータ型への変換にエラーがあることを意味します。 | |
| + |
|
||||||
| DoAdd | -実行エラー | +DoAdd | ++ 実行エラー | 算数・数学 | -加算式(+)を使用する際に何か問題が発生したようです。 | +加算式(+)を使用する際に何か問題が発生したようです。 | |
| DoMul | -実行エラー | +DoMul | ++ 実行エラー | 算数・数学 | -乗算 (*) 式を使用する際に何か問題が発生しました。 | +乗算 (*) 式を使用する際に何か問題が発生しました。 | |
| DoSub | -実行エラー | +DoSub | ++ 実行エラー | 算数・数学 | -引き算(-)式の使用時に何か問題が発生したようです。 | +引き算(-)式の使用時に何か問題が発生したようです。 | |
| DoSub | -実行エンジン -string タイプで操作できません。 | +DoSub | ++ 実行エンジン -string タイプで操作できません。 | 算数・数学 | -間違ったタイプの変数を引き算しようとしている(例えば、実数からstring を引き算する)。 | ++ 間違ったタイプの変数を引き算しようとしている(例えば、実数からstring を引き算する)。 | |
| DoDiv | -実行エラー | +DoDiv | ++ 実行エラー | 算数・数学 | -除算(/ または div )式を使用すると、何か問題が発生します。 | +除算(/ または div )式を使用すると、何か問題が発生します。 | |
| DoDiv | -実行エンジン -string タイプで操作できません。 | +DoDiv | ++ 実行エンジン -string タイプで操作できません。 | 算数・数学 | -間違ったタイプの変数を除算しようとしている(例えば、string を実数で除算する)。 | ++ 間違ったタイプの変数を除算しようとしている(例えば、string を実数で除算する)。 | |
| DoDiv | -ゼロで割る | +DoDiv | ++ ゼロで割る | 算数・数学 | -0で割ろうとしている(これは整数の割り算のときだけ起こることに注意。(0でない)実数を0で割ると無限大、0で割るとNaNが答えになる)。これらの値は (is_infinity) と (is_nan) で確認することができます。 | ++ 0で割ろうとしている(これは整数の割り算のときだけ起こることに注意。(0でない)実数を0で割ると無限大、0で割るとNaNが答えになる)。これらの値は (is_infinity) と (is_nan) で確認することができます。 | |
| DoMod | -実行エラー | +DoMod | ++ 実行エラー | 算数・数学 | -modulo (mod) 式を使用する際に何か問題が発生したようです。 | +modulo (mod) 式を使用する際に何か問題が発生したようです。 | |
| DoMod | -実行エンジン -string タイプで操作できません。 | +DoMod | ++ 実行エンジン -string タイプで操作できません。 | 算数・数学 | -modulo (mod) を間違ったタイプの変数に使おうとしています (例: mod astring by a real). | +modulo (mod) を間違ったタイプの変数に使おうとしています (例: mod astring by a real). | |
| + |
|
||||||
| DoAnd | -実行エラー | +DoAnd | ++ 実行エラー | ビット単位 | -ビット単位の "and" (&) 式を使用すると、何か問題が発生しました。 | +ビット単位の "and" + (&) 式を使用すると、何か問題が発生しました。 | |
| DoAnd | -実行エンジン -string タイプで操作できません。 | +DoAnd | ++ 実行エンジン -string タイプで操作できません。 | ビット単位 | -ビット単位の「と」(&)を間違った型の変数に使おうとしています(例えば、string と実数を「と」しようとしています)。 | +ビット単位の「と」(&)を間違った型の変数に使おうとしています(例えば、string + と実数を「と」しようとしています)。 | |
| DoOr | -実行エラー | +DoOr | ++ 実行エラー | ビット単位 | -ビット単位の "or" (|) 式を使用すると、何か問題が発生しました。 | +ビット単位の "or" + (|) 式を使用すると、何か問題が発生しました。 | |
| DoOr | -実行エンジン -string タイプで操作できません。 | +DoOr | ++ 実行エンジン -string タイプで操作できません。 | ビット単位 | -間違ったタイプの変数に "or" (|) を使おうとしています (例えばstring を実数で "or" しようとしています)。 | +間違ったタイプの変数に + "or" (|) を使おうとしています (例えばstring を実数で + "or" しようとしています)。 | |
| DoXor | -実行エラー | +DoXor | ++ 実行エラー | ビット単位 | -ビット単位の「xor」(^) 式を使用すると、何か問題が発生しました。 | +ビット単位の「xor」(^) 式を使用すると、何か問題が発生しました。 | |
| DoXor | -実行エンジン -string タイプで操作できません。 | +DoXor | ++ 実行エンジン -string タイプで操作できません。 | ビット単位 | -xor" (^) を間違ったタイプの変数に使おうとしています (例えばstring と実数を "xor" しようとしています)。 | +xor" (^) を間違ったタイプの変数に使おうとしています (例えばstring と実数を + "xor" しようとしています)。 | |
| DoShl | -実行エラー | +DoShl | ++ 実行エラー | ビット単位 | -値を左にビットシフト(<< )する際に何か問題が発生した。 | +値を左にビットシフト(<< )する際に何か問題が発生した。 | |
| DoShl | -実行エンジン -string タイプで操作できません。 | +DoShl | ++ 実行エンジン -string タイプで操作できません。 | ビット単位 | -間違ったタイプの変数を左ビットシフト (<<) しようとしています (例えばstring をビットシフトしようとしています)。 | +間違ったタイプの変数を左ビットシフト + (<<) しようとしています (例えばstring + をビットシフトしようとしています)。 | |
| DoShr | -実行エラー | +DoShr | ++ 実行エラー | ビット単位 | -値を右ビットシフト(>> )する際に何か問題が発生した。 | +値を右ビットシフト(>> )する際に何か問題が発生した。 | |
| DoShr | -実行エンジン -string タイプで操作できません。 | +DoShr | ++ 実行エンジン -string タイプで操作できません。 | ビット単位 | -間違ったタイプの変数を右ビットシフト(>> )しようとしている(例えば、string をビットシフトしようとしている)。 | +間違ったタイプの変数を右ビットシフト(>> )しようとしている(例えば、string をビットシフトしようとしている)。 | |
| + |
|
||||||
| DoNeg | -実行エラー | +DoNeg | ++ 実行エラー | ネゲート | -この型がそのような操作を許可していないのに、変数の型を負に変えようとしている。 | ++ この型がそのような操作を許可していないのに、変数の型を負に変えようとしている。 | |
| DoNot | -実行エラー | +DoNot | ++ 実行エラー | ネゲート | -変数の型がそのような操作を許可していないのに、"not "としようとしている。 | ++ 変数の型がそのような操作を許可していないのに、"not "としようとしている。 | |
| + |
|
||||||
| Push | -実行エラー - 変数インデックスが範囲外(var) | +Push | ++ 実行エラー - 変数インデックスが範囲外(var) | スタック | -アクセスされる変数がランナーに設定された範囲から外れている。 | ++ アクセスされる変数がランナーに設定された範囲から外れている。 | |
| Push | -変数取得(var) | +Push | ++ 変数取得(var) | スタック | -与えられた変数が定義されていないか、不明である。 | +与えられた変数が定義されていないか、不明である。 + | |
| Pop | -変数インデックスが範囲外(var) | +Pop | ++ 変数インデックスが範囲外(var) | スタック | -アクセスされる変数がランナーに設定された範囲から外れている。 | ++ アクセスされる変数がランナーに設定された範囲から外れている。 | |
| Pop | -変数取得(var) | +Pop | ++ 変数取得(var) | スタック | -与えられた変数が定義されていないか、不明である。 | +与えられた変数が定義されていないか、不明である。 + | |
| + |
|
||||||
| With | -withステートメントでグローバルは使用できません。 | +With | ++ withステートメントでグローバルは使用できません。 | と | -with" 文の中で "global" を変数として使おうとしていますね。 + | with" 文の中で "global" を変数として使おうとしていますね。 with (global) { //do something; @@ -272,10 +405,14 @@ ランナーエラー |
|
| With | -withステートメントでローカルを使用できない | +With | ++ withステートメントでローカルを使用できない | と | -with" 文の中で "local" を変数として使おうとしていますね。 + | with" 文の中で "local" を変数として使おうとしていますね。 with (local) { //do something; @@ -283,21 +420,33 @@ ランナーエラー |
|
| + |
|
||||||
| DoCall | -実行エンジンのタイプエラー | +DoCall | ++ 実行エンジンのタイプエラー | エンジン | -これは、Virtual Machine 内のundefined のエラーです。このような場合は、バグレポートを提出してください(バグレポートの作成方法については、ヘルプメニューを参照してください)。 | +これは、Virtual Machine + 内のundefined + のエラーです。このような場合は、バグレポートを提出してください(バグレポートの作成方法については、ヘルプメニューを参照してください)。 | |
| Stack Overflow | -- | +Stack Overflow | ++ - | エンジン | -スタックオーバーフローは、コールスタックで使用されるメモリが多すぎる場合に発生し、ゲームがコールスタックで使用可能な容量以上の領域を使用しようとした場合(つまり、コールスタックの境界を超えてメモリにアクセスしようとした場合、これは本質的にbuffer オーバーフローです)、スタックはオーバーフローすると言われ、結果としてプログラムがクラッシュすることになります。コンピュータとGameMakerを再起動し、エラーが続くようであれば、サポートに連絡するか、バグを報告してください(上記で説明したとおり)。 | ++ スタックオーバーフローは、コールスタックで使用されるメモリが多すぎる場合に発生し、ゲームがコールスタックで使用可能な容量以上の領域を使用しようとした場合(つまり、コールスタックの境界を超えてメモリにアクセスしようとした場合、これは本質的にbuffer オーバーフローです)、スタックはオーバーフローすると言われ、結果としてプログラムがクラッシュすることになります。コンピュータとGameMakerを再起動し、エラーが続くようであれば、サポートに連絡するか、バグを報告してください(上記で説明したとおり)。 | |
GameMakerでゲームをプログラミングする際のエラー報告の第一レベルは、コードまたはGML Visualエディタにある、シンタックスチェッカー(SyntaxChecker)です。コードを書いたり、アクションを追加すると、GameMakerはその言語で確立されたシンタックスに従っているかどうかをチェックし、問題があればflag 、ゲームの実行や実行ファイルのコンパイルに入る前に修正することができます。
-シンタックスエラーのチェックは、Feather Settingsで Featherを有効にしているかどうかで、動作が異なります。
+GameMakerでゲームをプログラミングする際のエラー報告の第一レベルは、コードまたはGML Visualエディタにある、シンタックスチェッカー(SyntaxChecker)です。コードを書いたり、アクションを追加すると、GameMakerはその言語で確立されたシンタックスに従っているかどうかをチェックし、問題があればflag 、ゲームの実行や実行ファイルのコンパイルに入る前に修正することができます。
+シンタックスエラーのチェックは、Feather + Settingsで Featherを有効にしているかどうかで、動作が異なります。


これらのエラーは大きく2つに分類されます。
構文エラーは、コードを書くと更新され(未完成のコードに対してエラーが報告されるのを防ぐため、何かをタイプしてからこのウィンドウにエラーが表示されるまでに短い間があります)、その形式に従って表示されます。
[object] - [event] - [Line Number] - [Position In Line]: [error string]
あるいは、エラーがscript にある場合、そうなります。
[script] - [Line Number] - [Position in line]: [error string]
- 出力コンソールに表示されたエラーのいずれかをダブルクリックすると、object イベントまたはscript のエラーのある行に移動し、その行を編集することができます。
出力コンソールに表示されたエラーのいずれかをダブルクリックすると、object イベントまたはscript のエラーのある行に移動し、その行を編集することができます。
これらのエラーの中には、コードの特定の場所に表示されるものもありますが、実際のエラーは他の場所に原因があったり、1つの問題で複数のエラーメッセージが発生する場合もありますので、注意が必要です。
-上の画像では、3つの
エラーはすべて、関数 variable_instance_exists() の220行目で、カンマ "," の代わりにセミコロン ";" を使ってしまったという、たった一つのミスによって引き起こされているのです。
上の画像では、3つの
エラーはすべて、関数 variable_instance_exists() の220行目で、カンマ "," の代わりにセミコロン ";"
+ を使ってしまったという、たった一つのミスによって引き起こされているのです。
以下の表は、さまざまなシンタックスエラーとその主な原因を示しています。
@@ -39,215 +56,451 @@








Featherを有効にすると、Syntax ErrorsウィンドウはFeather Messagesウィンドウに置き換わります。
-Feather Messages ウィンドウには、Feather がコード内で遭遇したエラーと警告、および特定のコードパターンを発見したときに表示されるサジェストが一覧表示されます。どのような種類のエラーが表示されるかは、Feather Settingsの Message Severity で定義したプロファイルに依存します。
このウィンドウでは、メッセージのリストをメッセージコード、メッセージテキスト(アルファベット順)、リソース(リソース名のアルファベット順)で昇順または降順にソートすることができます。また、ウィンドウの右上にある検索ボックスを使って検索することもできます。
+Feather Messages ウィンドウには、Feather
+ がコード内で遭遇したエラーと警告、および特定のコードパターンを発見したときに表示されるサジェストが一覧表示されます。どのような種類のエラーが表示されるかは、Feather Settingsの Message
+ Severity で定義したプロファイルに依存します。
+ このウィンドウでは、メッセージのリストをメッセージコード、メッセージテキスト(アルファベット順)、リソース(リソース名のアルファベット順)で昇順または降順にソートすることができます。また、ウィンドウの右上にある検索ボックスを使って検索することもできます。 +
フェザーメッセージは、3つのカテゴリーに分類されます。
このガイドでは、カスタム頂点フォーマットと 頂点バッファを使用したプリミティブの構築と使用方法について簡単に説明します。
-一般に、3D、特殊効果、複雑な描画処理、shaders を扱うようになると、GameMakerが自動的に頂点データをセットアップして渡してくれるので、vertex の形式をあまり気にする必要はないでしょう。しかし、速度を上げる必要がある場合や、余分な情報を渡したい場合など、独自にvertex データを作成し、適切なフォーマットにすることが必要な場合があります。例えば、標準のvertex フォーマットは、x, y, z の 3D ポジション、カラー(アルファ付き)、UVtexture 座標を含み、自分で作成する場合、次のようになります。
+このガイドでは、カスタム頂点フォーマットと 頂点バッファを使用したプリミティブの構築と使用方法について簡単に説明します。 +
+一般に、3D、特殊効果、複雑な描画処理、shaders を扱うようになると、GameMakerが自動的に頂点データをセットアップして渡してくれるので、vertex + の形式をあまり気にする必要はないでしょう。しかし、速度を上げる必要がある場合や、余分な情報を渡したい場合など、独自にvertex + データを作成し、適切なフォーマットにすることが必要な場合があります。例えば、標準のvertex フォーマットは、x, y, z の 3D + ポジション、カラー(アルファ付き)、UVtexture 座標を含み、自分で作成する場合、次のようになります。
vertex_format_begin();
vertex_format_add_position_3d();
vertex_format_add_colour();
vertex_format_add_textcoord();
my_format = vertex_format_end();
しかし、(例えば)shader を使ってvertex の位置を操作するだけであれば、色やtexture のデータを渡す必要はないでしょう。この場合、このように独自のフォーマットを作成することになる。
+しかし、(例えば)shader を使ってvertex の位置を操作するだけであれば、色やtexture のデータを渡す必要はないでしょう。この場合、このように独自のフォーマットを作成することになる。
vertex_format_begin();
vertex_format_add_position_3d();
my_format = vertex_format_end();
vertex フォーマットを定義する際に使用できるvertex の属性は、全部で 5 種類あります。
+vertex フォーマットを定義する際に使用できるvertex の属性は、全部で 5 + 種類あります。
一般に、フォーマットの一部として位置または3D位置を必ず提供しなければならないが、その他はすべて任意である。
-vertex フォーマットを作成したら、プリミティブを構築する際にvertex 属性の定義順を守らなければならないことに注意しなければなりません。つまり、vertex フォーマットに位置、色、texture 座標を定義した場合、これらの属性を同じ順序でプリミティブに追加しなければならず、そうでない場合はエラーが発生します。また、他の動的リソースと同様に、vertex フォーマットはメモリを必要とするので、不要になったら関数 vertex_format_delete().
-作成したプリミティブは、頂点バッファに保持されます。これはあらかじめ作成しておき、プリミティブを構築するための関数から参照される必要があります。vertex buffer は何度でも再利用して異なるプリミティブを作成することができます。また、ゲームやレベルの間、特定のプリミティブタイプを維持するために「凍結」することもできます(これは最も早い方法です。)
+vertex フォーマットを作成したら、プリミティブを構築する際にvertex 属性の定義順を守らなければならないことに注意しなければなりません。つまり、vertex フォーマットに位置、色、texture + 座標を定義した場合、これらの属性を同じ順序でプリミティブに追加しなければならず、そうでない場合はエラーが発生します。また、他の動的リソースと同様に、vertex フォーマットはメモリを必要とするので、不要になったら関数 vertex_format_delete().
+作成したプリミティブは、頂点バッファに保持されます。これはあらかじめ作成しておき、プリミティブを構築するための関数から参照される必要があります。vertex buffer + は何度でも再利用して異なるプリミティブを作成することができます。また、ゲームやレベルの間、特定のプリミティブタイプを維持するために「凍結」することもできます(これは最も早い方法です。)
単一の三角形プリミティブを構築する例を次のコードに示す。
// CREATE EVENT
v_buff = vertex_create_buffer();
@@ -58,12 +77,32 @@
ここでは、まずインスタンスの Create イベントで頂点buffer を作成します。次に、三角形プリミティブを構成するさまざまな頂点の定義を始め、使用する 3 点のそれぞれの位置、色、およびtexture UV 座標を指定します。そして、vertex の定義を終了し、このvertex データを含むbuffer vertex が変数 "v_buff" に格納されていることがわかります。
-注: buffer の内容が常に更新される場合、buffer が作成され、vertex のデータが与えられ、描画された後、再び破壊されることになるが、これらはすべて同じステップで行われる。
-vertex buffer shaderこれは非常に単純な例で、基本的にGameMakerが内部でどのように動作しているかを示しています。つまり、sprite を描くと、GameMaker は 4 つの頂点で 2 つの三角形を作るvertex buffer を作り(これは「四角形」とも呼ばれます)、textures この 2 つの三角形にsprite の画像を配置します。このsprite を描画すると、vertex buffer を送信していることになり、その内容が画面に描画される。
-vertex buffer を描画用に提出するときに、プリミティブタイプを供給していることにお気づきでしょう。プリミティブの種類には、点、線のリストまたはストリップ、三角形のリストまたはストリップがありますが、ほとんどのモバイルハードウェアはこのプリミティブの種類を受け付けないので、三角形のファンは許可されていません。vertex buffer を、描画に使用するプリミティブの種類に応じた正しい形式にすることを忘れないでください。たとえば、2つの三角形のプリミティブを三角形のリストとして描くには6ポイントが必要ですが、三角形のストリップとしてなら4ポイントでよいのです。どちらのタイプを使うかは、描画するものや実現したい効果によります。
-この方法で独自のvertex buffers を使用する場合の最後の重要なポイントは、GPU に送信される頂点バッチにどのような影響を与えるかということです。vertex buffer を作成するとき、あなたは最下層のグラフィックデータを作成していることになります。したがって、描画すると、GameMakerはあなたのbuffer を直接グラフィックカードに送信することだけが起こります。このため、より良いバッチ処理を行いたい場合は、自分で工夫して、バッチ処理したいものを同じbuffer 内に格納する必要があります。
-すでに述べたように、vertex のフォーマットは、以下の 5 種類の属性(適切な vertex_format_add_* 関数で追加される)を併用することで構築される。
+ここでは、まずインスタンスの Create イベントで頂点buffer を作成します。次に、三角形プリミティブを構成するさまざまな頂点の定義を始め、使用する 3 + 点のそれぞれの位置、色、およびtexture UV 座標を指定します。そして、vertex + の定義を終了し、このvertex データを含むbuffer vertex が変数 "v_buff" に格納されていることがわかります。
+注: buffer の内容が常に更新される場合、buffer が作成され、vertex + のデータが与えられ、描画された後、再び破壊されることになるが、これらはすべて同じステップで行われる。
+vertex buffer shaderこれは非常に単純な例で、基本的にGameMakerが内部でどのように動作しているかを示しています。つまり、sprite + を描くと、GameMaker は 4 つの頂点で 2 つの三角形を作るvertex buffer を作り(これは「四角形」とも呼ばれます)、textures この 2 つの三角形にsprite の画像を配置します。このsprite を描画すると、vertex buffer を送信していることになり、その内容が画面に描画される。
+vertex buffer + を描画用に提出するときに、プリミティブタイプを供給していることにお気づきでしょう。プリミティブの種類には、点、線のリストまたはストリップ、三角形のリストまたはストリップがありますが、ほとんどのモバイルハードウェアはこのプリミティブの種類を受け付けないので、三角形のファンは許可されていません。vertex buffer + を、描画に使用するプリミティブの種類に応じた正しい形式にすることを忘れないでください。たとえば、2つの三角形のプリミティブを三角形のリストとして描くには6ポイントが必要ですが、三角形のストリップとしてなら4ポイントでよいのです。どちらのタイプを使うかは、描画するものや実現したい効果によります。 +
+この方法で独自のvertex buffers を使用する場合の最後の重要なポイントは、GPU + に送信される頂点バッチにどのような影響を与えるかということです。vertex buffer + を作成するとき、あなたは最下層のグラフィックデータを作成していることになります。したがって、描画すると、GameMakerはあなたのbuffer を直接グラフィックカードに送信することだけが起こります。このため、より良いバッチ処理を行いたい場合は、自分で工夫して、バッチ処理したいものを同じbuffer 内に格納する必要があります。
+すでに述べたように、vertex のフォーマットは、以下の 5 種類の属性(適切な vertex_format_add_* 関数で追加される)を併用することで構築される。
vertex vertex shaderしかし、shader では、Position が"x" と "y" の座標だけであるのに対し、3D Positionは "x", "y", "z" の座標を持つことを除いて、Positionと3D Positionは同じ 属性として扱われています。では、vertex のフォーマットと、shader の属性定義をどのように対応させるのでしょうか。まず、デフォルトシェーダの典型的なアトリビュートセットを見てみましょ う。
+vertex vertex shaderしかし、shader では、Position が"x" と + "y" の座標だけであるのに対し、3D Positionは "x", "y", "z" + の座標を持つことを除いて、Positionと3D Positionは同じ 属性として扱われています。では、vertex + のフォーマットと、shader の属性定義をどのように対応させるのでしょうか。まず、デフォルトシェーダの典型的なアトリビュートセットを見てみましょ う。
attribute vec3 in_Position; // (x,y,z)
//attribute vec3 in_Normal; // (x,y,z) unused in this shader.
@@ -90,14 +133,27 @@
さて、shader 属性はどのようにしてvertex フォーマットタイプにマッチするのでしょうか?それは単に命名規則に基づいています。
+さて、shader 属性はどのようにしてvertex + フォーマットタイプにマッチするのでしょうか?それは単に命名規則に基づいています。
さて、同じ種類の属性が複数ある場合、事態はより複雑になりますが、それでも物事は同じ命名規則に基づいています。 または フォーマットでは、位置と法線の属性はshader vertex 1 つしかありませんが、色または の属性は複数存在texture できます。
-shader に色属性を追加する場合、shader 属性の末尾に番号を追加して、その属性がvertex フォーマットのどの項目に対応するのかを示す必要があります。以下はその例です。まず、vertex フォーマットの場合です。
++ さて、同じ種類の属性が複数ある場合、事態はより複雑になりますが、それでも物事は同じ命名規則に基づいています。 または フォーマットでは、位置と法線の属性はshader vertex 1 つしかありませんが、色または + の属性は複数存在texture できます。
+shader に色属性を追加する場合、shader + 属性の末尾に番号を追加して、その属性がvertex フォーマットのどの項目に対応するのかを示す必要があります。以下はその例です。まず、vertex フォーマットの場合です。
vertex_format_begin();
vertex_format_add_position_3d();
vertex_format_add_colour();
@@ -109,8 +165,13 @@
この場合、 in_Colour0 は最初の vertex_format_add_colour() に、 in_Colour1 は 2 番目のマップに対応します。
-テクスチャ座標は、色とは若干異なる扱いを受けます。基本的に、 in_Position 、 in_Normal または in_Colour[0 ... ] のいずれかの属性と呼ばれていないものは、texture の座標として扱われます。shader の属性リストで定義されている順番が、vertex のどの属性に対応するかを示しています。次のGML の例を参照してください。
+この場合、 in_Colour0 は最初の vertex_format_add_colour() に、 in_Colour1 は 2 番目のマップに対応します。
+テクスチャ座標は、色とは若干異なる扱いを受けます。基本的に、 in_Position 、 in_Normal または + in_Colour[0 ... ] のいずれかの属性と呼ばれていないものは、texture + の座標として扱われます。shader の属性リストで定義されている順番が、vertex + のどの属性に対応するかを示しています。次のGML の例を参照してください。 +
vertex_format_begin();
vertex_format_add_position_3d();
vertex_format_add_colour();
@@ -124,10 +185,14 @@
この例では、 in_myTexcoord 、 in_TextureCoord 、 in_Something が、texture 形式で定義された 3 つの連続するvertex 座標属性に対応します。
-vertex フォーマット、vertex buffers 、プリミティブの作成に必要な全機能の一覧は、次のページでご覧いただけます。
+この例では、 in_myTexcoord 、 in_TextureCoord 、 in_Something が、texture 形式で定義された 3 つの連続するvertex 座標属性に対応します。
+vertex フォーマット、vertex buffers 、プリミティブの作成に必要な全関数の一覧は、次のページでご覧いただけます。
@@ -135,11 +200,12 @@
GameMakerを長く使っていると、ほぼ間違いなくブレンドモードを目にし、おそらくゲームでも使っていることでしょう。ブレンドモードは、描画方法を変更することで、興味深い特殊なグラフィック効果を与えることができる素晴らしい方法ですが、その仕組みや使い方をご存知でしょうか?このセクションでは、ブレンドモードにまつわる謎を解き明かし、ゲームに最大限に活用できるようにしたいと思います。
+GameMakerを長く使っていると、ほぼ間違いなくブレンドモードを目にし、おそらくゲームでも使っていることでしょう。ブレンドモードは、描画方法を変更することで、興味深い特殊なグラフィック効果を与えることができる素晴らしい方法ですが、その仕組みや使い方をご存知でしょうか?このセクションでは、ブレンドモードにまつわる謎を解き明かし、ゲームに最大限に活用できるようにしたいと思います。 +
ブレンドモードは基本的に、ゲームに特定のものをあらかじめ描画されているものとブレンドして描画するように指示します。画面に描画されるものはすべて、赤、緑、青、アルファの4つの要素で構成されており、デフォルトでは、ブレンドモード( bm_normal )を使って画面に描画されます。このブレンドモードは、すべてのピクセルの色とアルファ値を基本的に変えずに描画します(ただし、このセクションの後半で、これが真実ではないことがわかります...)が、GameMakerには、この動作を変更するために設定できる、いくつかのブレンドモードが組み込まれています。
-GameMakerがピクセルを描画しようとするとき、ソースカラー(描画しようとするピクセルの色)とデスティネーションカラー(描画先のピクセルに既にある色)があります。ピクセルの新しい色を決定する際、GameMaker 、前述のようにブレンドモードに従ってソースカラーとデスティネーションカラーを組み合わせます。色の各要素は 0 から 1 の間の浮動小数点値として保存され、新しい色は、ソースカラーの各要素に何らかの係数を掛け、デスティネーションカラーの各要素に何らかの係数を掛けて、その結果を要素ごとに加算することによって計算されます。
+ブレンドモードは基本的に、ゲームに特定のものをあらかじめ描画されているものとブレンドして描画するように指示します。画面に描画されるものはすべて、赤、緑、青、アルファの4つの要素で構成されており、デフォルトでは、ブレンドモード( + bm_normal + )を使って画面に描画されます。このブレンドモードは、すべてのピクセルの色とアルファ値を基本的に変えずに描画します(ただし、このセクションの後半で、これが真実ではないことがわかります...)が、GameMakerには、この動作を変更するために設定できる、いくつかのブレンドモードが組み込まれています。 +
+GameMakerがピクセルを描画しようとするとき、ソースカラー(描画しようとするピクセルの色)とデスティネーションカラー(描画先のピクセルに既にある色)があります。ピクセルの新しい色を決定する際、GameMaker 、前述のようにブレンドモードに従ってソースカラーとデスティネーションカラーを組み合わせます。色の各要素は 0 から 1 + の間の浮動小数点値として保存され、新しい色は、ソースカラーの各要素に何らかの係数を掛け、デスティネーションカラーの各要素に何らかの係数を掛けて、その結果を要素ごとに加算することによって計算されます。
GameMakerは関数gpu_set_blendmode()を使って、ゲームが描画に使用するブレンディングを変更します。この関数は、たとえばsprite を描画する前に呼び、描画後に再び設定する、というようなものです。
+GameMakerは関数gpu_set_blendmode()を使って、ゲームが描画に使用するブレンディングを変更します。この関数は、たとえばsprite を描画する前に呼び、描画後に再び設定する、というようなものです。
gpu_set_blendmode(bm_add);
draw_self();
gpu_set_blendmode(bm_normal);
このコードは、加算 ブレンドモードを使用してインスタンスsprite を描画します。加算ブレンドモードは、利用可能なGML 定数のうちの 1 つを使用して設定します(基本モードには 4 つあります)。
+このコードは、加算 ブレンドモードを使用してインスタンスsprite を描画します。加算ブレンドモードは、利用可能なGML 定数のうちの 1 つを使用して設定します(基本モードには 4 つあります)。
bm_normal
bm_add
bm_subtract
bm_max
bm_normal がどのように見えるかは、すでに見てきました。- では、他の3つについてもう少し詳しく見ていきましょう...
-

このブレンドモードは、ソースピクセルとデスティネーションピクセルの色を足し合わせます(ただし、アルファ値には影響を与えません)。例えば、背景画像が RGB 値 (100,15,70) の無地で、次に RGB 値 (120,25,30) の矩形を描くと、(bm_add を使って)矩形の各画素の RGB 値は (220,40,100) に仕上がります。色の値は255以上(または0以下)にはならないので、それ以上の値を足すと255に固定されることに注意してください。
+このブレンドモードは、ソースピクセルとデスティネーションピクセルの色を足し合わせます(ただし、アルファ値には影響を与えません)。例えば、背景画像が RGB 値 (100,15,70) + の無地で、次に RGB 値 (120,25,30) の矩形を描くと、(bm_add を使って)矩形の各画素の RGB 値は (220,40,100) + に仕上がります。色の値は255以上(または0以下)にはならないので、それ以上の値を足すと255に固定されることに注意してください。
このブレンドモードを使用すると、「ネオンの輝き」のような外観を得ることができ、照明効果やレーザーなど、光っているように見せたいものに最もよく使用される方法です。
このブレンドモードは、前のものとは少し異なり、直接的な値ではなく、パーセントベースで動作します。このパーセントは、出力色(描画されるピクセルの色)から差し引かれるものです。これをよりよく説明するために、例を見てみましょう。
- room のある領域に描かれたすべてのピクセルの赤の値を 25% 減らしたい場合を想像してください。まず 255 の 25% を取得し、それを RGB の色値に変換し、最後に bm_subtract と共にそれを使用して領域上に描画する必要があります。このようなものです。
+ このブレンドモードは、前のものとは少し異なり、直接的な値ではなく、パーセントベースで動作します。このパーセントは、出力色(描画されるピクセルの色)から差し引かれるものです。これをよりよく説明するために、例を見てみましょう。 +
+ room のある領域に描かれたすべてのピクセルの赤の値を 25% 減らしたい場合を想像してください。まず 255
+ の 25% を取得し、それを RGB の色値に変換し、最後に bm_subtract と共にそれを使用して領域上に描画する必要があります。このようなものです。
var red = (25 / 100) * 255;
var col = make_colour_rgb(red, 0, 0);
gpu_set_blendmode(bm_subtract);
draw_rectangle_colour(0, 0, 128, 256, col, col, col, col, false);
gpu_set_blendmode(bm_normal);
同じルールで、背景の明るさを単純に50%減らすなら、赤50%、緑50%、青50%の色、つまりRGB(128、128、128)を使用します。このブレンドモードは、主に影を描いたり、興味深いフェードアウト効果を作成するために使用します。
++ 同じルールで、背景の明るさを単純に50%減らすなら、赤50%、緑50%、青50%の色、つまりRGB(128、128、128)を使用します。このブレンドモードは、主に影を描いたり、興味深いフェードアウト効果を作成するために使用します。 +
このブレンドモードは、説明するのがより複雑ですが、基本的には、ソースカラーにソースアルファを乗算し、それを逆ソースカラー値を乗算したデスティネーションカラー値に追加します。bm_max(および他のブレンドモード)の背後にある実際の数学は、我々の記事のパート2で説明しますが、あなたが知っておくべきことは、結果はより「飽和」で明るい色になりますが、 bm_add を使用して発生するのと同じ真っ白な輝きにつながることはありません。
-このブレンドモードは、重なり合った画像を、見えなくなってしまうほど明るくならずに描画する必要がある場合に便利です。明るい部分はより明るくなりますが、色と色相のレベルは維持されるはずです。ただし、このブレンドモードを使用すると、ソースイメージのアルファ値も最終的な効果に影響を与えることに注意してください。
+ このブレンドモードは、説明するのがより複雑ですが、基本的には、ソースカラーにソースアルファを乗算し、それを逆ソースカラー値を乗算したデスティネーションカラー値に追加します。bm_max(および他のブレンドモード)の背後にある実際の数学は、我々の記事のパート2で説明しますが、あなたが知っておくべきことは、結果はより「飽和」で明るい色になりますが、 + bm_add を使用して発生するのと同じ真っ白な輝きにつながることはありません。 +
+
+ このブレンドモードは、重なり合った画像を、見えなくなってしまうほど明るくならずに描画する必要がある場合に便利です。明るい部分はより明るくなりますが、色と色相のレベルは維持されるはずです。ただし、このブレンドモードを使用すると、ソースイメージのアルファ値も最終的な効果に影響を与えることに注意してください。
+
-
GameMakerのブレンドモードの基本的な使い方はご理解いただけたと思います。ブレンドモードは、元画像(描画されているもの)のRGBとアルファ値を取り、それを先画像(描画されているもの)のRGBとアルファ値にブレンドします。このブレンドは、各ピクセルの色とアルファの個々のコンポーネントに、達成したい効果に応じて異なる量を乗算することで行われます。この知識をもとに、ゲーム内でブレンドモードを使い始め、光るレーザー、リアルな影、彩度の高いトランジションエフェクトを得ることができますが、まだまだ学ぶべきことはあります。以下では、拡張ブレンドモードについて説明し、その背後にある数学についても少し掘り下げて、乗算やオーバーレイなどの独自のブレンディングエフェクトを作成できるようにします。
+GameMakerのブレンドモードの基本的な使い方はご理解いただけたと思います。ブレンドモードは、元画像(描画されているもの)のRGBとアルファ値を取り、それを先画像(描画されているもの)のRGBとアルファ値にブレンドします。このブレンドは、各ピクセルの色とアルファの個々のコンポーネントに、達成したい効果に応じて異なる量を乗算することで行われます。この知識をもとに、ゲーム内でブレンドモードを使い始め、光るレーザー、リアルな影、彩度の高いトランジションエフェクトを得ることができますが、まだまだ学ぶべきことはあります。以下では、拡張ブレンドモードについて説明し、その背後にある数学についても少し掘り下げて、乗算やオーバーレイなどの独自のブレンディングエフェクトを作成できるようにします。 +
上記では、関数 gpu_set_blendmode()について説明しましたが、ここでは gpu_set_blendmode_ext().これは(その名の通り)カスタムブレンドモードを 設定するための拡張関数ですが、これはどのように機能するのでしょうか?先に進む前に、技術的な答えを先に見ておきましょう。
+上記では、関数 gpu_set_blendmode()について説明しましたが、ここでは gpu_set_blendmode_ext().これは(その名の通り)カスタムブレンドモードを + 設定するための拡張関数ですが、これはどのように機能するのでしょうか?先に進む前に、技術的な答えを先に見ておきましょう。
さて、この文章は正しく、ブレンドモードが何をするものかを説明していますが、直感的に理解できるものではありません...そこで、もう少し詳しく、これがどういうものかを説明しましょう。
-ソースとは 描画されるピクセルの色とアルファ値のことで、デスティネーションとは その上に描画されるピクセルの色とアルファ値のことである。簡単に説明するために、元となる色を構成要素として書き出すと、次のようになります。
+ソースとは 描画されるピクセルの色とアルファ値のことで、デスティネーションとは + その上に描画されるピクセルの色とアルファ値のことである。簡単に説明するために、元となる色を構成要素として書き出すと、次のようになります。
つまり、私たちが画面に何かを描くとき、グラフィックス・プロセッサは実際には1ピクセルごとに次のような処理を行っているのです。
-final_pixel_colour = (Rs,Gs,Bs,As) * source_blend_factor + (Rd,Gd,Bd,Ad) * destination_blend_factor
-上記のブレンドファクターは、GameMakerではいくつかの定数(GML )で定義されており、それぞれがソースまたはデスティネーションのR、G、B、A値に乗じるべきファクターを表しています。利用可能なファクターは以下の通りです。
+final_pixel_colour = (Rs,Gs,Bs,As) * source_blend_factor + (Rd,Gd,Bd,Ad) * destination_blend_factor +
+上記のブレンドファクターは、GameMakerではいくつかの定数(GML )で定義されており、それぞれがソースまたはデスティネーションのR、G、B、A値に乗じるべきファクターを表しています。利用可能なファクターは以下の通りです。
GameMakerが持つ4つの「基本」ブレンドモードは、実はこのうちの2つのブレンドファクターを合成したものです。
それでは、GameMakerで描画するための実用的な例を見てみましょう。今回は、bm_normalについて見ていきます。
+それでは、GameMakerで描画するための実用的な例を見てみましょう。今回は、bm_normalについて見ていきます。
gpu_set_blendmode_ext(bm_src_alpha, bm_inv_src_alpha);
-ブレンドモードに関する問題の1つは、結果を視覚化することです。そこで、ブレンドモードの背後にある数学を示すために、このブレンドモードをテスト対象として使用することにします。色(64, 128, 255, 255, 255)の背景の上に、色(128, 255, 64, 255)の矩形を描いているとします。
+ブレンドモードに関する問題の1つは、結果を視覚化することです。そこで、ブレンドモードの背後にある数学を示すために、このブレンドモードをテスト対象として使用することにします。色(64, 128, + 255, 255, 255)の背景の上に、色(128, 255, 64, 255)の矩形を描いているとします。
つまり、ブレンドモードは次のようになります。
Source: (128, 255, 64, 255) = (0.5, 1, 0.25, 1)
Destination: (64, 128, 255, 255) = (0.25, 0.5, 1, 1)
@@ -109,8 +150,10 @@
つまり、ソースカラーは変更されないので、最終的なカラー値は(128, 255, 64, 255) となります。アルファを含めると、この値にも影響があることがおわかりいただけると思います。
+ (0.5, 1, 0.25, 1) + (0, 0, 0, 0) = (0.5, 1, 0.25, 1) = (128, 255, 64, 255) + +つまり、ソースカラーは変更されないので、最終的なカラー値は(128, 255, 64, 255) + となります。アルファを含めると、この値にも影響があることがおわかりいただけると思います。
Source (128, 255, 64, 128) = (0.5, 1, 0.25, 0.5)
Destination: (64, 128, 255, 255) = (0.25, 0.5, 1, 1)
@@ -123,40 +166,66 @@
これにより、最終的な画素の色は(96、192、159、192)となり、下図のような画像になります。
-
ブレンドモードファクターが何をするのか、そしてそれらを組み合わせることで描画がどのように変化し、興味深い効果を生み出すのか、ご理解いただけたかと思います。次に、これらの要素を組み合わせて独自のブレンドモードを作成する方法を、実際の例で見ていきます。
+
+ ブレンドモードファクターが何をするのか、そしてそれらを組み合わせることで描画がどのように変化し、興味深い効果を生み出すのか、ご理解いただけたかと思います。次に、これらの要素を組み合わせて独自のブレンドモードを作成する方法を、実際の例で見ていきます。 +
ブレンドモードの設定方法と、日常的なドローイングの使用例を見ていただきましたが、もう少し複雑なものを見てみましょう。
利用可能なさまざまな要素を使用して、独自のブレンドモードを作成し、通常では利用できないブレンドオプションを実現することができます。この例では、Photoshopで使用されているようなマルチプライエフェクトを 作成することにします。このブレンドモードは、上記のブレンドモード係数定数を2つ使って、次のようにシミュレートすることができます。
+利用可能なさまざまな要素を使用して、独自のブレンドモードを作成し、通常では利用できないブレンドオプションを実現することができます。この例では、Photoshopで使用されているようなマルチプライエフェクトを + 作成することにします。このブレンドモードは、上記のブレンドモード係数定数を2つ使って、次のようにシミュレートすることができます。
gpu_set_blendmode_ext(bm_dest_colour, bm_zero);
このブレンドモードを使って実際に何かを描く前に、Photoshopでどのように見えるかを見てみましょう。
拡張ブレンドモードを使用すると、次のようになります。
(Rs, Gs, Bs, As) * (Rd, Gd, Bd, Ad) + (Rd, Gd, Bd, Ad) * (0,0,0,0) = (Rs, Gs, Bs, As) * (Rd, Gd, Bd, Ad)
+
(Rs, Gs, Bs, As) * (Rd, Gd, Bd, Ad) + (Rd, Gd, Bd, Ad) * (0,0,0,0) = (Rs, Gs, Bs, As) * (Rd, Gd, Bd,
+ Ad)
Source colour * dest colour + dest colour * zero = source colour * dest colour
ブレンドファクター( bm_zero )は、デスティネーションカラーを効果的に方程式から排除します(ゼロの何倍もゼロなので)。したがって、ソースカラーにデスティネーションカラーのブレンドファクターを掛けたものが残り、このモードの名前が「マルチプライ」になっています。GameMakerでこれを使うには、Drawイベント内に以下のような内容を記述します。
+ブレンドファクター( bm_zero + )は、デスティネーションカラーを効果的に方程式から排除します(ゼロの何倍もゼロなので)。したがって、ソースカラーにデスティネーションカラーのブレンドファクターを掛けたものが残り、このモードの名前が「マルチプライ」になっています。GameMakerでこれを使うには、Drawイベント内に以下のような内容を記述します。
gpu_set_blendmode_ext(bm_dest_colour, bm_zero);
draw_self();
gpu_set_blendmode(bm_normal);
次の画像は、このコードを正確に使用したGameMaker のテストプロジェクトで撮影したものです。
-その違いを見分けられますか?おそらくないでしょう。しかし、使用するレンダリングツールの違いにより、両者の間には多少の誤差が生じますが、ほぼ予想通りの結果となります。ただし、アートプログラムで使用されているブレンドモードの中には、色値を255以上にすることで特殊な効果を生み出すものがあるため、GameMakerですべてのブレンドモードを使用できるわけではありませんが、これらのエフェクトの模倣や、まったく新しいエフェクトを作成することができないわけではありません。
GameMakerでは、 gpu_set_blendmode_ext_sepalpha() という機能を使うことで、さらに一歩踏み込むことができます。これは、異なるブレンドモードファクタのアルファ成分を分離し、それらを個別に使用して、さらに多くの組み合わせを作成することができます。この関数については、マニュアルで詳しく説明されているので、ここでは説明しませんが、使用可能であることを知っておくために、言及する価値があります。
+
+ その違いを見分けられますか?おそらくないでしょう。しかし、使用するレンダリングツールの違いにより、両者の間には多少の誤差が生じますが、ほぼ予想通りの結果となります。ただし、アートプログラムで使用されているブレンドモードの中には、色値を255以上にすることで特殊な効果を生み出すものがあるため、GameMakerですべてのブレンドモードを使用できるわけではありませんが、これらのエフェクトの模倣や、まったく新しいエフェクトを作成することができないわけではありません。
+
GameMakerでは、 gpu_set_blendmode_ext_sepalpha() + という関数を使うことで、さらに一歩踏み込むことができます。これは、異なるブレンドモードファクタのアルファ成分を分離し、それらを個別に使用して、さらに多くの組み合わせを作成することができます。この関数については、マニュアルで詳しく説明されているので、ここでは説明しませんが、使用可能であることを知っておくために、言及する価値があります。 +
それは、ブレンドモードが色のアルファ 成分にどのような影響を与えるかということです。アプリケーションサーフェスや ディスプレイバッファに描画する場合、描画先のアルファ値は常に 1であるため、考慮する必要はあまりありません。しかし、自分で作ったサーフェイスは違います。サーフェイスをクリアして、0から1までの好きなアルファ値を持たせることができるからです。これは、多くの人が予想するのとは逆の、興味深い効果をもたらします。
-これを説明するために、基本的なデフォルトの bm_normal を使って描画することを見ていきます。ほとんどの人は、サーフェイスをアルファ 0 にクリアして、アルファ 0.5 のものを描画すると、結果的にアルファ値も 0.5 になると思っていますが、これはそうではなく、多くの人がGameMaker のレンダリング方法における「バグ」だと思っているものです。しかし、見ての通り、これは全くバグではありません。
-例えば、すべてのピクセルがアルファ0のサーフェイスがあり、その上に bm_normal ブレンドモードを使ってアルファ0.5の円を描くとします。サーフェス全体はアルファ 0 のままですが、円の中のアルファは実際には 0.25 になります。
+それは、ブレンドモードが色のアルファ 成分にどのような影響を与えるかということです。アプリケーションサーフェスや ディスプレイバッファに描画する場合、描画先のアルファ値は常に + 1であるため、考慮する必要はあまりありません。しかし、自分で作ったサーフェイスは違います。サーフェイスをクリアして、0から1までの好きなアルファ値を持たせることができるからです。これは、多くの人が予想するのとは逆の、興味深い効果をもたらします。 +
+これを説明するために、基本的なデフォルトの bm_normal を使って描画することを見ていきます。ほとんどの人は、サーフェイスをアルファ 0 にクリアして、アルファ 0.5 + のものを描画すると、結果的にアルファ値も 0.5 になると思っていますが、これはそうではなく、多くの人がGameMaker + のレンダリング方法における「バグ」だと思っているものです。しかし、見ての通り、これは全くバグではありません。
+例えば、すべてのピクセルがアルファ0のサーフェイスがあり、その上に bm_normal ブレンドモードを使ってアルファ0.5の円を描くとします。サーフェス全体はアルファ 0 + のままですが、円の中のアルファは実際には 0.25 になります。
0.5 * 0.5 + 0 * 0.5 = 0.5 * 0.5 = 0.25
次に、既存の円の中にもう一つ円を描き、これもアルファ値を0.5とすると、円の外のアルファ値は0、円と円の間は0.25、小さい円の中は0.375となります。
0.5 * 0.5 + 0.25 * 0.5 = 0.25 + 0.125 = 0.375
0アルファのサーフェイスに0.5アルファの円をいくつも描き続け、このサーフェイスをroom に描くとしたら、このことがはっきりとわかるはずだ。
-アルファについてまだ少し混乱しているのであれば、アルファを単なる色の1つとして思い浮かべてみてください。アルファは色と同じように振る舞い、アルファに関するすべての計算は同じように行われます。アルファが他の色に与える影響はありますが、アルファは実際には見えません。ここで、サーフェスやブレンドモード( bm_normal も)を使用する際の最後の注意点があります...
サーフェスのアルファ値が0, 色成分はそのまま存在し、すべてのブレンド操作に影響します。.したがって、赤色でクリアされたアルファ値0のサーフェスに描画すると(例えば)、ソースカラーとデスティネーションカラーがブレンドされ、あなたが考えるのとは異なる効果が得られます。上のイメージは、黒い背景の上に黒でクリアされたサーフェスで作成されましたが、サーフェスを赤でクリアすると、代わりにこのようなイメージになります。
+
+ アルファについてまだ少し混乱しているのであれば、アルファを単なる色の1つとして思い浮かべてみてください。アルファは色と同じように振る舞い、アルファに関するすべての計算は同じように行われます。アルファが他の色に与える影響はありますが、アルファは実際には見えません。ここで、サーフェスやブレンドモード(
+ bm_normal も)を使用する際の最後の注意点があります...
+
サーフェスのアルファ値が0, + 色成分はそのまま存在し、すべてのブレンド操作に影響します。.したがって、赤色でクリアされたアルファ値0のサーフェスに描画すると(例えば)、ソースカラーとデスティネーションカラーがブレンドされ、あなたが考えるのとは異なる効果が得られます。上のイメージは、黒い背景の上に黒でクリアされたサーフェスで作成されましたが、サーフェスを赤でクリアすると、代わりにこのようなイメージになります。 +
なぜこのようなことが起こるのか、先に説明した計算式と bm_normal の適切な数値を使って、ご自身で考えてみてください。
@@ -164,11 +233,12 @@
buffer (プログラミングの場合) は基本的にシステムメモリ内のスペースで、あらゆるもののための小さなデータパケットを保存するために使用されます (たとえば、データ転送、衝突、カラーデータなど)。システムメモリ内にあるため、アクセスが非常に速く、buffer は一般的に、処理前のネットワーク情報の受信や、ゲームのチェックポイントの保存など、非常に短期間の保存に使用されます(これについては、このページの下の例で説明しています)。
-バッファは、システムメモリにバイト 数で計算されたスペースを割り当てることで作成され、ゲームが実行されている限り、または適切な関数を使用してbuffer を削除するまで、ゲームのために確保されます(ここにすべてのGML buffer 関数がリストされています)。つまり、ゲームにフォーカスが当たっていないときでも(たとえば、モバイルデバイスで電話をかけると、ゲームはバックグラウンドになります)、buffer は存在しますが、ゲームを閉じたり再スタートすると、buffer は失われてしまうのです。
注意:ゲームを再起動しても、buffer はクリアされず、削除されません !しかし、IDハンドルが失われ、メモリリークを引き起こし、最終的にゲームをクラッシュさせるため、以前に作成されたbuffer にそれ以上アクセスすることができなくなります。したがって、ゲームを再スタートするときは、まずbuffers を削除することを忘れないようにしてください。
-GameMakerでは、4種類のbuffer を作成することができます。その理由は、buffers は高度に最適化された一時記憶媒体として設計されているため、保存したいデータの種類に適したbuffer を作成する必要があり、そうしないとエラーが発生したり、コードのボトルネックになる可能性があるためです。このことをさらに説明する前に、利用可能な4つのbuffer 型(GML で定数として 定義されています)について見てみましょう。
+buffer (プログラミングの場合) は基本的にシステムメモリ内のスペースで、あらゆるもののための小さなデータパケットを保存するために使用されます + (たとえば、データ転送、衝突、カラーデータなど)。システムメモリ内にあるため、アクセスが非常に速く、buffer + は一般的に、処理前のネットワーク情報の受信や、ゲームのチェックポイントの保存など、非常に短期間の保存に使用されます(これについては、このページの下の例で説明しています)。
+バッファは、システムメモリにバイト 数で計算されたスペースを割り当てることで作成され、ゲームが実行されている限り、または適切な関数を使用してbuffer を削除するまで、ゲームのために確保されます(ここにすべてのGML
+ buffer
+ 関数がリストされています)。つまり、ゲームにフォーカスが当たっていないときでも(たとえば、モバイルデバイスで電話をかけると、ゲームはバックグラウンドになります)、buffer は存在しますが、ゲームを閉じたり再スタートすると、buffer は失われてしまうのです。
+
注意:ゲームを再起動しても、buffer はクリアされず、削除されません + !しかし、IDハンドルが失われ、メモリリークを引き起こし、最終的にゲームをクラッシュさせるため、以前に作成されたbuffer + にそれ以上アクセスすることができなくなります。したがって、ゲームを再スタートするときは、まずbuffers を削除することを忘れないようにしてください。
+GameMakerでは、4種類のbuffer + を作成することができます。その理由は、buffers は高度に最適化された一時記憶媒体として設計されているため、保存したいデータの種類に適したbuffer を作成する必要があり、そうしないとエラーが発生したり、コードのボトルネックになる可能性があるためです。このことをさらに説明する前に、利用可能な4つのbuffer 型(GML で定数として + 定義されています)について見てみましょう。
| buffer_fixed | - バイト単位で固定されたサイズのbuffer 。このサイズはbuffer の作成時に設定され、以後変更することはできません。 |
+ バイト単位で固定されたサイズのbuffer 。このサイズはbuffer
+ の作成時に設定され、以後変更することはできません。
| buffer_grow | - buffer データが追加されると動的に成長する。初期サイズ (格納されるデータのサイズの近似値) で作成し、この初期サイズを超えるデータを受け入れるために拡張します。 |
+ buffer データが追加されると動的に成長する。初期サイズ (格納されるデータのサイズの近似値)
+ で作成し、この初期サイズを超えるデータを受け入れるために拡張します。
+
| buffer_wrap | - buffer データが折り返される場所です。追加されるデータがbuffer サイズの限界に達すると、上書きはbuffer の先頭に戻され、その時点からさらに書き込みが続けられる。 |
+ buffer データが折り返される場所です。追加されるデータがbuffer
+ サイズの限界に達すると、上書きはbuffer の先頭に戻され、その時点からさらに書き込みが続けられる。
+
| buffer_fast | - これは特別な "stripped down"buffer で、読み書きが非常に高速になります。ただし、 buffer_u8 のデータ型でのみ使用でき、1 バイトアライメントでなければなりません。(データ型と バイトアライメントに関する情報は、このページのさらに下にあります)。 |
+ これは特別な "stripped down"buffer で、読み書きが非常に高速になります。ただし、 buffer_u8 のデータ型でのみ使用でき、1 バイトアライメントでなければなりません。(データ型と
+ バイトアライメントに関する情報は、このページのさらに下にあります)。
-
以上がGameMakerを使用する際に選択できるbuffer の種類ですが、どれを選ぶかは、使用したい用途によって大きく異なります。例えば、growbuffer は、実際に入るデータ量が分からないので、セーブゲームを作るためにデータの「スナップショット」を保存するのに使いますし、fastbuffer は、例えば画像のARGBデータを処理するときに、扱う値がすべて0〜255または-128〜127であることが分かっている場合に使います。
- buffer を作成する場合、常にその型に適したサイズで作成するようにします。一般的なルールとしては、保存するデータの最大サイズに対応するように作成し、疑わしい場合は、上書きエラーを防止するために grow を使用するようにします。buffer
以上がGameMakerを使用する際に選択できるbuffer + の種類ですが、どれを選ぶかは、使用したい用途によって大きく異なります。例えば、growbuffer + は、実際に入るデータ量が分からないので、セーブゲームを作るためにデータの「スナップショット」を保存するのに使いますし、fastbuffer は、例えば画像のARGBデータを処理するときに、扱う値がすべて0〜255または-128〜127であることが分かっている場合に使います。
+ buffer
+ を作成する場合、常にその型に適したサイズで作成するようにします。一般的なルールとしては、保存するデータの最大サイズに対応するように作成し、疑わしい場合は、上書きエラーを防止するために grow を使用するようにします。buffer
実際にbuffer を作成するコードは以下のようになります。
player_buffer = buffer_create(16384, buffer_fixed, 2);
- この場合、16384バイトでバイトアラインメントが2の固定buffer 。この関数は、後でこのbuffer を参照するために変数に格納されるユニークなID値を返します。
buffer にデータを読み書きするときは、その「データ型」で定義されたデータの「チャンク」単位で行います。データ型」は、書き込まれる値に対してbuffer 内で割り当てられるバイト数を設定するもので、これを正しく設定しないと、コードに非常に奇妙な結果(あるいはエラー)が発生することになります。
-バッファへの書き込み(および読み込み)は順次行われます。つまり、1つのデータが次々と書き込まれ、各データは決められた型になります。つまり、buffer に書き込むデータが何であるかを常に意識しておくことが理想的です。これらのデータ型は、GML 、以下の定数で定義されています。
+ この場合、16384バイトでバイトアラインメントが2の固定buffer 。この関数は、後でこのbuffer を参照するために変数に格納されるユニークなID値を返します。 +buffer にデータを読み書きするときは、その「データ型」で定義されたデータの「チャンク」単位で行います。データ型」は、書き込まれる値に対してbuffer 内で割り当てられるバイト数を設定するもので、これを正しく設定しないと、コードに非常に奇妙な結果(あるいはエラー)が発生することになります。
+バッファへの書き込み(および読み込み)は順次行われます。つまり、1つのデータが次々と書き込まれ、各データは決められた型になります。つまり、buffer に書き込むデータが何であるかを常に意識しておくことが理想的です。これらのデータ型は、GML + 、以下の定数で定義されています。
| データ型定数 | バイト | -商品説明 | +説明 |
|---|---|---|---|
| buffer_u8 | @@ -135,7 +169,9 @@buffer_string | N/A | - これは UTF-8 のヌル終端 (0x00) であるstring 。基本的にはGameMaker string がbuffer にダンプされ、末尾に 0 が付きます。 |
+ これは UTF-8 のヌル終端 (0x00) であるstring 。基本的にはGameMaker string がbuffer にダンプされ、末尾に 0 が付きます。
上記の例を見ると、buffer に異なるタイプのデータを同時に書き込むことができ(高速 バッファータイプを使用する場合は、特定のデータタイプにのみ制限されます)、このデータはbuffer に順次追加されます(ただしbuffer における実際の位置は、以下で説明するバイトアライメントによって決まります)。これは、buffer から情報を読み出す場合も同様で、上記の例の場合、buffer からデータを書き込んだのと同じ順序で、同じデータ型かどうかをチェックしながら読み出すことになります。
+上記の例を見ると、buffer に異なるタイプのデータを同時に書き込むことができ(高速 + バッファータイプを使用する場合は、特定のデータタイプにのみ制限されます)、このデータはbuffer に順次追加されます(ただしbuffer における実際の位置は、以下で説明するバイトアライメントによって決まります)。これは、buffer から情報を読み出す場合も同様で、上記の例の場合、buffer + からデータを書き込んだのと同じ順序で、同じデータ型かどうかをチェックしながら読み出すことになります。
global.Sound = buffer_read(buff, buffer_bool);
global.Music = buffer_read(buff, buffer_bool);
obj_Player.x = buffer_read(buff, buffer_s16);
obj_Player.y = buffer_read(buff, buffer_s16);
global.Player_Name = buffer_read(buff, buffer_string);
このように、buffer に読み込んだのと同じ順序で情報を読み出します。buffer のデータの追加と削除の方法については、以下の例を参照してください。
-このページをご覧になっている方は、buffer のバイトアライメントについて 言及されているのをご覧になったことがあると思います。これは基本的に、与えられたbuffer の中で新しいデータが格納される位置のことを指します。これはどのように機能するのでしょうか?シングルバイトアライメントbuffer の場合、各データはbuffer に順次書き込まれ、新しいデータは前のデータの直後に追加されます。しかし、2バイトアラインのbuffer は、各データを2バイト間隔で書き込むので、最初の書き込みが1バイトのデータであっても、次の書き込みは2バイトに揃うように移動されることになります。
-つまり、バイトアライメントを例えば4バイトに設定し、1バイトのデータを書き込んでからbuffer Tell (Tellは現在の読み書きの位置をbuffer )すると、1バイトのオフセット (この場合のオフセットは、buffer の先頭から現在の読み書きの位置までのバイト数です)が得られます。
しかし、1バイトのデータを書き込んでから 、buffer を実行すると、(2バイトのデータしか書いていないのに)5バイトのオフセットが発生します。これは、4バイトのbuffer アライメントに合わせるため、データをパディングしているためです。
-基本的には、アライメントが影響を与えるのは書き込む場所だけ なので、何かを書き込んだ後にbuffer を実行すると、前に書き込んだデータのすぐ後にある現在の書き込み位置が返されます。しかし、その後に別のデータを書き込むと、buffer は実際にデータを書き込む前に、書き込み位置をアライメントサイズの次の倍数に移動させることに注意してください。
+このように、buffer に読み込んだのと同じ順序で情報を読み出します。buffer + のデータの追加と削除の方法については、以下の例を参照してください。
+このページをご覧になっている方は、buffer のバイトアライメントについて + 言及されているのをご覧になったことがあると思います。これは基本的に、与えられたbuffer + の中で新しいデータが格納される位置のことを指します。これはどのように機能するのでしょうか?シングルバイトアライメントbuffer の場合、各データはbuffer に順次書き込まれ、新しいデータは前のデータの直後に追加されます。しかし、2バイトアラインのbuffer は、各データを2バイト間隔で書き込むので、最初の書き込みが1バイトのデータであっても、次の書き込みは2バイトに揃うように移動されることになります。
+つまり、バイトアライメントを例えば4バイトに設定し、1バイトのデータを書き込んでからbuffer Tell
+ (Tellは現在の読み書きの位置をbuffer )すると、1バイトのオフセット
+ (この場合のオフセットは、buffer の先頭から現在の読み書きの位置までのバイト数です)が得られます。
しかし、1バイトのデータを書き込んでから 、buffer + を実行すると、(2バイトのデータしか書いていないのに)5バイトのオフセットが発生します。これは、4バイトのbuffer + アライメントに合わせるため、データをパディングしているためです。
+基本的には、アライメントが影響を与えるのは書き込む場所だけ なので、何かを書き込んだ後にbuffer + を実行すると、前に書き込んだデータのすぐ後にある現在の書き込み位置が返されます。しかし、その後に別のデータを書き込むと、buffer + は実際にデータを書き込む前に、書き込み位置をアライメントサイズの次の倍数に移動させることに注意してください。
以下では、buffers をプロジェクトで使用する場合の例をいくつか紹介します。
どのプラットフォームのGameMakerゲームでも使える簡単な例として、buffer という関数があります。 game_save_buffer().この関数は、現在のゲーム状態の「スナップショット」を取り、あらかじめ定義されたbuffer に保存し、それを読み込んで再びその時点のゲームをロードすることができます。
-注意:この機能は非常に限定的で、初心者がチェックポイントシステムを素早く立ち上げるために設計されています。上級者は、データ構造、サーフェス、追加したsprites など、ランタイムに作成できる動的なリソースを保存しないため、ファイル機能を使用して独自のシステムをコーディングすることを好むかもしれません。
-まず、保存と読み込みを制御するために、object を新規に作成し、Create Event を与えることになります。このイベントには、次のようなコードを配置します。
+どのプラットフォームのGameMakerゲームでも使える簡単な例として、buffer という関数があります。 game_save_buffer().この関数は、現在のゲーム状態の「スナップショット」を取り、あらかじめ定義されたbuffer に保存し、それを読み込んで再びその時点のゲームをロードすることができます。
+注意:この関数は非常に限定的で、初心者がチェックポイントシステムを素早く立ち上げるために設計されています。上級者は、データ構造、サーフェス、追加したsprites など、ランタイムに作成できる動的なリソースを保存しないため、ファイル関数を使用して独自のシステムをコーディングすることを好むかもしれません。
+まず、保存と読み込みを制御するために、object を新規に作成し、Create Event + を与えることになります。このイベントには、次のようなコードを配置します。
SaveBuffer = buffer_create(1024, buffer_grow, 1);
StateSaved = false;
最初の行では、1024バイトで1バイトにアラインしたgrowbuffer (セーブデータの最終サイズが分からないので)を作成しています。そして、ゲームがセーブされているかどうかをチェックするための変数が作成されます(これはロード時に使用されます)。
+最初の行では、1024バイトで1バイトにアラインしたgrowbuffer + (セーブデータの最終サイズが分からないので)を作成しています。そして、ゲームがセーブされているかどうかをチェックするための変数が作成されます(これはロード時に使用されます)。
次に、キープレス・イベント(例)を追加して、現在のゲーム・ステートを作成したバッファに保存します。
StateSaved = true;
buffer_seek(SaveBuffer, buffer_seek_start, 0);
game_save_buffer(SaveBuffer);
上記は、まずコントロール変数を true に設定し(ゲームをbuffer に保存するときに、これが保存されるように)、現在の保存状態を書き込む前にbuffer の開始点にシークします。なぜ buffer_seek()?さて、このページですでに述べたように、buffer への読み書きは、最後にデータが追加された位置から行います。つまり、buffer を最初に戻さないと、保存するときに、現在のbuffer の読み書きの位置にあるbuffer にデータを追加することになるのです。そこで、関数 buffer_seek() を使って、tell をbuffer の先頭に移動させます。
-これで、現在のゲームの状態がbuffer に保存されました。 次のステップでは、おそらく別のキープレス・イベントで、それをロードする方法をコーディングします。
+上記は、まずコントロール変数を true に設定し(ゲームをbuffer に保存するときに、これが保存されるように)、現在の保存状態を書き込む前にbuffer + の開始点にシークします。なぜ buffer_seek()?さて、このページですでに述べたように、buffer + への読み書きは、最後にデータが追加された位置から行います。つまり、buffer を最初に戻さないと、保存するときに、現在のbuffer の読み書きの位置にあるbuffer にデータを追加することになるのです。そこで、関数 + buffer_seek() を使って、tell をbuffer の先頭に移動させます。 +
+これで、現在のゲームの状態がbuffer に保存されました。 + 次のステップでは、おそらく別のキープレス・イベントで、それをロードする方法をコーディングします。
if StateSaved
{
buffer_seek(SaveBuffer, buffer_seek_start, 0);
game_load_buffer(SaveBuffer);
}
そして、上記のコードを配置したイベントの終了時にゲームがロードされます。
-注意:これは同じroom でのみ使用され、ゲームを閉じたり再起動した後の完全なセーブゲームを生成するものではありません。
-object Buffers はメモリに保存されるため、終了時にクリーンアップしないと、メモリリークが発生し、最終的にゲームがラグやクラッシュする可能性があります。そこで、Room End Event(Otherevent category) を追加することになるでしょう。
+注意:これは同じroom + でのみ使用され、ゲームを閉じたり再起動した後の完全なセーブゲームを生成するものではありません。
+object Buffers + はメモリに保存されるため、終了時にクリーンアップしないと、メモリリークが発生し、最終的にゲームがラグやクラッシュする可能性があります。そこで、Room End + Event(Otherevent category) を追加することになるでしょう。
buffer_delete(SaveBuffer);
-このobject をroom に入れ、キーを押すとroom の状態を保存し、buffer から読み込むことができます。
+このobject をroom に入れ、キーを押すとroom の状態を保存し、buffer から読み込むことができます。
GameMakerの ネットワーク機能を使う場合、buffers 、ネットワーク接続で送信されるデータパケットを作成する必要があります。この例では、この方法を紹介するつもりですが、ネットワークの可能性の範囲から、buffers 自体の使い方を紹介するだけで、ネットワーク・システム全体を紹介するものではありません。
-最初に紹介するのは、ネットワーク接続のクライアント側のためのbuffer の作成と使用です。このbuffer は小さなデータパケットを作成するために使用され、その後server に送信されます。したがって、インスタンスの作成イベントでは、このようにbuffer を割り当てることになります。
+GameMakerの ネットワーク機能を使う場合、buffers + 、ネットワーク接続で送信されるデータパケットを作成する必要があります。この例では、この方法を紹介するつもりですが、ネットワークの可能性の範囲から、buffers + 自体の使い方を紹介するだけで、ネットワーク・システム全体を紹介するものではありません。
+最初に紹介するのは、ネットワーク接続のクライアント側のためのbuffer の作成と使用です。このbuffer は小さなデータパケットを作成するために使用され、その後server + に送信されます。したがって、インスタンスの作成イベントでは、このようにbuffer を割り当てることになります。
send_buff = buffer_create(256, buffer_grow, 1);
-大量のデータを保持することを目的としていないため、buffer を小さく(256バイト)し、さらに送信するデータをいつでも追加する必要がある場合にエラーが発生しないようにbuffer を大きくし、アライメントは便宜上1つに設定しています。
-server buffer この例では、プレイヤーが左矢印を押して ゲーム内を移動するときのようなKey Press Eventを送信することにします。これを行うには、まず必要なデータをbuffer に書き込み、それを送信します。
+大量のデータを保持することを目的としていないため、buffer + を小さく(256バイト)し、さらに送信するデータをいつでも追加する必要がある場合にエラーが発生しないようにbuffer + を大きくし、アライメントは便宜上1つに設定しています。
+server buffer + この例では、プレイヤーが左矢印を押して ゲーム内を移動するときのようなKey Press Eventを送信することにします。これを行うには、まず必要なデータをbuffer に書き込み、それを送信します。
buffer_seek(buff, buffer_seek_start, 0);
buffer_write(buff, buffer_u8, 1);
buffer_write(buff, buffer_s16, vk_left);
buffer_write(buff, buffer_bool, true);
network_send_packet(client, buff, buffer_tell(buff));
buffer に書き込む前に、ネットワークでは常にbuffer の先頭からデータを取得するため、tell をbuffer の先頭に設定しました。次にチェック値(これはserver で処理するイベントの種類を決定するために使用されます)、使用するキー、キーの状態(この場合、押されていれば真)を書き込んでいます。このbuffer は、ネットワーク機能によってデータパケットとして送信されます。このとき、buffer の全体を送信するのではないことに注意してください !buffer_tell 関数を使用してbuffer の現在の読み取り/書き込み位置を返し、書き込まれたデータのみを送信します (buffer に書き込むと、書き込まれたデータの最後に "tell" が移動することを思い出してください)。これは単に、必要以上のバイトを送らないようにするためです。
-server受信したデータパケットは、buffer のserver に書き込まれ、ゲームの更新に使用される必要があります。そのためには、以下の簡略化したコードのように、object のネットワーク・コントローラserver のNetworking Asynchronous Eventを使用することになります。
+buffer に書き込む前に、ネットワークでは常にbuffer の先頭からデータを取得するため、tell をbuffer + の先頭に設定しました。次にチェック値(これはserver + で処理するイベントの種類を決定するために使用されます)、使用するキー、キーの状態(この場合、押されていれば真)を書き込んでいます。このbuffer + は、ネットワーク機能によってデータパケットとして送信されます。このとき、buffer の全体を送信するのではないことに注意してください !buffer_tell + 関数を使用してbuffer の現在の読み取り/書き込み位置を返し、書き込まれたデータのみを送信します (buffer に書き込むと、書き込まれたデータの最後に "tell" + が移動することを思い出してください)。これは単に、必要以上のバイトを送らないようにするためです。
+server受信したデータパケットは、buffer + のserver に書き込まれ、ゲームの更新に使用される必要があります。そのためには、以下の簡略化したコードのように、object のネットワーク・コントローラserver のNetworking Asynchronous Eventを使用することになります。 +
var buff = ds_map_find_value(async_load, "buffer");
if (cmd == buffer_read(buff, buffer_u8))
{
key = buffer_read(buff, buffer_s16);
key_state = buffer_read(buff, buffer_bool);
}
非同期イベントには、特別な一時的DSマップ async_load (イベントの終了時に自動的にメモリから削除されます)、ネットワークから受信するデータの種類に応じて異なる情報が含まれます。この場合、マップがチェックされ、クライアントから送信されたbuffer データパケットであることが判明したと仮定している。buffer この場合、値「1」はキーイベントを表します。しかし、このようなものをコーディングする場合、物事を単純化するためにこれらの値を保持する定数を定義するべきです。そして、押されているキーとその状態(true = 押されている、 false = 離されている)を保存します。この情報は、送信側のクライアント・プレーヤーの新しいステータスですべてのクライアントを更新するために使用されます。
-注:DS マップから作成されるbuffer は、Network Asynchronous Event の終了時に自動的に削除されるため、ここでbuffer_delete()を使用する必要はない。
+非同期イベントには、特別な一時的DSマップ async_load + (イベントの終了時に自動的にメモリから削除されます)、ネットワークから受信するデータの種類に応じて異なる情報が含まれます。この場合、マップがチェックされ、クライアントから送信されたbuffer データパケットであることが判明したと仮定している。buffer + この場合、値「1」はキーイベントを表します。しかし、このようなものをコーディングする場合、物事を単純化するためにこれらの値を保持する定数を定義するべきです。そして、押されているキーとその状態(true = 押されている、 false = + 離されている)を保存します。この情報は、送信側のクライアント・プレーヤーの新しいステータスですべてのクライアントを更新するために使用されます。
+注:DS マップから作成されるbuffer は、Network Asynchronous Event + の終了時に自動的に削除されるため、ここでbuffer_delete()を使用する必要はない。
@@ -215,11 +312,12 @@
このガイドは、パーティクルの使い方や作り方を理解したい方のためのものです。このページでは、パーティクルのGameMaker Language関数と GML Visualアクションの両方について説明します。パーティクルはとても便利で、作るのがとても楽しいので、今まで使ったことがない方は、このガイドで始めていただければと思います。
-先に進む前に、パーティクルとは何かについて説明しておきましょう...。基本的にパーティクルは、パーティクルシステムによって定義された特定のプロパティを持つグラフィックリソースです。これらのプロパティは個々の パーティクルに対して直接操作することはできませんが、所属するシステムを定義するために使用されるコードやアクションを通じて一括して変更されます。インスタンスのようなCPUオーバーヘッドを伴わずに、美しく派手な効果や、繊細で控えめな効果をゲーム内で作り出すのに非常に有効な手段です。
-パーティクルシステムについて触れましたが、続きの前にそれが何であるかを説明しましょう。パーティクルシステムは、パーティクルをすぐに使えるように入れておく容器のようなものだと考えてください。コードやアクションを使ってパーティクルのビジュアル面を定義し、それを「容器」(パーティクルシステム)に入れることで、後で必要なときにいつでもどこでも取り出して使えるようにします。
-システムをセットアップしてパーティクルを作成する前に、いくつかのことを知っておくことが重要です。まず、パーティクルシステムのコードのほとんどは、ゲーム内で一度だけ呼び出されます。通常は、最初のobject またはレベルのコントローラroom で呼び出されます。これは必ずしもそうではありませんが、簡単のために、以下の簡単なガイドではこのシナリオを使用します。これは、パーティクルを使用する最も一般的な方法だからです。パーティクルシステムは一度作成するとメモリ内に留まり、いつでも使用できる状態になるため、複数回作成するとメモリ使用量がすぐに増え、深刻なラグが発生し、ゲームがクラッシュする可能性さえあります。このガイドでは簡略化のため、ゲーム内のどのインスタンスでもいつでも使えるグローバルパーティクルシステムを 作成することにします。
+ + + +このガイドは、パーティクルの使い方や作り方を理解したい方のためのものです。このページでは、パーティクルのGameMaker Language関数と GML + Visualアクションの両方について説明します。パーティクルはとても便利で、作るのがとても楽しいので、今まで使ったことがない方は、このガイドで始めていただければと思います。
++ 先に進む前に、パーティクルとは何かについて説明しておきましょう...。基本的にパーティクルは、パーティクルシステムによって定義された特定のプロパティを持つグラフィックリソースです。これらのプロパティは個々の + パーティクルに対して直接操作することはできませんが、所属するシステムを定義するために使用されるコードやアクションを通じて一括して変更されます。インスタンスのようなCPUオーバーヘッドを伴わずに、美しく派手な効果や、繊細で控えめな効果をゲーム内で作り出すのに非常に有効な手段です。 +
++ パーティクルシステムについて触れましたが、続きの前にそれが何であるかを説明しましょう。パーティクルシステムは、パーティクルをすぐに使えるように入れておく容器のようなものだと考えてください。コードやアクションを使ってパーティクルのビジュアル面を定義し、それを「容器」(パーティクルシステム)に入れることで、後で必要なときにいつでもどこでも取り出して使えるようにします。 +
++ システムをセットアップしてパーティクルを作成する前に、いくつかのことを知っておくことが重要です。まず、パーティクルシステムのコードのほとんどは、ゲーム内で一度だけ呼び出されます。通常は、最初のobject またはレベルのコントローラroom + で呼び出されます。これは必ずしもそうではありませんが、簡単のために、以下の簡単なガイドではこのシナリオを使用します。これは、パーティクルを使用する最も一般的な方法だからです。パーティクルシステムは一度作成するとメモリ内に留まり、いつでも使用できる状態になるため、複数回作成するとメモリ使用量がすぐに増え、深刻なラグが発生し、ゲームがクラッシュする可能性さえあります。このガイドでは簡略化のため、ゲーム内のどのインスタンスでもいつでも使えるグローバルパーティクルシステムを + 作成することにします。
++ +
まず最初に、パーティクルシステムを定義し、名前を付けて使用できるようにする必要があります。これはグローバルなシステムで、どのようなobject でも使用できるようにするため、コントローラobject + か、ゲーム開始時に実行する初期化関数で行います。GML は次のようなものです。
+global.P_System = part_system_create_layer("Instance_Layer", false);
+そして、GML Visualを使用します。
+提供されたレイヤー名は、システムが使用されるroom
+ で有効なレイヤーでなければならないことに注意してください。そうでなければ、パーティクルは表示されません。また、"persistent"flag
+ (in code and inGML Visual)をfalseに設定していることに注意してください。永続的なパーティクルシステムとは、rooms をまたいで「永続」するもので、room
+ ごとに破壊して再作成する必要がありません。しかし、このガイドでは、シンプルにするために、永続化を使用しません。
それでできたのがシステムですが、パーティクルはどうするのですか?パーティクルも定義しないと、このシステムは何の役にも立たない。
++
パーティクルをシステムで使用するには、まずその一般的なプロパティを定義する必要があります。これはobject + のプロパティのようなものですが、個々のパーティクルに対して一般的な + 方法でのみ適用されます。つまり、パーティクルの最小移動速度を1、最大移動速度を2に設定すると、システムで作成されたパーティクルは1ステップあたり1~2ピクセルの間でランダムな速度になり、全体としては平均速度が1.5となる、ということです。最初のパーティクルに名前を付け、システムを作成したのと同じGML で次のobject を使って追加してください。
+global.Particle1 = part_type_create();
+そして、GML Visualをご利用の方へ。
+ GML Visual を使って、ブレンド
+ オプションにもチェックを入れていることに注意してください。これによってパーティクルの加算ブレンディングが可能になりますが、これについてはもう少し後ほど説明します。
+ これでシステムとそこに入れるパーティクルができましたが、優れたエフェクトを作るにはまだ準備ができていません。パーティクルのプロパティ、つまりパーティクルの見た目(速度、回転、アルファ値など)を定義する必要があります。パーティクル効果を定義するために使用できる詳細がたくさんあるので、以下に最も重要な設定の概要と、それらをすべて使用するコードのスニペットとGML Visual を紹介します。
+さて、パーティクルを定義するコードを紹介する前に、ちょっとだけ「wiggle」の話を...。信じられないかもしれませんが、"wiggle + "はパーティクルのプロパティで、上記の多くの設定に対して個別に設定することが可能です。パーティクル関数やアクションの引数に "wiggle + "がある場合、1~20の数字を入れるとパーティクルはそのプロパティの最小値と最大値の間で "くねくね + "と揺れ、1だと遅く、20だと非常に速く揺れます。つまり、パーティクルの速度が最小値2、最大値5で、ウィグルが20の場合、作成された各パーティクルの寿命の間、最小/最大速度の間で非常に速く揺れ動くことになります。 +
++ 注意:他にも細かいパーティクルプロパティがありますが、ここではできるだけシンプルにするために説明しません。パーティクルプロパティの詳細については、各ページを参照してください。 +
+では、パーティクルを定義するコードを見てみましょう。
+// This defines the particle's shape
+
+ part_type_shape(global.Particle1,pt_shape_pixel);
+
+
+ // This is for the size
+
+ part_type_size(global.Particle1,1,1,0,2);
+
+
+ // This sets its colour. There are three different codes for this
+
+ part_type_color1(global.Particle1,c_white);
+
+
+ // This is its alpha. There are three different codes for this
+
+ part_type_alpha1(global.Particle1,1);
+
+
+ // The particles speed
+
+ part_type_speed(global.Particle1,0.50,2,-0.10,0);
+
+
+ // The direction
+
+ part_type_direction(global.Particle1,0,359,0,20);
+
+
+ // This changes the rotation of the particle
+
+ part_type_orientation(global.Particle1,0,0,0,0,true);
+
+
+ // This is the blend mode, either additive or normal
+
+ part_type_blend(global.Particle1,1);
+
+
+ // This is its lifespan in steps
+
+ part_type_life(global.Particle1,5,30);
+
これと同じパーティクル定義をGML Visual で作成するには、以下のアクションが必要です。
+というわけで、これで終了です。これでパーティクルの定義が完了し、使用できるようになりました。
+
パーティクルを作成する方法はいくつかあり、それぞれに長所と短所があります。エミッターを使用してパーティクルをはじいたり + 流したり する方法と、ポイントに直接 + パーティクルを作成する方法があります。どちらを使うかは、何を実現したいか、どんな効果を出したいかによりますが、まずは一番簡単な、パーティクルを直接作成する方法から説明します。GML では、以下のような関数を使用します。 +
+part_particles_create(global.P_System, x, y, global.Particle1, 10);
+で、GML Visualになります。
+このコードとアクションで、グローバルシステムから "Particle1
+ "というタイプのパーティクルがx/y座標に10個作成されます。簡単ですね。このコードとアクションの素晴らしいところは、どこでも簡単に使えることです。例えば、object のマウスのGlobal Left Pressedイベントで、mouse_x/y の位置の x/y
+ 値を変更すると、ボタンを押すたびにマウスの位置にパーティクルが作成されます。また、ロケットの場合は、ステップイベントにこれを配置し、ステップごとに煙のパーティクルを発生させることができます(ただし、10回よりも1回や2回のほうがいいかもしれません!)。x/y座標をランダムに変化させることで、ある範囲にパーティクルを発生させることも可能です。
+
repeat(50)
+
+ {
+
+ var xx = x + 20 - random(40);
+
+ var yy = y + 20 - random(40);
+
+ part_particles_create(global.P_System, xx, yy, global.Particle1, 1);
+
+ }
+
上記のコードでは、40px四方の領域内のランダムな位置に50個のパーティクルが作成されます。
+
+ パーティクルを作る簡単な方法を説明しましたので、次は少し複雑な方法、エミッターを使う方法を説明します。エミッターもパーティクルシステムの一部で、使用する前に定義する必要があります。そこで、システムやパーティクルに対して行ったのと同じように、グローバルエミッターを作成します。また、静的(動かない)エミッターにするかどうか、パーティクルをバーストさ + せるかストリームさ せるか、どの範囲にどのような分布でエミッターを使わせるかを決めなければなりません。
+どういうことでしょうか?例えば、丸太の火を考えてみてください。これは動かず、ただ炎を出すだけなので静的 + ですが、火の玉は動的エミッターを必要とし、画面上を移動します。バーストとストリーミングについては、バーストは1回限りのパーティクルの爆発であるのに対し、ストリームはステップごとに一定のパーティクルの流れになります。エリアと分布については、エミッターではパーティクルを放出するエリア(矩形、楕円、菱形、線)と分布曲線(ガウス、逆ガウス、線形)を定義することができます。 +
+以下の画像は、エミッターに利用可能なさまざまなタイプのエリアシェイプを説明したものです。
++


+
+ そして、その分布曲線(線形、ガウシアン、逆ガウシアン)を図解しています。
+

下記は、2つのエミッターを定義するために必要なコードとアクションの例です。通常、エミッターは、パーティクルシステムを定義した直後に、コントローラ(object )のCreate Eventに入ります。1つは静的で、パーティクルをroom 全体に流します。もう1つは動的で、マウスに追従し、小さな楕円から30ステップごとにバーストさせるものです。
- -
まず最初に、パーティクルシステムを定義し、名前を付けて使用できるようにする必要があります。これはグローバルなシステムで、どのようなobject でも使用できるようにするため、コントローラobject か、ゲーム開始時に実行する初期化関数で行います。GML は次のようなものです。
-global.P_System = part_system_create_layer("Instance_Layer", false);
-そして、GML Visualを使用します。
-提供されたレイヤー名は、システムが使用されるroom で有効なレイヤーでなければならないことに注意してください。そうでなければ、パーティクルは表示されません。また、"persistent"flag (in code and inGML Visual)をfalseに設定していることに注意してください。永続的なパーティクルシステムとは、rooms をまたいで「永続」するもので、room ごとに破壊して再作成する必要がありません。しかし、このガイドでは、シンプルにするために、永続化を使用しません。
それでできたのがシステムですが、パーティクルはどうするのですか?粒子も定義しないと、このシステムは何の役にも立たない。
--
パーティクルをシステムで使用するには、まずその一般的なプロパティを定義する必要があります。これはobject のプロパティのようなものですが、個々のパーティクルに対して一般的な 方法でのみ適用されます。つまり、パーティクルの最小移動速度を1、最大移動速度を2に設定すると、システムで作成されたパーティクルは1ステップあたり1~2ピクセルの間でランダムな速度になり、全体としては平均速度が1.5となる、ということです。最初のパーティクルに名前を付け、システムを作成したのと同じGML で次のobject を使って追加してください。
-global.Particle1 = part_type_create();
-そして、GML Visualをご利用の方へ。
- GML Visual を使って、ブレンド オプションにもチェックを入れていることに注意してください。これによってパーティクルの加算ブレンディングが可能になりますが、これについてはもう少し後ほど説明します。
これでシステムとそこに入れるパーティクルができましたが、優れたエフェクトを作るにはまだ準備ができていません。パーティクルのプロパティ、つまりパーティクルの見た目(速度、回転、アルファ値など)を定義する必要があります。パーティクル効果を定義するために使用できる詳細がたくさんあるので、以下に最も重要な設定の概要と、それらをすべて使用するコードのスニペットとGML Visual を紹介します。
-さて、パーティクルを定義するコードを紹介する前に、ちょっとだけ「wiggle」の話を...。信じられないかもしれませんが、"wiggle "はパーティクルのプロパティで、上記の多くの設定に対して個別に設定することが可能です。パーティクル関数やアクションの引数に "wiggle "がある場合、1~20の数字を入れるとパーティクルはそのプロパティの最小値と最大値の間で "くねくね "と揺れ、1だと遅く、20だと非常に速く揺れます。つまり、パーティクルの速度が最小値2、最大値5で、ウィグルが20の場合、作成された各パーティクルの寿命の間、最小/最大速度の間で非常に速く揺れ動くことになります。
-注意:他にも細かいパーティクルプロパティがありますが、ここではできるだけシンプルにするために説明しません。パーティクルプロパティの詳細については、各ページを参照してください。
-では、パーティクルを定義するコードを見てみましょう。
-// This defines the particle's shape
-
- part_type_shape(global.Particle1,pt_shape_pixel);
-
-
- // This is for the size
-
- part_type_size(global.Particle1,1,1,0,2);
-
-
- // This sets its colour. There are three different codes for this
-
- part_type_color1(global.Particle1,c_white);
-
-
- // This is its alpha. There are three different codes for this
-
- part_type_alpha1(global.Particle1,1);
-
-
- // The particles speed
-
- part_type_speed(global.Particle1,0.50,2,-0.10,0);
-
-
- // The direction
-
- part_type_direction(global.Particle1,0,359,0,20);
-
-
- // This changes the rotation of the particle
-
- part_type_orientation(global.Particle1,0,0,0,0,true);
-
-
- // This is the blend mode, either additive or normal
-
- part_type_blend(global.Particle1,1);
-
-
- // This is its lifespan in steps
-
- part_type_life(global.Particle1,5,30);
これと同じパーティクル定義をGML Visual で作成するには、以下のアクションが必要です。
-というわけで、これで終了です。これでパーティクルの定義が完了し、使用できるようになりました。
-
パーティクルを作成する方法はいくつかあり、それぞれに長所と短所があります。エミッターを使用してパーティクルをはじいたり 流したり する方法と、ポイントに直接 パーティクルを作成する方法があります。どちらを使うかは、何を実現したいか、どんな効果を出したいかによりますが、まずは一番簡単な、パーティクルを直接作成する方法から説明します。GML では、以下のような関数を使用します。
-part_particles_create(global.P_System, x, y, global.Particle1, 10);
-で、GML Visualになります。
-このコードとアクションで、グローバルシステムから "Particle1 "というタイプのパーティクルがx/y座標に10個作成されます。簡単ですね。このコードとアクションの素晴らしいところは、どこでも簡単に使えることです。例えば、object のマウスのGlobal Left Pressedイベントで、mouse_x/y の位置の x/y 値を変更すると、ボタンを押すたびにマウスの位置にパーティクルが作成されます。また、ロケットの場合は、ステップイベントにこれを配置し、ステップごとに煙のパーティクルを発生させることができます(ただし、10回よりも1回や2回のほうがいいかもしれません!)。x/y座標をランダムに変化させることで、ある範囲にパーティクルを発生させることも可能です。
repeat(50)
-
- {
-
- var xx = x + 20 - random(40);
-
- var yy = y + 20 - random(40);
-
- part_particles_create(global.P_System, xx, yy, global.Particle1, 1);
-
- }
上記のコードでは、40px四方の領域内のランダムな位置に50個のパーティクルが作成されます。
-
パーティクルを作る簡単な方法を説明しましたので、次は少し複雑な方法、エミッターを使う方法を説明します。エミッターもパーティクルシステムの一部で、使用する前に定義する必要があります。そこで、システムやパーティクルに対して行ったのと同じように、グローバルエミッターを作成します。また、静的(動かない)エミッターにするかどうか、パーティクルをバーストさ せるかストリームさ せるか、どの範囲にどのような分布でエミッターを使わせるかを決めなければなりません。
-どういうことでしょうか?例えば、丸太の火を考えてみてください。これは動かず、ただ炎を出すだけなので静的 ですが、火の玉は動的エミッターを必要とし、画面上を移動します。バーストとストリーミングについては、バーストは1回限りのパーティクルの爆発であるのに対し、ストリームはステップごとに一定のパーティクルの流れになります。エリアと分布については、エミッターではパーティクルを放出するエリア(矩形、楕円、菱形、線)と分布曲線(ガウス、逆ガウス、線形)を定義することができます。
-以下の画像は、エミッターに利用可能なさまざまなタイプのエリアシェイプを説明したものです。
--


-
- そして、その分布曲線(線形、ガウシアン、逆ガウシアン)を図解しています。

下記は、2つのエミッターを定義するために必要なコードとアクションの例です。通常、エミッターは、パーティクルシステムを定義した直後に、コントローラ(object )のCreate Eventに入ります。1つは静的で、パーティクルをroom 全体に流します。もう1つは動的で、マウスに追従し、小さな楕円から30ステップごとにバーストさせるものです。
--
global.Particle1_Emitter1 = part_emitter_create(global.P_System);
-
- global.Particle1_Emitter2 = part_emitter_create(global.P_System);
-
-
- // Set up the area that will emit particles
-
- part_emitter_region(global.P_System, global.Particle1_Emitter1, 0, room_width, 0, room_height, ps_shape_rectangle, ps_distr_linear);
-
- part_emitter_region(global.P_System, global.Particle1_Emitter2, mouse_x-10, mouse_x+10, mouse_y-10, mouse_y+10, ps_shape_ellipse, ps_distr_gaussian);
-
-
- // Set the first to stream 10 particles every step
-
- part_emitter_stream(global.P_System, global.Particle1_Emitter1, global.Particle1, 10);
-
-
- // This can now be forgotten as it will function until told to stop...
-
- // Set the alarm[0] event to burst the emitter2 particles...
-
- alarm[0] = 30;
ここでは、最初に作成したパーティクルシステムに割り当てるパーティクルエミッターを2つ作成します。これらのエミッターを作成する関数/アクションでは、パーティクルを放出する領域をroom で定義し、放出するパーティクルの種類と、定義した領域内で使用する形状や分布を指定できます。関数やアクションはエミッターIDの数値を返し、これを変数に格納することで、さらにエミッター関数を使用してこれらのエミッターをターゲットにすることができます。
パーティクルを流すためのコード/GML Visualができましたが(これらのパーティクルは、何もしなくてもゲームステップごとに放出されます)、特定の間隔でパーティクルをはじき出すためのAlarm[0] イベントも追加したいと思います。
-part_emitter_region(global.P_System, global.Particle1_Emitter2, mouse_x - 10, mouse_x + 10, mouse_y - 10, mouse_y + 10, ps_shape_ellipse, ps_distr_gaussian);
-
- part_emitter_burst(global.P_System, global.Particle1_Emitter2, global.Particle1, 30);
-
- alarm[0] = 30;
パーティクル・バーストは、ゲーム・ステップごとにパーティクルを一定量流すのではなく、エミッターから一度だけ爆発させるものです。
しかし、複数のobjects でパーティクルを放出させたい場合はどうしたらよいでしょうか。グローバルエミッターは一度に一ヶ所にしか設置できないので、各object にローカルエミッターを 作成する必要があります。これらのエミッターは、グローバルパーティクルシステムとその中にあるパーティクルを使用しますが、異なる形や大きさにすることができ、object 、ロケットや弾丸などに最適な動きをします。使用するコードは上記と全く同じですが、エミッター名の前に「global」という接頭辞を付けません。
-これでパーティクルの作成は完了ですが、もうひとつ大事なことがあります。使い終わった後の片付け。
--
冒頭で述べたように、パーティクルシステム(およびそのパーティクル、エミッターなど)は一度作成すると、すぐに使えるようにメモリに保存されます。素晴らしいことですが、ゲームを再起動したときはどうなるのでしょうか?あるいは、プレイヤーが死亡して、room を再び開始した場合はどうなるのでしょうか?ゲームを正しく管理しないと、メモリーリークが発生します。これは、何かが作成され、メモリを使用していたが、「参照解除」された、つまり、GameMaker はもうそれにアクセスできない、という場合です。このようなことが起こると、徐々にメモリが消費され、ゲームにラグが生じたり、コンピュータがブロックされてゲームがクラッシュしたりすることがあります。
-これを避けるにはどうしたらいいのでしょうか?GameMakerにはGML Code 関数とGML Visual アクションがあり、パーティクルシステムとそのエミッタやパーティクルを未使用時にメモリから削除します。以下のコードやアクションを使用する際に少し計画を立てれば、この潜在的な問題を簡単に防止することができます。
-まず、どこにシステムを作るか、どのように使うかを決める必要があります。最初のobject にあるroom のGame Start Eventでグローバルシステムを作ることもできますが(メニューやタイトル画面など)、これだと、ゲームを再起動したときに game_restart()関数を使用すると、再作成され、メモリリークが発生します。あるいは、任意のroom のインスタンスにローカルシステムを作成することもできますが、この場合もroom を離れると、システムにアクセスできなくなり、メモリリークが発生します。これを避けるには、以下のようなものを ゲーム終了イベントまたは クリーンアップイベントを作成します。
-part_type_destroy(global.Particle1);
-
- part_emitter_destroy(global.P_System, global.Particle1_Emitter);
-
- part_emitter_destroy(global.P_System, global.Particle2_Emitter);
-
- part_system_destroy(global.P_System);
これにより、定義されたパーティクル、エミッタ、そしてシステムがメモリから削除され、ゲームを再起動したり、room を変更したりすることができるようになります。システムを作るのに最も適した場所がどこかを考えたら、システムを破壊するのに最も適した場所がどこかも考えてください。
-
-
パーティクル、パーティクルシステム、エミッターについての基本がわかったので、次はそれらをゲームに追加してみましょうただし、パーティクルはインスタンスよりもCPUを消費しませんが、一度に何千個も使用するとラグが発生するため、すべてを解決するものではありません。最適なのは、実験して、ゲームの視覚的な「肉付け」と、やり過ぎない程度に目を楽しませるために、注意深く使用することです。
--
-