2DゲームC#のクリックして移動するサンプル?


7

現在、2Dゲームを作成してXNAの使い方を学んでいます。これまでのところ私は大丈夫ですが、キーを使用して移動するのではなく、クリックして移動を実装したいのですが、周りにサンプルが見つからないので、それに近づく方法については無知です。

XNAはxboxコントロールとキーボードでうまく機能することは知っていますが、マウスの操作に関連するものはまったく見たことがありません。また、PCゲーム以外のものを目指していないので、xboxについては特に気にしません。

だから私が探しているのは、クリックして移動が計算される方法のいくつかのサンプルであり、ゲームに表示されたマウスアイコンがxnaフレームワークからも機能しているか、それとも、現在のタイルの輝き、またはマウスがそこにあること、または同様のものを表示します。


更新:

マウスで移動することはまったく同じではありません。少なくとも私が計画していることについては、障害物も考慮する必要があります...

たとえば、クリックをまっすぐ歩くとみなして、ユーザーがクリックごとにユーザーを自動ナビゲートするのではなく、地図上を自分でナビゲートするように強制したいので、たとえば壁を越えてクリックした場合、壁に向かって歩いて止まるのではなく、ある場合は反対側へのルート...スクロールウィンドウなどでXとYのgetstateを使用して頭に浮かぶ別の疑問は、実際にマウスがどこにあるかを認識するか、ワールドの必要性があるでしょうか。ユーザーがクリックしたポイントBがどこにあるかを表示するための画面計算


助けとアドバイスをありがとう...

PS:誰かがClick-to-MoveタグやWorld-to-Screenを追加することはできますか?

PPS:なぜC#タグを追加できないのですか?


C#と2Dでタグ付けし直して、Click-to-MoveまたはWorld-to-Screenがタグとして必要になる理由を理解しないでください。また、すべてに集中できるようにするためだけに、2つ目の質問が1つ目の質問に実際に関連しているようには見えません。別の質問で投稿してください。
ジェシードーシー

なぜスクロールウィンドウがあるのですか。通常、ウィンドウはあなたの世界の特定の部分への単なるビューポートです。あなたは間違いなく点aから点bまで線形方程式を作ることができます。次に、いくつかの曲線関数を使用して、最初に加速し、最後に減速するなどのクールなことを行うことができます。
マイケルコールマン、2010

例として挙げましたが、スクロールウィンドウは使用していません。基本的forcing the user to navigate himself on the map instead of auto-navigating the user per clickに、ユーザーが確定した場所をクリックすると、プレーヤーが移動するとウィンドウが移動することを誤解しているかもしれませんが、たとえば、ドアが閉まっている家の中でプレーヤーがクリックしようとすると、家の家に向かって歩きます。直線で、最初の障害物で停止します。つまり、ユーザーは移動するための自動ナビゲートクリックはありませんが、行きたい場所に移動するためにクリックする必要があります。
Prix

回答:


6

編集:わかりました、コメントの1つから自動ナビゲーションを望まないことを読みました。その場合、リストがマウスをクリックした場所のみを保存し、障害物が見つかったときにそれ自体をクリアするという単純なケースで、この投稿の最後のセクション(「そのパスを歩く」)のみを考慮してください。また、投稿で一度タイルについて言及していることにも気づきました。その場合、可視性グラフは必要ありません。グリッド自体を使用して、Aスターを実行できます。とにかく、私はまだこれを2Dポイントアンドクリックナビゲーションの問題に対するより一般的な解決策として投稿しています。

あなたが求めているのは、2D環境でパスファインディングを行う方法です。その問題を解決できる1つのテクニックの概要を説明する前に、記事を書きました。まず、記事へのリンクを配置してから、アルゴリズムの簡単な説明を追加します。

http://www.david-gouveia.com/pathfinding-on-a-2d-polygonal-map/

もちろん、これがそれを解決する唯一の方法ではありません。可視性グラフを使用しています。ナビゲーションメッシュを使用することもできます。またはグリッド。可視性グラフには、パスの直線化を行わなくても、常にポイント間の最も直接的なパスが返されるという1つの利点があります。ポリゴンの上に可視性グラフを作成すると、歩行可能な領域を正確に指定できます。

概念

ここでの主なアイデアは、歩行可能な領域をポリゴンとして表し、ポリゴンの凹状の頂点を使用して可視性グラフを作成することです。ポリゴンに穴が含まれている場合は、凸状の頂点も使用します。

可視性グラフを作成するということは、グラフのすべてのノード(この場合は頂点)を取得して、「見える」他のすべての頂点に接続することを意味します。これを行うには、視線チェックが必要です。私が使用したものは、いくつかのチェックが追加された、単純な線分交差テストの上に構築されています。

次に、2つの場所の間のパスを見つけたいときはいつでも、それらを可視性グラフに一時的に追加し、その上で従来のA *パスファインディングアルゴリズムを実行します。

全体の構造は次のようになります。

可視性グラフ

どこ:

  • 黄色い線は、どこを歩くことができるかを表すポルジョンです。
  • 白い円は、可視性グラフ(ノード)を構成するポリゴンの頂点です。
  • 紫色の線は、互いの見通し内にある頂点(エッジ)を接続します。
  • 水色の線は、2つの場所(緑の点と赤の点)の間のパスを見つける例です。
  • 明るい緑色の線は、パスの開始ノードと終了ノード(緑色の点と赤色の点)とともにグラフに追加される一時的なエッジです。

実装

1)表現

これを実装するには、まず、床のポリゴンを表す方法が必要です。次のクラスで十分です:

public class Polygon
{
    public class SimplePolygon
    {
        List<Vector2> Vertices;
    }

    List<SimplePolygon> Outlines;
    List<SimplePolygon> Holes;
}

2)ノードの選択

次に、ポリゴンの各頂点を調べて、それらを可視性グラフのノードにするかどうかを決定する方法が必要です。その基準は、輪郭の凹状の頂点と穴の凸状の頂点です。私はこのような関数を使います:

public static bool IsVertexConcave(IList<Vector2> vertices, int vertex)
{
    Vector2 current = vertices[vertex];
    Vector2 next = vertices[(vertex + 1) % vertices.Count];
    Vector2 previous = vertices[vertex == 0 ? vertices.Count - 1 : vertex - 1];

    Vector2 left = new Vector2(current.X - previous.X, current.Y - previous.Y);
    Vector2 right = new Vector2(next.X - current.X, next.Y - current.Y);

    float cross = (left.X * right.Y) - (left.Y * right.X);

    return cross < 0;
}

3)エッジの選択

次に、これらの頂点のすべてのペアを調べ、それらが見通し内にあるかどうかを判断する必要があります。そのチェックの開始点として次の方法を使用しました。

static bool LineSegmentsCross(Vector2 a, Vector2 b, Vector2 c, Vector2 d)
{
    float denominator = ((b.X - a.X) * (d.Y - c.Y)) - ((b.Y - a.Y) * (d.X - c.X));

    if (denominator == 0)
    {
        return false;
    }

    float numerator1 = ((a.Y - c.Y) * (d.X - c.X)) - ((a.X - c.X) * (d.Y - c.Y));

    float numerator2 = ((a.Y - c.Y) * (b.X - a.X)) - ((a.X - c.X) * (b.Y - a.Y));

    if (numerator1 == 0 || numerator2 == 0)
    {
        return false;
    }

    float r = numerator1 / denominator;
    float s = numerator2 / denominator;

    return (r > 0 && r < 1) && (s > 0 && s < 1);
}

しかし、エッジケースの安定性のために他のいくつかのハックを使用する必要があったので、投稿するのは良い状態ではありません。まだ問題のクリーンで安定した解決策を見つけようとしています。

4)グラフを作成し、Aスターを実行する

これらの頂点とエッジを使用して可視性グラフを作成し、A *を実行する必要があります。グラフを作成してA *を適用する方法を学ぶには、次の記事を読むことをお勧めします。

http://blogs.msdn.com/b/ericlippert/archive/2007/10/02/path-finding-using-a-in-c-3-0.aspx

次に、これらすべてを単一のクラスにカプセル化して、次のような使いやすいインターフェイスを用意することができます。

public class Floor
{
    public Floor(Polygon polygon) 
    { 
        _polygon = polygon; 
        BuildGraph();
    }

    public IEnumerable<Vector> GetPath(Vector2 start, Vector2 end)
    {
       // Add start and end as temporary nodes and connect them to the graph
       // Run A* on the graph
       // Remove temporary nodes and edges
    }

    private Polygon _polygon;

    private Graph _graph;
}

この方法では、Floorインスタンスを作成し、2つの場所の間のパスを見つける必要があるときはいつでも、そのインスタンスでGetPathメソッドを呼び出す必要があります。

5)その道を歩く

最後に、キャラクターに生成されたパスを歩くようにする必要があります。そのためには何らかの内部メモリが必要ですが、実装するのはそれほど難しくありません。例えば:

  1. キャラクター内にリストを追加して、彼が現在フォローしているパスを保存します。
  2. 各更新サイクルで、リストから最初の値を取得し、それに向かってキャラクターを移動します。
  3. 彼が目的地に十分近づいたら、リストから最初の要素を削除して繰り返します。
  4. リストが空になると、目的地に到着したことになります。

すばらしい答えです。私が言えることはすべてカバーしていると思いますので、わざわざ答えるつもりはありません。+1
ジョシュアヘッジス

3

まあ...あなたが学んでいる間、Googleがこの努力の真の友であることを忘れないでください。

ステップ1は、マウスの位置を取得することです-http://msdn.microsoft.com/en-us/library/bb197572.aspx

ステップ2は、スプライトをロケーションAからロケーションBに移動することです。これには、基本的な物理/動きが含まれます-http://www.xnadevelopment.com/tutorials/thewizard/theWizard.shtml

これは、ユーザーがクリックする目的地を取得するためのマウスの移動と同じです。ポイントAからポイントBに移動します。

あなたが説明しているのは、処理方法を決定できる実装の詳細です。なんらかのグリッドで作業していると思います。これらのグリッド上のタイルには、歩行可能性などの特定のプロパティがあります。スプライトを移動先の方向に1ステップ近づけてみます。タイルが歩けない場合は、停止します。

スプライトが実際に目的地に到達するようにしたい場合は、タイルの歩行可能性を分析する実際のパスファインディングアルゴリズムを実装する必要があります。


役立つ最初のリンクに感謝しますが、2番目のリンクはそれほどではありません。チェックを気にしない場合、他のいくつかの点で質問を更新しました...ありがとう。
グランプリ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.