Adakah pola untuk memodelkan permainan papan? [Tutup]


93

Untuk bersenang-senang, saya mencoba menulis salah satu permainan papan favorit anak saya sebagai perangkat lunak. Akhirnya saya berharap untuk membangun UI WPF di atasnya, tetapi saat ini saya sedang membangun mesin yang memodelkan game dan aturannya.

Saat saya melakukan ini, saya terus melihat masalah yang menurut saya umum terjadi pada banyak permainan papan, dan mungkin orang lain telah menyelesaikannya lebih baik daripada yang saya lakukan.

(Perhatikan bahwa AI untuk memainkan game, dan pola seputar kinerja tinggi tidak menarik bagi saya.)

Sejauh ini pola saya adalah:

  • Beberapa tipe tetap yang mewakili entitas dalam kotak permainan, misalnya dadu, catur, kartu, papan, spasi di papan, uang, dll.

  • Objek untuk setiap pemain, yang berisi sumber daya pemain (misalnya uang, skor), nama mereka, dll.

  • Objek yang mewakili keadaan permainan: para pemain, siapa yang memutarnya, tata letak bagian-bagian di papan, dll.

  • Mesin negara yang mengatur urutan belokan. Misalnya, banyak game memiliki pra-permainan kecil di mana setiap pemain berguling untuk melihat siapa yang lebih dulu; itulah kondisi awal. Saat giliran pemain dimulai, pertama mereka berguling, lalu bergerak, kemudian mereka harus menari di tempat, lalu pemain lain menebak jenis ayam apa mereka, lalu mereka menerima poin.

Apakah ada seni sebelumnya yang dapat saya manfaatkan?

EDIT: Satu hal yang saya sadari baru-baru ini adalah bahwa status game dapat dibagi menjadi dua kategori:

  • Keadaan artefak game . "Saya punya $ 10" atau "tangan kiri saya di atas biru".

  • Status urutan game . "Saya telah menggulung ganda dua kali; yang berikutnya menempatkan saya di penjara". Mesin negara mungkin masuk akal di sini.

EDIT: Apa yang sebenarnya saya cari di sini adalah cara terbaik untuk mengimplementasikan game multiplayer berbasis giliran seperti Catur atau Scrabble atau Monopoli. Saya yakin saya bisa membuat permainan seperti itu hanya dengan mengerjakannya dari awal sampai akhir, tetapi, seperti Pola Desain lainnya, mungkin ada beberapa cara untuk membuat segalanya berjalan lebih lancar yang tidak terlihat jelas tanpa studi yang cermat. Itulah yang saya harapkan.


3
Anda sedang membangun semacam Hokey Pokey, Monopoli, sandiwara mashup?
Anthony Mastrean

Anda akan menginginkan mesin negara untuk aturan apa pun yang bergantung pada negara bagian (err ...) seperti aturan tiga ganda untuk Monopoli. Saya akan memposting jawaban yang lebih lengkap tetapi saya tidak memiliki pengalaman melakukan ini. Aku bisa memberi tahu tentang itu.
MSN

Jawaban:


115

Sepertinya ini adalah utas berusia 2 bulan yang baru saja saya perhatikan sekarang, tapi apa-apaan ini. Saya telah merancang dan mengembangkan kerangka permainan untuk permainan papan komersial berjaringan sebelumnya. Kami memiliki pengalaman yang sangat menyenangkan bekerja dengannya.

Permainan Anda mungkin dapat berada dalam (hampir) jumlah status yang tidak terbatas karena permutasi dari hal-hal seperti berapa banyak uang yang dimiliki pemain A, berapa banyak uang yang dimiliki pemain B, dan lain-lain ... Oleh karena itu, saya yakin Anda menginginkannya untuk menjauh dari mesin negara.

Ide di balik kerangka kerja kami adalah untuk merepresentasikan status game sebagai struktur dengan semua bidang data yang bersama-sama menyediakan status game lengkap (misalnya: jika Anda ingin menyimpan game ke disk, tulis struktur itu).

Kami menggunakan Pola Perintah untuk mewakili semua tindakan permainan valid yang dapat dilakukan pemain. Ini akan menjadi contoh tindakan:

class RollDice : public Action
{
  public:
  RollDice(int player);

  virtual void Apply(GameState& gameState) const; // Apply the action to the gamestate, modifying the gamestate
  virtual bool IsLegal(const GameState& gameState) const; // Returns true if this is a legal action
};

Jadi, Anda melihat bahwa untuk memutuskan apakah suatu langkah valid, Anda dapat membuat tindakan itu dan kemudian memanggil fungsi IsLegal-nya, meneruskan status game saat ini. Jika valid, dan pemain mengonfirmasi tindakannya, Anda dapat memanggil fungsi Terapkan untuk benar-benar mengubah status game. Dengan memastikan bahwa kode permainan Anda hanya dapat mengubah keadaan permainan dengan membuat dan mengirimkan Tindakan hukum (jadi dengan kata lain, kelompok metode Action :: Apply adalah satu-satunya hal yang secara langsung mengubah keadaan permainan), maka Anda memastikan bahwa permainan Anda negara tidak akan pernah valid. Selanjutnya, dengan menggunakan pola perintah, Anda memungkinkan untuk membuat serialisasi gerakan yang diinginkan pemain Anda dan mengirimkannya melalui jaringan untuk dieksekusi pada status permainan pemain lain.

Akhirnya ada satu gotcha dengan sistem ini yang ternyata memiliki solusi yang cukup elegan. Terkadang tindakan memiliki dua fase atau lebih. Misalnya, pemain dapat mendarat di properti di Monopoli dan sekarang harus membuat keputusan baru. Bagaimana keadaan permainan antara saat pemain melempar dadu, dan sebelum mereka memutuskan untuk membeli properti atau tidak? Kami mengelola situasi seperti ini dengan menampilkan anggota "Konteks Aksi" dari status game kami. Konteks tindakan biasanya nol, yang menunjukkan bahwa game saat ini tidak dalam keadaan khusus. Saat pemain melempar dadu dan tindakan melempar dadu diterapkan ke status permainan, ia akan menyadari bahwa pemain telah mendarat di properti yang tidak dimiliki, dan dapat membuat "PlayerDecideToPurchaseProperty" baru konteks tindakan yang berisi indeks pemain yang kami tunggu keputusannya. Pada saat tindakan RollDice selesai, status permainan kami menyatakan bahwa saat ini sedang menunggu pemain yang ditentukan untuk memutuskan apakah akan membeli properti atau tidak. Sekarang mudah bagi semua metode IsLegal tindakan lainnya untuk menampilkan false, kecuali untuk tindakan "BuyProperty" dan "PassPropertyPurchaseOpportunity", yang hanya legal jika status game memiliki konteks tindakan "PlayerDecideToPurchaseProperty".

Melalui penggunaan konteks aksi, tidak pernah ada satu titik pun dalam waktu hidup game papan di mana struktur status game tidak sepenuhnya mewakili PERSIS apa yang terjadi dalam game pada titik waktu tersebut. Ini adalah properti yang sangat diinginkan dari sistem permainan papan Anda. Akan jauh lebih mudah bagi Anda untuk menulis kode saat Anda dapat menemukan semua yang ingin Anda ketahui tentang apa yang terjadi dalam game dengan hanya memeriksa satu struktur.

Selain itu, ini meluas dengan sangat baik ke lingkungan jaringan, di mana klien dapat mengirimkan tindakan mereka melalui jaringan ke mesin host, yang dapat menerapkan tindakan tersebut ke status permainan "resmi" host, dan kemudian menggemakan tindakan itu kembali ke semua klien lain untuk minta mereka menerapkannya ke status game yang direplikasi.

Saya harap ini singkat dan bermanfaat.


4
Menurut saya ini tidak ringkas, tetapi sangat membantu! Suara positif.
Jay Bazuzi

Senang itu membantu ... Bagian mana yang tidak ringkas? Saya akan dengan senang hati melakukan edit klarifikasi.
Andrew Top

Saya sedang membangun game berbasis giliran sekarang dan postingan ini sangat membantu!
Kiv

Saya membaca bahwa Memento adalah pola yang digunakan untuk mengurungkan ... Memento vs Pola Perintah untuk mengurungkan,
tolong

Ini adalah jawaban terbaik yang saya baca di Stackoverflow sejauh ini. TERIMA KASIH!
Papipo

18

Struktur dasar mesin game Anda menggunakan Pola Status . Item kotak permainan Anda adalah lajang dari berbagai kelas. Struktur setiap negara bagian dapat menggunakan Pola Strategi atau Metode Template .

Sebuah Pabrik digunakan untuk membuat pemain yang dimasukkan ke dalam daftar pemain, tunggal lain. GUI akan mengawasi Game Engine dengan menggunakan pola Observer dan berinteraksi dengannya dengan menggunakan salah satu dari beberapa objek Perintah yang dibuat menggunakan Pola Perintah . Penggunaan Observer dan Command dapat digunakan dengan dalam konteks Tampilan Pasif. Tetapi hampir semua pola MVP / MVC dapat digunakan tergantung pada preferensi Anda. Saat Anda menyimpan game, Anda perlu mengambil kenang - kenangan tentang keadaannya saat ini

Saya merekomendasikan untuk melihat beberapa pola di situs ini dan melihat apakah ada yang menarik Anda sebagai titik awal. Sekali lagi jantung papan permainan Anda akan menjadi mesin negara. Kebanyakan game akan diwakili oleh dua keadaan pra-permainan / pengaturan dan permainan sebenarnya. Tetapi Anda dapat memiliki lebih banyak status jika game yang Anda modelkan memiliki beberapa mode permainan yang berbeda. Status tidak harus berurutan misalnya wargame Axis & Battles memiliki papan pertempuran yang dapat digunakan pemain untuk menyelesaikan pertempuran. Jadi ada tiga keadaan pra-permainan, papan utama, papan pertempuran dengan permainan terus-menerus beralih antara papan utama dan papan pertempuran. Tentu saja urutan belokan juga dapat diwakili oleh mesin negara.


15

Saya baru saja selesai merancang dan mengimplementasikan game berbasis negara menggunakan polimorfisme.

Menggunakan kelas abstrak dasar yang disebut GamePhaseyang memiliki satu metode penting

abstract public GamePhase turn();

Artinya setiap GamePhaseobjek memegang status game saat ini, dan panggilan untuk turn()melihat status saat ini dan mengembalikan status berikutnya GamePhase.

Setiap beton GamePhasememiliki konstruktor yang menahan seluruh status permainan. Setiap turn()metode memiliki sedikit aturan permainan di dalamnya. Meskipun ini menyebarkan aturan, itu membuat aturan terkait tetap dekat. Hasil akhir dari masing-masing turn()hanyalah membuat yang berikutnya GamePhasedan meneruskan dalam keadaan penuh ke fase berikutnya.

Ini memungkinkan turn()untuk menjadi sangat fleksibel. Bergantung pada gim Anda, status tertentu dapat bercabang ke berbagai jenis fase. Ini membentuk grafik dari semua fase permainan.

Pada level tertinggi, kode untuk menjalankannya sangat sederhana:

GamePhase state = ...initial phase
while(true) {
    // read the state, do some ui work
    state = state.turn();
}

Ini sangat berguna karena saya sekarang dapat dengan mudah membuat keadaan / fase game apa pun untuk pengujian

Sekarang untuk menjawab bagian kedua dari pertanyaan Anda, bagaimana cara kerjanya dalam multipemain? Dalam tertentu GamePhases yang memerlukan input pengguna, panggilan dari turn()akan meminta saat Playermereka Strategymengingat saat ini negara / fase. Strategyhanyalah antarmuka dari semua kemungkinan keputusan yang Playerbisa dibuat. Pengaturan ini juga memungkinkan Strategyuntuk diimplementasikan dengan AI!

Juga Andrew Top berkata:

Permainan Anda mungkin dapat berada dalam (hampir) jumlah status yang tidak terbatas karena permutasi dari hal-hal seperti berapa banyak uang yang dimiliki pemain A, berapa banyak uang yang dimiliki pemain B, dan lain-lain ... Oleh karena itu, saya yakin Anda menginginkannya untuk menjauh dari mesin negara.

Menurut saya pernyataan itu sangat menyesatkan, meskipun benar ada banyak status game yang berbeda, hanya ada beberapa fase game. Untuk menangani contohnya, semua itu akan menjadi parameter integer ke konstruktor beton saya GamePhase.

Monopoli

Contoh dari beberapa GamePhaseadalah:

  • GameStarts
  • PlayerRolls
  • PlayerLandsOnProperty (FreeParking, GoToJail, Go, dll)
  • PlayerTrades
  • PlayerPurchasesProperty
  • PlayerPurchasesHouses
  • PlayerPurchasesHotels
  • PlayerPaysRent
  • PlayerBankrupts
  • (Semua kartu Chance dan Community Chest)

Dan beberapa negara bagian di pangkalan GamePhaseadalah:

  • Daftar Pemain
  • Pemain Saat Ini (giliran siapa)
  • Uang / Properti Pemain
  • Rumah / Hotel di Properti
  • Posisi pemain

Dan kemudian beberapa fase akan merekam statusnya sendiri sesuai kebutuhan, misalnya PlayerRolls akan mencatat berapa kali seorang pemain menggulung ganda berturut-turut. Setelah kami meninggalkan fase PlayerRolls, kami tidak lagi peduli dengan gulungan yang berurutan.

Banyak fase yang dapat digunakan kembali dan ditautkan bersama. Misalnya, GamePhase CommunityChestAdvanceToGoakan membuat fase berikutnya PlayerLandsOnGodengan keadaan saat ini dan mengembalikannya. Dalam konstruktor PlayerLandsOnGo, pemain saat ini akan dipindahkan ke Go dan uang mereka akan bertambah $ 200.


8

Tentu saja ada banyak, banyak, banyak, banyak, banyak, banyak, banyak, banyak sekali, sumber daya tentang topik ini. Tapi saya pikir Anda berada di jalur yang benar membagi objek dan membiarkan mereka menangani kejadian / datanya sendiri dan seterusnya.

Saat melakukan permainan papan berbasis ubin, Anda akan merasa senang memiliki rutinitas untuk memetakan antara susunan papan dan baris / kolom dan belakang, bersama fitur lainnya. Saya ingat permainan papan pertama saya (dulu sekali) ketika saya berjuang dengan cara mendapatkan baris / kolom dari boardarray 5.

1  2  3  
4 (5) 6  BoardArray 5 = row 2, col 2
7  8  9  

Nostalgia. ;)

Bagaimanapun, http://www.gamedev.net/ adalah tempat yang baik untuk mendapatkan informasi. http://www.gamedev.net/reference/


Mengapa Anda tidak menggunakan array 2 dimensi saja? Kemudian kompilator dapat menangani ini untuk Anda.
Jay Bazuzi

Alasan saya adalah ini sudah lama sekali. ;)
Stefan

1
gamedev memiliki banyak barang, tapi saya tidak melihat apa yang saya cari.
Jay Bazuzi

bahasa apa yang kamu gunakan
zotherstupidguy

Basic, Basica, QB, QuickBasic, dan sebagainya. ;)
Stefan


3

Three Rings menawarkan pustaka Java LGPL. Nenya dan Vilya adalah perpustakaan untuk hal-hal yang berhubungan dengan game.

Tentu saja, akan membantu jika pertanyaan Anda menyebutkan platform dan / atau batasan bahasa yang mungkin Anda miliki.


"Akhirnya saya berharap untuk membangun UI WPF" - artinya .NET. Setidaknya, sejauh yang saya tahu.
Mark Allen

Sup alfabet yang saya tidak tahu.
jmucchiello

Ya, saya melakukan .NET, tetapi pertanyaan saya bukanlah bahasa- atau platform-spesifik.
Jay Bazuzi

2

Saya setuju dengan jawaban Pyrolistik dan saya lebih suka caranya melakukan sesuatu (saya hanya membaca sekilas jawaban yang lain).

Secara kebetulan saya juga menggunakan penamaan "GamePhase" -nya. Pada dasarnya apa yang akan saya lakukan dalam kasus permainan papan berbasis giliran adalah membuat kelas GameState Anda berisi objek GamePhase abstrak seperti yang disebutkan oleh Pyrolistic.

Katakanlah status permainannya adalah:

  1. Gulungan
  2. Pindah
  3. Beli / Jangan beli
  4. Penjara

Anda bisa memiliki kelas turunan konkret untuk setiap negara bagian. Memiliki fungsi virtual setidaknya untuk:

StartPhase();
EndPhase();
Action();

Dalam fungsi StartPhase () Anda dapat mengatur semua nilai awal untuk suatu keadaan misalnya menonaktifkan input pemain lain dan sebagainya.

Saat roll.EndPhase () dipanggil, pastikan penunjuk GamePhase disetel ke status berikutnya.

phase = new MovePhase();
phase.StartPhase();

Dalam MovePhase :: StartPhase () ini, Anda misalnya akan mengatur gerakan pemain aktif yang tersisa ke jumlah yang digulung di fase sebelumnya.

Sekarang dengan desain ini di tempat Anda dapat menyelesaikan masalah "3 x double = jail" Anda di dalam fase Roll. Kelas RollPhase dapat menangani statusnya sendiri. Sebagai contoh

GameState state; //Set in constructor.
Die die;         // Only relevant to the roll phase.
int doublesRemainingBeforeJail;
StartPhase()
{
    die = new Die();
    doublesRemainingBeforeJail = 3;
}

Action()
{
    if(doublesRemainingBeforeJail<=0)
    {
       state.phase = new JailPhase(); // JailPhase::StartPhase(){set moves to 0};            
       state.phase.StartPhase();
       return;
    }

    int die1 = die.Roll();
    int die2 = die.Roll();

    if(die1 == die2)
    {
       --doublesRemainingBeforeJail;
       state.activePlayer.AddMovesRemaining(die1 + die2);
       Action(); //Roll again.
    }

    state.activePlayer.AddMovesRemaining(die1 + die2);
    this.EndPhase(); // Continue to moving phase. Player has X moves remaining.
}

Saya berbeda dari Pyrolistik karena harus ada fase untuk semuanya termasuk ketika pemain mendarat di peti Komunitas atau sesuatu. Saya akan menangani ini semua di MovePhase. Ini karena jika Anda memiliki terlalu banyak fase berurutan, pemain kemungkinan besar akan merasa terlalu "dipandu". Misalnya, jika ada fase di mana pemain HANYA dapat membeli properti dan kemudian HANYA membeli hotel dan kemudian HANYA membeli rumah, itu seperti tidak ada kebebasan. Cukup banting semua bagian itu menjadi satu BuyPhase dan berikan pemain kebebasan untuk membeli apa pun yang dia inginkan. Kelas BuyPhase dapat dengan mudah menangani pembelian mana yang legal.

Akhirnya mari kita bahas gameboard. Meskipun array 2D baik-baik saja, saya akan merekomendasikan memiliki grafik ubin (di mana ubin adalah posisi di papan). Dalam kasus monopoli, daftar itu lebih suka menjadi daftar yang ditautkan ganda. Maka setiap ubin akan memiliki:

  1. PreviousTile
  2. nextTile

Jadi, akan lebih mudah untuk melakukan sesuatu seperti:

While(movesRemaining>0)
  AdvanceTo(currentTile.nextTile);

Fungsi AdvanceTo dapat menangani animasi langkah demi langkah atau apa pun yang Anda suka. Dan juga pengurangan sisa gerakan tentunya.

Saran RS Conley tentang Pola Pengamat untuk GUI bagus.

Saya belum banyak memposting sebelumnya. Semoga ini bisa membantu seseorang.


1

Apakah ada seni sebelumnya yang dapat saya manfaatkan?

Jika pertanyaan Anda bukan tentang bahasa atau platform tertentu. maka saya akan merekomendasikan agar Anda mempertimbangkan Pola AOP untuk Negara, Memento, Perintah, dll.

Apa jawaban NET untuk AOP ???

Coba juga temukan beberapa situs web keren seperti http://www.chessbin.com

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.