Saya ingin sesuatu terjadi setiap N detik, bagaimana saya melakukannya? Mungkin menggunakan timer tapi bagaimana caranya?
Saya ingin sesuatu terjadi setiap N detik, bagaimana saya melakukannya? Mungkin menggunakan timer tapi bagaimana caranya?
Jawaban:
Pendekatan umum untuk ini adalah dengan menggunakan loop pembaruan dan waktu delta.
float timerCurrent = 0f;
float timerTotal = 5f;
Update() {
timerCurrent += deltaTime;
if(timerCurrent >= timerTotal) {
//do timer action
timerCurrent -= timerTotal;
}
}
Ini mengandaikan bahwa Anda memiliki akses ke deltaTime
variabel. Waktu Delta hanyalah waktu yang telah berlalu sejak frame terakhir. Banyak mesin akan menyediakan ini untuk Anda, atau Anda dapat mempelajari lebih lanjut tentang pengaturan sendiri di sini .
Di sebagian besar bahasa, Anda harus memulai jam dengan semacam pemanggilan fungsi di sepanjang baris clock.startTimer()
sebelum Anda memasuki loop utama. Kemudian, Anda harus menyimpan nilai waktu jam sebelum Anda memasukkan loop utama ke dalam variabel dengan fungsi seperti time = clock.getTime()
. Simpan waktu langkah Anda ke dalam variabel n
.
Di loop utama Anda, centang yang ingin Anda buat adalah sesuatu di sepanjang baris
if(time + n <= clock.getTime())
//do stuff
time = clock.getTime() //important to assign new time value here
Catatan: Saya tidak yakin bahasa / perpustakaan apa yang Anda lihat jadi ini hanya algoritma generik yang saya pikirkan. Ini mungkin tidak sesuai dengan kebutuhan Anda. Beberapa bahasa / pustaka mengharuskan Anda membuat objek jam, sementara yang lain Anda bisa langsung membuat panggilan fungsi.
Sesuai komentar di bawah ini, Anda harus berhati-hati dengan masalah threading tergantung pada bahasa yang Anda gunakan. Anda juga harus menggunakan pelampung ganda untuk menyimpan time
.
time
akan menyimpan waktu permainan yang telah berlalu, itu harus menggunakan format floating point presisi ganda.
Seperti yang sudah ditunjukkan oleh jawaban lain, menerapkan timer dapat dilakukan dengan menambah nilai yang disimpan oleh masing-masing frame deltaTime
, dan membandingkannya dengan durasi yang diharapkan. Untuk kelengkapan, saya akan memasukkan kode yang sangat mirip dengan jawaban lain:
float elapsed = 0.0f;
float duration = 4.0f;
void update(float deltaTime) {
elapsed += deltaTime;
if (elapsed <= duration) {
// Run code.
elapsed = 0.0f;
// Maybe remove from update loop?
}
}
Bagaimana Anda ingin menangani // Run code.
porsinya terserah Anda. Mungkin Anda memiliki Timer
kelas, sebuah instance yang mengambil delegate
(C #) atau callback
(C ++) dan menyebutnya ketika penghitung waktu berakhir. Juga, menjeda penghitung waktu adalah masalah menghapusnya dari loop pembaruan.
Pendekatan alternatif adalah dengan menandai waktu mulai dari penghitung waktu, dan sebagai gantinya melakukan perhitungan berdasarkan permintaan waktu yang telah berlalu:
double startTime = 0.0; // This is a double for a reason, I'll explain below.
bool running = false;
void start() {
startTime = getTime(); // This is whatever system time call you want to use.
running = true;
}
double getElapsed() {
double elapsed = getTime() - startTime;
return elapsed;
}
Gaya ini memberi sedikit lebih banyak kontrol kepada pengguna timer. Struktur itu sendiri tidak peduli dengan apa yang harus dilakukan ketika waktu yang telah berlalu mencapai titik tertentu; bahkan tidak memperbarui. Pengguna dapat meminta waktu yang telah berlalu saat dibutuhkan. Pola ini memiliki efek samping yang disayangkan karena tidak ramah terhadap debugger. Waktu sistem berlanjut ketika program Anda dihentikan pada debugger, jadi timer seperti ini akan berperilaku berbeda ketika melangkah melalui program. Solusi potensial untuk itu adalah mempertahankan nilai waktu berlalu khusus-program yang diperbarui setiap frame menggunakan delta waktu sistem.
Saya pikir yang paling penting adalah dua kebiasaan mengatur waktu pada komputer, terutama dalam hal pengembangan game. Yang pertama adalah presisi floating point dan yang kedua adalah resolusi timer asli.
Anda akan perhatikan bahwa pada contoh kedua, saya menggunakan a double
jenis alih-alih float
, seperti pada contoh pertama (jenis nama tentu saja tergantung pada bahasa yang Anda gunakan). Alasan untuk ini adalah contoh kedua adalah menyimpan total waktu permainan yang telah berlalu . Jika permainan dibiarkan berjalan untuk waktu yang sangat lama, nilai format floating point presisi tunggal akan memiliki presisi yang tidak cukup untuk secara akurat mengukur waktu yang telah berlalu , yang mengarah ke masalah stabilitas. Contoh pertama baik-baik saja menggunakan float
tipe selama durasi besar tidak diharapkan.
Di ujung lain spektrum, jika waktu pembaruan yang Anda harapkan cukup kecil, Anda mungkin sebenarnya tidak dapat mencapainya pada awalnya, tergantung pada bagaimana Anda mendapatkan waktu sistem. Pengatur waktu akan sering bergantung pada resolusi pengatur waktu dari OS yang Anda jalankan. Misalnya, resolusi penghitung waktu default Windows 7 dan di bawahnya adalah 15,6 ms . Ini berarti bahwa ketepatan waktu terendah yang dapat Anda capai menggunakan fungsi sepertitimeGetTime
atau GetTickCount
, adalah 15,6 ms, kecuali jika Anda mengubah resolusi pengatur waktu (ada juga bahaya yang terkait dengannya).
Ya, itu agak lama, tetapi ini adalah hal-hal penting yang harus diperhatikan ketika mengimplementasikan timer.