我已经用C语言编写了一个简单的游戏,snake。我从使用睡眠(nanosleep)的游戏循环开始,但是现在我尝试通过使用计算机时钟(clock_gettime)使其变为软实时。简化的示例使用clock_gettime来获取程序的时间跨度,根据需要工作。但是,当我尝试每秒进行20次更新(移动)时,无法达到此更新/“移动蛇”。此代码没有任何“图形”来显示问题。 clock_gettime()使用 struct timespec ,它具有两个值,以秒为单位的时间和以纳秒为单位的时间。我制作了一个函数timespec_to_ms,将值对(秒/纳秒)转换为单秒级谷值,但它提供了非常高的输出值。
#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,并且“ ms”计时器(上次时间和时钟)非常高。
我在VirtualBox中使用Ubuntu Server 16(在Win 10中),并使用编译程序。
gcc -o rt rt.c -lncurses