Bagaimana saya bisa memeriksa apakah garis yang ditarik pemain mengikuti jalur?

8

Saya ingin menggambar jalur tak terlihat yang harus diikuti pengguna. Saya telah menyimpan jalur itu sebagai titik. Ketika seorang pemain menarik garis, bagaimana saya bisa menguji apakah itu mengikuti jalur yang saya simpan?

Ini contoh untuk melacak huruf A.

contoh jejak

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

( traitSpriteAdalah sprite.)

Android
sumber
Bagaimana Anda menyimpan jalur yang harus diikuti oleh garis pemain? Itukah sprite itu?
Anko
tidak, adalah poin yang saya masukkan secara manual. itu ide yang buruk, tapi saya pikir penggunaan "Vector2" akan menjadi solusi yang efektif tetapi saya tidak benar-benar tahu cara menggunakannya.
Android

Jawaban:

12

Inilah solusi berbasis vektor. Saya belum mencobanya, tetapi tampaknya baik secara konseptual.

Teori

Saya kira Anda telah menyimpan bentuk sebagai segmen garis. Inilah huruf A yang diwakili dengan tiga segmen garis.

segmen garis mewakili huruf

Saya berasumsi bahwa jalur dalam gambar pengguna disimpan sebagai daftar poin.

Kami dapat "mengembang" segmen garis tersebut untuk memungkinkan margin kesalahan saat memeriksa kedekatan : apakah jalur yang ditarik pengguna berada di dekat margin kesalahan garis yang benar.

segmen garis "meningkat" jalur yang ditarik pengguna di atas huruf dengan margin kesalahan

Namun, itu saja tidak cukup. Kami juga harus memeriksa cakupan : apakah gambar pengguna "menutupi" sebagian besar dari bentuk. Gambar-gambar ini buruk, karena meskipun sesuai dengan margin kesalahan, mereka kehilangan beberapa bagian surat:

gambar yang buruk

Jika kami memeriksa kedua hal itu, kami dapat memperkirakan apakah hasil undian pemain bagus.

Penerapan

Memeriksa kedekatan hanya berarti untuk setiap titik jalur pengguna, menemukan jarak antara itu dan setiap baris yang membentuk huruf, mengambil yang terendah dan memeriksa itu kurang dari margin kesalahan.

Memeriksa cakupan lebih rumit, tetapi Anda bisa mendapatkan perkiraan yang sangat baik dengan matematika vektor jika untuk setiap segmen garis, Anda menemukan jalur yang ditarik pengguna terdekat (hijau) dan memproyeksikan bagiannya (hijau gelap) ke segmen garis itu (hitam), kemudian periksa seberapa baik vektor yang diproyeksikan (biru) menutupnya:

cakupan-periksa dengan proyeksi vektor

Untuk memproyeksikan vektor ake vektor lain b, lakukan

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

di mana dotProductmenghitung titik produk dari dua vektor dan seperti lengthSquaredapa suaranya. Pada dasarnya, ini menemukan nilai skalar dari berapa banyak aberjalan dalam barah dan dikalikan bdengan itu untuk mendapatkan vektor dalam arah yang sama. ( Tutorial pendeteksian tabrakan Metanet Software A memiliki visualisasi yang bagus tentang ini dalam Lampiran A proyeksi § .)

Arah vektor yang diproyeksikan mungkin sebenarnya tidak penting. Jika Anda hanya menjumlahkan panjang dari vektor yang diproyeksikan dan membandingkannya dengan total panjang segmen garis, itu akan memberi tahu Anda apa bagian dari itu tercakup. (Kecuali dalam kasus aneh — lihat § Batasan di bawah).

Pada gambar di atas, jalan akan mencakup sekitar setengah dari segmen. Anda dapat memilih nilai toleransi apa pun yang Anda inginkan.

Keterbatasan

Huruf melengkung

Segmen baris kurang ideal: Banyak huruf melengkung! Bagaimana Anda mewakili 'P' atau 'O'?

Anda dapat menggunakan banyak segmen garis (mungkin dengan margin kesalahan lebih besar).

huruf P didekati dengan segmen garis huruf O didekati dengan segmen garis

Anda juga bisa mulai menggunakan kurva Bezier bukan garis untuk cocok lebih dekat, tetapi catatan bahwa menemukan titik terdekat pada Bezier adalah jauh lebih kompleks-seperti banyak operasi pengukuran lain.

Ketidakcocokan

Margin toleransi yang terlalu longgar untuk jarak dari garis dan cakupan surat itu bisa memiliki konsekuensi yang tidak diinginkan.

Misalnya, pemain mungkin mencoba menggambar huruf 'H' di sini.

sebuah huruf H yang secara keliru dikenali sebagai A

Loop dan tumpang tindih

loop dan tumpang tindih dalam (mungkin) surat yang dikenali

Loop atau tumpang tindih di jalur yang digambar pemain dapat mengakibatkan beberapa bagian dari gambar dihitung dua kali saat memproyeksikannya ke segmen garis terdekat.

Ini dapat dikerjakan dengan melakukan pemrosesan yang lebih bagus pada vektor yang diproyeksikan, mungkin menyimpan tepat di mana vektor yang diproyeksikan berada (menyimpan arah proyeksi juga, dan titik terdekat pada segmen garis ke titik pada garis yang dibuat pemain) , lalu menolak yang baru yang tumpang tindih.

Jika pemain menggambar jalur tunggal dan diproses mulai dari ujung yang ditandai dengan lingkaran biru, bagian hijau dari jalur itu akan diterima dan yang merah ditolak, karena proyeksi mereka akan tumpang tindih dengan beberapa bagian yang diproses sebelumnya.

menolak loop dan tumpang tindih

Implementasinya memiliki banyak seluk-beluk teknis yang mungkin masuk dalam pertanyaan yang berbeda.

Pemain petualang yang tidak terduga

Seorang pemain mungkin menggambar sesuatu yang aneh yang masih berlalu .

trolololol

Meskipun Anda bisa menyebutnya fitur! :)

Anko
sumber
terima kasih, apa yang kamu usulkan untuk tidak menggambar di luar surat itu?
Android
@Android Oranye "margin kesalahan" adalah untuk itu. Anda bisa menolak garis yang keluar dari mereka: seperti ini misalnya.
Anko
Yang saya inginkan adalah menjadikan surat itu sebagai SpriteBatch, maka satu-satunya area di mana saya dapat menggambar adalah kumpulan sprite itu, yang dapat berbentuk A atau B, X .... apakah ini mungkin? jika itu bagaimana saya bisa membuat tekstur seperti SpriteBatch? dan terima kasih sebelumnya.
Android
2

tl; dr Saya sarankan untuk membuat cat kuas pemain menjadi bidang 2d yang terlihat (atau tidak terlihat). Bedakan gambar yang dicat pengguna dengan yang asli (siluet yang diinginkan atau model 2d). Jika Anda ingin meningkatkan akurasi, buat garis pemandu dan sikat lebih sempit, agar lebih banyak ruang untuk kesalahan, buat sikat dan desain lebih tebal.

Jika tidak, Anda bisa mengukur jarak masing-masing (x, y) yang diklik / disentuh pengguna dari spline dengan menghitung titik ke jarak segmen. Kemudian Anda dapat meratakan jarak untuk menyusun ukuran akurasi dan efisiensi. Dibutuhkan lebih banyak pekerjaan untuk mendapatkan ukuran penyelesaian yang bermakna dan menyadari seberapa efektif kinerja pengguna.


Pertimbangan: Saya sarankan tidak melakukannya (memeriksa langsung jika suatu baris mengikuti jalur). Ini mungkin ide yang buruk. Sepertinya Anda ingin pengguna mengisi siluet. Path itu sendiri adalah spline (kerangka) yang mewakili siluet.

Jika Anda cukup membuat kuas para pemain menerapkan massa piksel monokrom berdenyut ke bidang 2d, Anda dapat menjalankan proses di latar belakang yang memeriksa berapa banyak piksel di dalam siluet dan berapa banyak dari mereka yang ada di luar. Ini dapat dengan mudah menghasilkan% dari keberhasilan, di mana berapa banyak% dari pola diisi adalah satu statistik yang menarik dan yang lain adalah berapa banyak% berada di luar batas model. Jika Anda memeriksa jarak sub-segmen, itu tidak terlalu akurat dari pekerjaan pengguna.

AturSams
sumber
1

Solusi terbaik tidak menggunakan grafik sama sekali, lakukan dengan matematika!

Anda dapat dengan mudah memahami seberapa jauh setiap titik (pengguna dicat) jauh dari segmen /programming/849211/shortest-distance-between-a-point-and-a---line-segment

Anda dapat menghitung kesalahan rata-rata, jadi ukur seberapa banyak pengguna yang benar.

Alexsey Shestacov
sumber
terima kasih, tetapi untuk apa huruf-huruf seperti "C" "O"? ... tidak ada jarak tetap antara titik-titik ..
Android
Anda dapat membuat "C" dan "O" dari 6-8 segmen garis, sama seperti yang lain, tetapi matematika akan sedikit berbeda, dalam hal pengukuran kesalahan
Alexsey Shestacov