Vektörleri kullanarak gerçekçi araba hareketi yaratmak için arıyorum


12

Bunu nasıl yapacağım ve bunu buldum http://www.helixsoft.nl/articles/circle/sincos.htm Ben bir gitmek vardı ama gösterilen işlevlerin çoğu işe yaramadı sadece hatalar aldım çünkü yoktu. Cos ve günah fonksiyonlarına baktım ama bunları nasıl kullanacağımı veya vektörleri kullanarak araba hareketinin nasıl doğru çalışacağını anlamıyorum. Üzgünüm ne yapacağımdan emin değilim çünkü hiçbir kod var.

Herhangi bir yardım takdir.

DÜZENLE:

Oyunum için TL motorunu kullanmam gereken kısıtlamalar var, herhangi bir fizik motoru eklememe izin verilmiyor. C ++ ile programlanmalıdır. Sağladığım bağlantıda ne yapıldığını takip etmeye çalıştığım şeyin bir örneği.

if(myEngine->KeyHeld(Key_W))
    {
        length += carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_S))
    {
        length -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_A))
    {
        angle -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_D))
    {
        angle += carSpeedIncrement;
    }

    carVolocityX = cos(angle);
    carVolocityZ = cos(angle);

    car->MoveX(carVolocityX * frameTime);
    car->MoveZ(carVolocityZ * frameTime);

Direksiyon davranışları için bu siteye göz atın: red3d.com/cwr/steer
MichaelHouse

"Gerçekçi araba hareketi" tanımlamanız gerekiyor
Maik Semder

1
Sanırım açınız direksiyon simidinden geliyor olabilir. Uzunluk, hızınızın büyüklüğü olmalıdır. Geçen kod parçacığı satırları üzerinde bir şey olabilir Yani: carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);, bunun dışında, girişinizi ne anlatmak ve araba nasıl davranması gerektiğini lütfen. Şimdi, yer düzlemine yönelmeli, ama yine de, bu hiç de genel değil. Bizi sadece ham bir Euler entegrasyon adımı
yaptınız

Yanıtlar:


23

Oldukça iyi bir araba hareketi oluşturmak o kadar zor değil (ancak bu yazı oldukça uzun olacak). Aracın fiziksel olarak mantıklı hareket etmesini sağlamak için birkaç temel kuvveti "simüle etmelisiniz".

(Tüm kod örnekleri sahte koddur.)

Hızlanma

İlk olarak, hızlanmaya ihtiyacınız olacak. Aşağıdaki satır kadar basit bir şey:

acceleration_vector = forward_vector * acceleration_input * acceleration_factor
  • forward_vector - Araba ile aynı yönü gösteren bir vektör.
  • acceleration_input - Giriş [-1, 1] aralığında olmalıdır.
  • acceleration_factor - Hızlanmanın değeri (piksel / saniye ^ 2 veya birimleriniz ne olursa olsun).

yönetim

Direksiyon da oldukça basit. Prensip olarak, yapacağınız şey , aracın başka bir yönünü gösterecek şekilde ileri vektörünü döndürmektir .

steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)

Ancak burada bir komplikasyonla karşılaşabilirsiniz. Girişiniz bir klavyeden geliyorsa değeri -1 veya 1 olacaktır, bu da aracınızın anında döneceği anlamına gelir. Bunu çok basit bir doğrusal enterpolasyon (lerping) kullanarak düzeltebilirsiniz:

 amount = time_since_last_frame * steer_lerp_factor
 forward_vector = lerp(forward_vector, new_forward_vector, amount)

Miktar, hareketinizin kare hızınıza bağlı olmayacağı şekilde zamana bağlı olmalıdır. Miktar [0, 1] arasında olmalı ve ne kadar küçük olursa, eski ve yeni vektörler arasındaki geçiş o kadar düzgün olacaktır.

(Bu noktada araba hala ayakta bile yönlendirmek göreceksiniz. Çarpın, bunu önlemek için steer_angletarafından current_speed / max_speed, nerede max_speedsizin tarafınızdan tanımlanan bir sabittir.)

Hareketli

Şimdi hızlanmayı uygulayacağız ve hızına, hızlanmasına ve direksiyonuna göre arabayı belirli sayıda piksel taşıyacağız. Aracın hızını sınırsız bir şekilde hareket etmeyecek şekilde sınırlamak isteyeceğiz.

current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Araban şimdi kayıyor

Eğer haklıysam arabanız buzdaymış gibi dönerken artık kayıyor gibi görünmelidir. Bunun nedeni sürtünme olmamasıdır. Gerçek bir arabada yüksek bir yanal sürtünme vardır (tekerleklerin yana dönememesi nedeniyle: P).

Yanal hızı azaltmanız gerekecektir. Tamamen düşürmeyerek arabanın sürüklendiğini de görebilirsiniz.

 lateral_velocity = right_vector * dot(velocity_vector, right_vector)
 lateral_friction = -lateral_velocity * lateral_friction_factor 

Sürtünme hakkında konuştuğumuz için, hızınızı azaltan bir hıza (sürtünme) sahip olmak da isteyebilirsiniz, böylece hızlanmayı bıraktığınızda arabanız sonunda durur.

 backwards_friction = -velocity_vector * backwards_friction_factor

Arabayı taşıma kodunuz şu şekilde görünmelidir:

// Friction should be calculated before you apply the acceleration
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
backwards_friction = -velocity_vector * backwards_friction_factor
velocity_vector += (backwards_friction + lateral_friction) * time_since_last_frame


current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{ 
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Kapanış notları

Direksiyona hareket etmeyi nasıl uygulamanız gerektiğinden bahsettim; Sanırım hızlanma ve muhtemelen dönüş açısı için de aynı şeyi yapmanız gerekebilir (değerlerini önceki kareden ve lerp'yi bundan saklamanız gerekecek). Ayrıca araca göre tüm vektörlerin (ileri, sağ, yukarı) uzunluğu 1 olmalıdır.

Ayrıca, sürtünme burada gösterdiğimden biraz daha karmaşık. Her zaman uzunluğunun, otomobilin durması için gereken hızlanmadan asla daha büyük olmadığından emin olmalısınız (aksi takdirde sürtünme, aracı ters yönde hareket ettirir). Yani şöyle bir şey olmalı:

dt = time_since_last_frame
backwards_friction.resize(min(backwards_friction.norm(), velocity_vector.norm() / dt))
lateral_friction.resize(min(lateral_friction.norm(), lateral_velocity.norm() / dt))

Vay be, bu harika bir cevap!
ezolotko

0

Sorunuzdan yola çıkarak, programlamaya nispeten yeni olduğunuzu varsayacağım (ki bu tamam bir btw!). Mevcut çerçeveleri gerçekçi araba simülasyonu olarak kullanmanızı öneririm, doğru yapmak için fiziğin en zor yönlerinden biridir.

2D / 3D kısıtlamalarından bahsetmediniz, bu yüzden devam edeceğim ve Havok SDK'yı (ticari olmayan kullanım için ücretsiz) indirmenizi ve basit bir demoyu çalıştırmanızı öneririz (aslında kutudan çıkan demolar var [get sisteminizde derlenmiş, tüm kod orada], derlemek için bir şey yapmak zorunda değilsiniz ... sadece projeyi açın ve yapı vurmak).

Araba fiziğinin sahne yönleri hakkında bir fikriniz olduğunda (fiziğin gerçek uygulamasını görmemenize rağmen, bu gizli, arayüzleri göreceksiniz), daha iyi bir konumda olacağınıza inanıyorum kendi başınıza yaptığınız zaman doğru olanı bulmak için.

Ben de çok uzun zaman önce benzer bir soru sordum . Oradaki bağlantılar da yardımcı olabilir. Ve işte başka bir bağlantı .


Düzenlemenize baktıktan sonra, hesaplanan açılara bağlı olarak aracın hızını değiştirmek istediğiniz görünüyor (gerçekçi btw değil, bu yüzden orijinal soruyu yansıtmak için değiştirmelisiniz). Açılar sorunun bir parçasıysa (değiştiremezsiniz) ve yeni hızı hesaplamak için açıları kullanmanız gerekiyorsa, @teodron'un yorumlara koyduğu şeye gidin.

Başka bir yol ise sadece vektörleri kullanmaktır. Vektörleri kullanan çoklu yaklaşımlar var, ben sunacağım.

Hız, yön * büyüklüktür (büyüklüğün hız olduğu ve yönün normalleştirilmiş bir vektör olduğu). Aracın mevcut hızını ve yönünü hesaplayın. Yönü al ve D'ona dik olan bir vektör (diyelim) ekleyelim . Bu, aracın hızını değiştirecektir. Yaklaşık bulaşmak Resim açılar (bu her ne kadar olabilir olabileceğin dik vektörün uzunluğunu belirlemek için açılarını kullanmak faktörü edecek [aşağıya bakınız])

Nasıl hesaplanırD' : Dikey vektörü bulmak için, orijinal hızın yönünü alın, vektörleri geçtiğiniz sıralamanın dikey vektörün yönünü belirlediği ekrana gelen yön vektörü ile çaprazlayın. Sonra bu perpiküler faktörü , aracın ne kadar hızlı döndüğünü belirleyen bir dönüş faktörü ile çarpın .


Yapabilirim ama bir fizik motoru kullanmama izin verilmiyor, oyun 3D ve tek yapmam gereken sadece ne olduklarını çözmek için ihtiyacım olan X ve Z vektörleri.
bobthemac

@bobthemac: Bu bir ev ödevi sorusu mu? Cevabınız evetse, sorunuzu, sahip olduğunuz kısıtlamaları işaret edecek şekilde düzenleyin ve belki de ilgili bir kod yayınlayalım. Btw, son bağlantı işlevselliği anlamak için aradığınız şey olabilir.
Samaursa

İstediğiniz bilgileri ekledim ve sağlanan bağlantılara baktım ancak hala anlamıyorum.
bobthemac

@bobthemac: Düzenlememi gör
Samaursa
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.