Menambahkan Putaran Realistis
Langkah selanjutnya adalah menambahkan belokan realistis untuk unit kami, sehingga mereka tampaknya tidak mengubah arah secara tiba-tiba setiap kali mereka perlu berbelok. Solusi sederhana melibatkan penggunaan spline untuk menghaluskan sudut-sudut yang tiba-tiba menjadi belokan. Sementara ini memecahkan beberapa masalah estetika, masih menghasilkan gerakan fisik yang sangat tidak realistis untuk sebagian besar unit. Misalnya, itu mungkin mengubah tikungan mendadak dari tangki menjadi kurva yang ketat, tetapi belokan yang melengkung masih akan jauh lebih ketat daripada yang bisa dilakukan oleh tangki.
Untuk solusi yang lebih baik, hal pertama yang perlu kita ketahui adalah radius belokan untuk unit kita. Radius putar adalah konsep yang cukup sederhana: jika Anda berada di tempat parkir besar di mobil Anda, dan putar roda ke kiri sejauh mungkin dan lanjutkan mengemudi dalam lingkaran, jari-jari lingkaran itu adalah giliran Anda radius. Jari-jari belok Volkswagen Beetle akan jauh lebih kecil dari pada SUV besar, dan jari-jari belok seseorang akan jauh lebih kecil dari pada beruang besar yang bergerak-gerak.
Katakanlah Anda berada pada suatu titik (asal) dan menunjuk ke arah tertentu, dan Anda perlu menuju ke titik lain (tujuan), seperti yang diilustrasikan dalam Gambar 5. Jalur terpendek ditemukan baik dengan berbelok ke kiri sejauh Anda bisa, berputar-putar sampai Anda langsung menunjuk ke tujuan, dan kemudian melanjutkan ke depan, atau dengan berbelok ke kanan dan melakukan hal yang sama.
Pada Gambar 5, rute terpendek jelas merupakan garis hijau di bagian bawah. Jalur ini ternyata cukup mudah untuk dihitung karena beberapa hubungan geometris, diilustrasikan dalam Gambar 6.
Pertama-tama kita menghitung lokasi titik P, yang merupakan pusat lingkaran putar kita, dan selalu radius r dari titik awal. Jika kita berbelok ke kanan dari arah awal kita, itu berarti P berada pada sudut (initial_direction - 90) dari titik asal, jadi:
angleToP = initial_direction - 90
P.x = Origin.x + r * cos(angleToP)
P.y = Origin.y + r * sin(angleToP)
Sekarang kita tahu lokasi titik pusat P, kita dapat menghitung jarak dari P ke tujuan, ditampilkan sebagai h pada diagram:
dx = Destination.x - P.x
dy = Destination.y - P.y
h = sqrt(dx*dx + dy*dy)
Pada titik ini kami juga ingin memeriksa bahwa tujuan tidak ada di dalam lingkaran, karena jika itu, kami tidak akan pernah bisa mencapainya:
if (h < r)
return false
Sekarang kita dapat menghitung panjang segmen d, karena kita sudah tahu panjang dua sisi lainnya dari segitiga siku-siku, yaitu h dan r. Kami juga dapat menentukan sudut dari hubungan segitiga-kanan:
d = sqrt(h*h - r*r)
theta = arccos(r / h)
Akhirnya, untuk mengetahui titik Q di mana untuk meninggalkan lingkaran dan mulai pada garis lurus, kita perlu mengetahui sudut total +, dan mudah ditentukan sebagai sudut dari P ke tujuan:
phi = arctan(dy / dx) [offset to the correct quadrant]
Q.x = P.x + r * cos(phi + theta)
Q.y = P.y + r * sin(phi + theta)
Perhitungan di atas mewakili jalur belok kanan. Path sebelah kiri dapat dihitung dengan cara yang persis sama, kecuali bahwa kita menambahkan 90 ke initial_direction untuk menghitung angleToP, dan kemudian kita gunakan - alih-alih +. Setelah menghitung keduanya, kita cukup melihat jalur mana yang lebih pendek dan menggunakannya.
Dalam penerapan algoritma ini dan yang mengikuti, kami menggunakan struktur data yang menyimpan hingga empat "segmen garis" yang berbeda, masing-masing lurus atau melengkung. Untuk jalur lengkung yang dijelaskan di sini, hanya ada dua segmen yang digunakan: busur yang diikuti oleh garis lurus. Struktur data berisi anggota yang menentukan apakah segmen itu busur atau garis lurus, panjang segmen, dan posisi awal. Jika segmen adalah garis lurus, struktur data juga menentukan sudutnya; untuk busur, ini menentukan pusat lingkaran, sudut awal pada lingkaran, dan total radian yang tercakup oleh busur.
Setelah kami menghitung jalur lengkung yang diperlukan untuk mencapai antara dua titik, kami dapat dengan mudah menghitung posisi dan arah kami pada waktu tertentu, seperti yang ditunjukkan pada Listing 2.
DAFTAR 2. Menghitung posisi dan orientasi pada waktu tertentu.
distance = unit_speed * elapsed_time
loop i = 0 to 3:
if (distance < LineSegment[i].length)
// Unit is somewhere on this line segment
if LineSegment[i] is an arc
//determine current angle on arc (theta) by adding or
//subtracting (distance / r) to the starting angle
//depending on whether turning to the left or right
position.x = LineSegment[i].center.x + r*cos(theta)
position.y = LineSegment[i].center.y + r*sin(theta)
//determine current direction (direction) by adding or
//subtracting 90 to theta, depending on left/right
else
position.x = LineSegment[i].start.x
+ distance * cos(LineSegment[i].line_angle)
position.y = LineSegment[i].start.y
+ distance * sin(LineSegment[i].line_angle)
direction = theta
break out of loop
else
distance = distance - LineSegment[i].length