Bagaimana saya bisa mencegat objek dengan gerakan memutar


23

Saya membuat game ruang 2d dan perlu membuat pesawat ruang angkasa mencegat planet. Saya memiliki kode kerja untuk penyadapan garis lurus tetapi tidak tahu bagaimana cara menghitung lokasi planet dalam orbit melingkar.

Permainan ini tidak akurat secara ilmiah sehingga saya tidak khawatir tentang inersia, gravitasi, orbit elips, dll.

Saya tahu lokasi dan kecepatan pesawat ruang angkasa dan juga orbit planet (Radius) dan kecepatan

masukkan deskripsi gambar di sini


1
Tidak, saya mencoba menghitung sudut yang harus dipindahkan kapal untuk mencegat planet ini.
Ausa

4
Ini mungkin akan bekerja lebih baik di math.stackexchange.com ..
Jari Komppa

2
Apakah kapal Anda dapat mengubah kecepatan dan arah, atau apakah itu konstan? Juga, pertanyaan tentang menghindari misil mengelilingi target mungkin bisa membantu.
thegrinner

4
Untuk memperjelas, apakah situasinya? diberikan untuk planet ini: pusat orbit, jari-jari orbit, kecepatan sudut, lokasi saat ini; untuk kapal : lokasi saat ini, kecepatan saat ini; tentukan arah pergerakan kapal untuk mencegat planet
AakashM

6
Sebagai catatan sejarah yang menarik: planet-planet biasanya berputar dalam arah yang sama dengan orbitnya, yang karenanya juga berlawanan arah jarum jam seperti yang terlihat dari atas belahan bumi utara. Dari fakta ini kita dapat menyimpulkan bahwa jam matahari ditemukan di belahan bumi utara . Jika jam matahari ditemukan di belahan bumi selatan maka searah jarum jam akan menjadi cara lain .
Eric Lippert

Jawaban:


3

Solusi analitik untuk ini sulit, tetapi kita dapat menggunakan pencarian biner untuk menemukan solusi dalam akurasi yang diperlukan.

Kapal dapat mencapai titik terdekat di orbit dalam waktu t_min :

shipOrbitRadius = (ship.position - planet.orbitCenter).length;
shortestDistance = abs(shipOrbitRadius - planet.orbitRadius);
t_min = shortestDistance/ship.maxSpeed;

Kapal dapat mencapai titik APAPUN di orbit dalam waktu kurang dari atau sama dengan t_max :

(Di sini, untuk kesederhanaan, saya menganggap kapal dapat mengemudi melalui matahari. Jika Anda ingin menghindari ini, Anda perlu beralih ke jalur non-garis lurus untuk setidaknya beberapa kasus. "Lingkaran ciuman" mungkin terlihat bagus dan orbital mekanika-y, tanpa mengubah algoritme lebih dari faktor konstan)

if(shipOrbitRadius > planet.orbitRadius)
{
   t_max = planet.orbitRadius * 2/ship.maxSpeed + t_min;
}
else
{
   t_max = planet.orbitRadius * 2/ship.maxSpeed - t_min;
}

Jika periode orbit kita pendek, kita mungkin dapat meningkatkan batas atas ini dengan memilih t_maxuntuk menjadi yang pertama kalinya setelah t_minitu, planet ini melakukan pendekatan terdekat dengan posisi awal kapal. Ambil yang mana dari kedua nilai t_maxini yang lebih kecil. Lihat jawaban ini nanti untuk penjelasan mengapa ini bekerja.

Sekarang kita dapat menggunakan pencarian biner antara ekstrem ini, t_min dan t_max . Kami akan mencari nilai-t yang membuat kesalahan mendekati nol:

error = (planet.positionAtTime(t) - ship.position).squareMagnitude/(ship.maxSpeed*ship.maxSpeed) - t*t;

(Menggunakan konstruksi ini, error @ t_min> = 0 dan error @ t_max <= 0, jadi harus ada setidaknya satu intersep dengan error = 0 untuk nilai-t di antaranya)

di mana, untuk kelengkapan, fungsi posisi adalah seperti ...

Vector2 Planet.positionAtTime(float t)
{
  angle = atan2(startPosition - orbitCenter) + t * orbitalSpeedInRadians;
  return new Vector2(cos(angle), sin(angle)) * orbitRadius + orbitCenter;
}

Perhatikan bahwa jika periode orbit planet ini sangat singkat dibandingkan dengan kecepatan kapal, fungsi kesalahan ini dapat mengubah tanda beberapa kali selama rentang waktu dari t_min ke t_max. Pantau terus pasangan + ve & -ve yang paling awal yang Anda temui, dan lanjutkan mencari di antara mereka sampai kesalahannya cukup dekat ke nol ("cukup dekat" peka terhadap unit dan konteks gameplay Anda. Kuadrat dari setengah durasi bingkai mungkin bekerja dengan baik - yang memastikan intersepsi akurat dalam bingkai)

Setelah Anda memiliki t meminimalkan meminimalkan kesalahan yang baik, Anda bisa mengarahkan kapal di planet.positionAtTime (t) dan pergi kecepatan penuh, yakin bahwa planet akan mencapai titik itu pada saat yang sama Anda lakukan.

Anda selalu dapat menemukan solusi dalam iterasi Log_2 ((2 * orbitRadius / ship.maxSpeed) / errorThreshold). Jadi misalnya, jika kapal saya dapat melintasi orbit dalam 60 frame, dan saya ingin intersep akurat dalam satu frame, saya akan membutuhkan sekitar 6 iterasi.


1
Banyak jawaban bagus di sini, juga beberapa opsi alternatif yang menarik tetapi dari apa yang sudah saya miliki, solusi ini terlihat yang terbaik untuk contoh saya. Saya telah membuat demo JavaScript kecil dari hasil saya. Demo
Ausa

11

Jangan terlalu memperumit ini. Ini bukan solusi "sempurna" tetapi harus bekerja untuk sebagian besar permainan dan ketidaksempurnaan apa pun harus tidak terlihat oleh pemain.

if(!OldTargetPoint)
  TargetPoint = PlanetPosition;
else
  TargetPoint = OldTargetPoint;
Distance = CurPosition - TargetPoint;
TimeNeeded = Distance / Speed;
TargetPoint = PlanetPositionInFuture(TimeNeeded);
SteerTowards(TargetPoint);
[...repeat this every AI update, for example every second...]
  1. Hitung waktu yang dibutuhkan untuk mencapai titik target.
  2. Hitung pada posisi apa planet ini akan berada pada waktu yang dihitung.
  3. Bergerak menuju titik terhitung.
  4. Ulangi

Ini berfungsi karena semakin dekat wahana antariksa semakin rendah kesalahannya. Jadi perhitungannya menjadi lebih stabil dari waktu ke waktu.

Kesalahannya adalah perbedaan antara waktu yang dibutuhkan yang dihitung untuk mencapai planet ini (TimeNeeded) dan waktu aktual yang dibutuhkan untuk mencapai planet ini (setelah memperhitungkan TargetPoint baru).


1
Anda mungkin ingin menjalankan 2 iterasi ini ketika memulai kursus penyadapan, jika tidak, Anda mungkin melihat kapal berkedip di antara dua arah sesaat (tebakan kedua bisa jauh lebih baik dari yang pertama, dan menghasilkan heading yang sangat berbeda - terutama jika kapal dekat atau di dalam orbit planet)
DMGregory

1
@DMGregory Oh! Kami hanya bisa mengambil Posisi Planet saat ini daripada Orbit Center sebagai titik awal. Ketika kita dekat itu jauh lebih dekat, jika kita jauh tidak masalah.
API-Beast

Perlu juga dicatat bahwa ini bekerja paling baik ketika planet ini bergerak lambat dibandingkan dengan kapal. Jika kecepatan planet ini sebanding dengan atau lebih besar dari kecepatan kapal, Anda mungkin melihat osilasi di jalur kapal. Pada rasio kecepatan patologis, kapal dapat mengejar planet ini selamanya pada orbit konsentris. Jika planet Anda cepat dan Anda melihat hal ini terjadi, Anda mungkin ingin merencanakan seluruh jalur intersep Anda di muka daripada melakukan iterasi di tengah penerbangan.
DMGregory

3

Mari kita mulai dengan melihat pada matematika di balik masalah.

Langkah 1:

Menemukan persimpangan antara garis dan bentuk hanyalah masalah memasukkan persamaan garis dalam persamaan bentuk, yang merupakan lingkaran dalam kasus ini.

Garis berpotongan dengan lingkaran

Ambil lingkaran dengan pusat c dan jari-jari r . Titik p ada di lingkaran jika

|pc|2=r2

Dengan garis yang dinyatakan sebagai p=p0+μv (di mana v adalah vektor, http://en.wikipedia.org/wiki/Euclidean_vector ), Anda memasukkan garis ke rumus lingkaran dan mendapatkan

|p0+μvc|2=r2

Jarak kuadrat dapat ditulis ulang sebagai produk titik ( http://en.wikipedia.org/wiki/Dot_product ).

(p0+μvc)(p0+μvc)=r2

Tentukan a=cp0 dan tulis ulang menjadi (μva)(μva)=r2

Lakukan produk titik dan kami mendapatkan μ2(vv)2μ(av)+aa=r2

Asumsikan bahwa |v|=1 dan sudah

μ22μ(av)+|a|2r2=0

yang merupakan persamaan kuadrat sederhana, dan kami tiba di solusinya

μ=av+sqrt((av)2a2r2)

Jika μ<0 , garis kapal dalam kasing Anda tidak berpotongan dengan orbit planet.

Jika μ=0 , garis kapal hanya akan menyentuh lingkaran di satu titik.

Kalau tidak, ini memberi kita dua nilai μ yang sesuai dengan dua titik di orbit!

Langkah 2:

μ

Apa yang bisa kita lakukan dengan ini? Nah, kita sekarang tahu jarak yang harus ditempuh kapal dan titik mana yang akan berakhir!

p=p0+μvμv

Sekarang, yang harus dilakukan adalah menghitung di mana planet ini seharusnya berada ketika kapal mulai mendekati orbitnya. Ini mudah dihitung dengan apa yang disebut dengan koodinat Polar ( http://mathworld.wolfram.com/PolarCoordinates.html )

x=c+rcos(θ)

y=c+rsin(θ)

tangularVelocity

Ringkasan

Pilih garis untuk kapal Anda, dan jalankan matematika untuk melihat apakah itu bertabrakan dengan orbit planet. Jika ya, hitung waktu yang diperlukan untuk sampai ke titik itu. Gunakan waktu ini untuk kembali dalam orbit dari titik ini dengan planet ini untuk menghitung di mana planet itu seharusnya ketika kapal mulai bergerak.


8
Analisis yang bagus, tetapi tampaknya tidak menjawab pertanyaan (diklarifikasi dalam komentar): "Tidak, saya mencoba menghitung sudut yang harus dipindahkan kapal untuk mencegat planet ini." Anda mengambil sudut kapal sebagai yang diberikan dan menghitung posisi planet, bukan sebaliknya.
Chaosed0

4
Tidak akan meng-downvote ini karena ini adalah analisis yang berguna, tapi saya setuju dengan @ Chaosed0 bahwa itu tidak menjawab pertanyaan. Dalam ringkasan Anda, Anda mengatakan "Pilih garis untuk kapal Anda ..." tetapi memilih garis itu adalah bagian yang sulit.
Drake

1

Berikut adalah dua solusi "keluar dari kotak".

Pertanyaannya adalah: mengingat bahwa kapal bergerak dalam garis lurus pada kecepatan tertentu, dan planet bergerak dalam lingkaran dengan jari-jari tertentu pada kecepatan sudut tertentu, dan posisi awal planet dan kapal, menentukan arah vektor dari kapal itu. garis lurus harus berada di plot plot intersep.

Solusi satu: Tolak premis pertanyaan. Kuantitas yang "dapat diabaikan" dalam pertanyaan adalah sudut. Sebaliknya, perbaiki itu. Arahkan kapal langsung ke pusat orbit.

  • Hitung posisi kapal yang akan menghadapi planet ini; itu mudah.
  • Hitung jarak dari kapal ke posisi intersepsi; juga mudah.
  • Hitung waktu yang diperlukan hingga planet berikutnya mencapai posisi intersep. Mudah.
  • Bagilah jarak dari kapal ke intersep pada saat itu sampai planet mencapai intersep.
  • Jika itu lebih kecil dari atau sama dengan kecepatan maksimum kapal, Anda selesai. Atur kapal bergerak dengan kecepatan itu langsung menuju matahari.
  • Jika tidak, tambahkan periode orbital planet ke waktu dan coba lagi. Terus lakukan itu sampai Anda mendapatkan kecepatan yang masuk akal untuk kapal.

Solusi dua: Jangan lakukan itu dengan autopilot sama sekali. Buat gim mini di mana pemain harus menggunakan pendorong untuk mendekati planet ini, dan jika mereka memukulnya dengan kecepatan relatif terlalu tinggi, mereka meledak, tetapi bahan bakarnya juga terbatas. Buat pemain belajar bagaimana memecahkan masalah intersepsi!


1

(x,y,t)

tv=x2+y2

v

Posisi planet dalam ruang dan waktu dapat ditentukan oleh misalnya

x=x0+rcos(wu+a)y=y0+rsin(wu+a)t=u

u0wau

uv=(x0+rcos(wu+a))2+(y0+rsin(wu+a))2u2v2=(x0+rcos(wu+a))2+(y0+rsin(wu+a))2u2v2=x02+y02+r2+2x0rcos(wu+a)+2y0rsin(wu+a)

Persamaan ini perlu diselesaikan secara numerik. Mungkin ada banyak solusi. Dengan melihatnya, sepertinya selalu ada solusinya


1

Inilah bagian dari solusi. Saya tidak bisa menyelesaikannya tepat waktu. Saya akan coba lagi nanti.

Jika saya mengerti dengan benar, Anda memiliki posisi & kecepatan planet, serta posisi dan kecepatan kapal. Anda ingin mendapatkan arah pergerakan kapal. Saya mengasumsikan kecepatan kapal dan planet konstan. Saya juga berasumsi, tanpa kehilangan sifat umum, bahwa kapal berada pada (0,0); untuk melakukan ini, kurangi posisi kapal dari planet ini, dan tambahkan posisi kapal kembali ke hasil operasi yang dijelaskan di bawah ini.

Sayangnya, tanpa lateks , saya tidak dapat memformat jawaban ini dengan baik, tetapi kami akan berusaha melakukannya. Membiarkan:

  • s_s = kecepatan kapal (s_s.x, s_s.y, juga)
  • s_a= bantalan kapal (sudut pergerakan, apa yang ingin kita hitung )
  • p_p = posisi awal planet, koordinat global
  • p_r = jarak planet (jari-jari) dari pusat orbit, dapat diturunkan dari p_p
  • p_a = sudut awal planet dalam radian, relatif terhadap pusat orbit
  • p_s = kecepatan sudut planet (rad / detik)
  • t = waktu untuk bertabrakan (ini ternyata menjadi sesuatu yang harus kita hitung juga)

Inilah persamaan untuk posisi dua badan, yang dipecah menjadi beberapa komponen:

ship.x = s_s.x * t * cos(s_a)
ship.y = s_s.y * t * sin(s_a)

planet.x = p_r * cos(p_a + p_s * t) + p_p.x
planet.y = p_r * sin(p_a + p_s * t) + p_p.y

Karena kami ingin ship.x = planet.xdan ship.y = planet.ydalam beberapa saat t, kami memperoleh persamaan ini ( ykasingnya hampir simetris):

   s_s.x * t * cos(s_a) = p_r * cos(p_a + p_s * t) + p_p.x
   s_s.y * t * sin(s_a) = p_r * sin(p_a + p_s * t) + p_p.y

Memecahkan persamaan teratas untuk s_a:

   s_s.x * t * cos(s_a) = p_r * cos(p_a + p_s * t) + p_p.x
=> s_a = arccos((p_r * cos(p_a + p_s * t) + p_p.x) / (s_s.x * t))

Mengganti ini menjadi persamaan kedua menghasilkan persamaan yang cukup menakutkan yang Wolfram alpha tidak akan pecahkan untuk saya . Mungkin ada cara yang lebih baik untuk melakukan ini tanpa melibatkan koordinat kutub. Jika ada yang ingin mencoba metode ini, Anda dapat melakukannya; Saya sudah membuat ini sebagai wiki. Kalau tidak, Anda mungkin ingin membawa ini ke Math StackExchange .


2
Saya ingin TeX diaktifkan untuk situs ini. Ini akan membuat beberapa hal yang berhubungan dengan grafis (misalnya vektor, matriks, angka empat ..) lebih mudah untuk diwakili.
mvw

0

Saya akan memperbaiki lokasi di mana untuk mencegat (menggesek lingkaran, di sisi "keluar" dari orbit.)

Sekarang Anda hanya perlu menyesuaikan kecepatan pesawat ruang angkasa sehingga planet dan kapal mencapai titik itu pada saat yang sama.

Perhatikan bahwa pertemuan bisa setelah N lebih banyak orbit, tergantung seberapa jauh kapal itu, dan seberapa cepat planet ini mengorbit bintang.

Pilih N yang tepat waktu, datang paling dekat dengan durasi perjalanan kapal dengan kecepatan saat ini.

Kemudian percepat atau perlambat kapal untuk mencocokkan stempel waktu dengan tepat untuk N orbit tersebut.

Dalam semua ini, jalan yang sebenarnya sudah diketahui! Hanya bukan kecepatannya.


Ini bisa memberikan perjalanan panjang yang tidak perlu. Katakanlah kita diposisikan sedemikian rupa sehingga planet ini menuju ke arah kita dan kita benar-benar dapat mencapai titik penggembalaan "masuk" pada saat yang sama dengan planet itu. Jika kita hanya melihat titik penggembalaan "keluar", maka kita bisa menghabiskan setengah setengah tahun dalam perjalanan!
DMGregory

Benar ... tergantung pada kecepatan orbit. Tapi itu juga meminimalkan kecepatan delta jika Anda selalu merumput saat keluar. Pada "masuk" Anda bisa terbakar di atmosfer, sedangkan di "keluar" Anda lebih mungkin dicocokkan. @DMGregory
Bram
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.