Piksel sanat hareketinde “merdiven efekti” nasıl önlenir?


21

Kenar yumuşatmanın neden olduğu bulanıklaştırma etkisini önlemek için tam piksel koordinatlarında sprite oluşturuyorum (sprite piksel sanat ve filtre uygulanmışsa korkunç görünecektir). Bununla birlikte, nesnelerin hareketi değişken hız, yerçekimi ve fiziksel etkileşimler içerdiğinden, yörünge alt piksel hassasiyeti ile hesaplanır.

Yeterince büyük ekran alanı hızlarında (2 veya 3 pikselden büyük vΔt) bu çok iyi çalışır. Bununla birlikte, hız küçük olduğunda, özellikle çapraz çizgiler boyunca belirgin bir merdiven etkisi görünebilir. Bu artık çok yavaş ekran alanı hızları (v << 1 piksel / saniye) bir sorun değil, bu yüzden sadece ara hız değerleri için bir çözüm arıyorum.

Solda, nesne koordinatlarının basit yuvarlanmasıyla elde edilen büyük bir hız için çizilen yörünge vardır. Ortada, hız küçüldüğünde ne olduğunu ve bahsettiğim merdiven efektini görebilirsiniz. Sağda, almak istediğim yörüngenin lokusu.

nesne yörüngesi için piksel koordinatları

Büyük ve küçük hızlarda orijinal davranışı korurken, takma adı en aza indirmek için yörüngeyi filtrelemek için algoritma fikirleriyle ilgileniyorum. Δt, anlık konum ve hızın yanı sıra isteğe bağlı önceki değerlere erişimim var, ancak gerçek zamanlı bir simülasyon olduğundan, gelecekteki değerler hakkında bilmiyorum (gerekirse, bir tahmin belirli varsayımlar altında tahmin edilebilir) . Fizik simülasyonu nedeniyle ani yön değişikliklerinin de olabileceğini unutmayın.

Yanıtlar:


18

İşte kafamın üstünde, makul derecede iyi çalışması gereken bir algoritmanın hızlı bir taslağı.

  1. İlk olarak, nesnenin hareket ettiği yönü hesaplayın ve yatay veya dikey yakın olup olmadığını kontrol edin.
  2. Yön dikeye (yatay) daha yakınsa , yön vektörü boyunca nesnenin konumunu en yakın piksel sırasının (sütun) ortasına ayarlayın.
  3. Konumu en yakın pikselin ortasına yuvarlayın.

Sözde kodda:

if ( abs(velocity.x) > abs(velocity.y) ) {
    x = round(position.x);
    y = round(position.y + (x - position.x) * velocity.y / velocity.x);
} else {
    y = round(position.y);
    x = round(position.x + (y - position.y) * velocity.x / velocity.y);
}

Düzenleme: Evet, test edildi, oldukça güzel çalışıyor.


+1, bu şaşırtıcı derecede iyi çalışıyor! Yavaş hızlarda dairesel hareketle garip geriye doğru atlamalar fark ettim, çünkü ayarlama hız vektörünün tersi yönde yapılabilir (genellikle Tamam, ancak küçük yörünge eğrilikleri ile değil). Bu velocity.y / velocity.x, hız ile orantılı bir düzeltme faktörü ile çarpılarak çözülebilir .
sam hocevar

@Sam: Yani küçük dönüş yarıçapı (= yüksek eğrilik), değil mi? Bu, düşük hızlarda doğrusal ekstrapolasyon ile ilgili sorunlara neden olabilir. (Temel olarak, hızlanma başına kare hızı 1 pikselden çok daha büyük olduğu sürece çalışır.) Olası bir (klugey) çözümü, son yuvarlanmış konumu hatırlamak ve yeni hesaplanandan daha yakınsa, gerçek konuma yeniden kullanmak olabilir. (Üst düzey ekstrapolasyon da denenebilir, ancak formüller oldukça çirkinleşir.)
Ilmari Karonen

Gerçekten de küçük yarıçap demek istedim. Benim hatam. Ve ek ipuçları için teşekkürler; performans burada kritik değildir, bu yüzden kaliteyi artırmayı göze alabilirim.
sam hocevar

3

Genel fizik tabanlı bir dünya için gerçekten yapabileceğiniz çok şey yok. Tüm nesneleriniz çizgiler veya belirli daireler boyunca hareket ediyorsa, bir şeyler yapabilirsiniz. Ama siz gerçek fizik altında çalışıyorsunuz. Nesne fiziğin koyduğu yerdir; bu konumun piksel tabanlı bir yaklaşımını çiziyorsunuz.

Piksel koordinatlarına bağlı kalmak istiyorsanız genellikle kabul etmeniz gereken bir şeydir. İnanılmaz derecede küçük bir çözünürlükte (ekranın doğal çözünürlüğüne ve boyutuna bağlı olmasına rağmen, 640x480'den az) görüntülenmediğiniz sürece çok fark edilmemelidir.


Yüksek çözünürlüklerde bile, eski okul görünümünü geliştirmek için görüntü oluşturma (en yakın komşu) yükseltilir. Bu sanatsal bir yön kararıdır.
sam hocevar

@ SamHocevar: Eğer bir "eski okul görünümü" istiyorsanız, neden tam bir "eski okul görünümü" istemiyorsunuz ? Neden herhangi bir "oldschool" oyununun sahip olacağı merdiven basamağı, elde etmek istediğiniz genel etkinin bir parçası değil?
Nicol Bolas

İyi bir eski okul oyununun o merdiven efektine sahip bir çapraz hareket uygulayacağını sanmıyorum, çünkü bok gibi görünecekti. Bok gibi
görünmüyor

@SamHocevar: Eski okul oyunlarının çoğu aksiyon oyunlarıdır ve bu nedenle farkedilecek kadar yavaş hareket etmezler. Ayrıca eğriler boyunca hareket etmeme eğilimindedirler. Özellikle düşündüğüm oyun, yavaş hareket ederken çok fazla etkisi olan Solar Jetman'dı. Verilmiş, kamera her zaman size odaklanmıştır, bu yüzden dünya hareketinde fark edersiniz, ancak orada çok fazla.
Nicol Bolas

3

Bekleyen hareket son harekete (ekran boşluğunda) dikey olduğunda hareketi yok sayın ve son ekran koordinatlarını kullanın. Bu, merdiven kadar kötü olan kekemeye yol açarsa, bekleyen ve son hareketin toplamını hareket ettirmeyi deneyebilirsiniz.

Bence problem v <sqrt (2) 'de yatıyor. v> sqrt (2) merdiven etkisinden kaçınarak daima en az bir köşegen hareket etmelidir. Önceki hareket karşılaştırmaları gerektiren budama için belki yararlı olabilir.


V. Ilmari'nin önerisi için bir üst sınır belirtmek için +1 daha ayrıntılıdır, ancak faydalı bilgiler sağlıyorsunuz.
sam hocevar
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.