Menyandikan status berbeda di Game Petualangan


12

Saya merencanakan permainan petualangan, dan tidak tahu apa cara yang tepat untuk menerapkan perilaku tingkat tergantung pada tingkat perkembangan cerita.

Permainan pemain tunggal saya menampilkan dunia yang sangat besar di mana pemain harus berinteraksi dengan orang-orang di kota di berbagai titik dalam permainan. Namun, tergantung pada perkembangan cerita, hal-hal yang berbeda akan disajikan kepada pemain, misalnya Pemimpin Guild akan mengubah lokasi dari alun-alun kota ke berbagai lokasi di sekitar kota; Pintu hanya akan membuka pada waktu-waktu tertentu dalam sehari setelah menyelesaikan rutinitas tertentu; Acara cut-screen / trigger yang berbeda terjadi hanya setelah tonggak pencapaian tertentu telah tercapai.

Saya secara naif berpikir untuk menggunakan pernyataan switch {} pada awalnya untuk memutuskan apa yang harus dikatakan oleh NPC atau di mana ia dapat ditemukan, dan membuat tujuan pencarian hanya dapat berinteraksi setelah memeriksa kondisi variabel game_state global. Tetapi saya menyadari bahwa saya akan dengan cepat mengalami banyak keadaan permainan dan saklar-kasus yang berbeda untuk mengubah perilaku suatu objek. Pernyataan peralihan itu juga akan sangat sulit untuk di-debug, dan saya kira mungkin juga akan sulit untuk digunakan dalam editor tingkat.

Jadi saya berpikir, alih-alih memiliki satu objek dengan banyak status, mungkin saya harus memiliki beberapa instance dari objek yang sama, dengan satu status. Dengan begitu, jika saya menggunakan sesuatu seperti editor level, saya dapat menempatkan instance NPC di semua lokasi berbeda yang pernah ia temui, dan juga sebuah instance untuk setiap status percakapan yang ia miliki. Tapi itu berarti akan ada banyak objek permainan yang tidak aktif dan tidak terlihat mengambang di sekitar level, yang mungkin kesulitan untuk memori, atau hanya sulit dilihat di editor level, saya tidak tahu.

Atau sederhananya, buat level yang identik, tetapi terpisah untuk setiap kondisi permainan. Ini terasa cara terbersih dan bebas bug untuk melakukan sesuatu, tetapi rasanya seperti kerja manual besar memastikan setiap versi level benar-benar identik satu sama lain.

Semua metode saya terasa sangat tidak efisien, sehingga untuk merangkum pertanyaan saya, apakah ada cara yang lebih baik atau standar untuk menerapkan perilaku tingkat tergantung pada tingkat perkembangan cerita?

PS: Saya belum memiliki editor level - berpikir untuk menggunakan sesuatu seperti JME SDK atau membuat milik saya.

Jawaban:


9

Saya pikir apa yang Anda butuhkan dalam kasus ini adalah Pola Desain Negara . Alih-alih memiliki beberapa instance dari setiap objek game, buat instance tunggal, tetapi enkapsulasi perilakunya dalam kelas yang terpisah. Buat beberapa kelas, satu untuk setiap perilaku yang mungkin, dan berikan semua kelas antarmuka yang sama. Kaitkan satu ke objek game Anda (keadaan awal) dan, ketika kondisi berubah (tonggak pencapaian tercapai, waktu hari berlalu, dll) Anda mengganti status objek itu (yaitu mengaitkannya dengan objek yang berbeda tergantung pada logika permainan Anda) dan perbarui propertinya jika berlaku.

Salah satu contoh tampilan antarmuka negara (dibuat sepenuhnya - hanya untuk menggambarkan tingkat kontrol yang diberikan skema ini kepada Anda):

interface NPCState {
    Scene whereAmI(NPC o);
    String saySomething(NPC o);
}

Dan dua kelas pelaksana:

class Busy implements NPCState {
    Scene whereAmI(NPC o) {
        return o.getWorkScene();
    }
    String saySomething(NPC o) {
        return "Can't talk now, I'm busy!";
    }
}

class Available implements NPCState {
    Scene whereAmI(NPC o) {
        return TAVERN;
    }
    String saySomething(NPC o) {
        String[] choices = o.getRandomChat();
        return choices[RANDOM.getInt(choices.length)];
    }
}

Dan beralih status:

// The time of day passed from "afternoon" to "evening"
NPCState available = new Available();
for ( NPC o : list ) {
    Scene oldScene = o.state.whereAmI(o);
    o.state = available;
    Scene newScene = o.state.whereAmI(o);
    moveGameObject(o, oldScene, newScene);
    ...

NPC penting mungkin memiliki status khusus mereka, logika pemilihan status mungkin lebih dapat disesuaikan, dan Anda dapat memiliki status berbeda untuk berbagai aspek permainan (dalam contoh ini, saya menggunakan satu kelas untuk memberi tahu lokasi dan obrolan, tetapi Anda dapat memisahkan mereka dan melakukan banyak kombinasi).

Ini berfungsi baik dengan editor level juga: Anda dapat memiliki kotak kombo sederhana untuk mengganti status "global" level, lalu menambahkan dan memposisikan ulang objek game seperti yang Anda inginkan muncul di status itu. Mesin game akan bertanggung jawab hanya untuk benar-benar "menambahkan" objek ke adegan ketika memiliki kondisi yang benar - tetapi parameternya masih dapat diedit dengan cara yang ramah pengguna.

(Penafian: Saya memiliki sedikit pengalaman dunia nyata dengan editor permainan, jadi saya dapat mengatakan dengan percaya diri tentang bagaimana editor profesional bekerja; tetapi poin saya tentang Pola Negara masih berlaku, mengatur kode Anda dengan cara ini harus bersih, dapat dipertahankan, dan bukan sistem pemborosan sumber daya.)


Anda tahu, Anda bisa menggabungkan pola desain keadaan ini dengan array asosiatif yang saya jelaskan. Anda bisa mengkode objek negara seperti yang dijelaskan di sini, lalu memilih antara objek negara yang berbeda menggunakan array asosiatif seperti yang saya sarankan.
jhocking

Saya setuju, itu juga baik untuk memisahkan game dari mesinnya, dan logika game hardcoding memperkuat kopling di antara mereka (mengurangi kemungkinan penggunaan kembali). Namun, ada kompromi, karena tergantung pada kompleksitas perilaku yang Anda maksudkan dengan mencoba "kode lunak", semuanya dapat mengakibatkan kekacauan yang tidak perlu . Dalam kasus ini, pendekatan campuran mungkin diinginkan (yaitu memiliki logika transisi status "generik", tetapi memungkinkan kode kustom untuk dimasukkan juga)
mgibsonbr

Jadi seperti yang saya pahami, ada pemetaan satu-ke-satu btwn NPCState dan GameState. Lalu aku akan meletakkan NPC dalam array dan beralih melalui itu, menugaskan NPCState baru ketika perubahan status game diamati. NPCState harus mampu mengetahui bagaimana menangani setiap NPC berbeda yang dikirim kepadanya, jadi pada dasarnya NPCState berisi perilaku semua NPC untuk keadaan tertentu? Saya suka semua perilaku disimpan dengan rapi dalam satu NPCState, yang memetakan secara bersih untuk implementasi editor game, tetapi itu agaknya membuat NPCState cukup besar.
Cardin

Oh, kurasa aku salah paham tentang ans. Saya mengubahnya sedikit untuk memasukkan pengamat. Jadi itu adalah satu NPCState berbeda untuk setiap NPC berbeda, kecuali yang super generik seperti NPC Crowd yang dapat berbagi keadaan. Untuk setiap kondisi permainan, NPC akan mendaftarkan dirinya dan NPCState-nya dengan seorang Pengamat. Oleh karena itu Pengamat akan tahu persis NPC mana yang terdaftar untuk mengubah perilaku di mana kondisi permainan, dan hanya mengulanginya. Dan di sisi editor game, editor game hanya harus memberikan sinyal kepada Pengamat untuk mengubah keadaan seluruh level.
Cardin

1
Ya, itulah idenya! NPC penting akan memiliki banyak negara, dan transisi negara akan sangat bergantung pada tonggak yang telah selesai. NPC umum juga terkadang bereaksi terhadap tonggak pencapaian, dan bahkan keadaan yang mereka pilih bergantung pada properti internal (misalkan semua NPC memiliki status awal default, dan ketika Anda berbicara dengan salah satu dari mereka untuk pertama kalinya ia memperkenalkan dirinya, kemudian masukkan siklus peralihan keadaan normal).
mgibsonbr

2

Pilihan yang akan saya pertimbangkan adalah membuat objek individual merespons gamestate yang berbeda, atau melayani level yang berbeda di gamestate yang berbeda. Pilihan di antara keduanya akan tergantung pada apa yang sebenarnya saya coba lakukan dalam game (apa status berbeda? Bagaimana transisi game antara status? Dll.)

Bagaimanapun, saya tidak akan melakukannya dengan mengkodekan status ke dalam kode permainan. Daripada pernyataan peralihan besar-besaran di objek NPC, saya lebih memilih perilaku NPC yang dimuat ke dalam array asosiatif dari file data dan kemudian menggunakan array asosiatif tersebut untuk menjalankan perilaku berbeda untuk status asosiasinya, seperti ini:

if (state in behaviors) {
  behaviors[state]();
}

Apakah file data itu menjadi semacam bahasa scripting? Saya pikir file data teks biasa mungkin tidak cukup untuk menggambarkan perilaku. Bagaimanapun, Anda benar bahwa itu harus dimuat secara dinamis. Saya tidak bisa berpikir untuk menggunakan editor game untuk menghasilkan kode Java yang valid, itu pasti harus diuraikan.
Cardin

1
Yah itu adalah pemikiran awal saya, tetapi setelah melihat jawaban mgibsonbr saya menyadari bahwa Anda dapat mengkodekan berbagai bevavior sebagai kelas yang terpisah dan kemudian dalam file data hanya mengatakan kelas perilaku mana yang sesuai dengan keadaan yang mana. Muat data itu ke dalam array asosiatif saat runtime.
jhocking

Oh .. Ya itu pasti lebih sederhana! : D Dibandingkan dengan skenario menanamkan sesuatu seperti Lua haha ​​..
Cardin

2

Bagaimana dengan menggunakan pola pengamat untuk mencari perubahan-tonggak sejarah? Jika perubahan terjadi, beberapa kelas akan mengenali ini dan menangani misalnya perubahan yang harus dilakukan ke NPC.

Alih-alih pola desain keadaan yang disebutkan saya akan menggunakan strategi-pola.

Jika sebuah npc memiliki n cara untuk berinteraksi dengan posisi karakter dan m di mana ia berada, ada maksimum (m * n) +1 kelas yang harus Anda desain. Menggunakan pola-strategi Anda akan berakhir dengan n + m + 1 kelas tetapi strategi ini juga dapat digunakan oleh npcs lainnya.

Jadi mungkin ada kelas yang menangani tonggak sejarah, dan kelas yang mengamati kelas ini dan menangani baik NPC atau musuh atau apa pun yang harus diubah. Jika pengamat diperbarui, mereka akan memutuskan apakah mereka harus mengubah sesuatu sesuai contoh yang mereka atur. Kelas NPC misalnya akan, dalam konstruktor, memberi tahu NPC-Manager kapan ia harus diperbarui dan apa yang harus diperbarui ...


Pola Pengamat tampaknya menarik. Saya pikir itu bisa dengan bersih meninggalkan semua tanggung jawab dengan NPC untuk mendaftar sendiri dengan pengamat negara. Pola Strategi terasa seperti perilaku Pemicu dan AI Unity Engine, yang digunakan untuk berbagi perilaku dengan objek permainan yang berbeda (saya pikir). Kedengarannya layak. Saya tidak yakin apa pro / kontra saat ini, tetapi bahwa Unity menggunakan metode yang sama juga agak meyakinkan haha ​​..
Cardin

Saya hanya menggunakan dua pola ini beberapa kali jadi saya tidak dapat memberi tahu Anda tentang kontra: - / Tapi saya pikir itu bagus jika ada satu tanggung jawab dan ketersediaan untuk menguji setiap strategi :) Mungkin akan membingungkan jika Anda menggunakan strategi di banyak kelas yang berbeda dan Anda ingin menemukan setiap kelas yang menggunakannya.
TOAOGG

0

Semua pendekatan yang diberikan valid. Itu tergantung pada situasi Anda pada saat tertentu. Banyak petualangan atau MMO menggunakan kombinasi ini.

Misalnya, jika suatu peristiwa penting mengubah sebagian besar level (mis. Seorang penagih utang membersihkan apartemen Anda dan semua orang di dalamnya ditangkap), biasanya lebih mudah untuk mengganti seluruh ruangan dengan kamar kedua yang terlihat serupa.

OTOH, jika karakter berjalan di sekitar peta dan melakukan hal yang berbeda di tempat yang berbeda, Anda sering memiliki aktor tunggal yang berputar melalui objek perilaku yang berbeda (Misalnya berjalan lurus ke depan / tidak ada percakapan vs. berdiri di sini / percakapan tentang kematian Mitch), yang mungkin termasuk "disembunyikan" jika tujuan mereka telah terpenuhi.

Yang mengatakan, biasanya memiliki duplikat objek yang Anda buat secara manual seharusnya tidak menimbulkan masalah. Berapa banyak objek yang dapat Anda buat? Jika Anda dapat membuat lebih banyak objek daripada yang dapat dilakukan permainan Anda, lihat properti "tersembunyi" mereka dan lewati, mesin Anda terlalu lambat. Jadi saya tidak akan terlalu khawatir tentang itu. Banyak game online yang melakukan ini. Karakter atau item tertentu selalu ada, tetapi tidak ditampilkan ke karakter yang tidak memiliki misi yang sesuai.

Anda bahkan dapat menggabungkan pendekatan: Memiliki dua pintu di gedung apartemen Anda. Satu mengarah ke apartemen "sebelum penagih utang", satu ke apartemen setelah. Ketika Anda memasuki koridor, hanya yang berlaku untuk kemajuan Anda dalam cerita yang benar-benar ditampilkan. Dengan begitu, Anda bisa memiliki mekanisme umum untuk "item terlihat pada titik saat ini dalam cerita" dan pintu dengan satu tujuan. Bergantian, Anda bisa membuat pintu yang lebih rumit yang dapat memiliki perilaku yang dapat ditukar, dan salah satunya adalah "pergi ke apartemen penuh", yang lain "pergi ke apartemen kosong". Ini mungkin tampak tidak masuk akal jika benar-benar hanya tujuan pintu berubah, tetapi jika penampilannya juga berubah (misalnya kunci besar di depan pintu yang pertama kali harus Anda retak),

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.