クリックアンドドラッグの動きを特定の領域に制限する方法


11

やや一般的なタイトルをお詫び申し上げます。私がやろうとしていることを成し遂げる方法については、あまり手がかりがありません。そのため、可能な解決策を研究することさえ難しくなっています。

私はある種のパスマーカーを実装しようとしています(たぶんそれに最適な名前があるかもしれませんが、これは私が思いつくことができる最高のものです)。

プレーヤーの前にはパスマーカーがあり、ターンの計画が完了したらプレーヤーがどのように移動するかを決定します。プレーヤーはマーカーをクリックして選択した位置にドラッグできますが、マーカーは定義された作業領域(灰色のビット)内でのみ移動できます。

パスマーカー図

そのため、次の2つの問題に悩まされています。

まず、その実行可能な領域をどのように正確に定義する必要がありますか?プレーヤーが実行可能な角度を形成するための開始点となる2つのベクトルを想像できます。これらの2つの弧は、プレーヤーの位置に中心がある円から発生する可能性がありますが、すべてをどのように配置するかは明確にわかりません一緒。

次に、マーカーを配置できる領域を定義した後、その領域内にのみマーカーを配置するように強制するにはどうすればよいですか?たとえば、プレーヤーがマーカーをクリックしてドラッグすると、マーカーは作業領域内を自由に移動できますが、領域の境界を離れてはなりません。たとえば、プレーヤーがマーカーを上向きにドラッグし始めると、マーカーが作業領域の端(下の最初の図)に到達するまで上向きに移動しますが、その後、プレーヤーが横向きにドラッグを開始する場合、マーカーはドラッグ中にドラッグに追従する必要がありますエリア内(下の2番目の図)。

最初の図:上に移動 2番目の図:ドラッグの後

これがあまり混乱しないことを願っています。みんなありがとう。

編集:これが違いを生む場合、私はマーマレードSDKでC ++を使用しています。


あなたが探している用語は「ウェイポイント」だと思いますが、灰色の領域を数学的に定義できますか?もしそうなら、あなたの問題の解決策はおそらくはるかに簡単になります。
ジョンマクドナルド

パスファインディングなどに関連するアレントウェイポイント?また、灰色の領域を数学的に定義することは私の問題の1つです。PIは、長方形や円のようなものを理解できると思いますが、そのような形状で、側面に2つの円弧があり、角度に他の2つの側面があります...私の頭の上に少し。
Vexille

また、ソリューションは主にプラットフォームに依存するため、使用している言語やツールキットを指定する必要もあります。
Raceimaztion

本当に?私はアルゴリズム的な解決策または疑似コードが役立つと考えました。念のため、とにかく質問を編集します。
Vexille、2012年

極座標で形状を定義します(文字の角度からの最大角度と文字からの最小/最大距離)。次に、マウスがこれらの境界内にある場合にのみ、ウェイポイントをマウスのある場所に更新します。それらのextreemのいずれかを超える場合は、可能な限り最大のextreem値にスナップします。エリア内をクリックすると更新を開始し、マウスを離すと停止します。
ClassicThunder 2012年

回答:


8

次の3つの値を使用して、質問のような作業可能領域を定義できます。

float innerRadius;
float outerRadius;
float maxAngle;

これらの値は、プレーヤーの位置である場合とそうでない場合がある中心点に基づいてます。作業可能領域の形状は、このポイントを配置する場所によって異なります。

ここに画像の説明を入力してください

上記の例では、中心位置はプレイヤーの後ろに一定の距離(たとえば50単位)あります。これは次のように簡単に計算できます。

float offset = -50;
Vector2 centerPosition = playerPosition + offset * playerForward;

マーカーの位置をその作業可能領域に制限するには、最初に通常どおりにマーカー移動します。次に、中心点とマーカーの間の距離検証します。

Vector2 direction = markerPosition - centerPosition;
float distance = direction.Length();
direction.Normalize();
markerPosition = centerPosition + direction * clamp(distance, innerRadius, outerRadius);

最後に、指定した範囲に対するマーカーの角度検証します。これには疑似コードを使用します。

- Find angle between vector C->M and vector playerForward
- If abs(angle) <= maxAngle Then do nothing
- Else If angle > 0 Then rotate M around C by maxAngle-angle
- Else If angle < 0 Then rotate M around C by -maxAngle-angle

点を別の点を中心に回転させる方法を見てみましょう。これは、三角法または変換行列を使用して実行できます。

マーカーのサイズを考慮して、半径と角度を少し小さくして補正することもできます。

編集:考え直してみると、最初に角度を検証してから距離を検証すると、より自然に見える可能性があるため、両方の選択肢を試してください!


素晴らしい解決策!2つの円と1つの三角形を含むものに遭遇しましたが、あなたのソリューションはエレガントにそれを簡素化します。角度の検証について、私は、playerForwardからmaxAngle(および-maxAngle)に立っている正規化されたベクトルを持っているという線に沿って、境界がある場合にC-> Mの長さを掛けることができると考えていました、角度的に。MをCの周りで回転させるソリューションの方がコストが低いと思いますが、そうですか?
Vexille、2012年

@Vexilleええと、回転にはa cossin操作が含まれるので、よくわかりません。ただし、これら2つのベクトルを計算するには、それらを回転させる必要もあります。ただし、順方向ベクトルが変更されたときにのみ実行する必要があります。とにかく大した問題ではないので、実装したいものを選んでください。
David Gouveia

10

形状が不規則で、数学的に定義できない場合、どうしたら問題を解決できるか考えていました。警告:これは汚い解決策であり、気の弱い人には向いていません。

1.お住まいの地域:

ここに画像の説明を入力してください

2.モノクロのビットマップに変換します。

ここに画像の説明を入力してください それにscale_0という名前を付けます

3.ビットマップのクローンを作成し、50%に縮小します。

ここに画像の説明を入力してください それにscale_1という名前を付けます

4.以下同様に、幅/高さが4ピクセル未満のビットマップになるまで:

ここに画像の説明を入力してください ここに画像の説明を入力してください ここに画像の説明を入力してください ここに画像の説明を入力してください ここに画像の説明を入力してください スケール:2、3、4、5、6

5.これで、さまざまな解像度の単色ビットマップとして領域ができました。 ここに画像の説明を入力してください

6.最後の画像(ここでは "scale_6")を取得し、そのすべてのピクセルを反復処理します。

  • 各ピクセルの座標を画面座標に変換しますx = Math.pow ( 2, scale_level );。scale_levelは、「scale_」の後に追加した数値です。実際にはクアッドツリーで作業しているわけではありませんが、クアッドツリーレベルと呼ぶこともできます。yについても同様です。
  • 変換されたxとyのピクセルが黒かどうかを確認します。そうでない場合、それは形状の一部ではありません。continueループの次のステップに進んでください。
  • ピクセルが以前にチェックされたピクセルよりもマウスカーソルに近いかどうかを確認します。そうであれば、ピクセルの座標を保存します。変換前の座標、つまりビットマップ内の座標を使用します。
  • ループの最後で、これらの座標に2を掛けてx *= 2; y*=2;、次の画像(前のスケール)の座標に変換します。

7.前の画像(ここでは "scale_5")を取得しますが、すべてのピクセルをループ処理しないでください。x = saved_xで始まり、x = saved_x + 2で終わります。yと同じです。つまり、今度はすべてのレベルで4ピクセルしかループしないからです。残りはpと同じです。6。

8.最初の画像(最大=最大解像度の画像)を取り、再び4ピクセルをループすると、最終的にマウスカーソルに最も近いピクセルが得られます。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ここに画像の説明を入力してください

9.ただし、ここでは「M」をポイントとして扱います。完全にフィットする円にしたい場合は、circle.radiusまずピクセルで形状を縮小(縮小)する必要があります。

このアルゴリズムは、単色ではなくグレースケールの画像を使用し、ピクセルが白でない場合は「フル」、完全に白の場合は「空」として扱う場合にのみ機能することを付け加えたいと思います...またはサイズ変更の場合アルゴリズムは、これらの4ピクセルの少なくとも1つが白でなかったときは常に、4ピクセルのすべてのグループを1つの黒ピクセルに変更します。


2
数学的に表現するのが難しい(不可能ではないにせよ)図形の答えの+1。
Cypher

うわー、とても面白い。+1も:D
Vexille 2012年

実際のプロジェクトに実装しましたが、問題が発生したと言わざるを得ません。基本的には、という名前の最も近いグリッドセルを取得するグリッドセルのリストを作成し、で最も遠いclosestまでの距離を確認する必要があります。距離に名前を付けましょう。次に、から最も近いポイントを持つすべてのセルをリストから削除し、レベルを深くする必要があります。したがって、このようなものの代わりに:i.imgur.com/4UuFo.png次のようなものです:i.imgur.com/dyTT3.pngclosestfurthest_distfurthest_dist
Markus von Broady
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.