パックマンで幽霊のAIについて多くの言及を見つけましたが、誰も幽霊がパックマンに食べられた後、目が中心の幽霊の穴に戻る方法について言及していませんでした。
私の実装では、シンプルだがひどいソリューションを実装しました。私は、どの方向をとるべきかを隅々までハードコーディングしました。
より良い/または最良のソリューションはありますか?異なるレベルのデザインで動作する一般的なものでしょうか?
実際、あなたのアプローチは、あらゆる種類の経路探索と比較して実行時間がほとんどゼロの、非常に素晴らしいソリューションです。
任意のマップに一般化する必要がある場合、任意のパス検索アルゴリズムを使用できます-たとえば、幅優先検索は実装が簡単です-それを使用して、ゲームを実行する前に、各コーナーでエンコードする方向を計算します。
編集(2010年8月11日):Pacmanシステムの非常に詳細なページを参照しました: The Pac-Man Dossier 、ここで受け入れられた答えがあるので、更新する必要があると感じました。この記事は、怪物の家に明示的に戻る行為を扱っているようには見えませんが、パックマンでの直接の経路探索は次の場合であると述べています。
この方法で汎用レベルのこの問題を解決しました。レベルを開始する前に、モンスターホールから何らかの「洪水」を起こします。壁ではない迷路のすべてのタイルには、穴からどれだけ離れているかを示す数字が付けられます。したがって、目が68の距離にあるタイルにある場合、隣接するタイルのどれが67の距離にあるかを確認します。それがその後の道です。
より伝統的な経路探索アルゴリズムの代替として、(適切な名前が付けられています!) Pac-Man Scent Antiobject pattern を見ることができます。
起動時に迷路の周りにモンスターの穴の匂いを拡散させ、目を家に追いかけることができます。
臭いが設定されると、ランタイムコストは非常に低くなります。
編集:残念ながらウィキペディアの記事は削除されたので、 WayBack Machine to the rescue ...
Dijkstraのアルゴリズム または A *アルゴリズム のようなパス検索アルゴリズムを見てください。これがあなたの問題です:グラフ/パスの問題。
動作するシンプルなソリューションはすべて、保守可能で信頼性が高く、十分なパフォーマンスを発揮するのが良いソリューションです。あなたはすでに良い解決策を見つけているようです...
経路探索ソリューションは、現在のソリューションよりも複雑になる可能性が高いため、デバッグが必要になる可能性が高くなります。また、おそらく遅くなります。
IMO、破損していない場合は修正しないでください。
[〜#〜] edit [〜#〜]
IMO、迷路が固定されている場合、現在のソリューションis良い/エレガントなコード。 「良い」または「エレガントな」を「賢い」と間違えないでください。単純なコードは、「良い」と「エレガントな」場合もあります。
構成可能な迷路レベルがある場合は、迷路を最初に構成するときにパスファインディングを実行する必要があるかもしれません。最も簡単なのは、迷路のデザイナーに手作業でやらせることです。あなたが途方もない迷路を持っている場合、またはユーザーがそれらを設計できる場合、私はこれを自動化するだけです。
(脇:経路が手作業で構成されている場合、迷路の設計者は準最適経路を使用してレベルをさらに面白くすることができます...)
オリジナルのパックマンでは、ゴーストは「臭い」で黄色いピルイーターを見つけ、マップ上に痕跡を残します。ゴーストは匂いを見つけるまでランダムに歩き回ります。プレーヤー。パックマンが移動するたびに、「香りの値」は1ずつ減少します。
さて、プロセス全体を逆にする簡単な方法は、「ゴーストの匂いのピラミッド」を持つことです。これは、マップの中心に最高点があり、ゴーストはこの匂いの方向に移動します。
Pacmanを追いかけるために必要なロジックをすでに持っていると仮定して、なぜそれを再利用しませんか?ターゲットを変更するだけです。まったく同じロジックを使用してまったく新しいルーチンを作成しようとするよりも、はるかに少ない作業になるようです。
これは、実際にどのように機能するかについて見つけることができる最高のソースでした。
http://gameai.com/wiki/index.php?title=Pac-Man#Respawn 幽霊が殺されると、実体化されていない目が元の場所に戻ります。これは、ゴーストのターゲットタイルをその場所に設定することで簡単に実現できます。ナビゲーションは同じルールを使用します。
実際には理にかなっています。世界で最も効率的ではないかもしれませんが、ターゲットを変更するだけで、他の状態やそれらの線に沿って何かを心配する必要のない素敵な方法です。
サイドノート:pac-manプログラマーが基本的に、非常に限られたメモリの非常に小さなスペースでメッセージシステム全体を作成していたことに気づきませんでした...それは驚くべきことです。
中心までの距離の値を持つ各正方形はどうですか?このようにして、指定された各正方形について、考えられるすべての方向で直接隣接する正方形の値を取得できます。最も低い値の正方形を選択し、その正方形に移動します。
値は、利用可能なアルゴリズムを使用して事前に計算されます。
これは経路探索の問題です。一般的なアルゴリズムについては、 http://wiki.gamedev.net/index.php/A* をご覧ください。
各コーナーでランダムな方向を選択するというdtb23の提案では、最終的にモンスターホールの音がひどく不十分であることがわかります。
ただし、ゲームの難易度により多くのバリエーションを導入することにより、非効率的な帰宅アルゴリズムを利用してゲームをより楽しくすることができます。これを行うには、ウェイポイントや塗りつぶしなどの上記のアプローチのいずれかを適用しますが、非決定的に実行します。そのため、すべてのコーナーで、乱数を生成して、最適な方法をとるか、ランダムな方向をとるかを決定できます。
プレイヤーがレベルを進めるにつれて、ランダムな方向が取られる可能性を減らします。これにより、レベル速度、ゴースト速度、ピルイーティングポーズ(など)に加えて、全体的な難易度レベルに別のレバーが追加されます。幽霊がただ無害な目である間にリラックスする時間がありますが、その時間は進むにつれて短くなります。
短い答え、あまりよくない。 :)パックマンの迷路を変更すると、目が必ずしも戻ってくるとは限りません。周りに浮かぶハックのいくつかはその問題を抱えています。だから、それは協力的な迷路を持つことに依存しています。
あなたの解決策は問題に対して正しいと思います、それよりも簡単です、幽霊の目が壁を通過できる新しいバージョンをより「現実的」にすることです=)
AmmoQのフラッドフィルのアイデアのアナログと擬似コードを次に示します。
queue q
enqueue q, ghost_Origin
set visited
while q has squares
p <= dequeue q
for each square s adjacent to p
if ( s not in visited ) then
add s to visited
s.returndirection <= direction from s to p
enqueue q, s
end if
next
next
アイデアは、幅優先探索であるため、新しい隣接する正方形に遭遇するたびに、最適なパスはpを経由します。 O(N)だと思う。
ゲームの実装方法についてはあまり知りませんが、次のことができます。
いくつかの擬似コード:
x = getRelativeOppositeLatitudinalCoord()
y
origX = x
while(eyesNotInPen())
x = getRelativeOppositeLatitudinalCoordofGate()
y = getRelativeOppositeLongitudinalCoordofGate()
if (getRelativeOppositeLatitudinalCoordofGate() == 0 && move(y) == false/*assume zero is neither left or right of the the gate and false means wall is in the way */)
while (move(y) == false)
move(origX)
x = getRelativeOppositeLatitudinalCoordofGate()
else if (move(x) == false) {
move(y)
endWhile
私は、幽霊が彼が穴からパックマンにたどった道を保存することを提案します。そのため、幽霊が死ぬとすぐに、彼はこの保存された経路を逆方向にたどることができます。
楽しい!
私のアプローチは(Pacman時代の観点から)少しメモリを集中的に使用しますが、一度計算するだけでよく、あらゆるレベルのデザイン(ジャンプを含む)で機能します。
最初にレベルをロードするときに、すべてのモンスターレイアノードに0(レイアからの距離を表す)のラベルを付けます。すべてのノードにラベルが付けられるまで、接続されたノード1、ノード2に接続されたノードなどに外向きのラベルを付けます。 (注:隠れ家に複数の入り口がある場合でも機能します)
各ノードを表すオブジェクトとそれらの隣人への接続が既にあると仮定しています。擬似コードは次のようになります。
public void fillMap(List<Node> nodes) { // call passing lairNodes
int i = 0;
while(nodes.count > 0) {
// Label with distance from lair
nodes.labelAll(i++);
// Find connected unlabelled nodes
nodes = nodes
.flatMap(n -> n.neighbours)
.filter(!n.isDistanceAssigned());
}
}
すべてのノードにラベルが付けられると、目のルーティングは簡単になります...最小距離ラベルを持つ隣接ノードを選択するだけです(注:複数のノードの距離が等しい場合、どちらを選択してもかまいません)。擬似コード:
public Node moveEyes(final Node current) {
return current.neighbours.min((n1, n2) -> n1.distance - n2.distance);
}
Pacmanパスが非ランダムであることを知っている(つまり、特定のレベル0-255、真っ黒、点滅、小指、およびクライドは、そのレベルに対してまったく同じパスで機能します)。
これを取って、pac manが幽霊を食べたとき、眼球オブジェクトがペンディングする「リターンパス」として迷路全体を囲むいくつかのマスターパスがあると思います。
Pacmanのゴーストは、目標が達成されるまで最初にXまたはYで一致しようとするという点で、予測可能なパターンに従います。私はいつも、これは目が戻ってきたときもまったく同じだと思っていました。
私のPacManゲームでは、やや「 shortest multiple path home
"アルゴリズム(これは一連のルール内で)で提供する迷路で機能し、トンネル全体でも機能します。
レベルがロードされると、すべてのpath home data in every crossroad
は空(デフォルト)で、ゴーストが迷宮を探索し始めると、crossroad path home information
は、「新しい」交差点に到達するたびに、または既知の交差点で別のパスから再びつまずくたびに更新され続けます。