Bagaimana menangani perbedaan antara koordinat layar 2D dan koordinat Cartesius

23
  • Sebagian besar layar 2D / sistem koordinat bitmap memiliki sumbu Y positif mengarah ke bawah (dengan asal di sudut kiri atas).
  • Ini bertentangan dengan bagaimana kebanyakan orang berpikir secara geometris dengan sumbu Y positif mengarah ke atas (dengan asal di tengah).

Bagaimana sebagian besar game mengelola dua sistem koordinat 2D yang berbeda? Ada dua jenis utama koordinat (layar vs Cartesian), tetapi mungkin ada banyak ruang koordinat yang berbeda: ruang sprite, ruang dunia, ruang tampilan, ruang layar, dll ...

Latar Belakang:

Saya awalnya membuat koordinat dunia dalam game saya cocok dengan konvensi koordinat layar 2D. Ini membuatnya sangat alami untuk menggunakan rutinitas menggambar grafik, tetapi masalah halus muncul ketika menggunakan fungsi trigonometri seperti atan2 (). Hasil pengumpanan atan2 () koordinat layar 2D sangat membingungkan karena atan2 () mengasumsikan sumbu y positif mengarah ke atas.

Jadi saya mengubah koordinat dunia saya untuk mengikuti sistem koordinat Cartesian klasik (dengan asal di bagian kiri bawah layar). Penalaran dengan atan2 () jauh lebih mudah, tetapi sekarang lebih sulit untuk melakukan jenis penalaran lain:

  • Jika saya mengklik layar di sini, sprite apa yang ada di bawahnya?
  • Di mana saya mengklik sprite itu?
  • Jika sprite diambil di lokasi yang salah, apa yang salah dihitung? Layar koordinat atau koordinat dunia?

Saya menyadari konversi dari layar ke koordinat Cartesian hanya melibatkan penskalaan nilai y dengan -1 dengan terjemahan opsional dari kedua nilai (x, y). Saya lebih tertarik dengan praktik terbaik untuk desain game:

  • Apakah sebagian besar game hanya bertahan dengan konvensi koordinat layar dan mengubah pemikiran mereka tentang bagaimana hal-hal seperti atan2 () harus bekerja?
  • Kapan / bagaimana konversi sistem koordinat dilakukan? (Menggunakan matriks, abstraksi OOP, dll)
  • Apakah lokasi sprite disimpan sebagai pusat sprite atau salah satu sudut? Tinggi / lebar sprite yang mengarah ke arah yang "salah" tampaknya menjadi masalah yang umum ketika saya menggambar mereka.

Meskipun pertanyaan saya terutama tentang game 2D, tampaknya OpenGL menggunakan sistem koordinat di mana sumbu Y mengarah. OpenGL akhirnya harus memproyeksikan koordinat 3D tersebut ke sistem koordinat layar 2D. Mungkin beberapa panduan dapat ditemukan dalam metode OpenGL ...

Leftium
sumber

Jawaban:

8

Setelah mencoba segala cara yang mungkin untuk melakukannya, saya telah menemukan jika ini murni permainan 2D, cukup gunakan sistem menggambar layar, itu akan membuat hidup Anda lebih mudah. Dosa, Cos, dan atan2 perlu digunakan sedikit berbeda, tetapi ketidaknyamanan ini mudah ditebus oleh kesederhanaan mengetahui jalan naik, turun, searah jarum jam dan berlawanan arah jarum jam. Saya juga merekomendasikan bekerja dalam piksel daripada meter untuk game 2D - jauh lebih mudah untuk memikirkan jarak di layar, dan kemungkinan Anda ingin mengubah seluruh skala permainan Anda mendekati nol.

"Bagaimana sebagian besar game mengelola dua sistem koordinat 2D yang berbeda?"

  • kebanyakan game 2D saya pernah melihat sumber untuk menggunakan sistem layar, tetapi setiap entitas harus tahu ruang dunianya, biarkan manajer gambar Anda mengonversikannya ke posisi layar. Pada titik ini Anda akan melakukan transformasi matriks apa pun yang Anda butuhkan.

"Apakah lokasi sprite disimpan sebagai pusat sprite atau salah satu sudut?"

  • Jika Anda bekerja dari tengah, itu membuat rotasi lebih lurus ke depan, meskipun Anda juga ingin tahu sudut-sudutnya.

"Mungkin beberapa petunjuk dapat ditemukan dalam metode OpenGL ..."

  • Mesin 3D adalah kasus yang sangat berbeda. Karena mereka memiliki kamera sejati, posisi layar bisa sangat berbeda dari posisi dunia. Untuk permainan top-down, Anda akan bekerja di sumbu X dan Z, daripada X dan Y untuk satu hal.
Iain
sumber
1

Saya mungkin terlalu menyederhanakan hal-hal di sini, tetapi kecenderungan saya adalah memiliki semua subsistem 2D / UI secara ketat dalam apa yang Anda juluki koordinat "layar". Anda akan memiliki dua matriks: ScreenToCartesianTransform dan CartesianToScreenTransform. Ketika peristiwa input mouse diterima, koordinat mouse akan ditransformasi menggunakan CartesianToScreenTransform sebelum diteruskan ke manajer input sistem 2D / UI. Dari sana, sistem UI akan melakukan pengujian-hit menggunakan sistem koordinat layar, dan menangani (atau tidak menangani) acara yang sesuai. Jika acara input mouse tidak ditangani oleh 2D / UI, itu dapat diteruskan ke sistem 3D (jika ada) menggunakan koordinat asli dan tidak diubah.

Karena sistem 2D / UI hanya akan menangani koordinat "layar", geometrinya perlu diubah melalui ScreenToCartesianTransform sebelum diproses oleh mesin rendering.

Mike Strobel
sumber
Sebenarnya, tergantung pada toolkit yang Anda gunakan, peristiwa input mouse mungkin sudah ada di koordinat layar. Dalam hal ini, Anda tidak akan mengubahnya untuk sistem 2D / UI, tetapi Anda akan mengubahnya untuk sistem 3D (jika ada).
Mike Strobel
0

Saya lebih suka menggunakan tampilan pohon seperti di Flash. Saya akan memiliki simpul akar (tampilan permainan) yang berisi anak untuk dunia (simpul dunia) dan satu di atas untuk HUD. Di dalam simpul dunia akan menjadi simpul untuk objek di dunia game.

Saya kemudian hanya mengubah simpul dunia. Bersamaan dengan terjemahan (panning kamera) dan penskalaan proporsional (zoom kamera) saya juga menerapkan dua transformasi lainnya:

  • Skala -1 y untuk membalikkan sistem koordinat.
  • Penskalaan untuk mengonversi satuan dunia (meter) ke unit layar (piksel)

Saya kemudian menggunakan koordinat y-up / world dalam kode menggambar objek game dan koordinat y-down / layar dalam kode menggambar HUD, yang keduanya terasa sangat alami.

Untuk menjawab pertanyaan seperti "objek apa yang saya klik" Saya menggunakan metode tampilan node untuk mengkonversi koordinat antara sistem koordinat (seperti globalToLocaldan kebalikannya di Flash).

Ngomong-ngomong, atantidak benar-benar bekerja secara berbeda ketika Anda turun, Anda hanya perlu memikirkan semua sudut sebagai arah jarum jam, bukan berlawanan arah jarum jam.

Bart van Heukelom
sumber
0

OpenGL, seperti DirectX, memiliki sumbu X dan Z di sepanjang bidang horizontal dan Y menghadap ke atas.
Saya tidak pernah memiliki masalah dengan koordinat layar, dan saya pikir cara termudah adalah dengan memperlakukannya seperti itu: jika sesuatu, seperti atan2, tidak menyukainya, maka ubah parameter yang diumpankan.

Jika Anda menggunakan koordinat relatif atau lokal, seperti grafik adegan, maka fungsi sederhana seperti ToGlobalCoords () bagus. Bahkan, jika Anda ingin mempelajari lebih lanjut tentang penentuan posisi spasial, grafik adegan, dan localToGlobal, ekstrak gratis dari Game Engine Architecture adalah tentang itu.

Sprite diambil dari sudut kiri atas atau (0,0) asal. Alasan mengapa adalah karena asal kiri atas jendela.

Tampaknya agak konyol untuk mengubah sistem koordinat jendela, dan akan membuat hal-hal seperti input, yang memainkan peran yang lebih besar untuk sebagian besar gim daripada trigonometri, secara signifikan lebih sulit. Ini juga mengasingkan Anda dari norma dan semua pengguna kode Anda.

Bebek Komunis
sumber