Godot Engineでのゲーム「Like coins」の作成。 パート1

Godot Engineは非常に高速に開発されており、世界中のゲーム開発者の心をつかんでいます。 おそらくこれは、ゲームを作成するための最も友好的で習得しやすいツールであり、これを確認するために、小さな2Dゲームを作成してみてください。 ゲーム開発プロセスをよく理解するには、2Dゲームから始める必要があります。これにより、より深刻なゲームシステムに入るためのしきい値が低くなります。 3Dへの移行自体は見た目ほど難しくはありませんが、結局のところ、Godotエンジンのほとんどの機能は2Dと3Dの両方で正常に使用できます。







はじめに



あなたが考えることができる最も簡単なことは、私たちの主人公がコインを収集するゲームです。 少し複雑にするために、制限要因として障害と時間を追加します。 ゲームには3つのシーンがあります: Player



Coin



、およびHUD



(この記事は考慮されません)。これらは1つのMain



シーンに結合されます。













プロジェクト設定



ゲームの作成に費やされる合計時間の約80〜90%であるスクリプト(スクリプト)の作成に飛び込む前に、まず行うべきことは、将来のプロジェクトをセットアップすることです。 大規模なプロジェクトでは、スクリプト、シーン、画像、音声を保存するための個別のフォルダーを作成すると便利です。最終結果がどうなるかは誰が知っているので、これを必ず考慮する必要があります。







この記事では、Godotエンジンに少し精通していること、およびこのツールの使用に関するある程度の知識とスキルがあることを前提としていますが、Godotエンジンに初めて遭遇するという事実に焦点を当てますが、まず、エンジンの基本的なコンポーネントに精通し、GDScriptの構文を調べて、使用されている用語(ノード、シーン、信号など)を理解し、ここに戻って知り合いを続けることをお勧めします。

プログラムメニューで、 Project -> Project Settings



]に移動します。







別の小さな余談。 Godotエンジンはロシア語をサポートしているという事実にもかかわらず、エンドユーザーがエンジンの英語インターフェイスを使用するという事実に基づいて、常に例を挙げます。 これは、プログラムインターフェイスの特定の要素の誤った/不正確な翻訳に関連する誤解や恥ずかしさを取り除くために行われます。

Display/Window



セクションを見つけ、幅を800



に、高さを600



ます。 また、このセクションでは、 Stretch/Mode



2D



Aspect



Keep



ます。 これにより、ウィンドウのサイズを変更する際にウィンドウのコンテンツの伸縮や変形が防止されますが、ウィンドウのサイズ変更を禁止するには、[サイズ変更Resizable



ボックスをオフにします。 これらのオプションを試してみることをお勧めします。







次に、 Rendering/Quality



セクションに移動し、右側のペインでUse Pixel Snap



Use Pixel Snap



を有効にしUse Pixel Snap



。 これは何のためですか? Godot Engineのベクトルの座標は浮動小数点数です。 オブジェクトはピクセルの半分しか描画できないため、この不一致はpixelart



を使用するゲームで視覚的な欠陥を引き起こす可能性があります。 そして、3Dではこのオプションが役に立たないことは注目に値します。 これを覚えておいてください。







プレイヤーシーン



最初のシーンPlayer



作成を始めましょう。







あらゆるシーンの利点は、最初はゲームの他の部分から独立していることです。これにより、それらを自由にテストし、元々そこに置かれていた結果を得ることができます。 一般に、ゲームオブジェクトをシーンに分割することは、複雑なゲームを作成するのに便利なツールです-エラーをキャッチし、シーン自体に変更を加えるのは簡単です。一方、ゲームの他の部分は影響を受けません。転送前に働いていたので。

シーンの作成は簡単なアクションです- Area2D



+



(追加/作成)をクリックし、 Area2D



ノードを選択し、混乱しないようにすぐに名前を変更します。 これは親ノードであり、機能を拡張するには子ノードを追加する必要があります。 私たちの場合、これらはAnimatedSprite



CollisionShape2D



ですが、急いではいけませんが、順番に始めましょう。 次に、すぐにルートノードを「ロック」します。













ボディコリジョンフォーム(CollisionShape2D)またはスプライト(AnimatedSprite)がシフトされ、親ノードを基準に引き伸ばされた場合、これは間違いなく予期しないエラーにつながり、後で修正するのが困難になります。 このオプションを有効にすると、「親」とそのすべての「子」が常に一緒に移動します。 面白そうに聞こえますが、この機能を使用すると非常に便利です。







AnimatedSprite



Area2D



他のオブジェクトとのオーバーラップイベントや衝突について知る必要がある場合に非常に便利なノードですが、それ自体は目に見えず、 Player



オブジェクトにAnimatedSprite



追加して表示します。 ノードの名前は、アニメーションとスプライトを扱うことを示しています。 Inspector



ウィンドウで、 Frames



パラメーターに移動し、新しいSpriteFrames



を作成します。 SpriteFrames



パネルでの作業は、必要なアニメーションを作成し、対応するスプライトをそれらにロードすることです。 アニメーション作成のすべての段階を詳細に分析することはせず、独立した学習のためにこれを残します。3つのアニメーション(歩行(歩行アニメーション)、 idle



(休止状態)、およびdie



(死または失敗アニメーション)が必要です。 SPEED (FPS)



値が8



あることを忘れないでください(ただし、別の値を選択できます-適切です)。













Collisionshape2d



Area2D



が衝突を検出するには、オブジェクトの形状を提供する必要があります。 シェイプは、 Shape2D



パラメーターによって定義され、長方形、円、ポリゴン、その他のより複雑なタイプのシェイプを含み、サイズはエディター自体で既に編集されていますが、 Inspector



を使用してさらに微調整することができます。







シナリオ



ここで、ゲームオブジェクトを「復活」させるために、スクリプトを設定する必要があります。このスクリプトに従って、このシナリオで説明するアクションを実行します。 「 Scene



タブで、スクリプトを作成し、設定を「デフォルト」のままにして、すべてのコメント(「#」記号で始まる行)を削除し、変数の宣言に進みます。







 export (int) var speed var velocity = Vector2() var window_size = Vector2(800, 600)
      
      





export



キーワードを使用すると、 Inspector



パネルウィンドウでspeed



変数の値を設定できます。 これは、 Inspector



ウィンドウで編集するのに便利なカスタム値を取得する場合に非常に便利な方法です。 Speed



350



設定します。 velocity



の値は移動の方向を決定し、 window_size



はプレーヤーの移動を制限する領域です。







アクションの詳細な順序は次のとおりですget_input()



関数を使用して、キーボード入力が行われているかどうかを確認します。 次に、押されたキーに従ってオブジェクトを移動し、アニメーションを再生します。 プレーヤーは4つの方向に移動します。 デフォルトでは、Godotエンジンには矢印キー( Project -> Project Settings -> Input Map



)に割り当てられたイベントがあるため、それらをプロジェクトに適用できます。 キーが押されたかどうかを確認するには、 Input.is_action_pressed()



を使用して、追跡するイベントの名前をスリップします。







 func get_input(): velocity = Vector2() if Input.is_action_pressed("ui_left"): velocity.x -= 1 if Input.is_action_pressed("ui_right"): velocity.x += 1 if Input.is_action_pressed("ui_up"): velocity.y -= 1 if Input.is_action_pressed("ui_down"): velocity.y += 1 if velocity.length() > 0: velocity = velocity.normalized() * speed
      
      





一見、すべてがよさそうですが、小さなニュアンスが1つあります。 押されたいくつかのキーの組み合わせ(たとえば、下と左)によってベクターが追加され、この場合、プレーヤーは単純に下に移動した場合よりも速く移動します。 これを避けるために、 normalized()



メソッドを使用します-ベクトルの長さを1



戻します。







そのため、キーストロークイベントが追跡されます。次に、 Player



オブジェクトを移動する必要があります。 _process()



関数はこれに役立ちます。これは、フレームの変更が発生するたびに呼び出されるため、頻繁に変更されるオブジェクトに使用することをお勧めします。







 func _process(delta): get_input() position += velocity * delta position.x = clamp(position.x, 0, window_size.x) position.y = clamp(position.y, 0, window_size.y)
      
      





delta



パラメーターに気づいていただければ幸いですdelta



パラメーターには、速度が乗算されます。 それが何であるかを説明する必要があります。 ゲームエンジンは、最初は毎秒60フレームの速度で動作するように構成されています。 それでも、コンピューターまたはGodotエンジン自体の速度が低下する場合があります。 フレームレートが一致しない場合(フレームが変化するのにかかる時間)、これはゲームオブジェクトの動きの「滑らかさ」に影響します(その結果、ジャークの動き)。 「Godotエンジン」は、 delta



変数を導入することにより(ほとんどの類似エンジンと同様に)この問題を解決します-フレームが変更された値を提供します。 これらの値のおかげで、動きを「調整」できます。 別の注目すべき機能に注意してください- clamp



(指定された2つのパラメーター内で値を返します)のおかげで、面積の最小値と最大値を設定するだけで、 Player



が移動できる領域を制限できます。







オブジェクトをアニメーション化することを忘れないでください。 オブジェクトが右に移動するときは、 AnimatedSprite



を反転する必要があります( flip_h



を使用)。ヒーローは、移動時に直接移動している方向を見ます。 AnimatedSprite



Playing



開始するには、 AnimatedSprite



パラメーターがPlaying



設定されていることを確認してください。







 if velocity.length() > 0: $AnimatedSprite.animation = "walk" $AnimatedSprite.flip_h = velocity.x < 0 else: $AnimatedSprite.animation = "idle"
      
      





誕生と死



ゲームを起動するとき、メインシーンに新しいゲームを開始する準備ができていることに関する主要なシーンを通知する必要があります。この場合、 Player



オブジェクトにゲームの開始を通知し、初期パラメーターを設定するset_process



ます。







 func start(pos): set_process(true) #     Vector2(x, y) position = pos $AnimatedSprite.animation = "idle"
      
      





また、タイムアウトになったときやプレーヤーが障害物にset_process (false)



ときにプレーヤーの死亡イベントを提供しますset_process (false)



を設定すると、このシーンで_process ()



関数が実行されなくなります。







 func die(): $AnimatedSprite.animation = "die" set_process(false)
      
      





衝突を追加する



プレイヤーにコインや障害物との衝突を検出させる番です。 これを行う最も簡単な方法は、シグナルを使用することです。 シグナルは、他のノードがそれらを検出して応答できるように、メッセージを送信するための優れた方法です。 ほとんどのノードにはすでに信号が組み込まれていますが、独自の目的で「ユーザー」信号を定義することは可能です。 スクリプトの冒頭で信号を宣言すると、信号が追加されます。







 signal pickup signal die
      
      





[ Inspector



]ウィンドウ([ Node



]タブ)で信号のリストを参照し、信号と既存の信号に注意してください。 ここでarea_entered ()



興味があり、衝突が発生するオブジェクトもArea2D



型であると想定しています。 [ Connect



]ボタンを使用してarea_entered ()



信号をConnect



し、[信号のConnect



]ウィンドウで強調表示されたノード(プレーヤー)を選択し、残りはデフォルトのままにします。







 func _on_Player_area_entered( area ): if area.is_in_group("coins"): #  emit_signal("pickup") area.pickup()
      
      





オブジェクトを簡単に検出して操作できるように、適切なグループでオブジェクトを識別する必要があります。 グループ自体の作成は現在省略されていますが、後でそれらに間違いなく戻ります。 pickup()



関数は、コインの動作を決定します(たとえば、アニメーションやサウンドの再生、オブジェクトの削除など)。







コインシーン



1つのコインでシーンを作成する場合、 AnimatedSprite



アニメーション(ハイライト)が1つしか存在しないことを除いて、「プレーヤー」シーンで行ったことすべてを行う必要があります。 Speed (FPS)



14



に増やすことができます。 また、 AnimatedSprite



- AnimatedSprite



のスケールを変更します。 CollisionShape2D



の寸法はコインの画像に対応する必要があります。主なことは、それを拡大縮小することではありません。つまり、2Dエディターのフォーム上の適切なマーカーを使用してサイズを変更します。

円の半径を調整します。













グループは、ノードのラベル付けの一種であり、類似したノードを識別することができます。 Player



オブジェクトがコインとの接触に反応するためには、コインはグループに属している必要があります。 Area2D



ノード( "Coin"という名前)を選択し、 Area2D



ノード] Node -> Groups



]タブでタグを割り当てて、対応するグループを作成します。













Coin



ノードの場合、スクリプトを作成します。 pickup()



関数はPlayer



オブジェクトのスクリプトによって呼び出され、コインが機能したときに何をすべきかをコインに伝えます。 queue_free()



メソッドは、すべての子ノードを持つツリーからノードを安全に削除し、メモリをクリアしますが、削除はすぐには機能せず、現在のフレームの最後に削除されるキューに最初に移動されます。 これは、ノードをすぐに削除するよりもはるかに安全です。ゲーム内の他の「参加者」(ノードまたはシーン)は、このノードが存在する必要があるためです。







 func pickup (): queue_free ()
      
      





おわりに



Main



シーンを作成し、 Player



Coin



両方のシーンをマウスで2Dエディターにドラッグし、シーンを開始してプレーヤーの動きとコインとの接触がどのように機能するかを確認します(F5)。 さて、ゲーム「Like Coins」の作成の最初の部分が終了したと言って急いでいます。休暇を取って、みんなの注意に感謝します。 何か言いたいことがあったり、資料を補足したり、記事に誤りがある場合は、以下のコメントを書いて報告してください。 タフで批判的であることを恐れないでください。 あなたの「フィードバック」は、私が正しい方向に進んでいるかどうか、そして素材をさらに面白く有用にするために修正できることを教えてくれます。








All Articles