Menggunakan waktu idle dalam game berbasis giliran (RPG) untuk memperbarui

9

Jika Anda mengambil game RPG berbasis giliran, akan ada periode waktu yang besar ketika tidak ada yang terjadi karena game ini mengulangi 'wait_for_player_input'. Tentu saja tampaknya masuk akal untuk menggunakan waktu ini untuk memperbarui berbagai hal.

Namun, ini segera menunjukkan bahwa itu perlu di-threaded. Apakah desain semacam ini dimungkinkan dalam satu utas?

loop:  
if not check_something_pressed:  
    update_a_very_small_amount  
else  
  keep going

Tetapi jika kita mengatakan 'a_very_small_amount' hanya memperbarui satu objek setiap loop, itu akan sangat lambat saat memperbarui.

Bagaimana Anda akan melakukan ini, terutama dalam satu utas?

EDIT: Saya telah menandai bahasa ini-agnostik karena tampaknya hal yang masuk akal, meskipun sesuatu yang lebih spesifik untuk Python akan lebih bagus. ;-)

Sunting kedua: Game ini tidak berencana memiliki komponen animasi apa pun; yaitu, saya sedang menjalankannya sebagai input menunggu-pemain-kemudian memperbarui semuanya dan menggambar. Jadi daripada X FPS itu tergantung pada kecepatan pengguna.

Bebek Komunis
sumber

Jawaban:

7

Ya, itu mungkin dilakukan dalam satu utas. Namun secara umum, Anda harus memperbarui objek setiap frame dan tidak hanya ketika ada siklus cadangan. Animasi dan gerakan Anda akan terputus dari frame rate dan terlihat agak berombak jika tidak. Jika Anda berbicara lebih banyak tentang pembaruan AI atau hal lain yang tidak perlu real-time, saya akan meletakkan timer di atasnya. Anda harus tahu berapa frame rate target Anda dan waktu idle akan menjadi apa pun yang tersisa setelah semuanya selesai.

Katakanlah Anda menargetkan 60 FPS untuk game Anda. Itu membuat Anda dengan 16,667 ms untuk melakukan semua pekerjaan yang Anda butuhkan untuk melakukan setiap frame. Di awal permainan, dapatkan waktu saat ini menggunakan timer resolusi tertinggi yang tersedia, tambahkan 16,667 ms ke sana dan simpan di suatu tempat. Saya pikir fungsi dalam python adalah waktu () meskipun sudah lama sejak saya bekerja dalam bahasa. Setelah pemrosesan Anda selesai, masukkan loop yang memeriksa waktu saat ini terhadap waktu yang telah Anda rekam. Jika waktu saat ini kurang dari waktu akhir bingkai, perbarui_a_very_small_amount. Saya tidak akan terlalu khawatir tentang pemrosesan yang melewati akhir frame karena pembaruan kecil Anda harus cepat diproses. Ini hanya akan menjadi sedikit keterlambatan pada awal frame berikutnya dan Anda tampaknya memiliki waktu idle yang cukup untuk menanganinya.

Setelah frame selesai diproses, tambahkan 16,667 ms ke waktu yang disimpan untuk akhir frame terakhir untuk mengetahui di mana ujung frame berikutnya seharusnya. Jika Anda menggunakan waktu saat ini + 16,667 ms dan pemrosesan berjalan, akhir frame berikutnya akan didorong keluar oleh seberapa banyak waktu frame terakhir berlari.

Re: Edit Kedua

Untuk memperjelas, saya menggunakan istilah frame-rate di sini untuk menunjukkan satu iterasi melalui loop utama. Jika didasarkan pada kecepatan input pengguna, saya membayangkan bahwa tujuan Anda adalah membuat game terasa responsif. Kalau tidak, Anda bisa memeriksa input dan memperbarui semuanya setiap kali melalui loop bahkan jika diperlukan 10 detik untuk melakukannya. Untuk membuatnya merasa responsif, Anda mungkin ingin memeriksa input sekitar 20 kali per detik yang memberikan frame rate efektif 20 FPS, bahkan jika Anda tidak benar-benar menggambar frame ini. Ini akan memberi Anda 50 ms untuk memperbarui hal-hal sebelum Anda perlu memeriksa input lagi.

Joel Baker
sumber
2

Khusus untuk Python, Anda dapat mencoba dan menggunakan Coroutine untuk melakukan perhitungan melalui beberapa panggilan pembaruan.

... coroutine adalah komponen program yang menggeneralisasi subrutin untuk memungkinkan beberapa titik masuk untuk menunda dan melanjutkan eksekusi di lokasi tertentu ...

PEP-0342 merinci implementasi coroutine dengan Python.

Anda dapat membuat penjadwal dan tugas Anda sendiri yang dapat mensimulasikan multithreading pada satu utas. Ini adalah cara yang sama yang memungkinkan kerangka kerja Javascript untuk pemrosesan multithreaded meskipun Javascript dijalankan pada satu proses.

David Young
sumber
1

Ya ini mungkin. Game Anda akan memiliki semacam loop game utama. Sesuatu seperti ini:

while(gameRunning)
{
  checkUserInput()
  updateGame()
  renderGame()
}

Di updateGame Anda dapat mengulangi objek game Anda dan memperbaruinya "sedikit". Jika Anda melakukan perhitungan berat dalam metode ini, permainan akan hang. Jadi, Anda perlu cara untuk membagi perhitungan ini untuk menjalankan beberapa iterasi dari loop game.

Cara membaginya, tergantung pada jenis gim yang Anda bangun. Misalkan Anda memiliki rutin pencari jalan yang menggunakan A * untuk menghitung jalur melalui labirin. Anda perlu menghentikan algoritme setelah waktu tertentu atau setelah iterasi dalam jumlah tetap, menjaga jalur yang dihitung sejauh ini dan mengembalikan kontrol kembali ke loop game. Temuan jalur akan dilanjutkan saat pembaruanGame berikutnya dipanggil. Anda bahkan dapat memindahkan karakter di sepanjang jalur parsial saat sedang dihitung.

Sering kali Anda tidak perlu khawatir tentang panggilan pembaruanGame terlalu lama.

"Optimalisasi prematur adalah akar dari semua kejahatan!"
Jika Anda mengalami hambatan kinerja dalam rutinitas pembaruan Anda, itulah saatnya untuk menyelidiki dan mengoptimalkan. Karena Anda tidak dapat mengetahui sebelumnya bagian mana dari permainan Anda yang akan paling banyak mengambil waktu untuk menghitung dan mungkin membuang waktu untuk mengoptimalkan hal-hal yang salah.

Stephen
sumber
1

Cara saya memahami pertanyaan Anda adalah bahwa pada dasarnya Anda bertanya tentang kerja sama multitasking.

Infrastruktur dasar akan menjadi daftar fungsi pointer, semua disebut secara round-robin (kecuali diperlukan prioritas yang lebih canggih), dan semua fungsi ini akan melakukan "sedikit kerja", cukup kecil untuk tidak menyebabkan permainan menjadi lamban. Saya sudah melakukan ini di DOS sebelum utasnya panas, dan juga pada perangkat seluler yang tidak mendukung threading.

Pertanyaan yang lebih baik, menurut saya, adalah apa yang harus dilakukan sambil menunggu pemain bergerak. Hal-hal macam apa yang akan begitu intensif prosesor sehingga tidak dapat dilakukan dengan cepat, sementara, pada saat yang sama, menjadi sangat opsional sehingga jika pemain hanya memalu beberapa tombol gerakan dengan cukup cepat, permainan tidak memiliki waktu untuk memproses ini. Jadi, hal-hal seperti menghitung A * untuk beberapa ribu AI keluar.

Solusi yang lebih baik, menurut saya, adalah dengan hanya menghasilkan / tidur, dan membiarkan manajemen daya komputer melakukan tugasnya. Pengguna laptop akan lebih menyukai Anda.

Jari Komppa
sumber