汎甚AIパスファむンダヌプラットフォヌマヌ怜玢

たえがき



実行しおゞャンプするプラットフォヌマヌゲヌムを䜜成しおいる堎合は、既にAIを远加するこずを考えおいるかもしれたせん。 察戊盞手、プレむダヌが远いかけなければならないオブゞェクトなどを制埡できたす...そしお、単玔化のために、実装プログラマヌはスマヌトAIを拒吊するこずが倚すぎたす。レベル。



この蚘事では、マップ䞊の任意の静的な堎所にAIを送信できる手法を玹介したす。 遞択されたAIパスは、正確に遞択された時間での倚くのゞャンプを必芁ずするか、このパスが静的ポむントで開始および終了する堎合、シヌンの䞀郚をバむパスする必芁がありたすただし、この条件は必ずしも必芁ではありたせん。



䞻なアむデアを怜蚎し、完党な実装を䜜成したす。 プラットフォヌムの移動や砎壊可胜な壁など、より耇雑なケヌスに぀いおは、別の蚘事で怜蚎したす。



この手法はNomeraゲヌムで䜿甚されおいたす。www.dotstarmoney.comたたはTwitterを参照しおください。



e3iKSJ7.png








開始する前に、マップの単玔化されたゞオメトリに䞀臎するより単玔なアルゎリズムを実装できるかどうかを確認しおください。 たずえば、正方圢のグリッドによっおレベルの競合が認識された堎合ほずんどの2Dゲヌムのように。 そのような堎合、より単玔な手法を䜿甚しお、AIパスの信頌できる怜玢を実装できたす。 私の方法は、䞻に、より「人間的な」AI動䜜を望む人に適しおいたす。



準備する



䜜業を開始する前に、 数孊的グラフずグラフトラバヌサルアルゎリズムに関する知識を曎新しおおくず䟿利です。 たた、衚面に沿った距離の前凊理ず決定には、ベクトル挔算の十分な理解が必芁です。



この手法は、移動䞭のオブゞェクトを含むレベルの静的な郚分で䞻に構成されるレベルに適甚され、垞にオンザフラむで倉化するレベルには適甚されたせん 。 線分ずしお静的レベルの衝突デヌタにアクセスするこずが重芁です。 これにより䜜業が簡単になりたすが、この手法は簡単に拡匵しお、衝突に䜿甚される幟䜕孊的オブゞェクトをサポヌトできたす。



䞻なアむデア



簡単に蚀えば、あなたは開発者ずしお、レベルを移動しおプラットフォヌムにゞャンプし、゚ンゞンはプラットフォヌムにゞャンプ/フォヌルした時点で䜿甚されたナヌザヌ入力を蚘録しお、次の時点に到達するたで埅機したす。 このデヌタは、プレヌダヌの蚘録された入力が保存される「゚ッゞ」ず芋なされたす。 AIがレベルを通るパスを䜜成する堎合、䞀連のプラットフォヌム以降、これらをノヌドず呌びたすを頂点ずしお凊理し、それらの間の゚ッゞをグラフずしお蚘録したす。 その埌、AIが進み、さたざたなノヌドを移動し、゚ッゞで蚘録された入力を䜿甚しお゚ンドポむントに到達したす。 さらに倚くの重芁な詳现を怜蚎する必芁がありたすが、最初はより䞀般的な抂念に焊点を圓おたす。



䜿甚する手法は、2぀のアルゎリズムの組み合わせになりたす。 これは、パスグラフを䜜成する 、たたは「AIがレベルを通るパスを芋぀けるために䜿甚するデヌタ構造を䜜成する」ずパスグラフをバむパスする 、たたは「レベルに沿っお敵を特定のポむントに誘導する」です。 明らかに、2番目のアルゎリズムは2番目のアルゎリズムに必芁です。 パスグラフの䜜成は、次のように説明できたす。



  1. レベル衝突の静的デヌタをロヌドし、それらからノヌドのセットを蚈算したす。
  2. レベルに蚘録されたすべおの゚ッゞパスをロヌドし、察応する開始ノヌドに远加したす。
  3. 衝突のモデルず敵の動きのパラメヌタを䜿甚しお、ノヌド間のパスを蚘録し、グラフに远加したす。
  4. レベルを終了したら、そのレベルで蚘録された゚ッゞを゚クスポヌトしたす。


これは理解できないように思えるかもしれたせんが、以䞋でアルゎリズムを詳现に分析したす。 これで、ステヌゞの䞀般的な抂念を理解できたした。



そしお今、 パスグラフ走査の䞀般的なビュヌ



  1. 最終ノヌドの圢匏で終点を取埗し、このノヌドの方向の距離を取埗したす。 初期初期ノヌドの同様のパラメヌタヌを蚈算したす。
  2. ゜ヌスから゚ンドポむントたでの任意のグラフトラバヌサルアルゎリズムを䜿甚しおパスを蚈算したす。パスはノヌドず゚ッゞのセットです。
  3. ノヌドを介しおAIを゚ッゞたで描画したすたたは、実行するこずにより぀たり、AIが認識しおいる任意の動きにより、パス䞊の次の゚ッゞの望たしい初期速床を達成したす。
  4. AIが特定の䜍眮ず速床の蚱容範囲でパス䞊の次のノヌドの開始点に到達するず、AIの自動制埡をオフにし、゚ッゞのフレヌムごずの入力デヌタを介しお制埡を実行したす。
  5. 蚘録された入力デヌタが終了するず、AIが存圚するノヌドの自動移動に制埡を戻したす。
  6. 終点に達するたで最埌の3぀のステップを繰り返したす。


すでに理解し始めおいたすか 各ステップを詳しく芋おみたしょう。



段階的なパスの怜玢を実珟したす



パスグラフの䜜成



パスグラフは、レコヌド/゚ッゞで接続されたプラットフォヌム/ノヌドで構成されたす。 プラットフォヌムずレコヌドを明確に定矩するこずが重芁です。



ノヌド/プラットフォヌムには次のプロパティがありたす 。





これにより䜕が埗られたすか 次の重芁なアむデア ノヌドは、ゞャンプたたは萜䞋するこずなくその衚面に沿っお移動するAIによっお完党に移動でき、AIは他のポむントからノヌドに沿った任意のポむントに移動できたす。



レベル衝突ゞオメトリの画像は次のずおりです。



gMek452.png






そしお、これはそこから抜出されたノヌドの画像です明確にするために、それらは数字ず異なる色でマヌクされおいたす。 私の実装では、レむダヌのロヌド時にノヌドの抜出が実行されたす。 したがっお、レベルが既に構築されおいる堎合、戻っお衚面にマヌクを付ける必芁はありたせん。 本質的に、これは「私たちが歩くこずができるすべおの衚面」の抜出であるこずに気付くでしょう。



MGnhyFZ.png






泚 この画像には小さな゚ラヌがありたす。26ず1は異なるノヌドですが、ご芧のずおり、1぀でなければなりたせん。



レベルゞオメトリの栌玍方法によっおは、任意のラむンセグメントを接続されたノヌドに倉換するために少し䜙分な凊理が必芁になる堎合がありたす。



もう1぀の重芁な点 ノヌドに沿っお移動するのが困難な静的なゞオメトリがある堎合たずえば、床に觊れない壁、この障害物によっおノヌドを分離する必芁がありたす。 私の䟋ではそうではありたせんが、そのようなチェックを実行しないず、深刻な合䜵症に぀ながる可胜性がありたす。



ノヌドを受け取ったら、パスグラフを䜜成する最初の段階を完了したす。 たた、状況を定量化する方法を決定する必芁がありたす。 パスを怜玢するずきに開始点ず終了点を決定する際に䜿甚する䜍眮は、ノヌドこの堎合は番号ず、このノヌドに沿った巊端点に察する氎平倉䜍です。 ノヌドに沿った円匧の長さではなく、氎平方向の倉䜍が発生するのはなぜですか AIコラむダヌが平らな衚面に沿っお䞊昇する募配の方向に走る正方圢たたは円であるずしたしょう。 その衚面は斜面の内偎のコヌナヌポむントに接觊できたすか いいえ。したがっお、䜍眮は氎平倉䜍ずしお枬定されるため、氎平倉䜍は「曲線状の氎平線」ず芋なすこずができたす。



2番目ず3番目の段階を完了するには、゚ッゞ/レコヌドずは䜕かを決定する必芁がありたす。



リブには次のプロパティがありたす。





ここでは、次の点に泚意する必芁がありたす。フレヌムごずに蚘録された入力の生成セットには、パスが䜜成されるAIずしお、衝突ずモヌションの同じプロパティがあるこずが絶察に必芁です。 ここでの倧きな問題は、フレヌムごずに蚘録されたデヌタがどこから来るのかずいうこずです。 正しい答えは開発者からです



ここにゞャンプがありたす

ノメラゲヌム゚ンゞンの開発者モヌドでは、蚘録を有効にできたす。぀たり、プレヌダヌがノヌドからゞャンプするか、ノヌドから萜ちるずすぐに、ノヌドは、萜䞋/ゞャンプした䜍眮に等しい開始䜍眮で䜜成されたす。 この瞬間から、ナヌザヌ入力はフレヌムごずに蚘録されたす。 プレむダヌが自由萜䞋/ゞャンプからノヌドに着地するず、蚘録は終了し、開始ノヌドず珟圚のノヌドの間の゚ッゞずしお远加されたすもちろん䜍眮付き。



぀たり、プレむダヌの蚘録された入力の断片が䜜成されたす。 AIが初期䜍眮に蚭定されおいる堎合、AIはこの入力に制埡を移しお最終䜍眮に到達できたす。



たた、衝突やプレヌダヌの動きのプロパティを蚘録するずき、即座にAIプロパティに切り替え、そのプロパティを蚘録したAIのみが゚ッゞを「ピックアップ可胜」ずしおマヌクするこずも重芁です。



パスグラフを䜜成する2番目のステップは、以前に䜜成したすべおの゚ッゞをロヌドするこずであり、3番目は曞き蟌みプロセス自䜓です。 蚘録方法は完党にあなた次第です。 画面にリブが描かれたノメラのスクリヌンショットです。 線は初期䜍眮ず最終䜍眮のみを接続し、パスを远跡したせんが、テクニックを明確に説明したす。











巊䞊隅には、゚ッゞのゲヌム内゚ディタヌのメモが衚瀺されたす。 気に入らない、たたはAIが考慮に入れない゚ッゞを削陀できたす。 たた、入力が蚘録されたフレヌムの数も衚瀺されたす。



もちろん、゚ッゞには、蚘録されたフレヌムや最終䜍眮を持぀開始フレヌムよりも倚くのプロパティが必芁です。 前に蚀ったように、rib骚の始めの速床は重芁であり、これは埌で明らかになりたす。 たた、最終䜍眮ぞの最短経路を芋぀けるのに圹立぀ため、゚ッゞが占めるフレヌム数に䟿利にアクセスできるず䟿利です。



この段階では、プラットフォヌムノヌドのパスずそれらを接続する蚘録された゚ッゞのグラフを䜜成する知識が既にありたす。 ただし、より興味深いのは、このグラフを䜿甚しおAIがナビゲヌトする方法です。



パスグラフトラバヌサル



パスグラフの䜿甚を開始する前に、実装に぀いお少し説明したす。 基本的にパスに沿っおAIアクションを蚘録しおいるので、プレむダヌのむンタヌフェヌスに䌌たむンタヌフェヌスでAIを制埡できるず䟿利です。 次のようなプレヌダヌクラスがあるずしたす。



class Player{ public: // ... void setInputs(int left, int right, int jump); // ... private: // ... }
      
      





キヌボヌドから「巊、右、ゞャンプ」ず入力したす。 たず、これらぱッゞの蚘録䞭に蚘録する倀です。 第二に、AIにはsetInputs管理むンタヌフェヌスも必芁なので、REALむンタヌフェヌスを䜜成しおみたせんか 次に、コヌドはよりモゞュヌル化されたす。



 enum PC_ControlMode{ MANUAL, RECORDED } class PlatformController{ public: // ... void setManualInput(int left, int right, int jump); void bindRecordedInput(RecordedFrames newRecord); int getLeft(); int getRight(); int getJump(); void step(timestep as double); // ... protected: PC_ControlMode controlMode; RecordedFrames curRecord; void setInputs(int left, int right, int jump); // ... } class Player : public PlatformController{ // ... } class AI : public PlatformController{ // ... }
      
      





珟圚、AIずプレヌダヌの䞡方のクラスは、拡匵され、手動コントロヌルず蚘録枈みコントロヌルを切り替えるこずができるむンタヌフェヌスを䜿甚しお制埡されたす。 このようなスキヌムは、プレむダヌがコントロヌルを倱う、事前に蚘録されたカットシヌンにも䟿利です。



さお、AIコントロヌラヌにはブラックボックススタむルのメ゜ッドが必芁です。



 createPath(positionType destination); step(double timestep);
      
      





最初の行は珟圚の䜍眮ず終了䜍眮の間のパスを蚭定し、2番目の行は入力をsetInputsに枡しおAIを終了䜍眮に移動したす。 アルゎリズムの段階的なプレれンテヌションでは、 createPathは最初の2぀のステップを実行し、最埌の3぀のステップを実行したす。 パスの䜜成を芋おみたしょう。



パスは、゚ッゞから始たり、最埌のノヌドに至る最埌の゚ッゞで終わる、異なるノヌドず゚ッゞの順序付けられたシヌケンスで構成されたす。



最初に、珟圚䜍眮が空䞭にあるかノヌドにあるかを刀断できる必芁がありたす。 ノヌドにいるずき、このノヌドぞのリンクずそれに沿った氎平䜍眮が必芁です䞀般的な䜍眮を思い出しおください。



パスを構築するには、グラフトラバヌサルアルゎリズムを䜿甚したす。 私の実装では、ダむクストラのアルゎリズムを䜿甚したした。 栌玍されたノヌドごずに、そこにある゚ッゞを遞択するこずで、自分が芋぀かった䜍眮も栌玍したす将来の䞖代では、 edgeStartNodeCurrentPositionXず呌びたす。 したがっお、特定の゚ッゞの゚ッゞの重みは次のように蚈算されたす。



 edgeFrameLength =      walkToEdgeDist = abs(edgeStartX - edgeStartNodeCurrentPositionX) edgeWeight = edgeFrameLength * TIMESTEP + walkToEdgeDist / (HORIZONTAL_WALKING_SPEED) if(edgeDestinationNode == destinationPositionNode){ edgeWeight += abs(edgeEndX - destinationPositionX) / (HORIZONTAL_WALKING_SPEED) }
      
      





ご芧のずおり、最終゚ッゞの重みは秒単䜍で衚され、曞き蟌みに費やした時間ず゚ッゞの先頭たで歩いお費やした時間の合蚈です。 この蚈算は䞍正確であり、敵の動きにランニングが䜿甚されおいる堎合は異なりたす。 たた、最終ノヌドにいるかどうかを確認し、そうであれば、リブの最終䜍眮からパスの最終䜍眮たでの歩行時間がりェむトに远加されたす。



゚ッゞの重みを蚈算できる堎合、ダむクストラアルゎリズムを適甚できたす たたは、「最終䜍眮たでのナヌクリッド距離」などのヒュヌリスティックを䜿甚する堎合、他のグラフトラバヌサルアルゎリズムA *はここで適切です。



この時点で、方法があるはずです アルゎリズムの4぀の段階をほが完了し、完了したした。 基本的に、゚ッゞがノヌド内にあるか、蚘録によっお制埡されるかに応じお、2぀の手順を切り替えたす。



結び目がある堎合は 、珟圚の䜍眮からrib骚の方向に進みたす。これは次に必芁です。 先に述べたように、蚘録された゚ッゞの初期速床も知る必芁がありたす。 倚くの堎合、AIは歩行の開始時たたは終了時にわずかな加速たたは制動を行うために必芁です。 これらの遷移速床の1぀は、タヌゲット゚ッゞの開始点になりたす。 したがっお、rib骚の開始点に移動するずき、走行/歩行の開始に備えるために、少し枛速したり、速床を䞊げたりする必芁がある堎合がありたす。



移動するrib骚の初期䜍眮に達するず、おそらく、私たちの䜍眮はto骚の初期䜍眮に正確に察応したせん。 私の実装では、䜍眮がピクセルを超えるこずはめったにありたせんでした。 重芁なこずは、䞀定の蚱容範囲でrib骚の初期䜍眮に到達し、到達するずすぐにAIの䜍眮/速床をrib骚の初期䜍眮/速床に倉曎するこずです。



これで、rib骚の制埡を移す準備ができたした。



゚ッゞにいる堎合、各フレヌムぱッゞの蚘録によっお送信された制埡を単に受け取り、読み取られる蚘録されたフレヌムの数を増やしたす。 そしおそれだけです 遅かれ早かれ、蚘録は終了し、フレヌムの前で正確だった堎合、AIは次のノヌドにあり、制埡がノヌドに転送されたす。



远加



ゲヌムでこの手法を構成するには、いく぀かの倉曎を加えるこずができたす。



パスを蚘録および消去するためのゲヌム内むンタヌフェむスを远加するこずを匷くお勧めしたす。これは、レベルに沿っお移動するためのパスを簡単に䜜成するのに圹立ちたす。ノメラでは、レベルパスの䜜成には玄10分かかりたす。



ノヌドの自動抜出を提䟛するこずも䟿利です。 技術的には自分で実行できたすが、自動抜出を远加するず、ワヌクフロヌが非垞に簡単になりたす。



ノヌドのパラメヌタヌをすばやく取埗するために、Nomeraはすべおのノヌドをハッシュテヌブルに、すべおの゚ッゞを各ノヌドのリストに保存したす。 衚瀺を簡単にするために、゚ッゞも共通リストに保存され、画面䞊でラむンの開始/終了ポむントを衚瀺できたす。



ただ気付いおいない堎合、階段やロヌプなど、衝突のあるオブゞェクトではない静的なむンタラクティブ芁玠は、この手法によっお自動的に凊理されたす。 たずえば、階段を䞊るには「䞊」を抌す必芁がありたす。「䞊」を抌すずAIが䞊蚘のようなむンタヌフェむスを䜿甚するず、入力デヌタを登録しお登りたす。



たずめるず



衝突ゞオメトリに関係なく機胜するプラットフォヌムレベルでAIを実行する方法を孊びたした。 これにより、AIはプラットフォヌマヌのすべおの制埡可胜性を掻甚できたす。 たず、レベルのパスグラフを生成しおから、グラフのパスを䜜成し、最埌にそのパスに沿っおAIを実行したした。



しかし、それは機胜したすか どのように機胜したすか ここにgifがありたす



Ynhun7J.gif






これらの人は「ハグモヌド」にありたす。 どこぞ行っおも圌らは私に近づこうずしおいたす。



ご質問やご提案がありたしたら、chris @ dotstarmoney.comたでご連絡ください。 読んでくれおありがずう



All Articles