Memalsukan grafik isometrik dalam game ruang 2D

15

Pertama-tama, saya tahu persis apa masalah menggambar saya, dan saya memiliki berbagai ide tentang cara pendekatan untuk menyelesaikannya. Saya di sini untuk mencari cara menyesuaikan frame mana yang digambar sehingga "ilusi" isometrik dipertahankan.

Saya sedang menulis game 2D, pandangan burung yang berlangsung di luar angkasa. Saya mencoba menggunakan grafik isometrik di dunia di mana Up adalah Utara, tidak ada putaran dunia game seperti di game isometrik tradisional (ingat, permainan berlangsung di ruang angkasa, tidak ada medan). Berikut adalah contoh sprite yang saya coba gunakan: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64.png Diputar 64 kali tentang sumbu vertikalnya sendiri dengan sudut pandang 35 derajat (alias, iso). Gambar itu dihasilkan, jadi ini bisa diubah.

Demi kejelasan, saya telah menentukan bahwa Utara (Atas) adalah 0 derajat, dan Timur (Kanan) adalah 90.

Masalah saya adalah sprite saya tidak selalu terlihat seperti menghadap ke tempat permainan berpikir itu karena perbedaan dalam pesawat 3D yang digunakan. Tidak yakin apakah saya menggunakan terminologi dengan benar, tetapi pesawat ruang angkasa saya diputar pada satu pesawat, dan pesawat pandangan mengharapkan hal-hal yang akan diputar pada pesawatnya sendiri. Berikut gambaran masalah:

http://cell.stat-life.com/images/stories/AsteroidOutpost/ProjectionIssue.png Di sebelah kiri, saya memiliki tampilan samping, di sebelah kanan saya memiliki tampilan top-down. Di bagian atas, saya memiliki tampilan kapal ruang / sprite dunia. Di bagian bawah, saya memiliki apa yang tampak seperti sprite ketika ditarik ke layar.

Di kanan atas adalah versi yang disederhanakan tentang bagaimana pesawat ruang angkasa saya diputar (pemisahan derajat antara setiap frame). Di kanan bawah adalah sudut yang sprite tampak menghadap ketika sudut tertentu digambar di layar. Masalahnya paling jelas sekitar 45 derajat. Berikut adalah gambar yang dilapis dengan garis "layar pesawat" yang mengarah ke arah yang seharusnya dihadapi kapal: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLine.png Garis merah harus selalu menunjuk ke arah yang sama persis seperti kapal, tetapi seperti yang Anda lihat, masalah proyeksi menyebabkan masalah. Saya harap saya menggambarkan masalah ini dengan cukup baik.

EDIT: Garis merah diputar pada bidang layar, sedangkan kapal ruang diputar pada "bidang pesawat", maka perbedaan besar antara sudut kapal dan sudut layar ketika digambar. AKHIR EDIT

Terlihat agak aneh ketika kapal ini menembakkan sinar laser ke target yang mengarah ke satu sisi, padahal seharusnya menembak lurus ke depan.

Jadi ... solusi yang saya buat adalah:

  1. Berhentilah mencoba memalsukan tampilan isometrik, pergi besar atau pulang. Putar duniaku. (PS: ini akan memperbaiki masalah saya, kan?)
  2. Ubah lembar sprite saya (entah bagaimana) untuk memiliki bingkai yang mewakili "sudut layar" di mana model akan dilihat. Jadi ketika saya meminta gambar 45 derajat, itu akan benar-benar terlihat seperti menghadap 45 derajat di layar.
  3. Ubah sistem rendering sprite saya untuk mengambil bingkai yang berbeda dari lembar sprite (entah bagaimana), mengetahui bahwa mengambil frame "normal" akan terlihat lucu. Jadi, alih-alih meraih frame 45 derajat, ia akan mengambil ... frame 33 derajat (hanya menebak) sehingga terlihat benar bagi pengguna.
  4. Cukup gunakan 3D! Jauh lebih mudah

Untuk satu: Solusi mana yang akan Anda rekomendasikan? Saya condong ke arah 2, meskipun saya tahu itu salah. Ingat bahwa saya memiliki akses penuh ke alat pembangkit sprite. Metode 3 akan menjadi pilihan kedua saya. Kedua metode ini hanya mengharuskan saya menerapkan beberapa matematika ke sudut (s) untuk mendapatkan hasil yang saya inginkan. Btw, saya menambahkan # 4 di sana sebagai lelucon, saya tidak ingin pindah ke 3D.

Untuk dua: Menggunakan metode 2 atau 3, bagaimana cara menyesuaikan sudut input atau output? Saya tidak terlalu bagus dengan proyeksi 3D, dan matriks 3D (apalagi matriks 2D), dan apa pun matematika lain yang dapat digunakan untuk mencapai hasil yang saya inginkan.

Berpikir keras di sini: jika saya mengambil unit vektor menghadap ke arah yang saya ingin kapal melihat (di layar pesawat), kemudian proyeksikan itu ke pesawat kapal, lalu cari tahu apa sudut antara garis yang diproyeksikan dan garis pesawat utara adalah, saya harus memiliki sudut grafik kapal yang ingin saya tampilkan. Baik? (solusi untuk # 3?) Man ... Saya tidak bisa menyelesaikannya.

EDIT:

Saya tahu masalahnya sulit untuk divisualisasikan dengan gambar statis, jadi saya telah memenuhi Sprite Library Visual Tester saya untuk menampilkan masalah: http://cell.stat-life.com/downloads/SpriteLibVisualTest.zip Diperlukan XNA 4.0 Aplikasi ini cukup memutar sprite, dan menggambar garis dari titik pusatnya ke luar pada sudut permainan berpikir kapal harus menghadap.

EDIT 8 September

Melanjutkan paragraf "berpikir keras": Alih-alih menggunakan proyeksi (karena terlihat keras), saya berpikir saya bisa mengambil vektor satuan yang menghadap ke utara (0x, 1y, 0z), gunakan matriks untuk memutarnya ke sudut sprite sebenarnya menghadap, kemudian putar lagi dari "pesawat melihat" ke luar ke "pesawat sprite" di sekitar sumbu X, lalu ... ratakan? vektor (pada dasarnya memproyeksikannya) kembali ke bidang tampilan dengan hanya menggunakan X dan Y (mengabaikan Z). Kemudian menggunakan vektor rata yang baru, saya bisa menentukan sudutnya dan menggunakannya untuk ... sesuatu. Saya akan berpikir lebih banyak nanti.

EDIT 8 September (2)

Saya mencoba mengikuti ide saya dari atas dengan beberapa keberhasilan, yay! Jadi ... untuk mendapatkan garis merah agar terlihat seperti langsung keluar dari pesawat ruang angkasa saya (tujuan pengujian saja), saya melakukan yang berikut:

Vector3 vect = new Vector3(0, 1, 0);
vect = Vector3.Transform(vect, Matrix.CreateRotationZ(rotation));
vect = Vector3.Transform(vect, Matrix.CreateRotationY((float)((Math.PI / 2) - MathHelper.ToRadians(AngleFromHorizon))));
Vector2 flattenedVect = new Vector2(vect.X, vect.Y);

float adjustedRotation = (float)(getAngle(flattenedVect.X, flattenedVect.Y));

Di mana rotationsudut layar dan adjustedRotationsekarang sudut layar terlihat pada bidang sprite. Saya tidak tahu mengapa saya perlu memutar Y alih-alih X, tapi itu mungkin ada hubungannya dengan 3D yang tidak saya ketahui.

Jadi, sekarang saya memiliki informasi tambahan, tetapi bagaimana saya menggunakan ini untuk memilih kerangka yang lebih tepat? Mungkin alih-alih memutar dari bidang pandangan ke bidang sprite, lalu memproyeksikan kembali, saya harus mencoba melakukannya sebaliknya. Inilah sprite saya dengan garis merah yang disesuaikan, tetapi yang ingin saya lakukan adalah menyesuaikan modelnya, bukan garisnya: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLineCorrected.png

Sunting 9 September

HORAY! Sudah diperbaiki! Saya akan menjelaskan apa yang saya lakukan untuk memperbaikinya:

Saya mengikuti saran eBusiness dan "diperas" oleh sistem koordinat dunia (atau ditarik ...?). Ini pada dasarnya solusi # 1, meskipun saya mendapat kesan bahwa saya harus memutar sistem koordinat dunia saya sehubungan dengan sistem coord layar. Tidak benar! Naik masih + y, dan Kanan masih + x. Saya memodifikasi metode WorldToScreen dan ScreenToWorld saya untuk mengkonversi antara dunia dan koordinat layar dengan benar. Metode ini mungkin tidak optimal, tetapi hanya ada dua metode dalam basis kode saya yang harus diubah.

public Vector2 ScreenToWorld(float x, float y)
{
    float deltaX = x - (size.Width / 2f);
    float deltaY = y - (size.Height / 2f);

    deltaX = deltaX * scaleFactor / (float)Math.Sqrt(3);
    deltaY = deltaY * scaleFactor;

    return new Vector2(focusWorldPoint.X + deltaX, focusWorldPoint.Y + deltaY);
}

public Vector2 WorldToScreen(float x, float y)
{
    float deltaX = x - focusWorldPoint.X;
    float deltaY = y - focusWorldPoint.Y;

    deltaX = deltaX / scaleFactor * (float)Math.Sqrt(3);
    deltaY = deltaY / scaleFactor;

    return new Vector2(size.Width / 2f + deltaX, size.Height / 2f + deltaY);
}

Itu dia! Mengubah kedua metode tersebut memengaruhi segalanya: apa yang saya lihat, di mana objek di mana ditarik, di mana saya mengklik, semuanya. Pesawat ruang angkasa saya sekarang melihat langsung ke target yang ditembakkan, dan semuanya jatuh ke tempatnya. Saya akan bereksperimen dengan proyeksi ortografi, melihat apakah itu membuat semuanya tampak lebih 'nyata'.

John McDonald
sumber
Selamat. Jangan lupa menusuk saya setelah Anda memiliki sesuatu yang dapat dimainkan, saya ingin melihat ke mana perginya.
aaaaaaaaaaaa
@eBusiness Seperti yang dijanjikan: cell.stat-life.com/images/stories/AsteroidOutpost/… dan cell.stat-life.com/images/stories/AsteroidOutpost/AOOhNoes.png Perhatikan bagaimana kapal terlihat seperti melihat menara itu? : D Terima kasih!
John McDonald
@eBusiness, Video youtube.com/watch?v=Q8pR9KDBsCo Ada juga tautan untuk mengunduh, karena Anda bertanya.
John McDonald

Jawaban:

4

Ketika Anda memilih perspektif isometrik, Anda perlu mengoreksi skala antara sumbu X dan sumbu Y. Jika jarak yang diberikan memproyeksikan ke 1 pada layar Y-axis maka jarak yang sama akan memproyeksikan ke sqrt (3) pada layar X-axis. Jadi, jika Anda menggambar sesuatu dengan rata di layar, Anda akan melakukan sesuatu seperti:

draw(object.image, object.x*sqrt(3), object.y)

Catatan tanpa jawaban:

  • Mengapa Anda mengacaukan lembaran sprite dan lainnya? Anda bisa mendapatkan penyaji 3D untuk melakukan isometrik jika mau.
  • Karena Anda menggunakan sprite sheet, mengapa tidak anti-alias?
  • Isometrik di luar angkasa, saya pikir saya belum pernah melihat penggunaan game itu, saya tidak yakin seberapa baik kerjanya karena kurangnya dasar isometrik yang jelas untuk referensi visual.
aaaaaaaaaaaa
sumber
1
Saya pikir ... Ini bisa memperbaiki semuanya. Ini adalah perbaikan yang mudah, dan saya bisa membiarkan lembaran itu sendirian. Saya akan mencoba ini secepatnya dan memberi tahu Anda bagaimana hasilnya. Untuk menjawab catatan Anda: 1) Saya menggunakan 2D karena itu yang saya kenal, dan saya menghasilkan lembaran saya dari model 3D. 2) Tepi harus tajam, tetapi di dalam tepi yang keras saya bisa menggunakan saluran alpha untuk anti-alias, yang akan datang. 3) Saya tidak berencana untuk mensimulasikan dimensi ketiga (banyak), saya terutama menginginkan grafik 2D yang tidak top-down dan memungkinkan Anda untuk melihat sisi-sisi hal.
John McDonald
5

Bagaimana sprite diputar dihasilkan? Apakah screenshot ini dari model 3D yang berputar? Sudut menghadap dapat dimatikan karena perspektif kamera alat pemodelan 3D. Perspektif isometrik bukan representasi akurat dari ruang 3D. Barang yang jauh dari 'kamera' tidak semakin kecil.

Jika Anda hanya ingin perbaikan cepat. Solusi 2 mungkin sulit untuk diperbaiki. Solusi 3 tampaknya mudah hanya menukar frame yang tidak cocok dengan sudut yang cocok dengan sudut yang lebih baik.

Laser terkadang masih mati. Karena Anda tidak melakukan rotasi yang halus tetapi menunjukkan bingkai yang berbeda untuk rentang derajat tertentu.

EDIT:

Masalah Anda adalah tangkapan layar yang dihasilkan bukan perspektif isometrik, melainkan tampilan kamera 3D normal.

masukkan deskripsi gambar di sini

Tampilan isometrik mensimulasikan ruang 3D tetapi bukan representasi yang akurat. Hal-hal menjadi lebih kecil dengan meningkatnya jarak dari kamera. Ini tidak dilakukan untuk perspektif isometrik karena ini akan menyebabkan artefak penskalaan jelek pada sprite.

Tangkapan layar kapal ruang angkasa Anda dibuat dengan perspektif kamera 3D. Karena itulah pemotretan laser tidak aktif. Bandingkan garis merah di 'isometrik' dan 'perspektif'.

Generator sprite Anda harus menggunakan Matrix.CreateOrthographic (), bukan Matrix.CreatePerspective () untuk matriks proyeksi.

Stephen
sumber
Sprite dihasilkan menggunakan alat 3D ke 2D yang saya kembangkan, jadi masalahnya bisa jadi ada di alat itu. Alat ini hanya memuat model 3D, kemudian untuk mencapai Spaceship64.png (di atas), ia memutar model dengan (360/64) = 5,625 derajat, menyimpannya sebagai sebuah bingkai, kemudian memutarnya lagi dengan jumlah yang sama hingga ia memiliki semua 64 bingkai. Kode yang digunakan untuk merender model ada di sini: code.google.com/p/sprite-maker/source/browse/trunk/XNAWindow/... Rotasi dilakukan di kelas lain. Saya juga berpikir bahwa solusi 2 dan 3 adalah kebalikan dari yang lain, bukan?
John McDonald
Sunting jawaban saya. Lihat di atas.
Stephen
Saya pikir saya mungkin perlu melakukan keduanya: membuat sprite generator saya menggunakan proyeksi ortografis DAN mengubah sistem koordinat dunia saya seperti apa yang dikatakan @eBusiness. Saya mencoba proyeksi Orthographic tadi malam, dan itu benar-benar mengubah penampilan kapal saya, tetapi itu saja tidak memperbaiki masalah sudut yang saya alami.
John McDonald
Baru saja melihat hasil edit Anda. Sprite yang dikoreksi terlihat seperti bagian tengah kapal tidak aktif dari bagian tengah garis merah. Mungkin itu cukup untuk menggambar kapal satu atau dua piksel lebih tinggi dari titik awal garis merah. Apakah kesalahan yang terlihat berubah saat kapal menjauh dari asal dunia Anda? Kemudian, menskalakan X-Axis mungkin memperbaikinya.
Stephen
1

Saya pikir apa yang Anda dapat di sini hanyalah bagaimana penampilan isometrik. Anda benar dalam hal itu, secara visual, tampaknya ada perbedaan yang lebih besar antara 0deg dan 10deg daripada antara 90deg dan 100deg. . . tapi itu karena isometrik secara intrinsik memampatkan satu sumbu. Jika Anda tidak ingin tampilan itu, Anda tidak ingin isometrik.

Yang mengatakan, saya pikir masalah visual yang Anda alami berkat tidak memiliki titik referensi visual. Otak Anda berasumsi Anda memandangnya dari atas ke bawah - hei, ini ruang, mengapa Anda tidak jadi - dan menafsirkannya sebagai tampilan top-down standar. Demi pengujian, coba tambahkan beberapa titik referensi holografik mengambang. Grid miring 45 derajat, misalnya, atau satu set lingkaran jangkauan di sekitar pesawat ruang angkasa Anda. Pastikan mereka terdistorsi dengan tepat seolah-olah mereka berada di bidang isometrik yang sama dengan yang digunakan pesawat ruang angkasa Anda. Saya berani bertaruh bahwa otak Anda akan mengetahui perspektif dan tiba-tiba akan terlihat benar.

Sekarang, cari tahu cara menyampaikannya kepada pengguna Anda. . . itu masalah lain sama sekali.

ZorbaTHut
sumber
Bukankah saya juga perlu memutar poros dunia untuk menyelesaikan ilusi menggunakan metode ini (metode # 1 dalam pertanyaan)?
John McDonald
Sejauh yang saya tahu, kapal sudah diterjemahkan dengan benar - tampilan samping menunjukkan pada sudut seharusnya isometrik terlihat "benar". Saya kira saya tidak yakin apa yang Anda maksud dengan "memutar poros dunia".
ZorbaTHut
Dengan "memutar poros dunia", maksud saya memutar dunia dalam kaitannya dengan kamera sebesar 45 derajat untuk membuat "Utara" mengarah ke kanan atas atau kiri atas layar pada diagonal alih-alih "Utara" lurus ke atas menuju bagian atas layar.
John McDonald
Itu mungkin membantu, tetapi di ruang angkasa seharusnya tidak membuat banyak perbedaan. Kecuali jika Anda memiliki grid yang terhampar di dunia, itu seharusnya tidak menjadi masalah.
ZorbaTHut