2D ekran koordinatları ve Kartezyen koordinatlar arasındaki farklarla nasıl baş edilir


23
  • Çoğu 2D ekran / bitmap koordinat sistemi, aşağı doğru işaret eden pozitif Y eksenine (menşe sol üst köşedeki) sahiptir.
  • Bu, çoğu insanın pozitif Y ekseni yukarı bakacak şekilde (merkezdeki orijinli) geometrik olarak nasıl düşündüklerine karşıdır .

Çoğu oyun iki farklı 2D koordinat sistemini nasıl yönetir? İki ana tür koordinat vardır (ekrana karşılık Kartezyen), ancak birçok farklı koordinat alanı olabilir: sprite alanı, dünya alanı, görüntüleme alanı, ekran alanı vb.

Arka fon:

Başlangıçta oyunumdaki dünya koordinatlarını 2D ekran koordinat kurallarına uydurdum. Bu, grafik çizme yordamlarını kullanmayı çok doğal hale getirdi, ancak atan2 () gibi trigonometrik işlevler kullanıldığında ortaya çıkan ince konular ortaya çıktı. Atan2 () 2B ekran koordinatlarını beslemenin sonuçları çok kafa karıştırıcı çünkü atan2 () pozitif y ekseninin işaret ettiğini varsayıyor.

Böylece dünya koordinatlarımı klasik Kartezyen koordinat sistemini (ekranın sol alt köşesinde bulunan) takip edecek şekilde değiştirdim. Atan2 () ile muhakeme, çok daha yalındır, ancak şimdi diğer akıl yürütme türlerini yapmak daha zor:

  • Buradaki ekranı tıklarsam, altındaki sprite nedir?
  • O sprite nereye tıkladım?
  • Bir sprite yanlış yere çizilirse, yanlış ne hesaplandı? Ekran koordinatları mı yoksa dünya koordinatları mı?

Ekrandan Kartezyen koordinatlarına dönüşümün, her iki (x, y) değerin isteğe bağlı olarak çevrilmesi ile y değerini -1 ile ölçeklendirmesini içerir. Oyun tasarımı için en iyi uygulamalarla daha çok ilgileniyorum:

  • Oyunların çoğu ekran koordinatına uyuyor ve atan2 () gibi şeylerin nasıl çalışması gerektiği hakkındaki düşüncelerini değiştiriyor mu?
  • Koordinat sistemi dönüşümleri ne zaman / nasıl yapılır? (Matris kullanma, OOP soyutlama, vb.)
  • Sprite konumları sprite merkezi olarak mı yoksa köşelerden biri olarak mı depolanıyor? Sprite 'yükseklik / genişlik "yanlış" yönde gidiyor ben onları çizerken yaygın bir sorun gibi görünüyor.

Sorumun esas olarak 2D oyunlar hakkında olmasına rağmen, OpenGL Y ekseninin işaret ettiği bir koordinat sistemi kullanıyor gibi görünüyor. OpenGL sonunda bu 3B koordinatları 2B ekran koordinat sistemine yansıtmalıdır. Belki OpenGL'nin metodunda bazı rehberlikler bulunabilir ...

Yanıtlar:


8

Akla gelebilecek her türlü yolu denedikten sonra, tamamen 2D bir oyun mu olduğunu gördüm, sadece ekran çizim sistemini kullanın, hayatınızı çok daha kolaylaştıracaktır. Sin, Cos ve atan2 biraz farklı şekilde kullanılmalıdır, ancak bu rahatsızlık kolayca yukarı, aşağı, saat yönünde ve saat yönünün tersine doğru nasıl olduğunu bilmenin basitliği ile kolayca yapılabilir. Ayrıca 2D oyunlar için metre yerine piksel olarak çalışmayı da tavsiye ederim - ekran mesafelerini düşünmek çok kolaydır ve oyununuzun tüm ölçeğini değiştirmek isteme ihtimaliniz sıfıra yakındır.

“Çoğu oyun iki farklı 2D koordinat sistemini nasıl yönetiyor?”

  • Çoğu 2D oyun ekran sistemini kullanmak için kaynak gördüm, ancak her varlık kendi dünya alanını bilmeli, çizim yöneticisinin bunu ekran konumuna getirmesine izin vermeli. Bu noktada ihtiyacınız olan matris dönüşümünü yapacaksınız.

"Sprite konumları, sprite merkezi olarak mı yoksa köşelerden biri olarak mı depolanıyor?"

  • Merkezden çalışıyorsanız, köşeleri de bilmek isteyeceksiniz olsa da, dönüşü daha düz hale getirir.

"OpenGL'in yönteminde belki bazı rehberlikler bulunabilir ..."

  • 3D motorlar tamamen farklı bir durum. Gerçek kameralara sahip olduklarından, ekran konumu dünya konumundan çılgınca farklı olabilir. Yukarıdan aşağıya bir oyun için, bir şey için X ve Y yerine X ve Z eksenlerinde çalışacaksınız.

1

Burada bazı şeyleri fazlasıyla basitleştiriyor olabilirim, ancak benim eğilimim, “ekran” koordinatlarında bahsettiğiniz şeyde kesinlikle herhangi bir 2B / UI alt sistemi anlaşması yapmak olacaktır. İki matrisiniz olurdu: ScreenToCartesianTransform ve CartesianToScreenTransform. Fare giriş olayları alındığında, fare koordinatları, 2D / UI sisteminin giriş yöneticisine geçmeden önce CartesianToScreenTransform kullanılarak dönüştürülür. Oradan, UI sistemi ekran koordinat sistemini kullanarak isabet testi yapacak ve olayı buna göre ele alacak (ya da ele almayacak). Bir fare giriş olayı 2D / UI tarafından işlenmezse, orijinal, dönüştürülmemiş koordinatlar kullanılarak 3D sisteme aktarılabilir (varsa).

2D / UI sistemi yalnızca "ekran" koordinatlarında kullanılacağından, işleme motoru tarafından işlenmeden önce geometrisinin ScreenToCartesianTransform aracılığıyla dönüştürülmesi gerekir.


Aslında, hangi araç kitini kullandığınıza bağlı olarak, fare girişi olayları zaten ekran koordinatlarında olabilir. Bu durumda, onları 2B / UI sistemi için dönüştürmezsiniz, ancak 3B sistemi için (varsa) değiştirirsiniz.
Mike Strobel

0

Flash'taki gibi bir ekran ağacı kullanmayı tercih ederim. Dünya için bir çocuk (dünya düğümü) ve biri HUD için bir tane içeren bir kök düğüme (oyun görünümü) sahip olacağım. Dünyadaki düğüm, oyun dünyasındaki nesnelerin düğümleri olacaktır.

Daha sonra dünya düğümünü değiştiriyorum. Çeviri (kamera kaydırma) ve orantılı ölçeklendirme (kamera yakınlaştırma) ile birlikte başka iki dönüşüm daha yapıyorum:

  • Koordinat sistemini çevirmek için -1 y ölçeği.
  • Dünya birimlerini (metre) ekran birimlerine (piksel) dönüştürmek için bir ölçeklendirme

Daha sonra oyun nesnesi çizim kodunda y-up / world koordinatlarını ve HUD çizim kodundaki y-down / screen koordinatlarını kullanıyorum, bu ikisi de çok doğal.

"Hangi nesneye tıklıyorum" gibi soruları yanıtlamak için koordinatları koordinatlar arasında dönüştürmek için görüntüleme düğümü yöntemlerini kullanıyorum (örneğin globalToLocalFlash'ta tersi gibi ).

Bu arada, atany düştüğünde farklı şekilde çalışmaz, tüm açıları saat yönünün tersine yerine saat yönünde gittiğini düşünmeniz gerekir.


0

OpenGL, DirectX gibi, yatay düzlem boyunca X ve Z eksenlerine ve Y yukarıya bakacak şekilde sahiptir.
Ekran koordinatları ile ilgili hiçbir sorun yaşamadım ve en kolay yolun nasıl olduğunu tedavi etmenin en kolay yolu olduğunu düşünüyorum: eğer atan2 gibi bir şey beğenmiyorsa, beslenen parametreleri değiştirin.

Sahne grafiği gibi göreceli veya yerel koordinatlar kullanıyorsanız, ToGlobalCoords () gibi basit bir fonksiyon iyidir. Aslında, uzamsal konumlandırma, sahne grafikleri ve localToGlobal hakkında daha fazla bilgi edinmek istiyorsanız, Game Engine Architecture'dan ücretsiz alıntı.

Sprite sol üst köşeden veya (0,0) orijininden çizilir. Sebepler, neden pencerenin sol üst kökünden kaynaklanıyor?

Pencere koordinat sistemini değiştirmek biraz saçma görünüyor ve çoğu oyun için trig'ten daha büyük bir rol oynayan girdi gibi şeyleri önemli ölçüde zorlaştırıyor. Ayrıca sizi normdan ve kodunuzun tüm kullanıcılarından yabancılaştırır.

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.