プレイヤーが描いた線がパスに沿っているかどうかを確認するにはどうすればよいですか?


8

ユーザーが辿らなければならない目に見えないパスを描きたいと思います。そのパスをポイントとして保存しました。プレーヤーが線を引いたとき、それが保存したパスをたどっているかどうかをどのようにテストできますか?

文字Aをトレースする例を次に示します。

トレースの例

if((traitSprite.getX()<=Invisible.X  && traitSprite.getX()>=Invisible.X )){...}

traitSpriteはスプライトです。)


プレイヤーが描いた線がたどるべき経路をどのように保存していますか?それはスプライトとは何ですか?
Anko

いいえ、手動で入力したポイントです。それは悪い考えですが、「Vector2」の使用は効果的な解決策になると思いますが、どうすればよいのかわかりません。
Android

回答:


12

これがベクターベースのソリューションです。まだ試していませんが、概念的には問題ないようです。

理論

形状を線分として保存しました。これは、3つの線分で表された文字Aです。

文字を表す線分

ユーザーの図面内のパスは、ポイントのリストとして格納されていると想定しています。

近さをチェックするときにエラーマージンを許可するために、これらのラインセグメントを「膨らませる」ことができます。ユーザーの描画パスが正しいラインのエラーマージンに近いかどうか。

「膨らんだ」線分 エラーマージンのあるレターの上にユーザーが描いたパス

しかし、それだけでは十分ではありません。カバレッジもチェックする必要があります。ユーザーの描画が図形の大部分を「カバー」しているかどうかです。これらの図面は、エラーマージン内に収まっているにもかかわらず、文字の一部が欠落しているため、不適切です。

悪い絵

これらの両方をチェックすると、プレイヤーの描画が良いかどうかを概算できます。

実装

近さをチェックすることは、ユーザーパスポイントごとに、それと文字を構成するすべての行との間の距離見つけ、最も低いものを取り、それがエラーマージンよりも小さいことを意味します。

カバレッジのチェックはより複雑ですが、各線分について最も近いユーザー描画パス(緑)を見つけ、その部分(濃い緑)をその線分(黒)に投影すると、ベクトル計算で非常に良い近似を得ることができます。次に、投影されたベクトル(青)がそれをどの程度カバーしているかを確認します。

ベクトル射影によるカバレッジチェック

ベクトルaを別のベクトルに投影するbには、次のようにします。

projection = dotProduct(a, b) / lengthSquared(b) * b

where は2つのベクトルの内積をdotProduct計算し、それはそのように聞こえます。基本的に、これは見つけスカラー値どのくらいの中に入るの方向と乗算同じ方向のベクトルを取得することによってを。(Metanet Softwareの衝突検出チュートリアルAは、付録プロジェクションでこれをわかりやすく視覚化しています。)lengthSquaredabb

投影されたベクトルの方向は実際には重要ではない場合があります。投影されたベクトルの長さを合計して、それらをラインセグメントの全長と比較すると、カバーされている部分がわかります。(奇妙な場合を除きます。以下の「制限」を参照してください)。

上の画像では、パスはセグメントの約半分をカバーしています。必要な許容値を選択できます。

制限事項

湾曲した文字

線分は理想的ではありません:多くの文字が湾曲しています!「P」または「O」をどのように表しますか?

多くのラインセグメントを使用できます(エラーマージンが大きい可能性があります)。

線分で近似された文字P 線分で近似された文字O

また、可能性が使用を開始するベジェ曲線の代わりに近いフィット感のためのラインのを、しかしなお、ベジェ上の最も近い点を見つけることである多くの、より複雑な、他の多くの測定動作です。

不一致

線からの距離と文字のカバレッジの許容範囲マージンが過度に緩和されていると、意図しない結果が生じる可能性があります。

たとえば、プレーヤーがここで「H」を描画しようとしていた可能性があります。

Aと誤って認識された文字H

ループとオーバーラップ

(おそらく)認識された文字でループしてオーバーラップする

プレーヤー描画パスのループまたはオーバーラップにより、図面の一部が最も近い線分に投影されたときに2回カウントされる可能性があります。

これは、投影されたベクトルに対してより精巧な処理を行うことで回避できます。おそらく、投影されたベクトルの位置を正確に保存します(投影の方向も保存し、ラインセグメント上の最も近い点をプレーヤーが描いた線上の点に保存します)。 、次にそれと重複する新しいものを拒否します。

プレーヤーが1つのパスを描画し、青い円でマークされた最後から処理された場合、そのパスの緑の部分は受け入れられ、赤のパスは拒否されます。これは、前に処理された一部の部分と投影が重なるためです。

ループとオーバーラップを拒否する

実装には、おそらく別の問題に属するであろう多くの技術的な微妙な点があります。

予想外の冒険的なプレーヤー

プレイヤーは、まだ通過する奇妙な何かを描くかもしれません。

トロロロール

あなたはそれを機能と呼ぶことができますが!:)


ありがとう、手紙の外に描かないようにあなたは何を提案しますか?
Android

@Androidオレンジ色の「エラーマージン」はそのためです。あなたはそれらの外に出る行を拒否することができます:例えばこのように。
Anko、2015年

私が欲しいのは文字をSpriteBatchとして作成することです。その場合、描画できる唯一の領域はそのスプライトバッチで、AまたはB、Xのいずれかの形式をとることができます。これは可能ですか?どのようにしてSpriteBatchのようなテクスチャを作成できますか?よろしくお願いします。
Android

2

tl; drプレイヤーのブラシを可視(または非可視)の2D平面にペイントすることをお勧めします。ユーザーのペイントしたイメージを原点(希望のシルエットまたは2Dモデル)と比較します。精度を高めたい場合は、ガイドラインとブラシをより細くし、エラーの余地を増やすために、ブラシとデザインを厚くします。

それ以外の場合は、ポイントからセグメントまでの距離を計算することにより、ユーザーがスプラインからクリック/タッチした各(x、y)の距離を測定できます。次に、距離を平均して、精度と効率の測定値を構成できます。完了の有意義な測定値を取得し、ユーザーがどれほど効率的に実行したかを理解するには、さらに多くの作業が必要になります。


考慮事項:そうしないことをお勧めします(線がパスをたどっているかどうかを直接確認します)。これはおそらく悪い考えです。ユーザーにシルエットを埋めてもらいたいようです。パス自体は、シルエットを表す(骨格)スプラインです。

プレーヤーのブラシで2d平面に淡いモノクロのピクセルを適用するだけで、シルエットの内側にあるピクセルの数と外側にあるピクセルの数をチェックするプロセスをバックグラウンドで実行できます。これは、パターンのどのくらいの割合が関心のある統計であり、もう1つがモデルの境界の外にどれだけあるかである場合、成功率を簡単にもたらす可能性があります。サブセグメントの距離を確認する場合、ユーザーの作業が正確であるかどうかは明確ではありません。


1

最善の解決策はグラフィックをまったく使用せず、数学で実行することです!

セグメントから遠く離れたすべてのポイント(ユーザーが描いたポイント)の量を簡単に理解できます /programming/849211/shortest-distance-between-a-point-and-a-line-segment

平均誤差を計算できるため、ユーザーがどれだけ正しいかを測定します。


ありがとう、でも "C" "O"のような文字はどうなるの?...ポイント間に固定距離はありません..
Android

「C」と「O」は、他のセグメントと同じように6〜8の線分から作成できますが、計算はエラー
測定の
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.