Почему условие в игровом цикле не выполняется, используя clock_gettime - PullRequest
1 голос
/ 23 марта 2019

Я написал для простой игры на С, змея. Я начал с игрового цикла, который использует сон (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
...