Je veux dessiner un chemin invisible que l'utilisateur doit suivre. J'ai enregistré ce chemin sous forme de points. Lorsqu'un joueur trace une ligne, comment puis-je tester si elle suit le chemin que j'ai enregistré?
Voici un exemple de traçage de la lettre A.
if((traitSprite.getX()<=Invisible.X && traitSprite.getX()>=Invisible.X )){...}
( traitSprite
est un sprite.)
libgdx
algorithm
vector
hand-drawn
Android
la source
la source
Réponses:
Voici une solution vectorielle. Je ne l'ai pas essayé, mais cela semble bien conceptuellement.
Théorie
Je suppose que vous avez stocké la forme sous forme de segments de ligne. Voici la lettre A représentée par trois segments de ligne.
J'ai supposé que les chemins dans le dessin de l'utilisateur sont stockés sous forme de listes de points.
Nous pouvons «gonfler» ces segments de ligne pour permettre une marge d'erreur lors de la vérification de la proximité : si le chemin tracé par l'utilisateur est proche de la marge d'erreur de lignes correcte.
Mais cela ne suffit pas. Nous devons également vérifier la couverture : si le dessin de l'utilisateur "recouvre" une grande partie de la forme. Ces dessins sont mauvais, car même s'ils s'inscrivent dans la marge d'erreur, il leur manque une partie de la lettre:
Si nous vérifions ces deux choses, nous pouvons approximer si le dessin du joueur est bon.
la mise en oeuvre
Vérifier la proximité signifie simplement pour chaque point de chemin utilisateur, trouver la distance entre cela et chaque ligne constituant la lettre, prendre le plus bas et vérifier qu'elle est inférieure à la marge d'erreur.
La vérification de la couverture est plus compliquée, mais vous pouvez obtenir une très bonne approximation avec les mathématiques vectorielles si pour chaque segment de ligne, vous trouvez le chemin dessiné par l'utilisateur le plus proche (vert) et projetez ses parties (vert foncé) sur ce segment de ligne (noir), puis vérifiez si les vecteurs projetés (en bleu) le couvrent:
Pour projeter un vecteur
a
sur un autre vecteurb
, faitesoù
dotProduct
calcule le produit scalaire des deux vecteurs etlengthSquared
correspond à ce à quoi il ressemble. Essentiellement, cela trouve la valeur scalaire de combiena
va dansb
la direction de et multiplieb
par celle-ci pour obtenir un vecteur dans la même direction. (Le didacticiel A sur la détection des collisions de Metanet Software en offre une belle visualisation dans l' annexe A § projection .)La direction du vecteur projeté peut ne pas être réellement importante. Si vous additionnez simplement les longueurs des vecteurs projetés et les comparez à la longueur totale du segment de ligne, cela vous indiquera quelle fraction est couverte. (Sauf dans les cas étranges - voir § Limitations ci-dessous).
Dans l'image ci-dessus, le chemin couvrirait environ la moitié du segment. Vous pouvez choisir n'importe quelle valeur de tolérance que vous souhaitez.
Limites
Lettres courbes
Les segments de ligne ne sont pas idéaux: de nombreuses lettres sont courbes! Comment représentez-vous un «P» ou un «O»?
Vous pouvez utiliser de nombreux segments de ligne (peut-être avec une marge d'erreur plus importante).
Vous aussi pouvez commencer à utiliser des courbes de Bézier au lieu de lignes pour un plus en forme, mais notez que trouver le point le plus proche sur un Bézier est beaucoup plus que complexe plus a beaucoup d' autres opérations de mesure.
Inadéquations
Des marges de tolérance trop détendues pour la distance des lignes et la couverture de la lettre pourraient avoir des conséquences inattendues.
Par exemple, le joueur a peut-être essayé de dessiner un «H» ici.
Boucles et chevauchements
Les boucles ou les chevauchements dans le chemin tracé par le joueur peuvent entraîner le comptage double de certaines parties du dessin lors de leur projection sur le segment de ligne le plus proche.
Cela pourrait être contourné en effectuant un traitement plus sophistiqué sur les vecteurs projetés, peut-être en stockant exactement où le vecteur projeté serait (stockez également la direction de la projection et le point le plus proche sur le segment de ligne au point sur la ligne dessinée par le joueur) , puis en rejeter de nouveaux qui le chevauchent.
Si le joueur dessinait un seul chemin et que celui-ci était traité en commençant à la fin marquée par le cercle bleu, les parties vertes de ce chemin seraient acceptées et les rouges rejetées, car leur projection chevaucherait certaines parties traitées auparavant.
L'implémentation a de nombreuses subtilités techniques qui appartiendraient probablement à une question différente.
Joueurs imprévisiblement aventureux
Un joueur peut dessiner quelque chose de bizarre qui passe toujours .
Bien que vous puissiez appeler cela une fonctionnalité! :)
la source
tl; dr Je suggère de faire de la peinture au pinceau des joueurs un plan 2D visible (ou invisible). Différez l'image peinte des utilisateurs avec l'origine (la silhouette souhaitée ou le modèle 2D). Si vous souhaitez augmenter la précision, rendez les lignes de guidage et la brosse plus étroites, pour laisser plus de place à l'erreur, rendez la brosse et le design plus épais.
Sinon, vous pouvez mesurer la distance de chacun (x, y) sur lequel les utilisateurs cliquent / touchent depuis la spline en calculant la distance point à segment. Ensuite, vous pouvez faire la moyenne des distances pour composer une mesure de précision et d'efficacité. Il faudra plus de travail pour obtenir une mesure significative de l'achèvement et réaliser l'efficacité de l'utilisateur.
Considération: je suggère de ne pas le faire (vérifier directement si une ligne suit un chemin). C'est peut-être une mauvaise idée. Il semble que vous souhaitiez que l'utilisateur remplisse une silhouette. Le chemin lui-même est une spline (squelettique) représentant la silhouette.
Si vous faites simplement appliquer au pinceau des joueurs une masse pulpeuse de pixels monochromes sur le plan 2D, vous pouvez exécuter un processus en arrière-plan qui vérifie combien de pixels se trouvent à l'intérieur de la silhouette et combien d'entre eux sont à l'extérieur. Cela peut facilement entraîner un% de réussite, où% du motif est rempli est une statistique intéressante et une autre est combien% est en dehors des frontières du modèle. Si vous vérifiez les distances des sous-segments, il n'est pas très clair de la précision du travail des utilisateurs.
la source
La meilleure solution n'est pas du tout d'utiliser des graphiques, faites-le avec les mathématiques!
Vous pouvez facilement comprendre combien chaque point (peint par l'utilisateur) est éloigné du segment /programming/849211/shortest-distance-between-a-point-and-a-line-segment
Que vous pouvez calculer l'erreur moyenne, alors mesurez combien d'utilisateurs sont corrects.
la source