Tôi muốn có một cái gì đó xảy ra cứ sau N giây, tôi sẽ làm thế nào? Có thể sử dụng đồng hồ bấm giờ nhưng làm thế nào?
Tôi muốn có một cái gì đó xảy ra cứ sau N giây, tôi sẽ làm thế nào? Có thể sử dụng đồng hồ bấm giờ nhưng làm thế nào?
Câu trả lời:
Một cách tiếp cận phổ biến cho việc này là sử dụng vòng cập nhật và thời gian delta.
float timerCurrent = 0f;
float timerTotal = 5f;
Update() {
timerCurrent += deltaTime;
if(timerCurrent >= timerTotal) {
//do timer action
timerCurrent -= timerTotal;
}
}
Điều này cho rằng bạn có quyền truy cập vào một deltaTime
biến. Thời gian Delta đơn giản là thời gian đã trôi qua kể từ khung cuối cùng. Nhiều động cơ sẽ có sẵn điều này cho bạn hoặc bạn có thể tìm hiểu thêm về cách thiết lập của riêng bạn ở đây .
Trong hầu hết các ngôn ngữ, bạn cần khởi động đồng hồ với một số loại chức năng gọi dọc theo các dòng clock.startTimer()
trước khi bạn vào vòng lặp chính. Sau đó, bạn phải lưu trữ giá trị thời gian của đồng hồ trước khi bạn nhập vòng lặp chính vào một biến có chức năng như thế nào time = clock.getTime()
. Lưu trữ thời gian bước của bạn vào biến n
.
Trong vòng lặp chính của bạn, kiểm tra bạn muốn thực hiện là một cái gì đó dọc theo dòng
if(time + n <= clock.getTime())
//do stuff
time = clock.getTime() //important to assign new time value here
Lưu ý: Tôi không chắc bạn đang xem ngôn ngữ / thư viện nào vì vậy đây chỉ là một thuật toán chung mà tôi nghĩ ra khỏi đỉnh đầu. Nó có thể không phù hợp với nhu cầu của bạn chính xác. Một số ngôn ngữ / thư viện yêu cầu bạn tạo một đối tượng đồng hồ trong khi những ngôn ngữ khác bạn có thể chỉ cần thực hiện một cuộc gọi hàm trực tiếp.
Theo các bình luận dưới đây, bạn phải cẩn thận với các vấn đề luồng tùy thuộc vào ngôn ngữ bạn đang sử dụng. Bạn cũng nên sử dụng một phao đôi để lưu trữ time
.
time
sắp lưu trữ thời gian trò chơi đã trôi qua, thì nên sử dụng định dạng dấu phẩy động có độ chính xác kép.
Như các câu trả lời khác đã chỉ ra, việc thực hiện bộ hẹn giờ có thể được thực hiện bằng cách tăng giá trị được lưu trữ theo từng khung deltaTime
và so sánh nó với thời lượng dự kiến. Để đầy đủ, tôi sẽ bao gồm mã rất giống với các câu trả lời khác:
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?
}
}
Làm thế nào bạn muốn xử lý // Run code.
phần là tùy thuộc vào bạn. Có thể bạn có một Timer
lớp, một thể hiện trong đó lấy một delegate
(C #) hoặc callback
(C ++) và gọi nó khi hết giờ. Ngoài ra, tạm dừng bộ hẹn giờ là vấn đề loại bỏ nó khỏi vòng cập nhật.
Một cách tiếp cận khác là đánh dấu thời gian bắt đầu của bộ hẹn giờ và thay vào đó là tính toán theo yêu cầu về thời gian đã trôi qua:
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;
}
Phong cách này cung cấp thêm một chút kiểm soát cho người sử dụng bộ đếm thời gian. Bản thân cấu trúc không quan tâm đến việc phải làm gì khi thời gian trôi qua đạt đến một điểm nhất định; nó thậm chí không cập nhật. Người dùng có thể chỉ cần truy vấn thời gian đã trôi qua khi cần thiết. Mẫu này có tác dụng phụ đáng tiếc là không thân thiện với trình gỡ lỗi. Thời gian hệ thống tiếp tục khi chương trình của bạn bị dừng trên trình gỡ lỗi, vì vậy các bộ tính giờ như thế này sẽ hoạt động khác đi khi bước qua các chương trình. Một giải pháp tiềm năng cho điều đó là duy trì giá trị thời gian trôi qua dành riêng cho chương trình, được cập nhật mọi khung hình bằng cách sử dụng đồng thời thời gian hệ thống.
Tôi nghĩ quan trọng nhất mặc dù là hai quirks về thời gian trên máy tính, đặc biệt là khi phát triển trò chơi. Đầu tiên là độ chính xác của dấu phẩy động và thứ hai là độ phân giải bộ đếm thời gian gốc.
Bạn sẽ lưu ý rằng trong ví dụ thứ hai, tôi đã sử dụng một double
loại thay vì một float
, như trong ví dụ đầu tiên (kiểu chữ tất nhiên phụ thuộc vào ngôn ngữ bạn đang sử dụng). Lý do cho điều này là ví dụ thứ hai là lưu trữ tổng thời gian trò chơi đã trôi qua . Nếu trò chơi không hoạt động trong một thời gian rất dài, các giá trị định dạng dấu phẩy động có độ chính xác đơn sẽ không đủ độ chính xác để đo chính xác thời gian đã trôi qua , dẫn đến các vấn đề ổn định. Ví dụ đầu tiên là tốt khi sử dụng float
loại miễn là thời lượng lớn không được mong đợi.
Ở đầu kia của quang phổ, nếu thời gian cập nhật bạn mong đợi đủ nhỏ, bạn có thể không thực sự có thể đạt được nó ban đầu, tùy thuộc vào cách bạn có được thời gian hệ thống. Bộ hẹn giờ thường sẽ phụ thuộc vào độ phân giải hẹn giờ của HĐH bạn đang chạy. Ví dụ: độ phân giải hẹn giờ mặc định của Windows 7 trở xuống là 15,6 ms . Điều này có nghĩa là độ chính xác của bộ hẹn giờ thấp nhất bạn có thể đạt được bằng cách sử dụng các chức năng như , timeGetTime
hoặc GetTickCount
là 15,6 ms, trừ khi bạn thay đổi độ phân giải của bộ hẹn giờ (cũng có những nguy hiểm liên quan đến điều đó).
Chà, điều đó hóa ra hơi lâu, nhưng đây là những điều quan trọng cần lưu ý khi thực hiện bộ tính giờ.