Baiklah, dirumuskan dengan cara ini saya yakin kedengarannya tidak jelas, tetapi saya akan melakukan yang terbaik untuk menggambarkan masalah saya.
Pertama, izinkan saya menjelaskan apa yang salah dengan kode sumber asli saya.
Saya membuat platformer, dan di sini adalah komponen saat ini dari permainan saya: Level , yang memegang kotak ubin sendiri dan juga lembar ubin dan Ubin , yang hanya menyimpan nama lembar ubin dan indeksnya di dalam lembaran genteng. Semua ini berada dalam proyek game XNA yang terpisah, bernama GameLib.
Berikut adalah bagaimana level saya diformat dalam file teks:
x x . . . . .
. . . b g r .
. . . . . . .
X X X X X X X
Di mana .
mewakili ubin kosong, b
mewakili platform biru, X
mewakili blok dengan warna acak, dll.
Alih-alih melakukan semua pekerjaan memuat level dalam kelas Level , saya memutuskan untuk mengambil keuntungan dari ekstensi pipa konten dan membuat LevelContentPipelineExtension.
Segera setelah saya mulai, saya segera menyadari bahwa saya tidak ingin kode-keras 20+ baris semacam itu:
if (symbol == 'b')
return new Tile(/*...*/);
Jadi, dengan harapan setidaknya memusatkan semua pembuatan konten ke dalam satu kelas, saya membuat kelas statis, yang disebut LevelContentCreation , yang menyimpan informasi tentang simbol mana yang menciptakan apa dan semua jenis barang ini. Ia juga menyimpan daftar semua jalur aset lembaran ubin, untuk memuatnya nanti. Kelas ini ada dalam proyek perpustakaan game GameLib saya.
Masalahnya adalah, saya menggunakan kelas statis LevelContentCreation ini di kedua kelas Tingkat saya (untuk memuat lembaran ubin yang sebenarnya) dan ekstensi pipa konten saya (untuk mengetahui simbol mana yang mewakili ubin apa) ...
Dan inilah tampilan kelas LevelContentCreation saya :
public static class LevelContentCreation
{
private static Dictionary<char, TileCreationInfo> AvailableTiles =
CreateAvailableTiles();
private static List<string> AvailableTileSheets { get; set; }
/* ... rest of the class */
}
Sekarang, karena kelas LevelContentCreation adalah bagian dari perpustakaan permainan, ekstensi pipa konten mencoba menggunakannya tetapi panggilan ke CreateAvailableTiles () tidak pernah terjadi dan saya tidak dapat memuat objek Level dari pipa konten.
Saya tahu ini karena pipa konten dijalankan sebelum kompilasi yang sebenarnya atau sesuatu seperti itu, tetapi bagaimana saya bisa memperbaiki masalahnya?
Saya tidak bisa benar-benar memindahkan kelas LevelContentCreation ke ekstensi pipa, karena kemudian kelas Level tidak akan dapat menggunakannya ... Saya sangat tersesat dan saya tidak tahu harus berbuat apa ... Saya tahu ini adalah keputusan desain yang sangat buruk, dan saya ingin jika seseorang dapat mengarahkan saya ke arah yang benar.
Terima kasih atas waktu berharga Anda.
Jika ada sesuatu yang tidak cukup jelas atau jika saya harus memberikan lebih banyak informasi / kode, silakan tinggalkan komentar di bawah ini.
Sedikit informasi lebih lanjut tentang proyek saya:
- Game - proyek game XNA Windows. Berisi referensi ke: Engine, GameLib dan GameContent
- GameLib - proyek perpustakaan game XNA. Berisi referensi ke: Engine
- GameContent - proyek konten XNA. Berisi referensi ke: LevelContentPipelineExtension
- Engine - proyek perpustakaan game XNA. Tidak ada referensi.
- LevelContentPipelineExtension - ekstensi pipa konten XNA. Berisi referensi ke: Engine dan GameLib
Saya tahu hampir tidak ada tentang XNA 4.0 dan saya sedikit bingung tentang bagaimana konten bekerja sekarang. Jika Anda memerlukan informasi lebih lanjut, beri tahu saya.
Jawaban:
Dalam kasus di mana Anda menggunakan lajang, kelas statis, atau variabel global, 99% waktu yang seharusnya Anda gunakan adalah layanan game . Layanan gim digunakan ketika Anda menginginkan satu instance kelas tersedia untuk semua kelas lain, tetapi penggabungan ketat dari opsi lain memberi Anda rasa lucu. Layanan juga tidak memiliki masalah instantiasi yang Anda lihat, mereka lebih dapat digunakan kembali, dan mereka dapat diejek (jika Anda peduli dengan pengujian unit otomatis) .
Untuk mendaftarkan layanan, Anda harus memberikan antarmuka sendiri pada kelas Anda. Lalu panggil saja
Game.Services.AddService()
. Untuk menggunakan layanan itu nanti di kelas lain, hubungiGame.Services.GetService()
.Dalam kasus Anda, kelas Anda akan terlihat seperti ini:
Pada titik tertentu di awal program, Anda harus mendaftarkan layanan Anda
Game.Services
. Saya lebih suka melakukan ini di awalLoadContent()
, tetapi beberapa orang lebih suka mendaftarkan setiap layanan di konstruktor kelas itu.Sekarang kapan pun Anda ingin mengakses
LevelContentCreation
kelas Anda di kelas lain, Anda cukup melakukan ini:Sebagai catatan, paradigma ini dikenal sebagai Inversion of Control (IoC), dan banyak digunakan di luar pengembangan XNA juga. Kerangka kerja paling populer untuk IoC di. Net adalah Ninject , yang memiliki sintaksis lebih bagus daripada metode Game.Services:
Ini juga mendukung injeksi ketergantungan , suatu bentuk IoC yang sedikit lebih kompleks, tetapi jauh lebih baik untuk digunakan.
[Sunting] Tentu saja, Anda juga bisa mendapatkan sintaks yang bagus dengan XNA:
sumber
Saya benar-benar menemukan cara untuk memperbaiki masalah: Saya menghapus kelas statis dan menjadikannya kelas normal. Dengan cara ini saya yakin pernyataan yang tepat akan dieksekusi pada waktu yang tepat.
Saya berharap saya tidak menyia-nyiakan waktu Anda seperti itu tetapi saya benar-benar mendapat ide untuk melakukannya dengan membaca komentar / jawaban.
Terima kasih.
sumber
if
/switch
pernyataan yang hanya mengembalikan tipe yang berbeda, Anda mungkin ingin nilai-nilai itu menjadi bagian dari kelas. Dalam kasus Anda, saya akan membuatTileType
kelas, yang berisi informasi (tekstur, simpan-file-surat, dll) tentang setiap jenis ubin. Kemudian untuk mendapatkanTileType
dari surat, cukup cari melalui daftar AndaTileTypes
, atau jika Anda khawatir tentang kinerja, simpan statisDictionary<char, TileType>
diTileType
kelas (Anda dapat mengisinya secara otomatis diTileType
konstruktor).Tile
(kelas yang mewakili ubin tunggal ditampilkan di layar) akan merujuk satuTileType
. Jika cukup ubin Anda memiliki perilaku unik yang memerlukan kode khusus, Anda akan ingin menggunakan hierarki kelas.Lihat ini: http://msdn.microsoft.com/en-us/library/bb447745.aspx
Untuk tata letak level saya baru saja meletakkan fungsi di dalam kelas Level saya yang disebut "LoadFromFile (nama string)". Karena jika Anda ingin menambahkan dukungan untuk peta khusus di game Anda nanti, Anda harus menyimpan dan memuat level dari format file Anda sendiri.
Anda juga masih dapat membuat importir konten, untuk memuat dari aset yang disertakan dan juga dari file yang disediakan pengguna. Lihat halaman ini untuk informasi lebih lanjut tentang cara membuat importir
http://msdn.microsoft.com/en-us/library/bb447743.aspx
sumber