Game Makerでシンプルなゲームを開発します。 エピソード0。最初の行



あなたがゲームが好きなら、あなたはそれらがどのように作られるのか疑問に思っていることは間違いありません。 ゲームを作りたいが、経験がない場合は、この記事で始める方法についてお話します。

ゲームエンジンGame Makerについて話し、Plants vs Zombiesなどの単純なゲームのクローンを作成する出版物を投稿したいと思います。 おそらく、ゲームパッドのサポートを追加し、たとえばAndroidバージョンを作成します。

ソースコードは公開されますが、無料で描画してコミュニティと共有したい人がいない場合、グラフィックはGraphicRiverで購入され、明白な理由でゲームとともに配布されません。 まあ、ゲームには豊富なアニメーションもありません。

エントリー


Game Makerは非常にシンプルなゲームエンジンであり、Windows、Mac OS X、Ubuntu、Android、iOS、Tizen、Windows Phone、Windows 8、PlayStation 3、PS 4、PS Vita、Xbox One、HTMLの多数のプラットフォーム向けのゲームを作成できます5. SteamWorksのサポートがあります。 ゲームが成功した場合、別のプラットフォームへの移植は難しくありません。

控えめな知識と動機が最小限であっても、開発速度は他のエンジンよりも主観的に高速です。 初心者向けのインストールとセットアップは可能な限り簡単で、特別な知識は必要ありません。 他のプラットフォーム用のコンパイルでは、ゲームコードを変更する必要はなく、ワンクリックで(まあ、ほぼ)実行されます。

Game Makerを作成した会社であるYoYoGamesは、最近Playtechに買収されました。これにより、Game Makerは今後も成長し続けると確信できます。 発表されたGame Maker 2.0は、おそらくさらにフレンドリーでシンプルなものになるでしょう。また、さらに優れた機能を備えていると考えるのも理にかなっています。 彼らがプレスリリースで言うように、GM 2.0は会社を買収した理由の1つです。

この記事では、Game Makerについて簡単に説明し、将来のプロジェクトの簡単なスケッチを作成します。

このエンジンは誰のために、どのような目的で使用できますか?
皆のために。 目標は2Dゲームです。 ただし、プログラミングがネイティブな要素ではない人や、ゲームを作成したりお金を稼ぎたい人のために最小限の労力でラピッドプロトタイピングとゲームを作成する場合は、Game Makerが最適です。

ゲームメーカーの長所


-簡単な入力;
-Java / C / C#...構文の誰もが知っている。
-異なるプラットフォームで簡単にコンパイルする機能。
-長年にわたって既に多くの問題を解決し、コードを書いてきた活発なコミュニティ。
-標準機能。これにより、大量のコードを自分で記述する必要がなくなります。
-extension'yによる拡張性。
-ヘルプ(F1)は非常にシンプルで便利で、優れた説明と例があります。

ゲームメーカーの短所


-有料(ゲームの出版まで成長したら、ライセンスを購入する必要があります);
-ユーザー変数の自動置換はなく、標準およびスクリプトのみ。
-最大ライセンスの高コスト(ただし、誰もがすべてのモジュールを直接必要とするわけではありません)。
-技術サポート(技術サポートに2回連絡しましたが、2週間後よりも早く応答しませんでした)。
-自動修復の可能性はありません。

ゲームの作成に移ります。 ゲームメーカーをインストールして空のプロジェクトを作成することは問題ではないと思います。 一般に、まず、すべての機能について考え、ダイアグラムを描画し、収益化について考えてみるとよいでしょうが、これは記事の目的ではないので、初心者のゲーム開発者向けのプロジェクトを作成する方法を紹介します。

プロジェクト構造について簡単に説明します。

残りはまだ興味がありません。

Game Makerのスプライトとは何ですか?


これは、ゲームで使用される画像/アニメーションです。 それらには独自のマスクがあり、その形状とサイズは変更できます。 マスクは、オブジェクトの衝突のイベントに反応する画像領域です(このスプライトが何らかのオブジェクトに割り当てられている場合)、クリックします。 描画点(原点)を指定できます-たとえば、中心、角、またはその他の点から。

スプライトのテクスチャグループを指定することもできます。 レンダリングを最適化する必要があります(たとえば、ゲーム画面があるときにメニュー画面で使用される画像を含むテクスチャページを保存する必要はありません)。 テクスチャグループごとに、それらが動作するプラットフォームを指定できます。 たとえば、Androidの場合、Windows 8タブレットの場合よりも詳細度の低い画像を使用できます。

ゲームメーカーのオブジェクトとは何ですか?


これは、独自のメソッド(関数)を持つエンティティの説明です。 各オブジェクトは(特に指定されていない限り)自身を描画し、標準のイベント(キーストローク、スプライトのクリックなど)に反応します。OOPと同様に、これはクラスです。

Game Makerのインスタンスとは何ですか?


オブジェクトがエンティティの単なる説明である場合、インスタンスはオブジェクトのインスタンスであり、ゲーム自体での実装です。 インスタンスを作成することで、インスタンスに命を吹き込むと、オブジェクト内に説明があるすべてのイベントが反応し始めます。
OOPと同様に、これはオブジェクトです。

最初に行うことは、新しい部屋を作成することです(左ペインで、[部屋]-[部屋の作成]を右クリックします)。 rm_gameと呼びましょう。 [設定]タブでウィンドウサイズを設定します-幅-800、高さ-480、速度-60。つまり、 ゲームは800x480のウィンドウで行われ、fpsは60フレームを超えない傾向があります。 保存して閉じます。

スプライトをいくつか追加します。 Sprites-> Spriteフォルダの作成を右クリックします。 これをspr_unit_shooterと呼び、54x54サイズなどの画像(記事の最後にあるgithubで入手可能)をアップロードして中央に配置します(中央ボタン)。 [OK]ボタンとデータが保存されます。



次に、最初のユニットが必要です。 古典的な射撃場にしましょう。 しかし、その前に、すべてのユーザーユニットの親となるオブジェクトを作成することをお勧めします(はい、OOPの継承とほぼ同じです)。 これにより、すべてのユニットに対してロジックを繰り返すことを回避できます。以下に示すように、ゲーム中にこのオブジェクトによって作成されたすべてのタイプの「オブジェクト」を参照できます。

スプライトと部屋に似た原理により、空のオブジェクトを作成します。 これをo_unit_parentと呼びますが、他には何もしません。 o_unit_shooterを作成し、Parent列でo_unit_parentを選択します。 彼にスプライト-spr_unit_shooterを与えましょう。 これを行うには、名前の下にあるボタンを使用します。



スプライト、オブジェクト、部屋などに名前を付ける 便利ですが、後で混乱しないように、すぐにスペードをスペードと呼びます。たとえば、接頭辞spr_を持つスプライト、オブジェクトobj_またはo_、スクリプト-scr_などです。

これで、ルームでo_unit_shooterオブジェクトを作成するたびに、選択したスプライトが描画されます(もちろん、これをコードでオーバーライドしない場合)。

スプライトはプログラムで設定することもできますが、この場合、左側のプロジェクト構造プレビューには表示されません。 次に、オブジェクトのインスタンスが作成されたときに発生するイベントを追加します。 このイベントでは、変数の初期初期化を設定する必要があります(存在する場合)。 [イベントを追加]をクリックします。 ご覧のとおり、ゲームメーカーでは、各オブジェクトが多数のイベントをキャッチできます。 興味がある-作成します。

アクションコンテナーの右側にあるように、いくつかのタブには膨大な量のドラッグアンドドロップ要素があり、理論的には、1行のコードを記述することなく完全なゲームを作成できます。 しかし、これは変態向けであり、おそらくGame Maker 2.0では、この不要な機能は最終的に削除されます。

[コードの実行]アイコンをドラッグまたは右クリックして、[コントロール]タブをクリックします。 ゲームロジックを配置できるテキストエディターが開きます。

覚えているように、ユニットは一定の期間で撃たなければなりません。 これは非常に簡単に行えます。 Createイベントで、次のコードを記述します。alarm [0] = room_speed * 2;
これは、番号0でアラームを実行し、room_speed * 2ステップ(フレーム)で起動することを意味します。 room_speedは60に等しく、これは1秒にほぼ等しいです。 したがって、アラーム[0]は120フレーム(2秒)後に起動します。 アラームは関数、またはオブジェクトイベントであり、ステップカウンターが0に達するとすぐに起動します。他のすべてのイベントと同様に、Addイベントを介して追加されます。 ここで、アラーム[0]に追加するロジックを登録する必要がありますが、まず、プラントが撮影するものを作成しましょう。

サイズと中心が16x16の新しいspr_bulletスプライトを作成します。 次に、新しいo_bulletオブジェクトを作成し、新しく作成したスプライトに設定します。 Createイベントで、コードhspeed = 7を追加します。 前のオブジェクトと同じです。 この行では、オブジェクトが水平速度7(hspeed =水平速度、誰かが理解できない場合)で移動することを指定します。 これは、各オブジェクトの組み込みプロパティです。 ゼロ以外の値を割り当てると、このオブジェクトは各ステップ(ステップ)で指定されたピクセル数(この例では、右に7)移動し始めます。 hspeed = -7に設定した場合; -オブジェクトはステップごとに-7ピクセル移動します。 右から左に移動します。

それだけです。o_unit_shooterオブジェクトに戻って、新しいイベント-アラーム0を作成します。このイベントで記述するコードは、Createイベントで作成したカウンターが実行されているときに発生します。 Alarm 0イベントでは、植物が放つ「弾丸」(元のエンドウ豆)を作成します。 次のコードを追加します。

/// shoot var b = instance_create(x + sprite_width/2, y, o_bullet); b.depth = depth + 1; alarm[0] = room_speed * 2; 

このコードを分析しましょう。

/// shootはイベントに行くときに表示される単なるコメントです。 デフォルトでは、「コードの一部を実行する」と表示されますが、あまり有益ではありません。 したがって、コードエディタへの切り替えに時間を浪費しないように、このようなコメントを記述することをお勧めします。
var b = instance_create(x + sprite_width / 2、y、o_bullet);
var b-このイベントでのみ使用できるローカル変数を宣言します。 イベントが完了すると、メモリが解放され、この変数にアクセスできなくなります。
instance_create(x + sprite_width / 2、y、o_bullet); -したがって、オブジェクトの新しいインスタンスを作成し、xに沿った座標に配置します:x + sprite_width / 2、y-yに沿って。 この場合、xとyは親オブジェクトの座標o_unit_shooterです。 o_bulletは、作成するオブジェクトです。
b.depth = depth + 1; -この行は、o_bulletの新しく作成されたインスタンスがo_unit_shooterより1層下になることを意味します。
最後の行は、アラーム[0]を再び開始することを意味します-プラントは常に撮影する必要があります。

覚えているように、オリジナルでは、特定のセルにのみ植生を配置できます。 植物を置くことができる範囲内で視覚的に明確にするために、背景を作成し、それを部屋で埋めます。 [背景]-[背景の作成]-[背景の読み込み]を右クリックして、目的の画像(64x64ピクセルなど)を選択し、bg_grassを呼び出します。 部屋(rm_game)の[背景]タブに移動し、1秒前に作成した背景を選択します。 画像のようになっていない場合は、ボックスをチェックします。



ここで、初期化を行う何らかの種類の開始オブジェクトが必要です。 新しいオブジェクトを作成し、o_gameなどの名前を付けます。 このオブジェクトは、フィールドのクリックに応答します。 これを行うには、イベントを追加します-マウス->グローバルマウス->グローバル左リリース。 通常のマウスイベントは、オブジェクトを直接クリックすることを意味しますが、o_gameにはスプライト+マスクなどがないためです。 プレーヤーが競技場の任意のポイントをクリックする必要があり、すべてのクリックイベントをキャッチする必要があります。 これがGlobal Mouseの機能です。 グローバル左リリースとは、ゲームウィンドウ内のどこかでタッチスクリーン上でマウスクリックまたはタッチが行われたことを意味します(指を離すとイベントが発生します)。

このイベントに次のコードを追加します。

 var tBgWidth = background_get_width(bg_grass); var tBgHeight = background_get_height(bg_grass); var iX = mouse_x - mouse_x % tBgWidth + tBgWidth; var iX = mouse_x - mouse_x % tBgWidth + tBgWidth/2; var iY = mouse_y - mouse_y % tBgHeight + tBgHeight/2; if (instance_position(iX, iY, o_unit_parent) != noone){ exit; } instance_create(iX, iY, o_unit_shooter); 


操作後のセミコロンは省略できますが、コードのロジックはこれから変更されず、エラーは発生しません。 しかし、賭けることができるなら、それをしないでください。 はい、より身近です。

最初の4行では、ローカル変数を宣言しています。 background_get_width、background_get_height-背景の幅と高さを返す組み込み関数。 ご覧のとおり、iXとiYを計算するにはこのデータが必要です。 iXおよびiY-これらは、o_unit_shooterオブジェクトをインスタンス化する座標になります。 mouse_x、mouse_y-マウスカーソル(指)の現在の座標を格納する、ゲームメーカーの組み込みグローバル変数(つまり、どこからでもアクセスできる変数)。 なぜなら グローバル左リリースイベントで作業し、ユーザーがマウスの左ボタンを離した(指を離した)最後の座標を保存します。 結果が変数iX、iYに割り当てられる数学演算は、o_unit_shooterオブジェクトのインスタンスがバックグラウンドセルbg_grassの真ん中に位置する座標を計算するために必要です。 つまり Plants Vs Zombiesでは、特定の場所にのみ植物を配置することはできませんが、任意の場所をクリックすると植物が適切な場所に配置されることに注意してください。 これが上記のコード全体です。

instance_position(iX、iY、o_unit_parent)をチェックする!= Nooneは、親オブジェクトがo_unit_parentであるインスタンス(オブジェクトのインスタンス)の座標iX、iYを見るという意味です。 継承可能なユニットはo_unit_shooterしかないため、競技場にo_unit_shooterインスタンスがあるかどうかを確認しますが、新しいユーザーユニットを追加してもコードが機能するようにo_unit_parentをチェックに書き込みます。 noone(「no one」から)は、他の言語では一種のヌル類似体です。

exit-イベントの実行を中断するコード。 つまり iX、iY座標に既にユニットがある場合、exitがトリガーされ、o_unit_shooterインスタンスは作成されません。 後続のすべてのコードの実行を中断します。 これは、2つのユーザーユニットが1つのセルに収まらないようにするために必要です。

さて、最初の敵を追加する時が来ました。 新しいオブジェクトを作成し、ベースの親オブジェクトを再度作成します。 o_enemy_zombieおよびo_enemy_parentを呼び出します。これらは親になります。 spr_enemy_zombieスプライトを作成し、中央に配置してo_enemy_zombieを割り当てます。

すべての敵の特性が植物に向かっている限り、Createイベントのo_enemy_parentに次のコードを作成します。

 cHspeed = -4; hspeed = cHspeed; HP = 10; canAttack = true; 

cHspeedは、hspeedに割り当てる値を持つユーザー定義変数であり、すでに検出しています。 なぜ単にhspeed = -4と書かないのですか? -後で参照してください。

以前にvar構文を介してユーザー変数を宣言しましたが、ここでは宣言しません。 cHspeed = -4の違いは何ですか? およびvar cHspeed = -4;?
簡単です-最初のケースでは、変数はこのオブジェクトのコードのどこからでもアクセスでき、他のオブジェクトからアクセスできますが、アクセスしているオブジェクトに言及することを忘れないでください。 今、これを掘り下げる必要はありません。 この変数は、オブジェクトが宣言されてからインスタンスが存在する間ずっと存在していたことに注意してください。 var cHspeed = -4の場合; 作成されたイベントの期間中のみ利用できます。

実際、別のオブジェクトからアクセスすることもできますが、作成されたイベントが既に終了したときに別のオブジェクトからアクセスすると、エラーが発生します-メモリからは既にnullポインタアンロード。

自分でhspeed、wspeed関数が気に入らない場合は、Stepイベントでxまたはyの値を変更することで自分で実装できます。 これらの機能はあなたのためにそれを行います。

HPは、敵のヒットポイントの数を格納する別の変数です。 各インスタンスはこの変数を「所有」しますが、敵の種類ごとのヒットポイントの最大数は異なります。 この値を何らかの方法でオーバーライド/再定義する必要があります。 または、すべての敵に同じ数のライフ(100など)を要求し、敵が受けるダメージが依存する防衛の概念を導入できますが、今ではそれを複雑化する意味はありませんか? したがって、1つの変数-HPのみを管理します。

ゲームメーカーで使用される言語であるgml(大文字と小文字は区別されます)、HP、hP、Hp、およびhpは異なる変数になることに注意してください。

canAttackは、値true(true)を割り当てる単なる変数です。 とりあえず、書いて忘れてください。

敵ごとに異なるHP値があるため、何らかの方法でこの値を再定義する必要があります。 とても簡単です。 o_enemy_zombieオブジェクトに移動し、Createイベントに対する反応を作成して、コードを記述します。

 event_inherited(); HP = 20; 

関数event_inherited(); 継承を扱います。 つまり o_enemy_zombieがコードを実行します:

 cHspeed = -4; hspeed = cHspeed; HP = 10; 

この関数を「インポート」してから、行が実行される値-HP = 20;
つまり 実際、Createイベントの最後に、o_enemy_zombieオブジェクトには次のプロパティがあります。

 cHspeed = -4; hspeed = cHspeed; HP = 20; 

関数event_inherited()を忘れた場合; または、親オブジェクトをo_enemy_zombieオブジェクトに指定するのを忘れると、敵は移動せず、このオブジェクトのcHspeed変数にアクセスしようとするとエラーが表示されます。

素晴らしい、別のタイプの敵を作成したい場合、作成イベントで同じことを書き、必要なHPの量を変更します。

 event_inherited(); HP = 100; 


ゾンビにはライフポイントがあるため、植物の中にいる必要があります。 コードHP = 20をo_unit_parentオブジェクトのCreateイベントに自分で追加します。 および文字列event_inherited(); o_unit_shooterオブジェクトのCreateイベントで。

知ってる?


Createイベントに何かを再定義して追加する必要がない場合は、コードevent_inherited()を追加します。 別のロジックがなければ、イベントは不要です-Game Makerがそれを行います。 作成だけでなく、他のイベントでも同じことが言えます。

さて、私たちのゾンビは現在オンになっていますが、弾丸にとられておらず、植物はそれを遅くしません。 まず、最初の問題を解決します。 o_bulletに移動して、イベントに対する新しいリアクションを作成しましょう-イベントの追加->衝突-> o_enemy_zombie。 このイベントは、o_bulletとo_enemy_zombieが互いに衝突したときにトリガーされます。 競合は、記事の冒頭で読んだマスクによってチェックされます。 コードを追加します。

 with(other){ HP -= 5; if (HP <= 0){ instance_destroy(); } } instance_destroy(); 

これは非常に興味深い点です。 otherは、イベントのこの時点で衝突が発生するオブジェクトのインスタンスです。 当然、なぜなら このコードは、o_enemy_zombieオブジェクトのインスタンスと衝突した場合に発生し、その他の場合はo_enemy_zombieインスタンスのみが発生します。

with(){}コンストラクトを使用して、この他の要素にアクセスします。 {}内で発生するすべては、オブジェクトのこのインスタンスにのみ適用されます。 したがって、HP-= 5; -これは、敵から5ライフポイントを引いたものです。 if(HP <= 0){}では、この特定のオブジェクトのヒットポイントの数も比較します。 通常の変数宣言とvarを介した変数の違いについて少し上で話したことを思い出してください。 この例では、状況を最終的に明らかにする必要があります。 なぜなら HP変数はvarを介して宣言されていないため、いつでも使用できます。 したがって、withコンストラクトを使用してアクセスできます。 別のオブジェクトの変数にアクセスする別の方法は次のようになります。

 other.HP -= 5; if(other.HP <= 0){ with(other){ instance_destroy(); } } } instance_destroy(); 

しかし、特にロジックが増える場合は、この方法で変数にアクセスするのはあまり便利ではありませんが、それでも場合によっては適用できます。

Createイベントではなく、宣言する前にアクセスするコードで変数を宣言した場合、変数からデータを読み取ろうとするとエラーが発生することを忘れないでください。

関数instance_destroy();を理解するために、英語の高度な知識は必要ありません。 オブジェクト(インスタンス)のこのインスタンスを削除します。

したがって、このコードはすべて、衝突でゾンビから5つのライフポイントを取得し、それらが0以下になった場合、ゾンビを破壊することを意味します。 結果に関係なく、最後に弾丸を削除します。 どこも簡単です。 一般に、ゾンビに自分の健康状態を独立して監視させる方がおそらく良いでしょうが、今のところ興味はありません。 しかし、これは別のストーリー最適化の問題です。

私たちのゾンビがダメージを受けるだけなら、それは間違っているでしょう。 ダメージを与える能力を追加する必要があります。 まず、o_enemy_parentオブジェクトのCreateイベントに新しい変数を追加します

 isActive = true; 

さきほどお話ししたStepイベントについて知りましょう。 このイベントはフレームごとに発生します。 すべてがシンプルです。 room_speedが60の場合、このイベントは毎秒約60回発生します。 このコードをo_enemy_zombieオブジェクトのStep-> Stepイベントに追加します。

 if (!isActive) exit; var tBgWidth = background_get_width(bg_grass); var leftCellCenterX = x - x % tBgWidth - tBgWidth/2; var frontEnemy = instance_position(leftCellCenterX, y, o_unit_parent); if (frontEnemy != noone){ var frontEnemySprtWidth; with(frontEnemy){ frontEnemySprtWidth = sprite_width; } if (x - sprite_width/2 - frontEnemy.x - frontEnemySprtWidth/2 <= 12){ hspeed = 0; if (!canAttack){ exit; } canAttack = false; alarm[0] = room_speed * 1.2; // cantAttack -> true; with(frontEnemy){ HP -= 5; if (HP <= 0){ instance_destroy(); } } } }else{ hspeed = cHspeed; } 


それに何の問題もありません;ほとんどすべてのデザインはすでにあなたに馴染みがあります。
if(!isActive)exit; -オブジェクトがアクティブでない場合、つまり、オブジェクトが静止/充電/スイングする場合、このイベントは実行されません。 次の2行では、インスタンスの中心が現在位置しているセルの左側にあるセルの中心の座標を取得します(x-は原点の座標を返し、スプライトの中心に設定されていることを思い出してください)。 次に、ユーザーユニットが座標(leftCellCenterX、y)にあるかどうかを調べます。 そこに何かがあれば、後続のロジックが発生しますが、それについてはすぐに、何もない場合は、cHspeed変数の値にhspeedを割り当てます。これは、Createイベントで作成します。 ここで役立ちました。 この背後にある意味は、私たちのゾンビが植物を攻撃して破壊するために停止した場合、途中で継続しなければならないということです。 もちろん、変数cHspeedを入力することはできませんが、速度を設定した場所を覚えておく必要がありますが、これは忘れられます。

これは、ゾンビの道に何もなければ、今私たちが戦いに直面している瞬間に戻ります。 最初の行は非常に興味深いものであることがわかりました。 実際、frontEnemyインスタンスでローカル変数frontEnemySprtWidthを宣言することで、それに値を割り当てています。 プログラミングに精通している人は言うでしょうが、この場合、私たちはゾンビの変数frontEnemySprtWidthを参照しているのではなく、同名であるがfrontEnemyインスタンスの変数を参照しています。 そうではありません。実際には、ローカル変数(varで宣言)が、frontEnemyインスタンス内からでも、このイベント内のどこにでも見えるようになります。 したがって、コードにエラーはありません。ゾンビ内部でローカルに宣言された変数を実際に参照します。 この点を理解していない場合、実験するか、ヘルプを読むと、すべてが完全に説明されているので、さらに先に進みます。
frontEnemySprtWidthを、ゾンビの左側のセルにあるユーザー(植物)のユニットのスプライトの長さ(幅)に設定します。 var frontEnemySprtWidth = sprite_get_width(spr_unit_shooter);を省くことができる場合、最初に理解するためになぜこのような複雑な構造をブロックする必要があるのか​​、ということでしょう。 答えは簡単です-現在、1つの植物があり、どのスプライトを適用するかがわかっていますが、新しいタイプのユニット(ヒマワリなど)を追加するときは、面倒なスイッチ構造をフェンスして、どのようなオブジェクトが目の前にあるのかを確認する必要がありますこの問題は単純に解決されます。

次に、ユーザーユニットの右端のポイントとゾンビの左端のポイント間の距離が12ピクセル未満であるかどうかを確認し、ゾンビを停止し、ゾンビが攻撃できるかどうかを確認します(o_enemy_parentオブジェクトのCreateイベントで以前に作成されたcanAttack変数の値を確認します)現在攻撃することは不可能であり、次回はroom_speed * 1.2フレーム(60 * 1.2以降)で実行できると言うコード-アラーム[0]でこれを行います(対応するイベントに自分で追加します(アラーム0 )of o_ene my_parent、コードの記述canAttack = true;)。 攻撃が可能な場合は、プラントから5つのライフポイントを取得し、まだ生きているかどうかを確認します。生きていない場合は破壊します。

さて、敵は完全に準備ができています-植物を破壊した場合、彼は動き、攻撃し、動き続けますが、1つの欠点があります-彼は存在しません。 敵の説明だけを作成しました。今度は、競技場にゾンビを配置する必要があります。 o_gameオブジェクトのCreateイベントに戻ります。 コードを追加
アラーム[0] = room_speed; //敵を生成します

つまり 60フレーム後、アラーム0が機能し、ゾンビが作成されますよね? いや このアラームのロジックは作成していません。 また、ここのコードも簡単です。

 var tBgHeight = background_get_height(bg_grass); var eY = irandom(room_height - room_height % tBgHeight); eY = eY - eY % tBgHeight + tBgHeight/2; instance_create(room_width + sprite_get_width(spr_enemy_zombie)/2 + 1, eY, o_enemy_zombie); alarm[0] = room_speed * 3; 

すべてが単純です-それを複雑にせず、3秒(60フレーム* 3)ごとにX座標でo_enemy_zombieインスタンスを作成します:room_width + sprite_get_width(spr_enemy_zombie)/ 2 + 1 i.e. 画面境界の右側に正確に1ピクセル、つまり ゾンビは最初は表示されず、Yはランダムなセルです。 既に理解しているように、room_widthとroom_heightは、部屋の幅と高さです。 つまり それぞれ800および480。

これはすべて素晴らしいことですが、誰かがo_gameオブジェクトのインスタンスを作成する必要があります。そうしないと、エピソード全体が意味を成しません。 しかし、最後のステップは非常に簡単です-ルームrm_game->オブジェクト->メニューでo_gameを選択し、ルームのどこにでも配置します。 代替オプションは次のようになります-[設定]-> [作成コード]タブ(-これは、この部屋に移動したときにトリガーされるコードです)。 行instance_create(0,0、o_game)を追加します。

座標は任意です。 これで、ゲームメーカーがrm_gameルームを開始するか、「多くのルームがある場合、どのゲームメーカーを開始するか」をどのように決定するかを質問できます。 すべてがいつものようにシンプルです-一番上の部屋が最初に始まります(マウスでドラッグして順序を変更できます)。 すぐに開始されるので、今はそれだけです。

次のようになります。



最初のエピソードは終わりました。 おめでとうございます、ゲームのプロトタイプを作成しました。 残りはほとんどありません-それから本格的なゲームを作るために、これは次のパートで行います。

このエピソードでは、できるだけ多くの機能を使用して、Game Makerの基本概念に慣れました。 いくつかの点はあまり合理的ではなく、やり直すことができますし、一度にすべてではありません。 何が起きているかを最初に理解するには、アマチュア風に書く方が良いと思います。

レッスンからわかるように、一部の計画では、現在のバージョンのGame Makerは完全ではなく、多くの点に留意する必要がありますが、Game Makerでは残りの作業が簡単です。 少し不便は価値があります。

ソースコード

次のエピソードで:

-/理論/スクリプト
-/理論/デバッグ
-/練習/ユニットひまわり
-/練習/マナ(太陽)
-/練習/敵の波の生成
-/練習/芝刈り機
-/練習/ゾンビと植物の新しいユニット
-/理論+実践/プリミティブインターフェイス

原則として、今ではすでに習得した知識から練習セクションのすべてをすでに実行できますが、おそらく、知識の手荷物を増やすために、より複雑な形式で実装します。

Source: https://habr.com/ru/post/J255995/


All Articles