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_angle
tarafından current_speed / max_speed
, nerede max_speed
sizin 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))