Я написал для простой игры на С, змея. Я начал с игрового цикла, который использует сон (nanosleep), но теперь я пытаюсь сделать его мягким в реальном времени, используя компьютерные часы (clock_gettime). Упрощенный пример использует clock_gettime для получения временного интервала программы, работает так, как хотел. Но когда я пытаюсь сделать обновление (движение) 20 раз в секунду, это обновление / «перемещение змеи» не достигается. Этот код без какой-либо "графики", чтобы показать проблему. Clock_gettime () использует struct timespec , которая имеет два значения: время в секундах и время в нано-секундах. Я сделал функцию timespec_to_ms для преобразования пары значений (sec / nanosec) в единичное значение msecond, но оно дает очень высокие выходные значения.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <ncurses.h>
#define BILL 1E9
int is_timespec_b_greater_than_a(struct timespec a, struct timespec b){
if(b.tv_sec > a.tv_sec){
return 1;
}else if(b.tv_sec == a.tv_sec){
if(b.tv_nsec > a.tv_nsec){
return 1;
}
}
return 0;
}
//I made this to get a single time-value
long timespec_to_ms(struct timespec tim){
return tim.tv_sec * 1000 + (tim.tv_nsec / 1000000L);
}
long get_clock_ms(){
struct timespec temp;
if (clock_gettime(CLOCK_REALTIME, &temp) == -1) return -1;
return timespec_to_ms(temp);
}
struct timespec add_ms(struct timespec tim, int milliseconds){
int sec = tim.tv_sec;
int ms1 = tim.tv_nsec / 1000000;
int add_sec = milliseconds / 1000; //if above 1000, > 0
milliseconds = milliseconds % 1000; //limit to 0-999
if(ms1 + milliseconds >= 1000){
sec++;
}
sec += add_sec;
ms1 = (ms1 + milliseconds) % 1000;
struct timespec new;
new.tv_sec = sec;
new.tv_nsec = ms1 * 1000000;
return new;
}
int kbhit (WINDOW * stds){
int ch = wgetch(stds);
if(ch != ERR){
ungetch(ch);
return 1;
} else {
return 0;
}
}
int main(){
struct timespec start, end, klockan, s_f;
double accum, comp;
int count = 0, diff=0, c1, c2, interval_ms = 50;
long clock, lasttime;
WINDOW * stds = initscr();
clear();
clock_gettime(CLOCK_REALTIME, &start);
if (clock_gettime(CLOCK_REALTIME, &s_f)== -1) printf("error1");
lasttime = get_clock_ms();
while(1){
clock = get_clock_ms();
if(clock > lasttime + interval_ms){
count++;
lasttime = clock;
}
if(kbhit(stds)){
break;
}
}
clock_gettime(CLOCK_REALTIME, &end);
accum = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / BILL;
endwin();
printf("%lf %d\t%d %ld\t%ld\n", accum, count, interval_ms, lasttime, clock);
return 0;
}
После однократного запуска (и короткого нажатия на клавиатуру) я получаю выход:
1.142959 0 50 1553331597068 1553331597068
Таким образом, программа работала в течение 1,1 секунды, она никогда не входила в область действия «ход игры», интервал составлял 50, а таймер «мс» (время последнего времени и часы) был очень высоким.
Я использую Ubuntu Server 16 в VirtualBox (в Win 10) и скомпилировал программу с
gcc -o rt rt.c -lncurses