Proyeksi Gerak - Panah

13

Dalam game 2D, saya hanya ingin menggambar lintasan panah dalam penerbangan. Dengan kode di bawah ini, lintasan (parabola) terlihat benar, tetapi sudut (atau rotasi) atau panahnya tidak.

float g = -9.8f;
float x = (launchVelocity * time);
float y = (launchVelocity * time) + (0.5f * g * (float)Math.Pow(time, 2));
float angle = (float)Math.Tanh(y / x);

Apa yang saya lewatkan? Terima kasih.

Martin
sumber
3
Tangkapan layar dapat membantu
doppelgreener

Jawaban:

10

Arctanhmemberi Anda garis singgung untuk kurva hiperbolik! Sejauh yang saya tahu parabola Anda bukan hiperbola.

Tapi kami punya kabar baik: menemukan garis singgung untuk parabola Anda lebih mudah. Persamaannya adalah

x = s · t => t = x / s; y = s · t + g / 2 · t² => y = x + g / 2 · x² / s²

Di mana milikmu launchVelocity. Sekarang kemiringan panah Anda adalah:

∂y / ∂y = g / (2s²) · x + 1

Anda dapat menggunakan keamanan Arctansekarang jika Anda mau.

Beberapa info tambahan tentang fisika:

Perkiraan lintasan yang Anda simulasikan berlaku untuk pusat massa panah Anda. Ketika Anda mengatakan "posisi" (x, y) Anda berbicara tentang posisi pusat massa. Pusat massa untuk panah sedikit maju dari titik tengah dan Anda harus memperhitungkannya jika Anda akan menggambar panah.

Ingatlah bahwa Anda tidak mempertimbangkan momentum inersia panah (yang dapat sangat bervariasi jika Anda menembakkan ballista raksasa) dan Anda tidak mempertimbangkan dinamika fluida panah: penerbangan panah tidak akan mengikuti jalur parabola!

FxIII
sumber
Terima kasih Fxlll. Adakah ide di mana saya bisa mendapatkan formula yang berlaku untuk fisik panah?
Martin
Saya pikir maksud Anda:! [& Part; y / & part; x = g / (2s & sup2;) & middot; x +1) [2] tetapi bagaimanapun saya pikir saya merekomendasikan pendekatan yang lebih baik di bawah ini. Untuk satu hal, Anda tidak menjelaskan tentang memisahkan komponen x dan y, jadi ini hardcoded ke sudut 45 derajat sewenang-wenang, dengan launchVelocity tidak benar-benar launchVelocity, tetapi komponen di kedua x dan y
Dov
Seseorang dapat menghitung momen inersia dengan mudah. Ini adalah dua untuk batang, satu untuk rotasi tentang pusat massanya dan yang lainnya untuk rotasi tentang sumbu batang. Prinsip superposisi berlaku untuk momen inersia sehingga panah dapat dibagi menjadi tiga bagian: bulu, tubuh dan ujung.
FxIII
1
Masalahnya adalah bahwa satu-satunya momentum yang mudah dihitung adalah momentum karena variasi sudut (Anda dapat melihat bahwa memperoleh dua kali parabola hanya dengan istilah yang tetap). Yang lain disebabkan oleh pemintalan karena bulu punggung. Di sini seret bulu dan gesekan terlibat, baik mengubah energi kinetik menjadi berputar, memperlambat panah tetapi menambahkan efek giroskopik. Ini memengaruhi lintasan dan cukup sulit untuk dimodelkan
FxIII
Lagi pula jika Anda dapat menghubungkan momentum dengan kecepatan yang diberikan pengaturan bulu, semua dapat dihitung integrasi menyeluruh tetapi saya tidak yakin Anda dapat memiliki bentuk tertutup untuk persamaan gerak (yaitu Anda bisa mendapatkan algoritma integrasi tetapi tidak parametrik persamaan).
FxIII
4

Anda ingin sudut panah pada suatu titik waktu. Anda ingat bahwa untuk menghitung sudut, ada garis singgung. Tapi di sinilah pemikiran Anda mulai salah:

  1. Yang Anda inginkan adalah delta y / delta x, karena slope adalah tingkat perubahan (disebutkan dalam salah satu jawaban lain). Perhatikan bahwa x hanya posisi di mana Anda berada kapan saja, bukan dx.

Ok, jadi jika Anda mengabaikan gesekan udara, maka kecepatan x panah adalah konstan.

Pertama, dekomposisi kecepatan menjadi komponen x dan y. Anda bisa memotret pada sudut 45 derajat atau 60 derajat. Jadi, Anda perlu launchVelocity dan sudut, itu bukan skalar.

Kedua, hitung semuanya sebagai ganda, bukan mengambang. Secara numerik Anda tidak cukup canggih untuk mengetahui kapan kesalahan pembulatan tidak akan membunuh Anda, jadi jangan coba-coba. Bagaimanapun, ini bukan penghemat waktu yang tepat.

Ketiga, jangan gunakan Math.pow, lambat dan tidak seakurat mengalikan untuk kekuatan integer. Anda juga dapat menghemat banyak waktu dengan menggunakan formulir Horner (lihat di bawah)

final double DEG2RAD = Math.PI/180;
double ang = launchAngle * DEG2RAD;
double v0x = launchVelocity * cos(ang); // initial velocity in x
double v0y = launchVelocity * sin(ang); // initial velocity in y

double x = (v0x * time);
// double y = (v0y * time) + (0.5 * g * (float)Math.Pow(time, 2));
double y = (0.5 * g * time + v0y) * time

Jika Anda sangat membutuhkan kinerja, Anda bahkan dapat melakukan precompute 0,5 * g, tetapi kode di atas akan membawa Anda 90% dari perjalanan ke sana tanpa melakukan sesuatu yang terlalu gila. Benchmark melakukan ini 10 juta kali jika Anda mau, ini memang diakui bukan jumlah yang besar, tetapi secara persentase itu cukup besar - perpustakaan sangat lambat di Jawa

Jadi, jika Anda ingin sudut di mana panah harus pergi, yang Anda inginkan adalah

atan(dy/dx)

Dan dalam hal ini, itu akan berhasil karena dx adalah konstanta. Tetapi secara umum, dx bisa menjadi nol, jadi Anda biasanya ingin menggunakan:

atan2(dy, dx)

yang merupakan fungsi yang dirancang khusus untuk pekerjaan ini.

Tapi seperti yang saya katakan, fungsi perpustakaan di Jawa sangat lambat, dan dalam hal ini ada cara yang lebih baik untuk melakukannya tanpa disinggung oleh @FxIII di atas.

Jika kecepatan horizontal selalu v0x, dan kecepatan vertikal adalah:

double vy = v0y - 0.5 * g * time;

maka delta Anda adalah: vx, vy

Anda tidak perlu sudut. Jika Anda ingin menggambar panah, gunakan sesuatu yang nominal seperti:

plot (x, y, x + vx, y + vy);

Saya tidak tahu apa yang Anda gambar, jadi jika Anda perlu sudut untuk memutarnya (seperti Anda menggunakan JOGL) maka tentu saja, gunakan sudutnya.

Jangan lupa jika Anda menggunakan opengl untuk mengubah sudut kembali menjadi derajat, karena ATAN2 mengembalikan radian:

final double RAD2DEG = 180 / Math.PI;
double ang = Math.atan2(vy,vx); // don't forget, vy first!!!
double deg = ang * RAD2DEG;
Dov
sumber
2

Tanh () ( garis singgung hiperbolik ) mengambil sudut sebagai parameter, tetapi Anda telah memberinya rasio sisi.

Yang Anda inginkan adalah menggunakan arctangent hiperbolik , yang menggunakan rasio sisi sebagai parameter, dan mengembalikan sudutnya. (Penamaan ini mungkin "atanh", "atanh2", "arctanh", atau sesuatu yang serupa; tampaknya sangat bervariasi antara perpustakaan matematika yang berbeda)

Trevor Powell
sumber
Tidak, Anda tidak ingin apa pun hiperbolik
Dov
Gah, kamu benar sekali. Saya segera mengetahui kesalahan "penggunaan trigonometri dasar", dan melewatkan bahwa fungsi yang ia gunakan benar-benar salah selama sisa pendekatannya.
Trevor Powell
Tan () mengambil sudut. Atan mengambil rasio sisi segitiga (sin / cos).
3Dave