( CAVEAT: Saya menggunakan dua pendekatan di sini: yang pertama mengambil d sebagai panjang busur, dan yang kedua menganggapnya sebagai panjang ortogonal. Kedua perkiraan ini harus baik untuk nilai relatif kecil dari d, tetapi mereka tidak memenuhi pertanyaan yang tepat seperti yang dijelaskan dalam komentar.)
Matematika tentang ini, untungnya, relatif mudah. Pertama-tama, kita dapat menemukan vektor relatif dari posisi tengah kita ke posisi kita saat ini:
deltaX = oX-cX;
deltaY = oY-cY;
Dan begitu kita memiliki vektor relatif ini, maka kita dapat mengetahui jari-jari lingkaran yang sedang kita kerjakan dengan menemukan panjangnya:
radius = sqrt(deltaX*deltaX+deltaY*deltaY);
Terlebih lagi, dari vektor relatif kita, kita dapat menemukan sudut yang tepat bahwa garis dari cX ke oX berada di:
curTheta = atan2(deltaX, deltaY);
Sekarang segalanya menjadi sedikit lebih rumit. Pertama-tama, pahami bahwa keliling lingkaran - yaitu, 'panjang busur' dari busur dengan ukuran sudut 2π - adalah 2πr. Secara umum, panjang busur dari busur dengan ukuran sudut θ sepanjang lingkaran jari-jari r hanya θr. Jika kita menggunakan d dalam diagram Anda sebagai panjang busur, dan karena kita tahu jari-jarinya, kita dapat menemukan perubahan dalam theta untuk membawa kita ke posisi baru dengan hanya membagi:
deltaTheta = d/radius; // treats d as a distance along the arc
Untuk kasus di mana d perlu jarak linear, hal-hal sedikit lebih rumit, tetapi untungnya tidak banyak. Di sana, d adalah satu sisi dari segitiga isoceles yang dua sisi lainnya adalah jari-jari lingkaran (dari cX / cY ke oX / oY dan aX / aY masing-masing), dan membagi dua segitiga isoceles ini memberi kita dua segitiga siku-siku, masing-masing memiliki d / 2 sebagai satu sisi dan jari-jari sebagai sisi miring; ini berarti bahwa sinus setengah sudut kita adalah (d / 2) / radius, dan sudut penuh hanya dua kali ini:
deltaTheta = 2*asin(d/(2*radius)); // treats d as a linear distance
Perhatikan bagaimana jika Anda mengeluarkan asin dari rumus ini, dan membatalkan 2s, ini akan sama dengan rumus terakhir; ini sama dengan mengatakan bahwa dosa (x) kira-kira x untuk nilai-nilai kecil x, yang merupakan perkiraan yang berguna untuk diketahui.
Sekarang kita dapat menemukan sudut baru dengan hanya menambahkan atau mengurangi:
newTheta = curTheta+deltaTheta; // This will take you to aX, aY. For bX/bY, use curTheta-deltaTheta
Setelah kami memiliki sudut baru, maka kami dapat menggunakan beberapa trigonometri dasar untuk menemukan vektor relatif kami yang diperbarui:
newDeltaX = radius*cos(newTheta);
newDeltaY = radius*sin(newTheta);
dan dari posisi tengah kami dan vektor relatif kami, kami dapat (akhirnya) menemukan titik target:
aX = cX+newDeltaX;
aY = cY+newDeltaY;
Sekarang, dengan semua ini, ada beberapa peringatan besar yang harus diperhatikan. Untuk satu, Anda akan melihat bahwa matematika ini sebagian besar adalah floating-point, dan sebenarnya hampir pasti; mencoba menggunakan metode ini untuk memperbarui dalam satu lingkaran dan kembali ke nilai integer pada setiap langkah dapat melakukan segalanya mulai dari membuat lingkaran Anda tidak tertutup (baik berputar ke dalam atau ke luar setiap kali Anda memutar lingkaran) untuk tidak memulainya di awal tempat! (Jika d Anda terlalu kecil, maka Anda mungkin menemukan bahwa versi bulat aX / aY atau bX / bY persis di mana posisi awal Anda oX / oY berada.) Untuk yang lain, ini sangat mahal, terutama untuk apa yang berusaha untuk melakukan; secara umum, jika Anda tahu karakter Anda akan bergerak dalam busur melingkar, Anda harus merencanakan seluruh busur di muka dan tidaktandai dari bingkai ke bingkai seperti ini, karena banyak perhitungan paling mahal di sini dapat dimuat di depan untuk mengurangi biaya. Cara lain yang bagus untuk memangkas biaya, jika Anda benar-benar ingin memperbarui secara bertahap seperti ini, adalah dengan tidak menggunakan trigonometri di tempat pertama; jika d kecil dan Anda tidak perlu tepat tetapi hanya sangat dekat, maka Anda dapat melakukan 'trik' dengan menambahkan vektor panjang d ke oX / oY, ortogonal ke vektor menuju pusat Anda (perhatikan bahwa a vektor orthogonal ke (dX, dY) diberikan oleh (-dY, dX)), dan kemudian mengecilkannya ke panjang yang tepat. Saya tidak akan menjelaskan kode ini selangkah demi selangkah, tetapi mudah-mudahan masuk akal mengingat apa yang telah Anda lihat sejauh ini. Perhatikan bahwa kita 'menyusutkan' vektor delta baru secara implisit pada langkah terakhir,
deltaX = oX-cX; deltaY = oY-cY;
radius = sqrt(deltaX*deltaX+deltaY*deltaY);
orthoX = -deltaY*d/radius;
orthoY = deltaX*d/radius;
newDeltaX = deltaX+orthoX; newDeltaY = deltaY+orthoY;
newLength = sqrt(newDeltaX*newDeltaX+newDeltaY*newDeltaY);
aX = cX+newDeltaX*radius/newLength; aY = cY+newDeltaY*radius/newLength;
d
jarak linear atau busur?