Atış Hareketi - Ok


13

Bir 2D oyunda, sadece uçuşta bir okun yörüngesini çizmek istiyorum. Aşağıdaki kodla, yörünge (parabol) doğru görünüyor, ancak açı (veya dönüş) veya ok değil.

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);

Neyi kaçırıyorum? Teşekkürler.


3
Ekran görüntüsü yardımcı olabilir
doppelgreener

Yanıtlar:


10

Arctanhhiperbolik eğri için teğet verir! Bildiğim kadarıyla parabolünüz hiperbol değil.

Ancak iyi haberlerimiz var: parabolünüz için tanjant bulmak daha kolaydır. Denklemi

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

Nerede senin launchVelocity. Şimdi okunuzun eğimi:

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

İsterseniz Arctanşimdi güvenlik kullanabilirsiniz .

Fizik hakkında bazı ek bilgiler:

Simüle ettiğiniz yaklaşık yörünge, okunuzun kütle merkezi için geçerlidir. "Pozisyon" (x, y) dediğinizde, kütle merkezi konumundan bahsediyorsunuz. Bir ok için kütle merkezi orta noktadan biraz ileri doğrudur ve oku çizecekseniz bunu dikkate almalısınız.

Okun atalet momentumunu düşünmediğinizi (dev bir balista fırlatırsanız çok değişebilir) ve okun akışkan dinamiğini düşünmediğinizi unutmayın: yay oku uçuşu parabolik bir yol izlemez!


Teşekkürler Fxlll. Bir ok fiziğine uygulanan formülleri nereden bulabilirim?
Martin

Demek istediğim:! [& Part; y / & part; x = g / (2s & sup2;) & middot; x + 1] [2] ama her durumda aşağıda daha iyi bir yaklaşım öneriyorum. Bir kere, x ve y bileşenlerini ayırma hakkında açıklama yapmadınız, bu yüzden bu, keyfi bir 45 derecelik açıya sabit olarak kodlanır, launchVelocity gerçekten başlatılmazVelocity, ancak hem x hem de y'deki bileşen
Dov

Atalet momentlerini kolaylıkla hesaplayabilirsiniz. Bunlar çubuklar için iki, biri kütle merkezi etrafındaki dönüş için ve diğeri çubuğun ekseni etrafındaki dönüş için. Süperpozisyon prensibi atalet momentleri için geçerlidir, böylece ok üç kısma ayrılabilir: tüyler, gövde ve uç.
FxIII

1
Sorun, tek momentumun hesaplanması kolay olması, açı değişiminden kaynaklanmaktadır (iki sabit parabolün sadece sabit bir terim kaldığını görebilirsiniz). Diğerine arka tüy nedeniyle eğirme neden olur. Burada tüy sürüklenmeleri ve sürtünme hem kinetik enerjiyi dönmeye çevirir, oku yavaşlatır, ancak jiroskopik etki ekler. Bu yörüngeyi etkiler ve modellemesi oldukça zordur
FxIII

Her neyse, bir tüy ayarı verilen hız ile momentumu ilişkilendirebilirseniz, tüm kapsamlı entegrasyon hesaplanabilir, ancak hareket denklemleri için kapalı bir forma sahip olabileceğinizden emin değilim (yani bir entegrasyon algoritması alabilirsiniz, ancak bir parametrik değil denklem).
FxIII

4

Okun açısını herhangi bir zamanda istersiniz. Bir açıyı hesaplamak için bir teğet olduğunu hatırladınız. Ancak burada düşünceniz yanlış gitmeye başladı:

  1. İstediğiniz şey delta y / delta x, çünkü eğim değişim oranıdır (diğer cevaplardan birinde belirtilmiştir). X'in dx değil, herhangi bir zamanda bulunduğunuz konum olduğunu unutmayın.

Tamam, eğer hava sürtünmesini ihmal ederseniz, o zaman okun x hızı sabittir.

İlk olarak, hızı x ve y bileşenlerine ayırın. 45 derecelik veya 60 derecelik bir açıda çekim yapıyor olabilirsiniz. Bu yüzden launchVelocity ve bir açıya ihtiyacınız var, bu bir skaler değil.

İkincisi, her şeyi float değil, çift olarak hesaplayın. Roundoff hatasının sizi ne zaman öldürmeyeceğini bilmek için sayısal olarak sofistike değilsiniz, bu yüzden denemeyin. Her durumda büyük bir zaman tasarrufu değildir.

Üçüncüsü, Math.pow'u kullanma, yavaş ve tamsayı güçleri için çarpma kadar doğru değil. Ayrıca Horner'ın formunu kullanarak çok zaman kazanabilirsiniz (aşağıya bakın)

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

Performans için çaresizseniz, 0.5 * g'yi önceden hesaplayabilirsiniz, ancak yukarıdaki kod çok çılgın bir şey yapmadan sizi% 90 oranında oraya götürecektir. Benchmark bunu 10 milyon kez yapıyorsa, kuşkusuz çok büyük bir zaman değil, yüzde olarak oldukça büyük - kütüphaneler Java'da çok yavaş

Yani, okun gitmesi gereken açıyı istiyorsanız, istediğiniz şey

atan(dy/dx)

Ve bu durumda, dx sabit olduğu için bu işe yarar. Ancak genel olarak, dx sıfır olabilir, bu nedenle genellikle kullanmak istersiniz:

atan2(dy, dx)

bu iş için özel olarak tasarlanmış bir işlevdir.

Ama dediğim gibi, Java'daki kütüphane işlevleri korkunç derecede yavaş ve bu durumda yukarıdaki @FxIII tarafından belirtildiği gibi bunu yapmanın daha iyi bir yolu var.

Yatay hız her zaman v0x ise ve dikey hız ise:

double vy = v0y - 0.5 * g * time;

o zaman deltalarınız: vx, vy

Açıya ihtiyacınız yok. Bir ok çizmek istiyorsanız, nominal olarak şöyle bir şey kullanın:

çizim (x, y, x + vx, y + vy);

Ne çizdiğinizi bilmiyorum, bu yüzden döndürmek için açıya ihtiyacınız varsa (JOGL kullandığınız gibi), o zaman açıyı kullanın.

Açıyı tekrar dereceye çevirmek için opengl kullanıyorsanız unutmayınız, çünkü ATAN2 radyan döndürür:

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

2

Tanh () (hiperbolik tanjant ) parametre olarak bir açı alır, ancak kenarların oranını beslediniz.

Gerçekten istediğiniz şey , kenarların oranını bir parametre olarak alan ve açıyı döndüren hiperbolik arktanjant kullanmaktır . (Buna isim vermek "atanh", "atanh2", "arctanh" veya başka bir şey olabilir; farklı matematik kütüphaneleri arasında çok farklılıklar var gibi görünüyor)


Hayır hiperbolik bir şey istemiyorsun
Dov

Gah, kesinlikle haklısın. Hemen "temel trigonometri kullanımı" hatasını aldım ve kullandığı işlevin yaklaşımının geri kalanı için tamamen yanlış olduğunu kaçırdım.
Trevor Powell

Tan () bir açı alır. Atan üçgen yan oran (sin / cos) alır.
3Dave
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.