ユーザーが辿らなければならない目に見えないパスを描きたいと思います。そのパスをポイントとして保存しました。プレーヤーが線を引いたとき、それが保存したパスをたどっているかどうかをどのようにテストできますか?
文字Aをトレースする例を次に示します。
if((traitSprite.getX()<=Invisible.X && traitSprite.getX()>=Invisible.X )){...}
(traitSprite
はスプライトです。)
ユーザーが辿らなければならない目に見えないパスを描きたいと思います。そのパスをポイントとして保存しました。プレーヤーが線を引いたとき、それが保存したパスをたどっているかどうかをどのようにテストできますか?
文字Aをトレースする例を次に示します。
if((traitSprite.getX()<=Invisible.X && traitSprite.getX()>=Invisible.X )){...}
(traitSprite
はスプライトです。)
回答:
これがベクターベースのソリューションです。まだ試していませんが、概念的には問題ないようです。
形状を線分として保存しました。これは、3つの線分で表された文字Aです。
ユーザーの図面内のパスは、ポイントのリストとして格納されていると想定しています。
近さをチェックするときにエラーマージンを許可するために、これらのラインセグメントを「膨らませる」ことができます。ユーザーの描画パスが正しいラインのエラーマージンに近いかどうか。
しかし、それだけでは十分ではありません。カバレッジもチェックする必要があります。ユーザーの描画が図形の大部分を「カバー」しているかどうかです。これらの図面は、エラーマージン内に収まっているにもかかわらず、文字の一部が欠落しているため、不適切です。
これらの両方をチェックすると、プレイヤーの描画が良いかどうかを概算できます。
近さをチェックすることは、ユーザーパスポイントごとに、それと文字を構成するすべての行との間の距離を見つけ、最も低いものを取り、それがエラーマージンよりも小さいことを意味します。
カバレッジのチェックはより複雑ですが、各線分について最も近いユーザー描画パス(緑)を見つけ、その部分(濃い緑)をその線分(黒)に投影すると、ベクトル計算で非常に良い近似を得ることができます。次に、投影されたベクトル(青)がそれをどの程度カバーしているかを確認します。
ベクトルa
を別のベクトルに投影するb
には、次のようにします。
projection = dotProduct(a, b) / lengthSquared(b) * b
where は2つのベクトルの内積をdotProduct
計算し、それはそのように聞こえます。基本的に、これは見つけスカラー値どのくらいの中に入るの方向と乗算同じ方向のベクトルを取得することによってを。(Metanet Softwareの衝突検出チュートリアルAは、付録 A§ プロジェクションでこれをわかりやすく視覚化しています。)lengthSquared
a
b
b
投影されたベクトルの方向は実際には重要ではない場合があります。投影されたベクトルの長さを合計して、それらをラインセグメントの全長と比較すると、カバーされている部分がわかります。(奇妙な場合を除きます。以下の「制限」を参照してください)。
上の画像では、パスはセグメントの約半分をカバーしています。必要な許容値を選択できます。
線分は理想的ではありません:多くの文字が湾曲しています!「P」または「O」をどのように表しますか?
多くのラインセグメントを使用できます(エラーマージンが大きい可能性があります)。
また、可能性が使用を開始するベジェ曲線の代わりに近いフィット感のためのラインのを、しかしなお、ベジェ上の最も近い点を見つけることである多くの、より複雑な、他の多くの測定動作です。
線からの距離と文字のカバレッジの許容範囲マージンが過度に緩和されていると、意図しない結果が生じる可能性があります。
たとえば、プレーヤーがここで「H」を描画しようとしていた可能性があります。
プレーヤー描画パスのループまたはオーバーラップにより、図面の一部が最も近い線分に投影されたときに2回カウントされる可能性があります。
これは、投影されたベクトルに対してより精巧な処理を行うことで回避できます。おそらく、投影されたベクトルの位置を正確に保存します(投影の方向も保存し、ラインセグメント上の最も近い点をプレーヤーが描いた線上の点に保存します)。 、次にそれと重複する新しいものを拒否します。
プレーヤーが1つのパスを描画し、青い円でマークされた最後から処理された場合、そのパスの緑の部分は受け入れられ、赤のパスは拒否されます。これは、前に処理された一部の部分と投影が重なるためです。
実装には、おそらく別の問題に属するであろう多くの技術的な微妙な点があります。
プレイヤーは、まだ通過する奇妙な何かを描くかもしれません。
あなたはそれを機能と呼ぶことができますが!:)
tl; drプレイヤーのブラシを可視(または非可視)の2D平面にペイントすることをお勧めします。ユーザーのペイントしたイメージを原点(希望のシルエットまたは2Dモデル)と比較します。精度を高めたい場合は、ガイドラインとブラシをより細くし、エラーの余地を増やすために、ブラシとデザインを厚くします。
それ以外の場合は、ポイントからセグメントまでの距離を計算することにより、ユーザーがスプラインからクリック/タッチした各(x、y)の距離を測定できます。次に、距離を平均して、精度と効率の測定値を構成できます。完了の有意義な測定値を取得し、ユーザーがどれほど効率的に実行したかを理解するには、さらに多くの作業が必要になります。
考慮事項:そうしないことをお勧めします(線がパスをたどっているかどうかを直接確認します)。これはおそらく悪い考えです。ユーザーにシルエットを埋めてもらいたいようです。パス自体は、シルエットを表す(骨格)スプラインです。
プレーヤーのブラシで2d平面に淡いモノクロのピクセルを適用するだけで、シルエットの内側にあるピクセルの数と外側にあるピクセルの数をチェックするプロセスをバックグラウンドで実行できます。これは、パターンのどのくらいの割合が関心のある統計であり、もう1つがモデルの境界の外にどれだけあるかである場合、成功率を簡単にもたらす可能性があります。サブセグメントの距離を確認する場合、ユーザーの作業が正確であるかどうかは明確ではありません。
最善の解決策はグラフィックをまったく使用せず、数学で実行することです!
セグメントから遠く離れたすべてのポイント(ユーザーが描いたポイント)の量を簡単に理解できます /programming/849211/shortest-distance-between-a-point-and-a-line-segment
平均誤差を計算できるため、ユーザーがどれだけ正しいかを測定します。